1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
205e84878SDylan Reid /*
305e84878SDylan Reid *
405e84878SDylan Reid * Implementation of primary alsa driver code base for Intel HD Audio.
505e84878SDylan Reid *
6*e09f9f52SPierre-Louis Bossart * Copyright(c) 2004 Intel Corporation
705e84878SDylan Reid *
805e84878SDylan Reid * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
905e84878SDylan Reid * PeiSen Hou <pshou@realtek.com.tw>
1005e84878SDylan Reid */
1105e84878SDylan Reid
1205e84878SDylan Reid #include <linux/clocksource.h>
1305e84878SDylan Reid #include <linux/delay.h>
14f0b1df88SDylan Reid #include <linux/interrupt.h>
1505e84878SDylan Reid #include <linux/kernel.h>
1605e84878SDylan Reid #include <linux/module.h>
17154867cfSDylan Reid #include <linux/pm_runtime.h>
1805e84878SDylan Reid #include <linux/slab.h>
19bfcba288SGuneshwor Singh
20bfcba288SGuneshwor Singh #ifdef CONFIG_X86
21bfcba288SGuneshwor Singh /* for art-tsc conversion */
22bfcba288SGuneshwor Singh #include <asm/tsc.h>
23bfcba288SGuneshwor Singh #endif
24bfcba288SGuneshwor Singh
2505e84878SDylan Reid #include <sound/core.h>
2605e84878SDylan Reid #include <sound/initval.h>
2704438a06STakashi Iwai #include <sound/pcm_params.h>
2805e84878SDylan Reid #include "hda_controller.h"
29c0f1886dSTakashi Iwai #include "hda_local.h"
3005e84878SDylan Reid
3143db4a59STakashi Iwai #define CREATE_TRACE_POINTS
3218486508SLibin Yang #include "hda_controller_trace.h"
3343db4a59STakashi Iwai
342b5fd6c2SDylan Reid /* DSP lock helpers */
357833c3f8STakashi Iwai #define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev))
367833c3f8STakashi Iwai #define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev))
377833c3f8STakashi Iwai #define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev))
382b5fd6c2SDylan Reid
3905e84878SDylan Reid /* assign a stream for the PCM */
4005e84878SDylan Reid static inline struct azx_dev *
azx_assign_device(struct azx * chip,struct snd_pcm_substream * substream)4105e84878SDylan Reid azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
4205e84878SDylan Reid {
437833c3f8STakashi Iwai struct hdac_stream *s;
4405e84878SDylan Reid
457833c3f8STakashi Iwai s = snd_hdac_stream_assign(azx_bus(chip), substream);
467833c3f8STakashi Iwai if (!s)
477833c3f8STakashi Iwai return NULL;
487833c3f8STakashi Iwai return stream_to_azx_dev(s);
4905e84878SDylan Reid }
5005e84878SDylan Reid
5105e84878SDylan Reid /* release the assigned stream */
azx_release_device(struct azx_dev * azx_dev)5205e84878SDylan Reid static inline void azx_release_device(struct azx_dev *azx_dev)
5305e84878SDylan Reid {
547833c3f8STakashi Iwai snd_hdac_stream_release(azx_stream(azx_dev));
5505e84878SDylan Reid }
5605e84878SDylan Reid
57820cc6cfSTakashi Iwai static inline struct hda_pcm_stream *
to_hda_pcm_stream(struct snd_pcm_substream * substream)58820cc6cfSTakashi Iwai to_hda_pcm_stream(struct snd_pcm_substream *substream)
59820cc6cfSTakashi Iwai {
60820cc6cfSTakashi Iwai struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
61820cc6cfSTakashi Iwai return &apcm->info->stream[substream->stream];
62820cc6cfSTakashi Iwai }
63820cc6cfSTakashi Iwai
azx_adjust_codec_delay(struct snd_pcm_substream * substream,u64 nsec)6405e84878SDylan Reid static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
6505e84878SDylan Reid u64 nsec)
6605e84878SDylan Reid {
6705e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
68820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
6905e84878SDylan Reid u64 codec_frames, codec_nsecs;
7005e84878SDylan Reid
7105e84878SDylan Reid if (!hinfo->ops.get_delay)
7205e84878SDylan Reid return nsec;
7305e84878SDylan Reid
7405e84878SDylan Reid codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream);
7505e84878SDylan Reid codec_nsecs = div_u64(codec_frames * 1000000000LL,
7605e84878SDylan Reid substream->runtime->rate);
7705e84878SDylan Reid
7805e84878SDylan Reid if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
7905e84878SDylan Reid return nsec + codec_nsecs;
8005e84878SDylan Reid
8105e84878SDylan Reid return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
8205e84878SDylan Reid }
8305e84878SDylan Reid
8405e84878SDylan Reid /*
8505e84878SDylan Reid * PCM ops
8605e84878SDylan Reid */
8705e84878SDylan Reid
azx_pcm_close(struct snd_pcm_substream * substream)8805e84878SDylan Reid static int azx_pcm_close(struct snd_pcm_substream *substream)
8905e84878SDylan Reid {
9005e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
91820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
9205e84878SDylan Reid struct azx *chip = apcm->chip;
9305e84878SDylan Reid struct azx_dev *azx_dev = get_azx_dev(substream);
9405e84878SDylan Reid
9518486508SLibin Yang trace_azx_pcm_close(chip, azx_dev);
9605e84878SDylan Reid mutex_lock(&chip->open_mutex);
9705e84878SDylan Reid azx_release_device(azx_dev);
9861ca4107STakashi Iwai if (hinfo->ops.close)
9905e84878SDylan Reid hinfo->ops.close(hinfo, apcm->codec, substream);
10005e84878SDylan Reid snd_hda_power_down(apcm->codec);
10105e84878SDylan Reid mutex_unlock(&chip->open_mutex);
1029a6246ffSTakashi Iwai snd_hda_codec_pcm_put(apcm->info);
10305e84878SDylan Reid return 0;
10405e84878SDylan Reid }
10505e84878SDylan Reid
azx_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)10605e84878SDylan Reid static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
10705e84878SDylan Reid struct snd_pcm_hw_params *hw_params)
10805e84878SDylan Reid {
10905e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
11005e84878SDylan Reid struct azx *chip = apcm->chip;
111602518a2STakashi Iwai struct azx_dev *azx_dev = get_azx_dev(substream);
11204438a06STakashi Iwai struct hdac_stream *hdas = azx_stream(azx_dev);
1137a6d4a5aSTakashi Iwai int ret = 0;
11405e84878SDylan Reid
11518486508SLibin Yang trace_azx_pcm_hw_params(chip, azx_dev);
116602518a2STakashi Iwai dsp_lock(azx_dev);
117602518a2STakashi Iwai if (dsp_is_locked(azx_dev)) {
11805e84878SDylan Reid ret = -EBUSY;
11905e84878SDylan Reid goto unlock;
12005e84878SDylan Reid }
12105e84878SDylan Reid
12204438a06STakashi Iwai /* Set up BDLEs here, return -ENOMEM if too many BDLEs are required */
12304438a06STakashi Iwai hdas->bufsize = params_buffer_bytes(hw_params);
12404438a06STakashi Iwai hdas->period_bytes = params_period_bytes(hw_params);
12504438a06STakashi Iwai hdas->format_val = 0;
12604438a06STakashi Iwai hdas->no_period_wakeup =
12704438a06STakashi Iwai (hw_params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
12804438a06STakashi Iwai (hw_params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
12904438a06STakashi Iwai if (snd_hdac_stream_setup_periods(hdas) < 0)
13004438a06STakashi Iwai ret = -ENOMEM;
131193c7e14STakashi Iwai
13205e84878SDylan Reid unlock:
133602518a2STakashi Iwai dsp_unlock(azx_dev);
13405e84878SDylan Reid return ret;
13505e84878SDylan Reid }
13605e84878SDylan Reid
azx_pcm_hw_free(struct snd_pcm_substream * substream)13705e84878SDylan Reid static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
13805e84878SDylan Reid {
13905e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
14005e84878SDylan Reid struct azx_dev *azx_dev = get_azx_dev(substream);
141820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
14205e84878SDylan Reid
14305e84878SDylan Reid /* reset BDL address */
14405e84878SDylan Reid dsp_lock(azx_dev);
145ccc98865STakashi Iwai if (!dsp_is_locked(azx_dev))
146ccc98865STakashi Iwai snd_hdac_stream_cleanup(azx_stream(azx_dev));
14705e84878SDylan Reid
14805e84878SDylan Reid snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
14905e84878SDylan Reid
1506d23c8f5STakashi Iwai azx_stream(azx_dev)->prepared = 0;
15105e84878SDylan Reid dsp_unlock(azx_dev);
1527a6d4a5aSTakashi Iwai return 0;
15305e84878SDylan Reid }
15405e84878SDylan Reid
azx_pcm_prepare(struct snd_pcm_substream * substream)15505e84878SDylan Reid static int azx_pcm_prepare(struct snd_pcm_substream *substream)
15605e84878SDylan Reid {
15705e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
15805e84878SDylan Reid struct azx *chip = apcm->chip;
15905e84878SDylan Reid struct azx_dev *azx_dev = get_azx_dev(substream);
160820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
16105e84878SDylan Reid struct snd_pcm_runtime *runtime = substream->runtime;
16261b52df4SCezary Rojewski unsigned int format_val, stream_tag, bits;
16305e84878SDylan Reid int err;
16405e84878SDylan Reid struct hda_spdif_out *spdif =
16505e84878SDylan Reid snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
16605e84878SDylan Reid unsigned short ctls = spdif ? spdif->ctls : 0;
16705e84878SDylan Reid
16818486508SLibin Yang trace_azx_pcm_prepare(chip, azx_dev);
16905e84878SDylan Reid dsp_lock(azx_dev);
17005e84878SDylan Reid if (dsp_is_locked(azx_dev)) {
17105e84878SDylan Reid err = -EBUSY;
17205e84878SDylan Reid goto unlock;
17305e84878SDylan Reid }
17405e84878SDylan Reid
1757833c3f8STakashi Iwai snd_hdac_stream_reset(azx_stream(azx_dev));
17661b52df4SCezary Rojewski bits = snd_hdac_stream_format_bits(runtime->format, SNDRV_PCM_SUBFORMAT_STD, hinfo->maxbps);
17761b52df4SCezary Rojewski
17861b52df4SCezary Rojewski format_val = snd_hdac_spdif_stream_format(runtime->channels, bits, runtime->rate, ctls);
17905e84878SDylan Reid if (!format_val) {
18005e84878SDylan Reid dev_err(chip->card->dev,
18105e84878SDylan Reid "invalid format_val, rate=%d, ch=%d, format=%d\n",
18205e84878SDylan Reid runtime->rate, runtime->channels, runtime->format);
18305e84878SDylan Reid err = -EINVAL;
18405e84878SDylan Reid goto unlock;
18505e84878SDylan Reid }
18605e84878SDylan Reid
1870dd76f36STakashi Iwai err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val);
18805e84878SDylan Reid if (err < 0)
18905e84878SDylan Reid goto unlock;
19005e84878SDylan Reid
1915eb4ff88SCezary Rojewski snd_hdac_stream_setup(azx_stream(azx_dev), false);
19205e84878SDylan Reid
1937833c3f8STakashi Iwai stream_tag = azx_dev->core.stream_tag;
19405e84878SDylan Reid /* CA-IBG chips need the playback stream starting from 1 */
19505e84878SDylan Reid if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
19605e84878SDylan Reid stream_tag > chip->capture_streams)
19705e84878SDylan Reid stream_tag -= chip->capture_streams;
19805e84878SDylan Reid err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
1997833c3f8STakashi Iwai azx_dev->core.format_val, substream);
20005e84878SDylan Reid
20105e84878SDylan Reid unlock:
20205e84878SDylan Reid if (!err)
2036d23c8f5STakashi Iwai azx_stream(azx_dev)->prepared = 1;
20405e84878SDylan Reid dsp_unlock(azx_dev);
20505e84878SDylan Reid return err;
20605e84878SDylan Reid }
20705e84878SDylan Reid
azx_pcm_trigger(struct snd_pcm_substream * substream,int cmd)20805e84878SDylan Reid static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
20905e84878SDylan Reid {
21005e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
21105e84878SDylan Reid struct azx *chip = apcm->chip;
212a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
21305e84878SDylan Reid struct azx_dev *azx_dev;
21405e84878SDylan Reid struct snd_pcm_substream *s;
215ccc98865STakashi Iwai struct hdac_stream *hstr;
216ccc98865STakashi Iwai bool start;
217ccc98865STakashi Iwai int sbits = 0;
218ccc98865STakashi Iwai int sync_reg;
21905e84878SDylan Reid
22005e84878SDylan Reid azx_dev = get_azx_dev(substream);
22143db4a59STakashi Iwai trace_azx_pcm_trigger(chip, azx_dev, cmd);
22243db4a59STakashi Iwai
223ccc98865STakashi Iwai hstr = azx_stream(azx_dev);
224ccc98865STakashi Iwai if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
225ccc98865STakashi Iwai sync_reg = AZX_REG_OLD_SSYNC;
226ccc98865STakashi Iwai else
227ccc98865STakashi Iwai sync_reg = AZX_REG_SSYNC;
22805e84878SDylan Reid
2296d23c8f5STakashi Iwai if (dsp_is_locked(azx_dev) || !hstr->prepared)
23005e84878SDylan Reid return -EPIPE;
23105e84878SDylan Reid
23205e84878SDylan Reid switch (cmd) {
23305e84878SDylan Reid case SNDRV_PCM_TRIGGER_START:
23405e84878SDylan Reid case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
23505e84878SDylan Reid case SNDRV_PCM_TRIGGER_RESUME:
236ccc98865STakashi Iwai start = true;
23705e84878SDylan Reid break;
23805e84878SDylan Reid case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
23905e84878SDylan Reid case SNDRV_PCM_TRIGGER_SUSPEND:
24005e84878SDylan Reid case SNDRV_PCM_TRIGGER_STOP:
241ccc98865STakashi Iwai start = false;
24205e84878SDylan Reid break;
24305e84878SDylan Reid default:
24405e84878SDylan Reid return -EINVAL;
24505e84878SDylan Reid }
24605e84878SDylan Reid
24705e84878SDylan Reid snd_pcm_group_for_each_entry(s, substream) {
24805e84878SDylan Reid if (s->pcm->card != substream->pcm->card)
24905e84878SDylan Reid continue;
25005e84878SDylan Reid azx_dev = get_azx_dev(s);
2517833c3f8STakashi Iwai sbits |= 1 << azx_dev->core.index;
25205e84878SDylan Reid snd_pcm_trigger_done(s, substream);
25305e84878SDylan Reid }
25405e84878SDylan Reid
255a41d1224STakashi Iwai spin_lock(&bus->reg_lock);
25605e84878SDylan Reid
25705e84878SDylan Reid /* first, set SYNC bits of corresponding streams */
258ccc98865STakashi Iwai snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg);
25905e84878SDylan Reid
26005e84878SDylan Reid snd_pcm_group_for_each_entry(s, substream) {
26105e84878SDylan Reid if (s->pcm->card != substream->pcm->card)
26205e84878SDylan Reid continue;
26305e84878SDylan Reid azx_dev = get_azx_dev(s);
26405e84878SDylan Reid if (start) {
2657833c3f8STakashi Iwai azx_dev->insufficient = 1;
2664fe20d62SZhang Yiqun snd_hdac_stream_start(azx_stream(azx_dev));
26705e84878SDylan Reid } else {
2687833c3f8STakashi Iwai snd_hdac_stream_stop(azx_stream(azx_dev));
26905e84878SDylan Reid }
27005e84878SDylan Reid }
271a41d1224STakashi Iwai spin_unlock(&bus->reg_lock);
272ccc98865STakashi Iwai
273ccc98865STakashi Iwai snd_hdac_stream_sync(hstr, start, sbits);
274ccc98865STakashi Iwai
275a41d1224STakashi Iwai spin_lock(&bus->reg_lock);
27605e84878SDylan Reid /* reset SYNC bits */
277ccc98865STakashi Iwai snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg);
278ccc98865STakashi Iwai if (start)
279ccc98865STakashi Iwai snd_hdac_stream_timecounter_init(hstr, sbits);
280a41d1224STakashi Iwai spin_unlock(&bus->reg_lock);
28105e84878SDylan Reid return 0;
28205e84878SDylan Reid }
28305e84878SDylan Reid
azx_get_pos_lpib(struct azx * chip,struct azx_dev * azx_dev)284b6050ef6STakashi Iwai unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
28505e84878SDylan Reid {
2867833c3f8STakashi Iwai return snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
28705e84878SDylan Reid }
288b6050ef6STakashi Iwai EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
28905e84878SDylan Reid
azx_get_pos_posbuf(struct azx * chip,struct azx_dev * azx_dev)290b6050ef6STakashi Iwai unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
291b6050ef6STakashi Iwai {
2927833c3f8STakashi Iwai return snd_hdac_stream_get_pos_posbuf(azx_stream(azx_dev));
29305e84878SDylan Reid }
294b6050ef6STakashi Iwai EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
29505e84878SDylan Reid
azx_get_position(struct azx * chip,struct azx_dev * azx_dev)29605e84878SDylan Reid unsigned int azx_get_position(struct azx *chip,
297b6050ef6STakashi Iwai struct azx_dev *azx_dev)
29805e84878SDylan Reid {
2997833c3f8STakashi Iwai struct snd_pcm_substream *substream = azx_dev->core.substream;
30005e84878SDylan Reid unsigned int pos;
30105e84878SDylan Reid int stream = substream->stream;
30205e84878SDylan Reid int delay = 0;
30305e84878SDylan Reid
304b6050ef6STakashi Iwai if (chip->get_position[stream])
305b6050ef6STakashi Iwai pos = chip->get_position[stream](chip, azx_dev);
306b6050ef6STakashi Iwai else /* use the position buffer as default */
307b6050ef6STakashi Iwai pos = azx_get_pos_posbuf(chip, azx_dev);
30805e84878SDylan Reid
3097833c3f8STakashi Iwai if (pos >= azx_dev->core.bufsize)
31005e84878SDylan Reid pos = 0;
31105e84878SDylan Reid
31205e84878SDylan Reid if (substream->runtime) {
313b6050ef6STakashi Iwai struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
314820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
315b6050ef6STakashi Iwai
316b6050ef6STakashi Iwai if (chip->get_delay[stream])
317b6050ef6STakashi Iwai delay += chip->get_delay[stream](chip, azx_dev, pos);
31805e84878SDylan Reid if (hinfo->ops.get_delay)
31905e84878SDylan Reid delay += hinfo->ops.get_delay(hinfo, apcm->codec,
32005e84878SDylan Reid substream);
32105e84878SDylan Reid substream->runtime->delay = delay;
32205e84878SDylan Reid }
32305e84878SDylan Reid
32443db4a59STakashi Iwai trace_azx_get_position(chip, azx_dev, pos, delay);
32505e84878SDylan Reid return pos;
32605e84878SDylan Reid }
32705e84878SDylan Reid EXPORT_SYMBOL_GPL(azx_get_position);
32805e84878SDylan Reid
azx_pcm_pointer(struct snd_pcm_substream * substream)32905e84878SDylan Reid static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
33005e84878SDylan Reid {
33105e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
33205e84878SDylan Reid struct azx *chip = apcm->chip;
33305e84878SDylan Reid struct azx_dev *azx_dev = get_azx_dev(substream);
33405e84878SDylan Reid return bytes_to_frames(substream->runtime,
335b6050ef6STakashi Iwai azx_get_position(chip, azx_dev));
33605e84878SDylan Reid }
33705e84878SDylan Reid
338bfcba288SGuneshwor Singh /*
339bfcba288SGuneshwor Singh * azx_scale64: Scale base by mult/div while not overflowing sanely
340bfcba288SGuneshwor Singh *
341bfcba288SGuneshwor Singh * Derived from scale64_check_overflow in kernel/time/timekeeping.c
342bfcba288SGuneshwor Singh *
343bfcba288SGuneshwor Singh * The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which
344bfcba288SGuneshwor Singh * is about 384307 ie ~4.5 days.
345bfcba288SGuneshwor Singh *
346bfcba288SGuneshwor Singh * This scales the calculation so that overflow will happen but after 2^64 /
347bfcba288SGuneshwor Singh * 48000 secs, which is pretty large!
348bfcba288SGuneshwor Singh *
349bfcba288SGuneshwor Singh * In caln below:
350bfcba288SGuneshwor Singh * base may overflow, but since there isn’t any additional division
351bfcba288SGuneshwor Singh * performed on base it’s OK
352bfcba288SGuneshwor Singh * rem can’t overflow because both are 32-bit values
353bfcba288SGuneshwor Singh */
354bfcba288SGuneshwor Singh
355bfcba288SGuneshwor Singh #ifdef CONFIG_X86
azx_scale64(u64 base,u32 num,u32 den)356bfcba288SGuneshwor Singh static u64 azx_scale64(u64 base, u32 num, u32 den)
357bfcba288SGuneshwor Singh {
358bfcba288SGuneshwor Singh u64 rem;
359bfcba288SGuneshwor Singh
360bfcba288SGuneshwor Singh rem = do_div(base, den);
361bfcba288SGuneshwor Singh
362bfcba288SGuneshwor Singh base *= num;
363bfcba288SGuneshwor Singh rem *= num;
364bfcba288SGuneshwor Singh
365bfcba288SGuneshwor Singh do_div(rem, den);
366bfcba288SGuneshwor Singh
367bfcba288SGuneshwor Singh return base + rem;
368bfcba288SGuneshwor Singh }
369bfcba288SGuneshwor Singh
azx_get_sync_time(ktime_t * device,struct system_counterval_t * system,void * ctx)370bfcba288SGuneshwor Singh static int azx_get_sync_time(ktime_t *device,
371bfcba288SGuneshwor Singh struct system_counterval_t *system, void *ctx)
372bfcba288SGuneshwor Singh {
373bfcba288SGuneshwor Singh struct snd_pcm_substream *substream = ctx;
374bfcba288SGuneshwor Singh struct azx_dev *azx_dev = get_azx_dev(substream);
375bfcba288SGuneshwor Singh struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
376bfcba288SGuneshwor Singh struct azx *chip = apcm->chip;
377bfcba288SGuneshwor Singh struct snd_pcm_runtime *runtime;
378bfcba288SGuneshwor Singh u64 ll_counter, ll_counter_l, ll_counter_h;
379bfcba288SGuneshwor Singh u64 tsc_counter, tsc_counter_l, tsc_counter_h;
380bfcba288SGuneshwor Singh u32 wallclk_ctr, wallclk_cycles;
381bfcba288SGuneshwor Singh bool direction;
382bfcba288SGuneshwor Singh u32 dma_select;
3834dca80b4SColin Ian King u32 timeout;
384bfcba288SGuneshwor Singh u32 retry_count = 0;
385bfcba288SGuneshwor Singh
386bfcba288SGuneshwor Singh runtime = substream->runtime;
387bfcba288SGuneshwor Singh
388bfcba288SGuneshwor Singh if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
389bfcba288SGuneshwor Singh direction = 1;
390bfcba288SGuneshwor Singh else
391bfcba288SGuneshwor Singh direction = 0;
392bfcba288SGuneshwor Singh
393bfcba288SGuneshwor Singh /* 0th stream tag is not used, so DMA ch 0 is for 1st stream tag */
394bfcba288SGuneshwor Singh do {
395bfcba288SGuneshwor Singh timeout = 100;
396bfcba288SGuneshwor Singh dma_select = (direction << GTSCC_CDMAS_DMA_DIR_SHIFT) |
397bfcba288SGuneshwor Singh (azx_dev->core.stream_tag - 1);
398bfcba288SGuneshwor Singh snd_hdac_chip_writel(azx_bus(chip), GTSCC, dma_select);
399bfcba288SGuneshwor Singh
400bfcba288SGuneshwor Singh /* Enable the capture */
401bfcba288SGuneshwor Singh snd_hdac_chip_updatel(azx_bus(chip), GTSCC, 0, GTSCC_TSCCI_MASK);
402bfcba288SGuneshwor Singh
403bfcba288SGuneshwor Singh while (timeout) {
404bfcba288SGuneshwor Singh if (snd_hdac_chip_readl(azx_bus(chip), GTSCC) &
405bfcba288SGuneshwor Singh GTSCC_TSCCD_MASK)
406bfcba288SGuneshwor Singh break;
407bfcba288SGuneshwor Singh
408bfcba288SGuneshwor Singh timeout--;
409bfcba288SGuneshwor Singh }
410bfcba288SGuneshwor Singh
411bfcba288SGuneshwor Singh if (!timeout) {
412bfcba288SGuneshwor Singh dev_err(chip->card->dev, "GTSCC capture Timedout!\n");
413bfcba288SGuneshwor Singh return -EIO;
414bfcba288SGuneshwor Singh }
415bfcba288SGuneshwor Singh
416bfcba288SGuneshwor Singh /* Read wall clock counter */
417bfcba288SGuneshwor Singh wallclk_ctr = snd_hdac_chip_readl(azx_bus(chip), WALFCC);
418bfcba288SGuneshwor Singh
419bfcba288SGuneshwor Singh /* Read TSC counter */
420bfcba288SGuneshwor Singh tsc_counter_l = snd_hdac_chip_readl(azx_bus(chip), TSCCL);
421bfcba288SGuneshwor Singh tsc_counter_h = snd_hdac_chip_readl(azx_bus(chip), TSCCU);
422bfcba288SGuneshwor Singh
423bfcba288SGuneshwor Singh /* Read Link counter */
424bfcba288SGuneshwor Singh ll_counter_l = snd_hdac_chip_readl(azx_bus(chip), LLPCL);
425bfcba288SGuneshwor Singh ll_counter_h = snd_hdac_chip_readl(azx_bus(chip), LLPCU);
426bfcba288SGuneshwor Singh
427bfcba288SGuneshwor Singh /* Ack: registers read done */
428bfcba288SGuneshwor Singh snd_hdac_chip_writel(azx_bus(chip), GTSCC, GTSCC_TSCCD_SHIFT);
429bfcba288SGuneshwor Singh
430bfcba288SGuneshwor Singh tsc_counter = (tsc_counter_h << TSCCU_CCU_SHIFT) |
431bfcba288SGuneshwor Singh tsc_counter_l;
432bfcba288SGuneshwor Singh
433bfcba288SGuneshwor Singh ll_counter = (ll_counter_h << LLPC_CCU_SHIFT) | ll_counter_l;
434bfcba288SGuneshwor Singh wallclk_cycles = wallclk_ctr & WALFCC_CIF_MASK;
435bfcba288SGuneshwor Singh
436bfcba288SGuneshwor Singh /*
437bfcba288SGuneshwor Singh * An error occurs near frame "rollover". The clocks in
438bfcba288SGuneshwor Singh * frame value indicates whether this error may have
439bfcba288SGuneshwor Singh * occurred. Here we use the value of 10 i.e.,
440bfcba288SGuneshwor Singh * HDA_MAX_CYCLE_OFFSET
441bfcba288SGuneshwor Singh */
442bfcba288SGuneshwor Singh if (wallclk_cycles < HDA_MAX_CYCLE_VALUE - HDA_MAX_CYCLE_OFFSET
443bfcba288SGuneshwor Singh && wallclk_cycles > HDA_MAX_CYCLE_OFFSET)
444bfcba288SGuneshwor Singh break;
445bfcba288SGuneshwor Singh
446bfcba288SGuneshwor Singh /*
447bfcba288SGuneshwor Singh * Sleep before we read again, else we may again get
448bfcba288SGuneshwor Singh * value near to MAX_CYCLE. Try to sleep for different
449bfcba288SGuneshwor Singh * amount of time so we dont hit the same number again
450bfcba288SGuneshwor Singh */
451bfcba288SGuneshwor Singh udelay(retry_count++);
452bfcba288SGuneshwor Singh
453bfcba288SGuneshwor Singh } while (retry_count != HDA_MAX_CYCLE_READ_RETRY);
454bfcba288SGuneshwor Singh
455bfcba288SGuneshwor Singh if (retry_count == HDA_MAX_CYCLE_READ_RETRY) {
456bfcba288SGuneshwor Singh dev_err_ratelimited(chip->card->dev,
457bfcba288SGuneshwor Singh "Error in WALFCC cycle count\n");
458bfcba288SGuneshwor Singh return -EIO;
459bfcba288SGuneshwor Singh }
460bfcba288SGuneshwor Singh
461bfcba288SGuneshwor Singh *device = ns_to_ktime(azx_scale64(ll_counter,
462bfcba288SGuneshwor Singh NSEC_PER_SEC, runtime->rate));
463bfcba288SGuneshwor Singh *device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) /
464bfcba288SGuneshwor Singh ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate));
465bfcba288SGuneshwor Singh
466bfcba288SGuneshwor Singh *system = convert_art_to_tsc(tsc_counter);
467bfcba288SGuneshwor Singh
468bfcba288SGuneshwor Singh return 0;
469bfcba288SGuneshwor Singh }
470bfcba288SGuneshwor Singh
471bfcba288SGuneshwor Singh #else
azx_get_sync_time(ktime_t * device,struct system_counterval_t * system,void * ctx)472bfcba288SGuneshwor Singh static int azx_get_sync_time(ktime_t *device,
473bfcba288SGuneshwor Singh struct system_counterval_t *system, void *ctx)
474bfcba288SGuneshwor Singh {
475bfcba288SGuneshwor Singh return -ENXIO;
476bfcba288SGuneshwor Singh }
477bfcba288SGuneshwor Singh #endif
478bfcba288SGuneshwor Singh
azx_get_crosststamp(struct snd_pcm_substream * substream,struct system_device_crosststamp * xtstamp)479bfcba288SGuneshwor Singh static int azx_get_crosststamp(struct snd_pcm_substream *substream,
480bfcba288SGuneshwor Singh struct system_device_crosststamp *xtstamp)
481bfcba288SGuneshwor Singh {
482bfcba288SGuneshwor Singh return get_device_system_crosststamp(azx_get_sync_time,
483bfcba288SGuneshwor Singh substream, NULL, xtstamp);
484bfcba288SGuneshwor Singh }
485bfcba288SGuneshwor Singh
is_link_time_supported(struct snd_pcm_runtime * runtime,struct snd_pcm_audio_tstamp_config * ts)486bfcba288SGuneshwor Singh static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime,
487bfcba288SGuneshwor Singh struct snd_pcm_audio_tstamp_config *ts)
488bfcba288SGuneshwor Singh {
489bfcba288SGuneshwor Singh if (runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME)
490bfcba288SGuneshwor Singh if (ts->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED)
491bfcba288SGuneshwor Singh return true;
492bfcba288SGuneshwor Singh
493bfcba288SGuneshwor Singh return false;
494bfcba288SGuneshwor Singh }
495bfcba288SGuneshwor Singh
azx_get_time_info(struct snd_pcm_substream * substream,struct timespec64 * system_ts,struct timespec64 * audio_ts,struct snd_pcm_audio_tstamp_config * audio_tstamp_config,struct snd_pcm_audio_tstamp_report * audio_tstamp_report)4969e94df3aSPierre-Louis Bossart static int azx_get_time_info(struct snd_pcm_substream *substream,
497fcae40c9SBaolin Wang struct timespec64 *system_ts, struct timespec64 *audio_ts,
4989e94df3aSPierre-Louis Bossart struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
4999e94df3aSPierre-Louis Bossart struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
50005e84878SDylan Reid {
50105e84878SDylan Reid struct azx_dev *azx_dev = get_azx_dev(substream);
502bfcba288SGuneshwor Singh struct snd_pcm_runtime *runtime = substream->runtime;
503bfcba288SGuneshwor Singh struct system_device_crosststamp xtstamp;
504bfcba288SGuneshwor Singh int ret;
50505e84878SDylan Reid u64 nsec;
50605e84878SDylan Reid
5079e94df3aSPierre-Louis Bossart if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
5089e94df3aSPierre-Louis Bossart (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
5099e94df3aSPierre-Louis Bossart
5109e94df3aSPierre-Louis Bossart snd_pcm_gettime(substream->runtime, system_ts);
5119e94df3aSPierre-Louis Bossart
5127833c3f8STakashi Iwai nsec = timecounter_read(&azx_dev->core.tc);
5139e94df3aSPierre-Louis Bossart if (audio_tstamp_config->report_delay)
51405e84878SDylan Reid nsec = azx_adjust_codec_delay(substream, nsec);
51505e84878SDylan Reid
516fcae40c9SBaolin Wang *audio_ts = ns_to_timespec64(nsec);
5179e94df3aSPierre-Louis Bossart
5189e94df3aSPierre-Louis Bossart audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
5199e94df3aSPierre-Louis Bossart audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */
5209e94df3aSPierre-Louis Bossart audio_tstamp_report->accuracy = 42; /* 24 MHz WallClock == 42ns resolution */
5219e94df3aSPierre-Louis Bossart
522bfcba288SGuneshwor Singh } else if (is_link_time_supported(runtime, audio_tstamp_config)) {
523bfcba288SGuneshwor Singh
524bfcba288SGuneshwor Singh ret = azx_get_crosststamp(substream, &xtstamp);
525bfcba288SGuneshwor Singh if (ret)
526bfcba288SGuneshwor Singh return ret;
527bfcba288SGuneshwor Singh
528bfcba288SGuneshwor Singh switch (runtime->tstamp_type) {
529bfcba288SGuneshwor Singh case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
530bfcba288SGuneshwor Singh return -EINVAL;
531bfcba288SGuneshwor Singh
532bfcba288SGuneshwor Singh case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
533fcae40c9SBaolin Wang *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw);
534bfcba288SGuneshwor Singh break;
535bfcba288SGuneshwor Singh
536bfcba288SGuneshwor Singh default:
537fcae40c9SBaolin Wang *system_ts = ktime_to_timespec64(xtstamp.sys_realtime);
538bfcba288SGuneshwor Singh break;
539bfcba288SGuneshwor Singh
540bfcba288SGuneshwor Singh }
541bfcba288SGuneshwor Singh
542fcae40c9SBaolin Wang *audio_ts = ktime_to_timespec64(xtstamp.device);
543bfcba288SGuneshwor Singh
544bfcba288SGuneshwor Singh audio_tstamp_report->actual_type =
545bfcba288SGuneshwor Singh SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED;
546bfcba288SGuneshwor Singh audio_tstamp_report->accuracy_report = 1;
547bfcba288SGuneshwor Singh /* 24 MHz WallClock == 42ns resolution */
548bfcba288SGuneshwor Singh audio_tstamp_report->accuracy = 42;
549bfcba288SGuneshwor Singh
550bfcba288SGuneshwor Singh } else {
5519e94df3aSPierre-Louis Bossart audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
552bfcba288SGuneshwor Singh }
55305e84878SDylan Reid
55405e84878SDylan Reid return 0;
55505e84878SDylan Reid }
55605e84878SDylan Reid
557c56fc8c9SJulia Lawall static const struct snd_pcm_hardware azx_pcm_hw = {
55805e84878SDylan Reid .info = (SNDRV_PCM_INFO_MMAP |
55905e84878SDylan Reid SNDRV_PCM_INFO_INTERLEAVED |
56005e84878SDylan Reid SNDRV_PCM_INFO_BLOCK_TRANSFER |
56105e84878SDylan Reid SNDRV_PCM_INFO_MMAP_VALID |
56205e84878SDylan Reid /* No full-resume yet implemented */
56305e84878SDylan Reid /* SNDRV_PCM_INFO_RESUME |*/
56405e84878SDylan Reid SNDRV_PCM_INFO_PAUSE |
56505e84878SDylan Reid SNDRV_PCM_INFO_SYNC_START |
5669e94df3aSPierre-Louis Bossart SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
5679e94df3aSPierre-Louis Bossart SNDRV_PCM_INFO_HAS_LINK_ATIME |
56805e84878SDylan Reid SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
56905e84878SDylan Reid .formats = SNDRV_PCM_FMTBIT_S16_LE,
57005e84878SDylan Reid .rates = SNDRV_PCM_RATE_48000,
57105e84878SDylan Reid .rate_min = 48000,
57205e84878SDylan Reid .rate_max = 48000,
57305e84878SDylan Reid .channels_min = 2,
57405e84878SDylan Reid .channels_max = 2,
57505e84878SDylan Reid .buffer_bytes_max = AZX_MAX_BUF_SIZE,
57605e84878SDylan Reid .period_bytes_min = 128,
57705e84878SDylan Reid .period_bytes_max = AZX_MAX_BUF_SIZE / 2,
57805e84878SDylan Reid .periods_min = 2,
57905e84878SDylan Reid .periods_max = AZX_MAX_FRAG,
58005e84878SDylan Reid .fifo_size = 0,
58105e84878SDylan Reid };
58205e84878SDylan Reid
azx_pcm_open(struct snd_pcm_substream * substream)58305e84878SDylan Reid static int azx_pcm_open(struct snd_pcm_substream *substream)
58405e84878SDylan Reid {
58505e84878SDylan Reid struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
586820cc6cfSTakashi Iwai struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
58705e84878SDylan Reid struct azx *chip = apcm->chip;
58805e84878SDylan Reid struct azx_dev *azx_dev;
58905e84878SDylan Reid struct snd_pcm_runtime *runtime = substream->runtime;
59005e84878SDylan Reid int err;
59105e84878SDylan Reid int buff_step;
59205e84878SDylan Reid
5939a6246ffSTakashi Iwai snd_hda_codec_pcm_get(apcm->info);
59405e84878SDylan Reid mutex_lock(&chip->open_mutex);
59505e84878SDylan Reid azx_dev = azx_assign_device(chip, substream);
59618486508SLibin Yang trace_azx_pcm_open(chip, azx_dev);
59705e84878SDylan Reid if (azx_dev == NULL) {
59861ca4107STakashi Iwai err = -EBUSY;
59961ca4107STakashi Iwai goto unlock;
60005e84878SDylan Reid }
601ccc98865STakashi Iwai runtime->private_data = azx_dev;
60250279d9bSGuneshwor Singh
60305e84878SDylan Reid runtime->hw = azx_pcm_hw;
604c1c6c877STakashi Iwai if (chip->gts_present)
605c1c6c877STakashi Iwai runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
60605e84878SDylan Reid runtime->hw.channels_min = hinfo->channels_min;
60705e84878SDylan Reid runtime->hw.channels_max = hinfo->channels_max;
60805e84878SDylan Reid runtime->hw.formats = hinfo->formats;
60905e84878SDylan Reid runtime->hw.rates = hinfo->rates;
61005e84878SDylan Reid snd_pcm_limit_hw_rates(runtime);
61105e84878SDylan Reid snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
61205e84878SDylan Reid
61305e84878SDylan Reid /* avoid wrap-around with wall-clock */
61405e84878SDylan Reid snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
61505e84878SDylan Reid 20,
61605e84878SDylan Reid 178000000);
61705e84878SDylan Reid
61805e84878SDylan Reid if (chip->align_buffer_size)
61905e84878SDylan Reid /* constrain buffer sizes to be multiple of 128
62005e84878SDylan Reid bytes. This is more efficient in terms of memory
62105e84878SDylan Reid access but isn't required by the HDA spec and
62205e84878SDylan Reid prevents users from specifying exact period/buffer
62305e84878SDylan Reid sizes. For example for 44.1kHz, a period size set
62405e84878SDylan Reid to 20ms will be rounded to 19.59ms. */
62505e84878SDylan Reid buff_step = 128;
62605e84878SDylan Reid else
62705e84878SDylan Reid /* Don't enforce steps on buffer sizes, still need to
62805e84878SDylan Reid be multiple of 4 bytes (HDA spec). Tested on Intel
62905e84878SDylan Reid HDA controllers, may not work on all devices where
63005e84878SDylan Reid option needs to be disabled */
63105e84878SDylan Reid buff_step = 4;
63205e84878SDylan Reid
63305e84878SDylan Reid snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
63405e84878SDylan Reid buff_step);
63505e84878SDylan Reid snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
63605e84878SDylan Reid buff_step);
637cc72da7dSTakashi Iwai snd_hda_power_up(apcm->codec);
63861ca4107STakashi Iwai if (hinfo->ops.open)
63905e84878SDylan Reid err = hinfo->ops.open(hinfo, apcm->codec, substream);
64061ca4107STakashi Iwai else
64161ca4107STakashi Iwai err = -ENODEV;
64205e84878SDylan Reid if (err < 0) {
64305e84878SDylan Reid azx_release_device(azx_dev);
64461ca4107STakashi Iwai goto powerdown;
64505e84878SDylan Reid }
64605e84878SDylan Reid snd_pcm_limit_hw_rates(runtime);
64705e84878SDylan Reid /* sanity check */
64805e84878SDylan Reid if (snd_BUG_ON(!runtime->hw.channels_min) ||
64905e84878SDylan Reid snd_BUG_ON(!runtime->hw.channels_max) ||
65005e84878SDylan Reid snd_BUG_ON(!runtime->hw.formats) ||
65105e84878SDylan Reid snd_BUG_ON(!runtime->hw.rates)) {
65205e84878SDylan Reid azx_release_device(azx_dev);
65361ca4107STakashi Iwai if (hinfo->ops.close)
65405e84878SDylan Reid hinfo->ops.close(hinfo, apcm->codec, substream);
65561ca4107STakashi Iwai err = -EINVAL;
65661ca4107STakashi Iwai goto powerdown;
65705e84878SDylan Reid }
65805e84878SDylan Reid
6599e94df3aSPierre-Louis Bossart /* disable LINK_ATIME timestamps for capture streams
66005e84878SDylan Reid until we figure out how to handle digital inputs */
6619e94df3aSPierre-Louis Bossart if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
6629e94df3aSPierre-Louis Bossart runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
6639e94df3aSPierre-Louis Bossart runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
6649e94df3aSPierre-Louis Bossart }
66505e84878SDylan Reid
66605e84878SDylan Reid snd_pcm_set_sync(substream);
66705e84878SDylan Reid mutex_unlock(&chip->open_mutex);
66805e84878SDylan Reid return 0;
66961ca4107STakashi Iwai
67061ca4107STakashi Iwai powerdown:
67161ca4107STakashi Iwai snd_hda_power_down(apcm->codec);
67261ca4107STakashi Iwai unlock:
67361ca4107STakashi Iwai mutex_unlock(&chip->open_mutex);
6749a6246ffSTakashi Iwai snd_hda_codec_pcm_put(apcm->info);
67561ca4107STakashi Iwai return err;
67605e84878SDylan Reid }
67705e84878SDylan Reid
6786769e988SJulia Lawall static const struct snd_pcm_ops azx_pcm_ops = {
67905e84878SDylan Reid .open = azx_pcm_open,
68005e84878SDylan Reid .close = azx_pcm_close,
68105e84878SDylan Reid .hw_params = azx_pcm_hw_params,
68205e84878SDylan Reid .hw_free = azx_pcm_hw_free,
68305e84878SDylan Reid .prepare = azx_pcm_prepare,
68405e84878SDylan Reid .trigger = azx_pcm_trigger,
68505e84878SDylan Reid .pointer = azx_pcm_pointer,
6869e94df3aSPierre-Louis Bossart .get_time_info = azx_get_time_info,
68705e84878SDylan Reid };
68805e84878SDylan Reid
azx_pcm_free(struct snd_pcm * pcm)68905e84878SDylan Reid static void azx_pcm_free(struct snd_pcm *pcm)
69005e84878SDylan Reid {
69105e84878SDylan Reid struct azx_pcm *apcm = pcm->private_data;
69205e84878SDylan Reid if (apcm) {
69305e84878SDylan Reid list_del(&apcm->list);
694820cc6cfSTakashi Iwai apcm->info->pcm = NULL;
69505e84878SDylan Reid kfree(apcm);
69605e84878SDylan Reid }
69705e84878SDylan Reid }
69805e84878SDylan Reid
69905e84878SDylan Reid #define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
70005e84878SDylan Reid
snd_hda_attach_pcm_stream(struct hda_bus * _bus,struct hda_codec * codec,struct hda_pcm * cpcm)7010a50575bSTakashi Iwai int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
70205e84878SDylan Reid struct hda_pcm *cpcm)
70305e84878SDylan Reid {
704a41d1224STakashi Iwai struct hdac_bus *bus = &_bus->core;
705a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
70605e84878SDylan Reid struct snd_pcm *pcm;
70705e84878SDylan Reid struct azx_pcm *apcm;
70805e84878SDylan Reid int pcm_dev = cpcm->device;
70905e84878SDylan Reid unsigned int size;
71005e84878SDylan Reid int s, err;
711fc478143STakashi Iwai int type = SNDRV_DMA_TYPE_DEV_SG;
71205e84878SDylan Reid
71305e84878SDylan Reid list_for_each_entry(apcm, &chip->pcm_list, list) {
71405e84878SDylan Reid if (apcm->pcm->device == pcm_dev) {
71505e84878SDylan Reid dev_err(chip->card->dev, "PCM %d already exists\n",
71605e84878SDylan Reid pcm_dev);
71705e84878SDylan Reid return -EBUSY;
71805e84878SDylan Reid }
71905e84878SDylan Reid }
72005e84878SDylan Reid err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
72105e84878SDylan Reid cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,
72205e84878SDylan Reid cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams,
72305e84878SDylan Reid &pcm);
72405e84878SDylan Reid if (err < 0)
72505e84878SDylan Reid return err;
72675b1a8f9SJoe Perches strscpy(pcm->name, cpcm->name, sizeof(pcm->name));
72705e84878SDylan Reid apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
728a3aa60d5SBo Chen if (apcm == NULL) {
729a3aa60d5SBo Chen snd_device_free(chip->card, pcm);
73005e84878SDylan Reid return -ENOMEM;
731a3aa60d5SBo Chen }
73205e84878SDylan Reid apcm->chip = chip;
73305e84878SDylan Reid apcm->pcm = pcm;
73405e84878SDylan Reid apcm->codec = codec;
735820cc6cfSTakashi Iwai apcm->info = cpcm;
73605e84878SDylan Reid pcm->private_data = apcm;
73705e84878SDylan Reid pcm->private_free = azx_pcm_free;
73805e84878SDylan Reid if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
73905e84878SDylan Reid pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
74005e84878SDylan Reid list_add_tail(&apcm->list, &chip->pcm_list);
74105e84878SDylan Reid cpcm->pcm = pcm;
74205e84878SDylan Reid for (s = 0; s < 2; s++) {
74305e84878SDylan Reid if (cpcm->stream[s].substreams)
74405e84878SDylan Reid snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
74505e84878SDylan Reid }
74605e84878SDylan Reid /* buffer pre-allocation */
74705e84878SDylan Reid size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
74805e84878SDylan Reid if (size > MAX_PREALLOC_SIZE)
74905e84878SDylan Reid size = MAX_PREALLOC_SIZE;
750fc478143STakashi Iwai if (chip->uc_buffer)
75158a95dfaSTakashi Iwai type = SNDRV_DMA_TYPE_DEV_WC_SG;
7527a6d4a5aSTakashi Iwai snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
75305e84878SDylan Reid size, MAX_PREALLOC_SIZE);
75405e84878SDylan Reid return 0;
75505e84878SDylan Reid }
75605e84878SDylan Reid
azx_command_addr(u32 cmd)7576e85dddcSDylan Reid static unsigned int azx_command_addr(u32 cmd)
7586e85dddcSDylan Reid {
7596e85dddcSDylan Reid unsigned int addr = cmd >> 28;
7606e85dddcSDylan Reid
7616e85dddcSDylan Reid if (addr >= AZX_MAX_CODECS) {
7626e85dddcSDylan Reid snd_BUG();
7636e85dddcSDylan Reid addr = 0;
7646e85dddcSDylan Reid }
7656e85dddcSDylan Reid
7666e85dddcSDylan Reid return addr;
7676e85dddcSDylan Reid }
7686e85dddcSDylan Reid
7696e85dddcSDylan Reid /* receive a response */
azx_rirb_get_response(struct hdac_bus * bus,unsigned int addr,unsigned int * res)770a41d1224STakashi Iwai static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
771cad372f1STakashi Iwai unsigned int *res)
7726e85dddcSDylan Reid {
773a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
774a41d1224STakashi Iwai struct hda_bus *hbus = &chip->bus;
7755f2cb361STakashi Iwai int err;
7766e85dddcSDylan Reid
7776e85dddcSDylan Reid again:
7785f2cb361STakashi Iwai err = snd_hdac_bus_get_response(bus, addr, res);
7795f2cb361STakashi Iwai if (!err)
780cad372f1STakashi Iwai return 0;
78188452da9STakashi Iwai
782a41d1224STakashi Iwai if (hbus->no_response_fallback)
783cad372f1STakashi Iwai return -EIO;
7846e85dddcSDylan Reid
7858af42130SBard Liao if (!bus->polling_mode) {
7866e85dddcSDylan Reid dev_warn(chip->card->dev,
7876e85dddcSDylan Reid "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n",
788a41d1224STakashi Iwai bus->last_cmd[addr]);
7898af42130SBard Liao bus->polling_mode = 1;
7906e85dddcSDylan Reid goto again;
7916e85dddcSDylan Reid }
7926e85dddcSDylan Reid
7936e85dddcSDylan Reid if (chip->msi) {
7946e85dddcSDylan Reid dev_warn(chip->card->dev,
7956e85dddcSDylan Reid "No response from codec, disabling MSI: last cmd=0x%08x\n",
796a41d1224STakashi Iwai bus->last_cmd[addr]);
797a41d1224STakashi Iwai if (chip->ops->disable_msi_reset_irq &&
798cad372f1STakashi Iwai chip->ops->disable_msi_reset_irq(chip) < 0)
799cad372f1STakashi Iwai return -EIO;
8006e85dddcSDylan Reid goto again;
8016e85dddcSDylan Reid }
8026e85dddcSDylan Reid
8036e85dddcSDylan Reid if (chip->probing) {
8046e85dddcSDylan Reid /* If this critical timeout happens during the codec probing
8056e85dddcSDylan Reid * phase, this is likely an access to a non-existing codec
8066e85dddcSDylan Reid * slot. Better to return an error and reset the system.
8076e85dddcSDylan Reid */
808cad372f1STakashi Iwai return -EIO;
8096e85dddcSDylan Reid }
8106e85dddcSDylan Reid
81141438f13STakashi Iwai /* no fallback mechanism? */
81241438f13STakashi Iwai if (!chip->fallback_to_single_cmd)
81341438f13STakashi Iwai return -EIO;
81441438f13STakashi Iwai
8156e85dddcSDylan Reid /* a fatal communication error; need either to reset or to fallback
8166e85dddcSDylan Reid * to the single_cmd mode
8176e85dddcSDylan Reid */
818a41d1224STakashi Iwai if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) {
819a41d1224STakashi Iwai hbus->response_reset = 1;
820dd65f7e1STakashi Iwai dev_err(chip->card->dev,
821dd65f7e1STakashi Iwai "No response from codec, resetting bus: last cmd=0x%08x\n",
822dd65f7e1STakashi Iwai bus->last_cmd[addr]);
823cad372f1STakashi Iwai return -EAGAIN; /* give a chance to retry */
8246e85dddcSDylan Reid }
8256e85dddcSDylan Reid
826475feec0STakashi Iwai dev_err(chip->card->dev,
8276e85dddcSDylan Reid "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n",
828a41d1224STakashi Iwai bus->last_cmd[addr]);
8296e85dddcSDylan Reid chip->single_cmd = 1;
830a41d1224STakashi Iwai hbus->response_reset = 0;
831a41d1224STakashi Iwai snd_hdac_bus_stop_cmd_io(bus);
832cad372f1STakashi Iwai return -EIO;
8336e85dddcSDylan Reid }
8346e85dddcSDylan Reid
8356e85dddcSDylan Reid /*
8366e85dddcSDylan Reid * Use the single immediate command instead of CORB/RIRB for simplicity
8376e85dddcSDylan Reid *
8386e85dddcSDylan Reid * Note: according to Intel, this is not preferred use. The command was
8396e85dddcSDylan Reid * intended for the BIOS only, and may get confused with unsolicited
8406e85dddcSDylan Reid * responses. So, we shouldn't use it for normal operation from the
8416e85dddcSDylan Reid * driver.
8426e85dddcSDylan Reid * I left the codes, however, for debugging/testing purposes.
8436e85dddcSDylan Reid */
8446e85dddcSDylan Reid
8456e85dddcSDylan Reid /* receive a response */
azx_single_wait_for_response(struct azx * chip,unsigned int addr)8466e85dddcSDylan Reid static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
8476e85dddcSDylan Reid {
8486e85dddcSDylan Reid int timeout = 50;
8496e85dddcSDylan Reid
8506e85dddcSDylan Reid while (timeout--) {
8516e85dddcSDylan Reid /* check IRV busy bit */
852fb1d8ac2STakashi Iwai if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
8536e85dddcSDylan Reid /* reuse rirb.res as the response return value */
854a41d1224STakashi Iwai azx_bus(chip)->rirb.res[addr] = azx_readl(chip, IR);
8556e85dddcSDylan Reid return 0;
8566e85dddcSDylan Reid }
8576e85dddcSDylan Reid udelay(1);
8586e85dddcSDylan Reid }
8596e85dddcSDylan Reid if (printk_ratelimit())
8606e85dddcSDylan Reid dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n",
8616e85dddcSDylan Reid azx_readw(chip, IRS));
862a41d1224STakashi Iwai azx_bus(chip)->rirb.res[addr] = -1;
8636e85dddcSDylan Reid return -EIO;
8646e85dddcSDylan Reid }
8656e85dddcSDylan Reid
8666e85dddcSDylan Reid /* send a command */
azx_single_send_cmd(struct hdac_bus * bus,u32 val)867a41d1224STakashi Iwai static int azx_single_send_cmd(struct hdac_bus *bus, u32 val)
8686e85dddcSDylan Reid {
869a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
8706e85dddcSDylan Reid unsigned int addr = azx_command_addr(val);
8716e85dddcSDylan Reid int timeout = 50;
8726e85dddcSDylan Reid
873a41d1224STakashi Iwai bus->last_cmd[azx_command_addr(val)] = val;
8746e85dddcSDylan Reid while (timeout--) {
8756e85dddcSDylan Reid /* check ICB busy bit */
876fb1d8ac2STakashi Iwai if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
8776e85dddcSDylan Reid /* Clear IRV valid bit */
8786e85dddcSDylan Reid azx_writew(chip, IRS, azx_readw(chip, IRS) |
879fb1d8ac2STakashi Iwai AZX_IRS_VALID);
8806e85dddcSDylan Reid azx_writel(chip, IC, val);
8816e85dddcSDylan Reid azx_writew(chip, IRS, azx_readw(chip, IRS) |
882fb1d8ac2STakashi Iwai AZX_IRS_BUSY);
8836e85dddcSDylan Reid return azx_single_wait_for_response(chip, addr);
8846e85dddcSDylan Reid }
8856e85dddcSDylan Reid udelay(1);
8866e85dddcSDylan Reid }
8876e85dddcSDylan Reid if (printk_ratelimit())
8886e85dddcSDylan Reid dev_dbg(chip->card->dev,
8896e85dddcSDylan Reid "send_cmd timeout: IRS=0x%x, val=0x%x\n",
8906e85dddcSDylan Reid azx_readw(chip, IRS), val);
8916e85dddcSDylan Reid return -EIO;
8926e85dddcSDylan Reid }
8936e85dddcSDylan Reid
8946e85dddcSDylan Reid /* receive a response */
azx_single_get_response(struct hdac_bus * bus,unsigned int addr,unsigned int * res)895a41d1224STakashi Iwai static int azx_single_get_response(struct hdac_bus *bus, unsigned int addr,
896cad372f1STakashi Iwai unsigned int *res)
8976e85dddcSDylan Reid {
898cad372f1STakashi Iwai if (res)
899a41d1224STakashi Iwai *res = bus->rirb.res[addr];
900cad372f1STakashi Iwai return 0;
9016e85dddcSDylan Reid }
9026e85dddcSDylan Reid
9036e85dddcSDylan Reid /*
9046e85dddcSDylan Reid * The below are the main callbacks from hda_codec.
9056e85dddcSDylan Reid *
9066e85dddcSDylan Reid * They are just the skeleton to call sub-callbacks according to the
9076e85dddcSDylan Reid * current setting of chip->single_cmd.
9086e85dddcSDylan Reid */
9096e85dddcSDylan Reid
9106e85dddcSDylan Reid /* send a command */
azx_send_cmd(struct hdac_bus * bus,unsigned int val)911a41d1224STakashi Iwai static int azx_send_cmd(struct hdac_bus *bus, unsigned int val)
9126e85dddcSDylan Reid {
913a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
9146e85dddcSDylan Reid
9156e85dddcSDylan Reid if (chip->disabled)
9166e85dddcSDylan Reid return 0;
917b13593e3SPeter Ujfalusi if (chip->single_cmd || bus->use_pio_for_commands)
9186e85dddcSDylan Reid return azx_single_send_cmd(bus, val);
9196e85dddcSDylan Reid else
920a41d1224STakashi Iwai return snd_hdac_bus_send_cmd(bus, val);
9216e85dddcSDylan Reid }
9226e85dddcSDylan Reid
9236e85dddcSDylan Reid /* get a response */
azx_get_response(struct hdac_bus * bus,unsigned int addr,unsigned int * res)924a41d1224STakashi Iwai static int azx_get_response(struct hdac_bus *bus, unsigned int addr,
925cad372f1STakashi Iwai unsigned int *res)
9266e85dddcSDylan Reid {
927a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
928a41d1224STakashi Iwai
9296e85dddcSDylan Reid if (chip->disabled)
9306e85dddcSDylan Reid return 0;
931b13593e3SPeter Ujfalusi if (chip->single_cmd || bus->use_pio_for_commands)
932cad372f1STakashi Iwai return azx_single_get_response(bus, addr, res);
9336e85dddcSDylan Reid else
934cad372f1STakashi Iwai return azx_rirb_get_response(bus, addr, res);
9356e85dddcSDylan Reid }
9366e85dddcSDylan Reid
9377e8be1b3STakashi Iwai static const struct hdac_bus_ops bus_core_ops = {
9387e8be1b3STakashi Iwai .command = azx_send_cmd,
9397e8be1b3STakashi Iwai .get_response = azx_get_response,
9407e8be1b3STakashi Iwai };
9417e8be1b3STakashi Iwai
9422b5fd6c2SDylan Reid #ifdef CONFIG_SND_HDA_DSP_LOADER
9432b5fd6c2SDylan Reid /*
9442b5fd6c2SDylan Reid * DSP loading code (e.g. for CA0132)
9452b5fd6c2SDylan Reid */
9462b5fd6c2SDylan Reid
9472b5fd6c2SDylan Reid /* use the first stream for loading DSP */
9482b5fd6c2SDylan Reid static struct azx_dev *
azx_get_dsp_loader_dev(struct azx * chip)9492b5fd6c2SDylan Reid azx_get_dsp_loader_dev(struct azx *chip)
9502b5fd6c2SDylan Reid {
9517833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
9527833c3f8STakashi Iwai struct hdac_stream *s;
9537833c3f8STakashi Iwai
9547833c3f8STakashi Iwai list_for_each_entry(s, &bus->stream_list, list)
9557833c3f8STakashi Iwai if (s->index == chip->playback_index_offset)
9567833c3f8STakashi Iwai return stream_to_azx_dev(s);
9577833c3f8STakashi Iwai
9587833c3f8STakashi Iwai return NULL;
9592b5fd6c2SDylan Reid }
9602b5fd6c2SDylan Reid
snd_hda_codec_load_dsp_prepare(struct hda_codec * codec,unsigned int format,unsigned int byte_size,struct snd_dma_buffer * bufp)9610a50575bSTakashi Iwai int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format,
9622b5fd6c2SDylan Reid unsigned int byte_size,
9632b5fd6c2SDylan Reid struct snd_dma_buffer *bufp)
9642b5fd6c2SDylan Reid {
9650a50575bSTakashi Iwai struct hdac_bus *bus = &codec->bus->core;
966a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
9672b5fd6c2SDylan Reid struct azx_dev *azx_dev;
968ccc98865STakashi Iwai struct hdac_stream *hstr;
969ccc98865STakashi Iwai bool saved = false;
9702b5fd6c2SDylan Reid int err;
9712b5fd6c2SDylan Reid
9722b5fd6c2SDylan Reid azx_dev = azx_get_dsp_loader_dev(chip);
973ccc98865STakashi Iwai hstr = azx_stream(azx_dev);
974a41d1224STakashi Iwai spin_lock_irq(&bus->reg_lock);
975ccc98865STakashi Iwai if (hstr->opened) {
9762b5fd6c2SDylan Reid chip->saved_azx_dev = *azx_dev;
977ccc98865STakashi Iwai saved = true;
978ccc98865STakashi Iwai }
979a41d1224STakashi Iwai spin_unlock_irq(&bus->reg_lock);
9802b5fd6c2SDylan Reid
981ccc98865STakashi Iwai err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp);
982ccc98865STakashi Iwai if (err < 0) {
983a41d1224STakashi Iwai spin_lock_irq(&bus->reg_lock);
984ccc98865STakashi Iwai if (saved)
9852b5fd6c2SDylan Reid *azx_dev = chip->saved_azx_dev;
986a41d1224STakashi Iwai spin_unlock_irq(&bus->reg_lock);
987ccc98865STakashi Iwai return err;
988ccc98865STakashi Iwai }
989ccc98865STakashi Iwai
9906d23c8f5STakashi Iwai hstr->prepared = 0;
9912b5fd6c2SDylan Reid return err;
9922b5fd6c2SDylan Reid }
9930a50575bSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_prepare);
9942b5fd6c2SDylan Reid
snd_hda_codec_load_dsp_trigger(struct hda_codec * codec,bool start)9950a50575bSTakashi Iwai void snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start)
9962b5fd6c2SDylan Reid {
9970a50575bSTakashi Iwai struct hdac_bus *bus = &codec->bus->core;
998a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
9992b5fd6c2SDylan Reid struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
10002b5fd6c2SDylan Reid
1001ccc98865STakashi Iwai snd_hdac_dsp_trigger(azx_stream(azx_dev), start);
10022b5fd6c2SDylan Reid }
10030a50575bSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_trigger);
10042b5fd6c2SDylan Reid
snd_hda_codec_load_dsp_cleanup(struct hda_codec * codec,struct snd_dma_buffer * dmab)10050a50575bSTakashi Iwai void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
10062b5fd6c2SDylan Reid struct snd_dma_buffer *dmab)
10072b5fd6c2SDylan Reid {
10080a50575bSTakashi Iwai struct hdac_bus *bus = &codec->bus->core;
1009a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
10102b5fd6c2SDylan Reid struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
1011ccc98865STakashi Iwai struct hdac_stream *hstr = azx_stream(azx_dev);
10122b5fd6c2SDylan Reid
10130a50575bSTakashi Iwai if (!dmab->area || !hstr->locked)
10142b5fd6c2SDylan Reid return;
10152b5fd6c2SDylan Reid
1016ccc98865STakashi Iwai snd_hdac_dsp_cleanup(hstr, dmab);
1017a41d1224STakashi Iwai spin_lock_irq(&bus->reg_lock);
1018ccc98865STakashi Iwai if (hstr->opened)
10192b5fd6c2SDylan Reid *azx_dev = chip->saved_azx_dev;
1020ccc98865STakashi Iwai hstr->locked = false;
1021a41d1224STakashi Iwai spin_unlock_irq(&bus->reg_lock);
10222b5fd6c2SDylan Reid }
10230a50575bSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_cleanup);
10242b5fd6c2SDylan Reid #endif /* CONFIG_SND_HDA_DSP_LOADER */
10252b5fd6c2SDylan Reid
1026f43923ffSDylan Reid /*
1027f43923ffSDylan Reid * reset and start the controller registers
1028f43923ffSDylan Reid */
azx_init_chip(struct azx * chip,bool full_reset)102917c3ad03SThierry Reding void azx_init_chip(struct azx *chip, bool full_reset)
1030f43923ffSDylan Reid {
1031a41d1224STakashi Iwai if (snd_hdac_bus_init_chip(azx_bus(chip), full_reset)) {
1032a41d1224STakashi Iwai /* correct RINTCNT for CXT */
1033a41d1224STakashi Iwai if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
1034a41d1224STakashi Iwai azx_writew(chip, RINTCNT, 0xc0);
1035a41d1224STakashi Iwai }
1036f43923ffSDylan Reid }
1037f43923ffSDylan Reid EXPORT_SYMBOL_GPL(azx_init_chip);
1038f43923ffSDylan Reid
azx_stop_all_streams(struct azx * chip)10397833c3f8STakashi Iwai void azx_stop_all_streams(struct azx *chip)
10407833c3f8STakashi Iwai {
10417833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
10427833c3f8STakashi Iwai
104324ad3835SPierre-Louis Bossart snd_hdac_stop_streams(bus);
10447833c3f8STakashi Iwai }
10457833c3f8STakashi Iwai EXPORT_SYMBOL_GPL(azx_stop_all_streams);
10467833c3f8STakashi Iwai
azx_stop_chip(struct azx * chip)1047f43923ffSDylan Reid void azx_stop_chip(struct azx *chip)
1048f43923ffSDylan Reid {
1049a41d1224STakashi Iwai snd_hdac_bus_stop_chip(azx_bus(chip));
1050f43923ffSDylan Reid }
1051154867cfSDylan Reid EXPORT_SYMBOL_GPL(azx_stop_chip);
1052f43923ffSDylan Reid
1053f0b1df88SDylan Reid /*
1054f0b1df88SDylan Reid * interrupt handler
1055f0b1df88SDylan Reid */
stream_update(struct hdac_bus * bus,struct hdac_stream * s)10567833c3f8STakashi Iwai static void stream_update(struct hdac_bus *bus, struct hdac_stream *s)
10577833c3f8STakashi Iwai {
1058a41d1224STakashi Iwai struct azx *chip = bus_to_azx(bus);
10597833c3f8STakashi Iwai struct azx_dev *azx_dev = stream_to_azx_dev(s);
10607833c3f8STakashi Iwai
10617833c3f8STakashi Iwai /* check whether this IRQ is really acceptable */
10627833c3f8STakashi Iwai if (!chip->ops->position_check ||
10637833c3f8STakashi Iwai chip->ops->position_check(chip, azx_dev)) {
1064a41d1224STakashi Iwai spin_unlock(&bus->reg_lock);
1065a41d1224STakashi Iwai snd_pcm_period_elapsed(azx_stream(azx_dev)->substream);
1066a41d1224STakashi Iwai spin_lock(&bus->reg_lock);
10677833c3f8STakashi Iwai }
10687833c3f8STakashi Iwai }
10697833c3f8STakashi Iwai
azx_interrupt(int irq,void * dev_id)1070f0b1df88SDylan Reid irqreturn_t azx_interrupt(int irq, void *dev_id)
1071f0b1df88SDylan Reid {
1072f0b1df88SDylan Reid struct azx *chip = dev_id;
10737833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
1074f0b1df88SDylan Reid u32 status;
1075473f4145STakashi Iwai bool active, handled = false;
1076473f4145STakashi Iwai int repeat = 0; /* count for avoiding endless loop */
1077f0b1df88SDylan Reid
1078364aa716STakashi Iwai if (azx_has_pm_runtime(chip))
10797b0a48f3SDylan Reid if (!pm_runtime_active(chip->card->dev))
1080f0b1df88SDylan Reid return IRQ_NONE;
1081f0b1df88SDylan Reid
1082a41d1224STakashi Iwai spin_lock(&bus->reg_lock);
1083f0b1df88SDylan Reid
1084473f4145STakashi Iwai if (chip->disabled)
1085473f4145STakashi Iwai goto unlock;
1086f0b1df88SDylan Reid
1087473f4145STakashi Iwai do {
1088f0b1df88SDylan Reid status = azx_readl(chip, INTSTS);
1089473f4145STakashi Iwai if (status == 0 || status == 0xffffffff)
1090473f4145STakashi Iwai break;
1091f0b1df88SDylan Reid
1092473f4145STakashi Iwai handled = true;
1093473f4145STakashi Iwai active = false;
1094473f4145STakashi Iwai if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
1095473f4145STakashi Iwai active = true;
1096f0b1df88SDylan Reid
1097f0b1df88SDylan Reid status = azx_readb(chip, RIRBSTS);
1098f0b1df88SDylan Reid if (status & RIRB_INT_MASK) {
10996d011d50SMohan Kumar /*
11006d011d50SMohan Kumar * Clearing the interrupt status here ensures that no
11016d011d50SMohan Kumar * interrupt gets masked after the RIRB wp is read in
11026d011d50SMohan Kumar * snd_hdac_bus_update_rirb. This avoids a possible
11036d011d50SMohan Kumar * race condition where codec response in RIRB may
11046d011d50SMohan Kumar * remain unserviced by IRQ, eventually falling back
11056d011d50SMohan Kumar * to polling mode in azx_rirb_get_response.
11066d011d50SMohan Kumar */
11076d011d50SMohan Kumar azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
1108473f4145STakashi Iwai active = true;
1109f0b1df88SDylan Reid if (status & RIRB_INT_RESPONSE) {
1110ef85f299STakashi Iwai if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
1111f0b1df88SDylan Reid udelay(80);
1112a41d1224STakashi Iwai snd_hdac_bus_update_rirb(bus);
1113f0b1df88SDylan Reid }
1114f0b1df88SDylan Reid }
1115473f4145STakashi Iwai } while (active && ++repeat < 10);
1116f0b1df88SDylan Reid
1117473f4145STakashi Iwai unlock:
1118a41d1224STakashi Iwai spin_unlock(&bus->reg_lock);
1119f0b1df88SDylan Reid
1120473f4145STakashi Iwai return IRQ_RETVAL(handled);
1121f0b1df88SDylan Reid }
1122f0b1df88SDylan Reid EXPORT_SYMBOL_GPL(azx_interrupt);
1123f0b1df88SDylan Reid
1124154867cfSDylan Reid /*
1125154867cfSDylan Reid * Codec initerface
1126154867cfSDylan Reid */
1127154867cfSDylan Reid
1128154867cfSDylan Reid /*
1129154867cfSDylan Reid * Probe the given codec address
1130154867cfSDylan Reid */
probe_codec(struct azx * chip,int addr)1131154867cfSDylan Reid static int probe_codec(struct azx *chip, int addr)
1132154867cfSDylan Reid {
1133154867cfSDylan Reid unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
1134154867cfSDylan Reid (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
11357833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
1136cad372f1STakashi Iwai int err;
1137a41d1224STakashi Iwai unsigned int res = -1;
1138154867cfSDylan Reid
11397e8be1b3STakashi Iwai mutex_lock(&bus->cmd_mutex);
1140154867cfSDylan Reid chip->probing = 1;
11417e8be1b3STakashi Iwai azx_send_cmd(bus, cmd);
11427e8be1b3STakashi Iwai err = azx_get_response(bus, addr, &res);
1143154867cfSDylan Reid chip->probing = 0;
11447e8be1b3STakashi Iwai mutex_unlock(&bus->cmd_mutex);
1145cad372f1STakashi Iwai if (err < 0 || res == -1)
1146154867cfSDylan Reid return -EIO;
1147154867cfSDylan Reid dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr);
1148154867cfSDylan Reid return 0;
1149154867cfSDylan Reid }
1150154867cfSDylan Reid
snd_hda_bus_reset(struct hda_bus * bus)11510a50575bSTakashi Iwai void snd_hda_bus_reset(struct hda_bus *bus)
1152154867cfSDylan Reid {
1153a41d1224STakashi Iwai struct azx *chip = bus_to_azx(&bus->core);
1154154867cfSDylan Reid
1155154867cfSDylan Reid bus->in_reset = 1;
1156154867cfSDylan Reid azx_stop_chip(chip);
115717c3ad03SThierry Reding azx_init_chip(chip, true);
1158a41d1224STakashi Iwai if (bus->core.chip_init)
11590a50575bSTakashi Iwai snd_hda_bus_reset_codecs(bus);
1160154867cfSDylan Reid bus->in_reset = 0;
1161154867cfSDylan Reid }
1162154867cfSDylan Reid
116396d2bd6eSTakashi Iwai /* HD-audio bus initialization */
azx_bus_init(struct azx * chip,const char * model)116419abfefdSTakashi Iwai int azx_bus_init(struct azx *chip, const char *model)
1165154867cfSDylan Reid {
1166a41d1224STakashi Iwai struct hda_bus *bus = &chip->bus;
116796d2bd6eSTakashi Iwai int err;
1168154867cfSDylan Reid
116919abfefdSTakashi Iwai err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops);
1170154867cfSDylan Reid if (err < 0)
1171154867cfSDylan Reid return err;
1172154867cfSDylan Reid
1173a41d1224STakashi Iwai bus->card = chip->card;
1174a41d1224STakashi Iwai mutex_init(&bus->prepare_mutex);
1175ef744978STakashi Iwai bus->pci = chip->pci;
1176ef744978STakashi Iwai bus->modelname = model;
11772f0eaad9STakashi Iwai bus->mixer_assigned = -1;
1178ccc98865STakashi Iwai bus->core.snoop = azx_snoop(chip);
1179ccc98865STakashi Iwai if (chip->get_position[0] != azx_get_pos_lpib ||
1180ccc98865STakashi Iwai chip->get_position[1] != azx_get_pos_lpib)
1181ccc98865STakashi Iwai bus->core.use_posbuf = true;
11824f0189beSTakashi Iwai bus->core.bdl_pos_adj = chip->bdl_pos_adj;
1183a41d1224STakashi Iwai if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)
1184a41d1224STakashi Iwai bus->core.corbrp_self_clear = true;
1185ef744978STakashi Iwai
1186de1ab6afSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY)
1187de1ab6afSTakashi Iwai bus->core.align_bdle_4k = true;
1188de1ab6afSTakashi Iwai
1189b13593e3SPeter Ujfalusi if (chip->driver_caps & AZX_DCAPS_PIO_COMMANDS)
1190b13593e3SPeter Ujfalusi bus->core.use_pio_for_commands = true;
1191b13593e3SPeter Ujfalusi
1192f34a4c9dSTakashi Iwai /* enable sync_write flag for stable communication as default */
1193d068ebc2STakashi Iwai bus->core.sync_write = 1;
119496d2bd6eSTakashi Iwai
119596d2bd6eSTakashi Iwai return 0;
119696d2bd6eSTakashi Iwai }
1197a41d1224STakashi Iwai EXPORT_SYMBOL_GPL(azx_bus_init);
119896d2bd6eSTakashi Iwai
119996d2bd6eSTakashi Iwai /* Probe codecs */
azx_probe_codecs(struct azx * chip,unsigned int max_slots)120096d2bd6eSTakashi Iwai int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
120196d2bd6eSTakashi Iwai {
1202a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
120396d2bd6eSTakashi Iwai int c, codecs, err;
120496d2bd6eSTakashi Iwai
1205154867cfSDylan Reid codecs = 0;
1206154867cfSDylan Reid if (!max_slots)
1207154867cfSDylan Reid max_slots = AZX_DEFAULT_CODECS;
1208154867cfSDylan Reid
1209154867cfSDylan Reid /* First try to probe all given codec slots */
1210154867cfSDylan Reid for (c = 0; c < max_slots; c++) {
1211a41d1224STakashi Iwai if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
1212154867cfSDylan Reid if (probe_codec(chip, c) < 0) {
1213154867cfSDylan Reid /* Some BIOSen give you wrong codec addresses
1214154867cfSDylan Reid * that don't exist
1215154867cfSDylan Reid */
1216154867cfSDylan Reid dev_warn(chip->card->dev,
1217154867cfSDylan Reid "Codec #%d probe error; disabling it...\n", c);
1218a41d1224STakashi Iwai bus->codec_mask &= ~(1 << c);
1219642b02b4Ssongxiebing /* no codecs */
1220642b02b4Ssongxiebing if (bus->codec_mask == 0)
1221642b02b4Ssongxiebing break;
1222154867cfSDylan Reid /* More badly, accessing to a non-existing
1223154867cfSDylan Reid * codec often screws up the controller chip,
1224154867cfSDylan Reid * and disturbs the further communications.
1225154867cfSDylan Reid * Thus if an error occurs during probing,
1226154867cfSDylan Reid * better to reset the controller chip to
1227154867cfSDylan Reid * get back to the sanity state.
1228154867cfSDylan Reid */
1229154867cfSDylan Reid azx_stop_chip(chip);
123017c3ad03SThierry Reding azx_init_chip(chip, true);
1231154867cfSDylan Reid }
1232154867cfSDylan Reid }
1233154867cfSDylan Reid }
1234154867cfSDylan Reid
1235154867cfSDylan Reid /* Then create codec instances */
1236154867cfSDylan Reid for (c = 0; c < max_slots; c++) {
1237a41d1224STakashi Iwai if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
1238154867cfSDylan Reid struct hda_codec *codec;
1239a41d1224STakashi Iwai err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec);
1240154867cfSDylan Reid if (err < 0)
1241154867cfSDylan Reid continue;
12423a182c84STakashi Iwai codec->jackpoll_interval = chip->jackpoll_interval;
1243154867cfSDylan Reid codec->beep_mode = chip->beep_mode;
1244d045bcefSJaroslav Kysela codec->ctl_dev_id = chip->ctl_dev_id;
1245154867cfSDylan Reid codecs++;
1246154867cfSDylan Reid }
1247154867cfSDylan Reid }
1248154867cfSDylan Reid if (!codecs) {
1249154867cfSDylan Reid dev_err(chip->card->dev, "no codecs initialized\n");
1250154867cfSDylan Reid return -ENXIO;
1251154867cfSDylan Reid }
1252154867cfSDylan Reid return 0;
1253154867cfSDylan Reid }
125496d2bd6eSTakashi Iwai EXPORT_SYMBOL_GPL(azx_probe_codecs);
1255154867cfSDylan Reid
1256154867cfSDylan Reid /* configure each codec instance */
azx_codec_configure(struct azx * chip)1257154867cfSDylan Reid int azx_codec_configure(struct azx *chip)
1258154867cfSDylan Reid {
1259d94815f9STakashi Iwai struct hda_codec *codec, *next;
1260c0f1886dSTakashi Iwai int success = 0;
1261d94815f9STakashi Iwai
1262c0f1886dSTakashi Iwai list_for_each_codec(codec, &chip->bus) {
1263c0f1886dSTakashi Iwai if (!snd_hda_codec_configure(codec))
1264c0f1886dSTakashi Iwai success++;
1265154867cfSDylan Reid }
126617890880STakashi Iwai
1267c0f1886dSTakashi Iwai if (success) {
1268c0f1886dSTakashi Iwai /* unregister failed codecs if any codec has been probed */
1269c0f1886dSTakashi Iwai list_for_each_codec_safe(codec, next, &chip->bus) {
1270c0f1886dSTakashi Iwai if (!codec->configured) {
1271c0f1886dSTakashi Iwai codec_err(codec, "Unable to configure, disabling\n");
1272c0f1886dSTakashi Iwai snd_hdac_device_unregister(&codec->core);
1273c0f1886dSTakashi Iwai }
1274c0f1886dSTakashi Iwai }
1275c0f1886dSTakashi Iwai }
1276c0f1886dSTakashi Iwai
1277c0f1886dSTakashi Iwai return success ? 0 : -ENODEV;
1278154867cfSDylan Reid }
1279154867cfSDylan Reid EXPORT_SYMBOL_GPL(azx_codec_configure);
1280154867cfSDylan Reid
stream_direction(struct azx * chip,unsigned char index)12817833c3f8STakashi Iwai static int stream_direction(struct azx *chip, unsigned char index)
128293e3423eSRafal Redzimski {
12837833c3f8STakashi Iwai if (index >= chip->capture_index_offset &&
12847833c3f8STakashi Iwai index < chip->capture_index_offset + chip->capture_streams)
12857833c3f8STakashi Iwai return SNDRV_PCM_STREAM_CAPTURE;
12867833c3f8STakashi Iwai return SNDRV_PCM_STREAM_PLAYBACK;
128793e3423eSRafal Redzimski }
128893e3423eSRafal Redzimski
1289154867cfSDylan Reid /* initialize SD streams */
azx_init_streams(struct azx * chip)1290a41d1224STakashi Iwai int azx_init_streams(struct azx *chip)
1291154867cfSDylan Reid {
1292154867cfSDylan Reid int i;
12937833c3f8STakashi Iwai int stream_tags[2] = { 0, 0 };
1294154867cfSDylan Reid
1295154867cfSDylan Reid /* initialize each stream (aka device)
1296154867cfSDylan Reid * assign the starting bdl address to each stream (device)
1297154867cfSDylan Reid * and initialize
1298154867cfSDylan Reid */
1299154867cfSDylan Reid for (i = 0; i < chip->num_streams; i++) {
13007833c3f8STakashi Iwai struct azx_dev *azx_dev = kzalloc(sizeof(*azx_dev), GFP_KERNEL);
13017833c3f8STakashi Iwai int dir, tag;
130293e3423eSRafal Redzimski
13037833c3f8STakashi Iwai if (!azx_dev)
13047833c3f8STakashi Iwai return -ENOMEM;
13057833c3f8STakashi Iwai
13067833c3f8STakashi Iwai dir = stream_direction(chip, i);
130793e3423eSRafal Redzimski /* stream tag must be unique throughout
130893e3423eSRafal Redzimski * the stream direction group,
130993e3423eSRafal Redzimski * valid values 1...15
131093e3423eSRafal Redzimski * use separate stream tag if the flag
131193e3423eSRafal Redzimski * AZX_DCAPS_SEPARATE_STREAM_TAG is used
131293e3423eSRafal Redzimski */
131393e3423eSRafal Redzimski if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
13147833c3f8STakashi Iwai tag = ++stream_tags[dir];
131593e3423eSRafal Redzimski else
13167833c3f8STakashi Iwai tag = i + 1;
13177833c3f8STakashi Iwai snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev),
13187833c3f8STakashi Iwai i, dir, tag);
1319154867cfSDylan Reid }
1320154867cfSDylan Reid
1321154867cfSDylan Reid return 0;
1322154867cfSDylan Reid }
1323a41d1224STakashi Iwai EXPORT_SYMBOL_GPL(azx_init_streams);
1324a41d1224STakashi Iwai
azx_free_streams(struct azx * chip)1325a41d1224STakashi Iwai void azx_free_streams(struct azx *chip)
1326a41d1224STakashi Iwai {
1327a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
1328a41d1224STakashi Iwai struct hdac_stream *s;
1329a41d1224STakashi Iwai
1330a41d1224STakashi Iwai while (!list_empty(&bus->stream_list)) {
1331a41d1224STakashi Iwai s = list_first_entry(&bus->stream_list, struct hdac_stream, list);
1332a41d1224STakashi Iwai list_del(&s->list);
1333a41d1224STakashi Iwai kfree(stream_to_azx_dev(s));
1334a41d1224STakashi Iwai }
1335a41d1224STakashi Iwai }
1336a41d1224STakashi Iwai EXPORT_SYMBOL_GPL(azx_free_streams);
1337