162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Implementation of primary alsa driver code base for Intel HD Audio. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright(c) 2004 Intel Corporation. All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> 962306a36Sopenharmony_ci * PeiSen Hou <pshou@realtek.com.tw> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/clocksource.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifdef CONFIG_X86 2162306a36Sopenharmony_ci/* for art-tsc conversion */ 2262306a36Sopenharmony_ci#include <asm/tsc.h> 2362306a36Sopenharmony_ci#endif 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <sound/core.h> 2662306a36Sopenharmony_ci#include <sound/initval.h> 2762306a36Sopenharmony_ci#include "hda_controller.h" 2862306a36Sopenharmony_ci#include "hda_local.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 3162306a36Sopenharmony_ci#include "hda_controller_trace.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* DSP lock helpers */ 3462306a36Sopenharmony_ci#define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev)) 3562306a36Sopenharmony_ci#define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev)) 3662306a36Sopenharmony_ci#define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev)) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* assign a stream for the PCM */ 3962306a36Sopenharmony_cistatic inline struct azx_dev * 4062306a36Sopenharmony_ciazx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct hdac_stream *s; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci s = snd_hdac_stream_assign(azx_bus(chip), substream); 4562306a36Sopenharmony_ci if (!s) 4662306a36Sopenharmony_ci return NULL; 4762306a36Sopenharmony_ci return stream_to_azx_dev(s); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* release the assigned stream */ 5162306a36Sopenharmony_cistatic inline void azx_release_device(struct azx_dev *azx_dev) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci snd_hdac_stream_release(azx_stream(azx_dev)); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic inline struct hda_pcm_stream * 5762306a36Sopenharmony_cito_hda_pcm_stream(struct snd_pcm_substream *substream) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 6062306a36Sopenharmony_ci return &apcm->info->stream[substream->stream]; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, 6462306a36Sopenharmony_ci u64 nsec) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 6762306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 6862306a36Sopenharmony_ci u64 codec_frames, codec_nsecs; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (!hinfo->ops.get_delay) 7162306a36Sopenharmony_ci return nsec; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream); 7462306a36Sopenharmony_ci codec_nsecs = div_u64(codec_frames * 1000000000LL, 7562306a36Sopenharmony_ci substream->runtime->rate); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 7862306a36Sopenharmony_ci return nsec + codec_nsecs; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* 8462306a36Sopenharmony_ci * PCM ops 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int azx_pcm_close(struct snd_pcm_substream *substream) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 9062306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 9162306a36Sopenharmony_ci struct azx *chip = apcm->chip; 9262306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci trace_azx_pcm_close(chip, azx_dev); 9562306a36Sopenharmony_ci mutex_lock(&chip->open_mutex); 9662306a36Sopenharmony_ci azx_release_device(azx_dev); 9762306a36Sopenharmony_ci if (hinfo->ops.close) 9862306a36Sopenharmony_ci hinfo->ops.close(hinfo, apcm->codec, substream); 9962306a36Sopenharmony_ci snd_hda_power_down(apcm->codec); 10062306a36Sopenharmony_ci mutex_unlock(&chip->open_mutex); 10162306a36Sopenharmony_ci snd_hda_codec_pcm_put(apcm->info); 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int azx_pcm_hw_params(struct snd_pcm_substream *substream, 10662306a36Sopenharmony_ci struct snd_pcm_hw_params *hw_params) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 10962306a36Sopenharmony_ci struct azx *chip = apcm->chip; 11062306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 11162306a36Sopenharmony_ci int ret = 0; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci trace_azx_pcm_hw_params(chip, azx_dev); 11462306a36Sopenharmony_ci dsp_lock(azx_dev); 11562306a36Sopenharmony_ci if (dsp_is_locked(azx_dev)) { 11662306a36Sopenharmony_ci ret = -EBUSY; 11762306a36Sopenharmony_ci goto unlock; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci azx_dev->core.bufsize = 0; 12162306a36Sopenharmony_ci azx_dev->core.period_bytes = 0; 12262306a36Sopenharmony_ci azx_dev->core.format_val = 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciunlock: 12562306a36Sopenharmony_ci dsp_unlock(azx_dev); 12662306a36Sopenharmony_ci return ret; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic int azx_pcm_hw_free(struct snd_pcm_substream *substream) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 13262306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 13362306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* reset BDL address */ 13662306a36Sopenharmony_ci dsp_lock(azx_dev); 13762306a36Sopenharmony_ci if (!dsp_is_locked(azx_dev)) 13862306a36Sopenharmony_ci snd_hdac_stream_cleanup(azx_stream(azx_dev)); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci snd_hda_codec_cleanup(apcm->codec, hinfo, substream); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci azx_stream(azx_dev)->prepared = 0; 14362306a36Sopenharmony_ci dsp_unlock(azx_dev); 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int azx_pcm_prepare(struct snd_pcm_substream *substream) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 15062306a36Sopenharmony_ci struct azx *chip = apcm->chip; 15162306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 15262306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 15362306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 15462306a36Sopenharmony_ci unsigned int format_val, stream_tag; 15562306a36Sopenharmony_ci int err; 15662306a36Sopenharmony_ci struct hda_spdif_out *spdif = 15762306a36Sopenharmony_ci snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); 15862306a36Sopenharmony_ci unsigned short ctls = spdif ? spdif->ctls : 0; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci trace_azx_pcm_prepare(chip, azx_dev); 16162306a36Sopenharmony_ci dsp_lock(azx_dev); 16262306a36Sopenharmony_ci if (dsp_is_locked(azx_dev)) { 16362306a36Sopenharmony_ci err = -EBUSY; 16462306a36Sopenharmony_ci goto unlock; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci snd_hdac_stream_reset(azx_stream(azx_dev)); 16862306a36Sopenharmony_ci format_val = snd_hdac_calc_stream_format(runtime->rate, 16962306a36Sopenharmony_ci runtime->channels, 17062306a36Sopenharmony_ci runtime->format, 17162306a36Sopenharmony_ci hinfo->maxbps, 17262306a36Sopenharmony_ci ctls); 17362306a36Sopenharmony_ci if (!format_val) { 17462306a36Sopenharmony_ci dev_err(chip->card->dev, 17562306a36Sopenharmony_ci "invalid format_val, rate=%d, ch=%d, format=%d\n", 17662306a36Sopenharmony_ci runtime->rate, runtime->channels, runtime->format); 17762306a36Sopenharmony_ci err = -EINVAL; 17862306a36Sopenharmony_ci goto unlock; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val); 18262306a36Sopenharmony_ci if (err < 0) 18362306a36Sopenharmony_ci goto unlock; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci snd_hdac_stream_setup(azx_stream(azx_dev)); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci stream_tag = azx_dev->core.stream_tag; 18862306a36Sopenharmony_ci /* CA-IBG chips need the playback stream starting from 1 */ 18962306a36Sopenharmony_ci if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && 19062306a36Sopenharmony_ci stream_tag > chip->capture_streams) 19162306a36Sopenharmony_ci stream_tag -= chip->capture_streams; 19262306a36Sopenharmony_ci err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, 19362306a36Sopenharmony_ci azx_dev->core.format_val, substream); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci unlock: 19662306a36Sopenharmony_ci if (!err) 19762306a36Sopenharmony_ci azx_stream(azx_dev)->prepared = 1; 19862306a36Sopenharmony_ci dsp_unlock(azx_dev); 19962306a36Sopenharmony_ci return err; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 20562306a36Sopenharmony_ci struct azx *chip = apcm->chip; 20662306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 20762306a36Sopenharmony_ci struct azx_dev *azx_dev; 20862306a36Sopenharmony_ci struct snd_pcm_substream *s; 20962306a36Sopenharmony_ci struct hdac_stream *hstr; 21062306a36Sopenharmony_ci bool start; 21162306a36Sopenharmony_ci int sbits = 0; 21262306a36Sopenharmony_ci int sync_reg; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci azx_dev = get_azx_dev(substream); 21562306a36Sopenharmony_ci trace_azx_pcm_trigger(chip, azx_dev, cmd); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci hstr = azx_stream(azx_dev); 21862306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) 21962306a36Sopenharmony_ci sync_reg = AZX_REG_OLD_SSYNC; 22062306a36Sopenharmony_ci else 22162306a36Sopenharmony_ci sync_reg = AZX_REG_SSYNC; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (dsp_is_locked(azx_dev) || !hstr->prepared) 22462306a36Sopenharmony_ci return -EPIPE; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci switch (cmd) { 22762306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_START: 22862306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 22962306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_RESUME: 23062306a36Sopenharmony_ci start = true; 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 23362306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_SUSPEND: 23462306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_STOP: 23562306a36Sopenharmony_ci start = false; 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci default: 23862306a36Sopenharmony_ci return -EINVAL; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci snd_pcm_group_for_each_entry(s, substream) { 24262306a36Sopenharmony_ci if (s->pcm->card != substream->pcm->card) 24362306a36Sopenharmony_ci continue; 24462306a36Sopenharmony_ci azx_dev = get_azx_dev(s); 24562306a36Sopenharmony_ci sbits |= 1 << azx_dev->core.index; 24662306a36Sopenharmony_ci snd_pcm_trigger_done(s, substream); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci spin_lock(&bus->reg_lock); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* first, set SYNC bits of corresponding streams */ 25262306a36Sopenharmony_ci snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci snd_pcm_group_for_each_entry(s, substream) { 25562306a36Sopenharmony_ci if (s->pcm->card != substream->pcm->card) 25662306a36Sopenharmony_ci continue; 25762306a36Sopenharmony_ci azx_dev = get_azx_dev(s); 25862306a36Sopenharmony_ci if (start) { 25962306a36Sopenharmony_ci azx_dev->insufficient = 1; 26062306a36Sopenharmony_ci snd_hdac_stream_start(azx_stream(azx_dev)); 26162306a36Sopenharmony_ci } else { 26262306a36Sopenharmony_ci snd_hdac_stream_stop(azx_stream(azx_dev)); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci spin_unlock(&bus->reg_lock); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci snd_hdac_stream_sync(hstr, start, sbits); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci spin_lock(&bus->reg_lock); 27062306a36Sopenharmony_ci /* reset SYNC bits */ 27162306a36Sopenharmony_ci snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg); 27262306a36Sopenharmony_ci if (start) 27362306a36Sopenharmony_ci snd_hdac_stream_timecounter_init(hstr, sbits); 27462306a36Sopenharmony_ci spin_unlock(&bus->reg_lock); 27562306a36Sopenharmony_ci return 0; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ciunsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci return snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev)); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_get_pos_lpib); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ciunsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci return snd_hdac_stream_get_pos_posbuf(azx_stream(azx_dev)); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_get_pos_posbuf); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ciunsigned int azx_get_position(struct azx *chip, 29162306a36Sopenharmony_ci struct azx_dev *azx_dev) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci struct snd_pcm_substream *substream = azx_dev->core.substream; 29462306a36Sopenharmony_ci unsigned int pos; 29562306a36Sopenharmony_ci int stream = substream->stream; 29662306a36Sopenharmony_ci int delay = 0; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (chip->get_position[stream]) 29962306a36Sopenharmony_ci pos = chip->get_position[stream](chip, azx_dev); 30062306a36Sopenharmony_ci else /* use the position buffer as default */ 30162306a36Sopenharmony_ci pos = azx_get_pos_posbuf(chip, azx_dev); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (pos >= azx_dev->core.bufsize) 30462306a36Sopenharmony_ci pos = 0; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (substream->runtime) { 30762306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 30862306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (chip->get_delay[stream]) 31162306a36Sopenharmony_ci delay += chip->get_delay[stream](chip, azx_dev, pos); 31262306a36Sopenharmony_ci if (hinfo->ops.get_delay) 31362306a36Sopenharmony_ci delay += hinfo->ops.get_delay(hinfo, apcm->codec, 31462306a36Sopenharmony_ci substream); 31562306a36Sopenharmony_ci substream->runtime->delay = delay; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci trace_azx_get_position(chip, azx_dev, pos, delay); 31962306a36Sopenharmony_ci return pos; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_get_position); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 32662306a36Sopenharmony_ci struct azx *chip = apcm->chip; 32762306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 32862306a36Sopenharmony_ci return bytes_to_frames(substream->runtime, 32962306a36Sopenharmony_ci azx_get_position(chip, azx_dev)); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci/* 33362306a36Sopenharmony_ci * azx_scale64: Scale base by mult/div while not overflowing sanely 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * Derived from scale64_check_overflow in kernel/time/timekeeping.c 33662306a36Sopenharmony_ci * 33762306a36Sopenharmony_ci * The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which 33862306a36Sopenharmony_ci * is about 384307 ie ~4.5 days. 33962306a36Sopenharmony_ci * 34062306a36Sopenharmony_ci * This scales the calculation so that overflow will happen but after 2^64 / 34162306a36Sopenharmony_ci * 48000 secs, which is pretty large! 34262306a36Sopenharmony_ci * 34362306a36Sopenharmony_ci * In caln below: 34462306a36Sopenharmony_ci * base may overflow, but since there isn’t any additional division 34562306a36Sopenharmony_ci * performed on base it’s OK 34662306a36Sopenharmony_ci * rem can’t overflow because both are 32-bit values 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci#ifdef CONFIG_X86 35062306a36Sopenharmony_cistatic u64 azx_scale64(u64 base, u32 num, u32 den) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci u64 rem; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci rem = do_div(base, den); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci base *= num; 35762306a36Sopenharmony_ci rem *= num; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci do_div(rem, den); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return base + rem; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic int azx_get_sync_time(ktime_t *device, 36562306a36Sopenharmony_ci struct system_counterval_t *system, void *ctx) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct snd_pcm_substream *substream = ctx; 36862306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 36962306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 37062306a36Sopenharmony_ci struct azx *chip = apcm->chip; 37162306a36Sopenharmony_ci struct snd_pcm_runtime *runtime; 37262306a36Sopenharmony_ci u64 ll_counter, ll_counter_l, ll_counter_h; 37362306a36Sopenharmony_ci u64 tsc_counter, tsc_counter_l, tsc_counter_h; 37462306a36Sopenharmony_ci u32 wallclk_ctr, wallclk_cycles; 37562306a36Sopenharmony_ci bool direction; 37662306a36Sopenharmony_ci u32 dma_select; 37762306a36Sopenharmony_ci u32 timeout; 37862306a36Sopenharmony_ci u32 retry_count = 0; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci runtime = substream->runtime; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 38362306a36Sopenharmony_ci direction = 1; 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci direction = 0; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* 0th stream tag is not used, so DMA ch 0 is for 1st stream tag */ 38862306a36Sopenharmony_ci do { 38962306a36Sopenharmony_ci timeout = 100; 39062306a36Sopenharmony_ci dma_select = (direction << GTSCC_CDMAS_DMA_DIR_SHIFT) | 39162306a36Sopenharmony_ci (azx_dev->core.stream_tag - 1); 39262306a36Sopenharmony_ci snd_hdac_chip_writel(azx_bus(chip), GTSCC, dma_select); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Enable the capture */ 39562306a36Sopenharmony_ci snd_hdac_chip_updatel(azx_bus(chip), GTSCC, 0, GTSCC_TSCCI_MASK); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci while (timeout) { 39862306a36Sopenharmony_ci if (snd_hdac_chip_readl(azx_bus(chip), GTSCC) & 39962306a36Sopenharmony_ci GTSCC_TSCCD_MASK) 40062306a36Sopenharmony_ci break; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci timeout--; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!timeout) { 40662306a36Sopenharmony_ci dev_err(chip->card->dev, "GTSCC capture Timedout!\n"); 40762306a36Sopenharmony_ci return -EIO; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Read wall clock counter */ 41162306a36Sopenharmony_ci wallclk_ctr = snd_hdac_chip_readl(azx_bus(chip), WALFCC); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* Read TSC counter */ 41462306a36Sopenharmony_ci tsc_counter_l = snd_hdac_chip_readl(azx_bus(chip), TSCCL); 41562306a36Sopenharmony_ci tsc_counter_h = snd_hdac_chip_readl(azx_bus(chip), TSCCU); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* Read Link counter */ 41862306a36Sopenharmony_ci ll_counter_l = snd_hdac_chip_readl(azx_bus(chip), LLPCL); 41962306a36Sopenharmony_ci ll_counter_h = snd_hdac_chip_readl(azx_bus(chip), LLPCU); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /* Ack: registers read done */ 42262306a36Sopenharmony_ci snd_hdac_chip_writel(azx_bus(chip), GTSCC, GTSCC_TSCCD_SHIFT); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci tsc_counter = (tsc_counter_h << TSCCU_CCU_SHIFT) | 42562306a36Sopenharmony_ci tsc_counter_l; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci ll_counter = (ll_counter_h << LLPC_CCU_SHIFT) | ll_counter_l; 42862306a36Sopenharmony_ci wallclk_cycles = wallclk_ctr & WALFCC_CIF_MASK; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* 43162306a36Sopenharmony_ci * An error occurs near frame "rollover". The clocks in 43262306a36Sopenharmony_ci * frame value indicates whether this error may have 43362306a36Sopenharmony_ci * occurred. Here we use the value of 10 i.e., 43462306a36Sopenharmony_ci * HDA_MAX_CYCLE_OFFSET 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci if (wallclk_cycles < HDA_MAX_CYCLE_VALUE - HDA_MAX_CYCLE_OFFSET 43762306a36Sopenharmony_ci && wallclk_cycles > HDA_MAX_CYCLE_OFFSET) 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* 44162306a36Sopenharmony_ci * Sleep before we read again, else we may again get 44262306a36Sopenharmony_ci * value near to MAX_CYCLE. Try to sleep for different 44362306a36Sopenharmony_ci * amount of time so we dont hit the same number again 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_ci udelay(retry_count++); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci } while (retry_count != HDA_MAX_CYCLE_READ_RETRY); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (retry_count == HDA_MAX_CYCLE_READ_RETRY) { 45062306a36Sopenharmony_ci dev_err_ratelimited(chip->card->dev, 45162306a36Sopenharmony_ci "Error in WALFCC cycle count\n"); 45262306a36Sopenharmony_ci return -EIO; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci *device = ns_to_ktime(azx_scale64(ll_counter, 45662306a36Sopenharmony_ci NSEC_PER_SEC, runtime->rate)); 45762306a36Sopenharmony_ci *device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) / 45862306a36Sopenharmony_ci ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate)); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci *system = convert_art_to_tsc(tsc_counter); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci return 0; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci#else 46662306a36Sopenharmony_cistatic int azx_get_sync_time(ktime_t *device, 46762306a36Sopenharmony_ci struct system_counterval_t *system, void *ctx) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci return -ENXIO; 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci#endif 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistatic int azx_get_crosststamp(struct snd_pcm_substream *substream, 47462306a36Sopenharmony_ci struct system_device_crosststamp *xtstamp) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci return get_device_system_crosststamp(azx_get_sync_time, 47762306a36Sopenharmony_ci substream, NULL, xtstamp); 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic inline bool is_link_time_supported(struct snd_pcm_runtime *runtime, 48162306a36Sopenharmony_ci struct snd_pcm_audio_tstamp_config *ts) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci if (runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME) 48462306a36Sopenharmony_ci if (ts->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED) 48562306a36Sopenharmony_ci return true; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return false; 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic int azx_get_time_info(struct snd_pcm_substream *substream, 49162306a36Sopenharmony_ci struct timespec64 *system_ts, struct timespec64 *audio_ts, 49262306a36Sopenharmony_ci struct snd_pcm_audio_tstamp_config *audio_tstamp_config, 49362306a36Sopenharmony_ci struct snd_pcm_audio_tstamp_report *audio_tstamp_report) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct azx_dev *azx_dev = get_azx_dev(substream); 49662306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 49762306a36Sopenharmony_ci struct system_device_crosststamp xtstamp; 49862306a36Sopenharmony_ci int ret; 49962306a36Sopenharmony_ci u64 nsec; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) && 50262306a36Sopenharmony_ci (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) { 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci snd_pcm_gettime(substream->runtime, system_ts); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci nsec = timecounter_read(&azx_dev->core.tc); 50762306a36Sopenharmony_ci if (audio_tstamp_config->report_delay) 50862306a36Sopenharmony_ci nsec = azx_adjust_codec_delay(substream, nsec); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci *audio_ts = ns_to_timespec64(nsec); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; 51362306a36Sopenharmony_ci audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */ 51462306a36Sopenharmony_ci audio_tstamp_report->accuracy = 42; /* 24 MHz WallClock == 42ns resolution */ 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci } else if (is_link_time_supported(runtime, audio_tstamp_config)) { 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci ret = azx_get_crosststamp(substream, &xtstamp); 51962306a36Sopenharmony_ci if (ret) 52062306a36Sopenharmony_ci return ret; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci switch (runtime->tstamp_type) { 52362306a36Sopenharmony_ci case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC: 52462306a36Sopenharmony_ci return -EINVAL; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: 52762306a36Sopenharmony_ci *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw); 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci default: 53162306a36Sopenharmony_ci *system_ts = ktime_to_timespec64(xtstamp.sys_realtime); 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci *audio_ts = ktime_to_timespec64(xtstamp.device); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci audio_tstamp_report->actual_type = 53962306a36Sopenharmony_ci SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED; 54062306a36Sopenharmony_ci audio_tstamp_report->accuracy_report = 1; 54162306a36Sopenharmony_ci /* 24 MHz WallClock == 42ns resolution */ 54262306a36Sopenharmony_ci audio_tstamp_report->accuracy = 42; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci } else { 54562306a36Sopenharmony_ci audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci return 0; 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic const struct snd_pcm_hardware azx_pcm_hw = { 55262306a36Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 55362306a36Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 55462306a36Sopenharmony_ci SNDRV_PCM_INFO_BLOCK_TRANSFER | 55562306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 55662306a36Sopenharmony_ci /* No full-resume yet implemented */ 55762306a36Sopenharmony_ci /* SNDRV_PCM_INFO_RESUME |*/ 55862306a36Sopenharmony_ci SNDRV_PCM_INFO_PAUSE | 55962306a36Sopenharmony_ci SNDRV_PCM_INFO_SYNC_START | 56062306a36Sopenharmony_ci SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */ 56162306a36Sopenharmony_ci SNDRV_PCM_INFO_HAS_LINK_ATIME | 56262306a36Sopenharmony_ci SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), 56362306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE, 56462306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 56562306a36Sopenharmony_ci .rate_min = 48000, 56662306a36Sopenharmony_ci .rate_max = 48000, 56762306a36Sopenharmony_ci .channels_min = 2, 56862306a36Sopenharmony_ci .channels_max = 2, 56962306a36Sopenharmony_ci .buffer_bytes_max = AZX_MAX_BUF_SIZE, 57062306a36Sopenharmony_ci .period_bytes_min = 128, 57162306a36Sopenharmony_ci .period_bytes_max = AZX_MAX_BUF_SIZE / 2, 57262306a36Sopenharmony_ci .periods_min = 2, 57362306a36Sopenharmony_ci .periods_max = AZX_MAX_FRAG, 57462306a36Sopenharmony_ci .fifo_size = 0, 57562306a36Sopenharmony_ci}; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic int azx_pcm_open(struct snd_pcm_substream *substream) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 58062306a36Sopenharmony_ci struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); 58162306a36Sopenharmony_ci struct azx *chip = apcm->chip; 58262306a36Sopenharmony_ci struct azx_dev *azx_dev; 58362306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 58462306a36Sopenharmony_ci int err; 58562306a36Sopenharmony_ci int buff_step; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci snd_hda_codec_pcm_get(apcm->info); 58862306a36Sopenharmony_ci mutex_lock(&chip->open_mutex); 58962306a36Sopenharmony_ci azx_dev = azx_assign_device(chip, substream); 59062306a36Sopenharmony_ci trace_azx_pcm_open(chip, azx_dev); 59162306a36Sopenharmony_ci if (azx_dev == NULL) { 59262306a36Sopenharmony_ci err = -EBUSY; 59362306a36Sopenharmony_ci goto unlock; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci runtime->private_data = azx_dev; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci runtime->hw = azx_pcm_hw; 59862306a36Sopenharmony_ci if (chip->gts_present) 59962306a36Sopenharmony_ci runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME; 60062306a36Sopenharmony_ci runtime->hw.channels_min = hinfo->channels_min; 60162306a36Sopenharmony_ci runtime->hw.channels_max = hinfo->channels_max; 60262306a36Sopenharmony_ci runtime->hw.formats = hinfo->formats; 60362306a36Sopenharmony_ci runtime->hw.rates = hinfo->rates; 60462306a36Sopenharmony_ci snd_pcm_limit_hw_rates(runtime); 60562306a36Sopenharmony_ci snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* avoid wrap-around with wall-clock */ 60862306a36Sopenharmony_ci snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 60962306a36Sopenharmony_ci 20, 61062306a36Sopenharmony_ci 178000000); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci if (chip->align_buffer_size) 61362306a36Sopenharmony_ci /* constrain buffer sizes to be multiple of 128 61462306a36Sopenharmony_ci bytes. This is more efficient in terms of memory 61562306a36Sopenharmony_ci access but isn't required by the HDA spec and 61662306a36Sopenharmony_ci prevents users from specifying exact period/buffer 61762306a36Sopenharmony_ci sizes. For example for 44.1kHz, a period size set 61862306a36Sopenharmony_ci to 20ms will be rounded to 19.59ms. */ 61962306a36Sopenharmony_ci buff_step = 128; 62062306a36Sopenharmony_ci else 62162306a36Sopenharmony_ci /* Don't enforce steps on buffer sizes, still need to 62262306a36Sopenharmony_ci be multiple of 4 bytes (HDA spec). Tested on Intel 62362306a36Sopenharmony_ci HDA controllers, may not work on all devices where 62462306a36Sopenharmony_ci option needs to be disabled */ 62562306a36Sopenharmony_ci buff_step = 4; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 62862306a36Sopenharmony_ci buff_step); 62962306a36Sopenharmony_ci snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 63062306a36Sopenharmony_ci buff_step); 63162306a36Sopenharmony_ci snd_hda_power_up(apcm->codec); 63262306a36Sopenharmony_ci if (hinfo->ops.open) 63362306a36Sopenharmony_ci err = hinfo->ops.open(hinfo, apcm->codec, substream); 63462306a36Sopenharmony_ci else 63562306a36Sopenharmony_ci err = -ENODEV; 63662306a36Sopenharmony_ci if (err < 0) { 63762306a36Sopenharmony_ci azx_release_device(azx_dev); 63862306a36Sopenharmony_ci goto powerdown; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci snd_pcm_limit_hw_rates(runtime); 64162306a36Sopenharmony_ci /* sanity check */ 64262306a36Sopenharmony_ci if (snd_BUG_ON(!runtime->hw.channels_min) || 64362306a36Sopenharmony_ci snd_BUG_ON(!runtime->hw.channels_max) || 64462306a36Sopenharmony_ci snd_BUG_ON(!runtime->hw.formats) || 64562306a36Sopenharmony_ci snd_BUG_ON(!runtime->hw.rates)) { 64662306a36Sopenharmony_ci azx_release_device(azx_dev); 64762306a36Sopenharmony_ci if (hinfo->ops.close) 64862306a36Sopenharmony_ci hinfo->ops.close(hinfo, apcm->codec, substream); 64962306a36Sopenharmony_ci err = -EINVAL; 65062306a36Sopenharmony_ci goto powerdown; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci /* disable LINK_ATIME timestamps for capture streams 65462306a36Sopenharmony_ci until we figure out how to handle digital inputs */ 65562306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 65662306a36Sopenharmony_ci runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */ 65762306a36Sopenharmony_ci runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci snd_pcm_set_sync(substream); 66162306a36Sopenharmony_ci mutex_unlock(&chip->open_mutex); 66262306a36Sopenharmony_ci return 0; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci powerdown: 66562306a36Sopenharmony_ci snd_hda_power_down(apcm->codec); 66662306a36Sopenharmony_ci unlock: 66762306a36Sopenharmony_ci mutex_unlock(&chip->open_mutex); 66862306a36Sopenharmony_ci snd_hda_codec_pcm_put(apcm->info); 66962306a36Sopenharmony_ci return err; 67062306a36Sopenharmony_ci} 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic const struct snd_pcm_ops azx_pcm_ops = { 67362306a36Sopenharmony_ci .open = azx_pcm_open, 67462306a36Sopenharmony_ci .close = azx_pcm_close, 67562306a36Sopenharmony_ci .hw_params = azx_pcm_hw_params, 67662306a36Sopenharmony_ci .hw_free = azx_pcm_hw_free, 67762306a36Sopenharmony_ci .prepare = azx_pcm_prepare, 67862306a36Sopenharmony_ci .trigger = azx_pcm_trigger, 67962306a36Sopenharmony_ci .pointer = azx_pcm_pointer, 68062306a36Sopenharmony_ci .get_time_info = azx_get_time_info, 68162306a36Sopenharmony_ci}; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic void azx_pcm_free(struct snd_pcm *pcm) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci struct azx_pcm *apcm = pcm->private_data; 68662306a36Sopenharmony_ci if (apcm) { 68762306a36Sopenharmony_ci list_del(&apcm->list); 68862306a36Sopenharmony_ci apcm->info->pcm = NULL; 68962306a36Sopenharmony_ci kfree(apcm); 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci} 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci#define MAX_PREALLOC_SIZE (32 * 1024 * 1024) 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ciint snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, 69662306a36Sopenharmony_ci struct hda_pcm *cpcm) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci struct hdac_bus *bus = &_bus->core; 69962306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 70062306a36Sopenharmony_ci struct snd_pcm *pcm; 70162306a36Sopenharmony_ci struct azx_pcm *apcm; 70262306a36Sopenharmony_ci int pcm_dev = cpcm->device; 70362306a36Sopenharmony_ci unsigned int size; 70462306a36Sopenharmony_ci int s, err; 70562306a36Sopenharmony_ci int type = SNDRV_DMA_TYPE_DEV_SG; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci list_for_each_entry(apcm, &chip->pcm_list, list) { 70862306a36Sopenharmony_ci if (apcm->pcm->device == pcm_dev) { 70962306a36Sopenharmony_ci dev_err(chip->card->dev, "PCM %d already exists\n", 71062306a36Sopenharmony_ci pcm_dev); 71162306a36Sopenharmony_ci return -EBUSY; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, 71562306a36Sopenharmony_ci cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, 71662306a36Sopenharmony_ci cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, 71762306a36Sopenharmony_ci &pcm); 71862306a36Sopenharmony_ci if (err < 0) 71962306a36Sopenharmony_ci return err; 72062306a36Sopenharmony_ci strscpy(pcm->name, cpcm->name, sizeof(pcm->name)); 72162306a36Sopenharmony_ci apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); 72262306a36Sopenharmony_ci if (apcm == NULL) { 72362306a36Sopenharmony_ci snd_device_free(chip->card, pcm); 72462306a36Sopenharmony_ci return -ENOMEM; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci apcm->chip = chip; 72762306a36Sopenharmony_ci apcm->pcm = pcm; 72862306a36Sopenharmony_ci apcm->codec = codec; 72962306a36Sopenharmony_ci apcm->info = cpcm; 73062306a36Sopenharmony_ci pcm->private_data = apcm; 73162306a36Sopenharmony_ci pcm->private_free = azx_pcm_free; 73262306a36Sopenharmony_ci if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) 73362306a36Sopenharmony_ci pcm->dev_class = SNDRV_PCM_CLASS_MODEM; 73462306a36Sopenharmony_ci list_add_tail(&apcm->list, &chip->pcm_list); 73562306a36Sopenharmony_ci cpcm->pcm = pcm; 73662306a36Sopenharmony_ci for (s = 0; s < 2; s++) { 73762306a36Sopenharmony_ci if (cpcm->stream[s].substreams) 73862306a36Sopenharmony_ci snd_pcm_set_ops(pcm, s, &azx_pcm_ops); 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci /* buffer pre-allocation */ 74162306a36Sopenharmony_ci size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; 74262306a36Sopenharmony_ci if (size > MAX_PREALLOC_SIZE) 74362306a36Sopenharmony_ci size = MAX_PREALLOC_SIZE; 74462306a36Sopenharmony_ci if (chip->uc_buffer) 74562306a36Sopenharmony_ci type = SNDRV_DMA_TYPE_DEV_WC_SG; 74662306a36Sopenharmony_ci snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev, 74762306a36Sopenharmony_ci size, MAX_PREALLOC_SIZE); 74862306a36Sopenharmony_ci return 0; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic unsigned int azx_command_addr(u32 cmd) 75262306a36Sopenharmony_ci{ 75362306a36Sopenharmony_ci unsigned int addr = cmd >> 28; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci if (addr >= AZX_MAX_CODECS) { 75662306a36Sopenharmony_ci snd_BUG(); 75762306a36Sopenharmony_ci addr = 0; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci return addr; 76162306a36Sopenharmony_ci} 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci/* receive a response */ 76462306a36Sopenharmony_cistatic int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, 76562306a36Sopenharmony_ci unsigned int *res) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 76862306a36Sopenharmony_ci struct hda_bus *hbus = &chip->bus; 76962306a36Sopenharmony_ci int err; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci again: 77262306a36Sopenharmony_ci err = snd_hdac_bus_get_response(bus, addr, res); 77362306a36Sopenharmony_ci if (!err) 77462306a36Sopenharmony_ci return 0; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci if (hbus->no_response_fallback) 77762306a36Sopenharmony_ci return -EIO; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci if (!bus->polling_mode) { 78062306a36Sopenharmony_ci dev_warn(chip->card->dev, 78162306a36Sopenharmony_ci "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", 78262306a36Sopenharmony_ci bus->last_cmd[addr]); 78362306a36Sopenharmony_ci bus->polling_mode = 1; 78462306a36Sopenharmony_ci goto again; 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci if (chip->msi) { 78862306a36Sopenharmony_ci dev_warn(chip->card->dev, 78962306a36Sopenharmony_ci "No response from codec, disabling MSI: last cmd=0x%08x\n", 79062306a36Sopenharmony_ci bus->last_cmd[addr]); 79162306a36Sopenharmony_ci if (chip->ops->disable_msi_reset_irq && 79262306a36Sopenharmony_ci chip->ops->disable_msi_reset_irq(chip) < 0) 79362306a36Sopenharmony_ci return -EIO; 79462306a36Sopenharmony_ci goto again; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci if (chip->probing) { 79862306a36Sopenharmony_ci /* If this critical timeout happens during the codec probing 79962306a36Sopenharmony_ci * phase, this is likely an access to a non-existing codec 80062306a36Sopenharmony_ci * slot. Better to return an error and reset the system. 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_ci return -EIO; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci /* no fallback mechanism? */ 80662306a36Sopenharmony_ci if (!chip->fallback_to_single_cmd) 80762306a36Sopenharmony_ci return -EIO; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* a fatal communication error; need either to reset or to fallback 81062306a36Sopenharmony_ci * to the single_cmd mode 81162306a36Sopenharmony_ci */ 81262306a36Sopenharmony_ci if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { 81362306a36Sopenharmony_ci hbus->response_reset = 1; 81462306a36Sopenharmony_ci dev_err(chip->card->dev, 81562306a36Sopenharmony_ci "No response from codec, resetting bus: last cmd=0x%08x\n", 81662306a36Sopenharmony_ci bus->last_cmd[addr]); 81762306a36Sopenharmony_ci return -EAGAIN; /* give a chance to retry */ 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci dev_err(chip->card->dev, 82162306a36Sopenharmony_ci "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", 82262306a36Sopenharmony_ci bus->last_cmd[addr]); 82362306a36Sopenharmony_ci chip->single_cmd = 1; 82462306a36Sopenharmony_ci hbus->response_reset = 0; 82562306a36Sopenharmony_ci snd_hdac_bus_stop_cmd_io(bus); 82662306a36Sopenharmony_ci return -EIO; 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci/* 83062306a36Sopenharmony_ci * Use the single immediate command instead of CORB/RIRB for simplicity 83162306a36Sopenharmony_ci * 83262306a36Sopenharmony_ci * Note: according to Intel, this is not preferred use. The command was 83362306a36Sopenharmony_ci * intended for the BIOS only, and may get confused with unsolicited 83462306a36Sopenharmony_ci * responses. So, we shouldn't use it for normal operation from the 83562306a36Sopenharmony_ci * driver. 83662306a36Sopenharmony_ci * I left the codes, however, for debugging/testing purposes. 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci/* receive a response */ 84062306a36Sopenharmony_cistatic int azx_single_wait_for_response(struct azx *chip, unsigned int addr) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci int timeout = 50; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci while (timeout--) { 84562306a36Sopenharmony_ci /* check IRV busy bit */ 84662306a36Sopenharmony_ci if (azx_readw(chip, IRS) & AZX_IRS_VALID) { 84762306a36Sopenharmony_ci /* reuse rirb.res as the response return value */ 84862306a36Sopenharmony_ci azx_bus(chip)->rirb.res[addr] = azx_readl(chip, IR); 84962306a36Sopenharmony_ci return 0; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci udelay(1); 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci if (printk_ratelimit()) 85462306a36Sopenharmony_ci dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n", 85562306a36Sopenharmony_ci azx_readw(chip, IRS)); 85662306a36Sopenharmony_ci azx_bus(chip)->rirb.res[addr] = -1; 85762306a36Sopenharmony_ci return -EIO; 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci/* send a command */ 86162306a36Sopenharmony_cistatic int azx_single_send_cmd(struct hdac_bus *bus, u32 val) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 86462306a36Sopenharmony_ci unsigned int addr = azx_command_addr(val); 86562306a36Sopenharmony_ci int timeout = 50; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci bus->last_cmd[azx_command_addr(val)] = val; 86862306a36Sopenharmony_ci while (timeout--) { 86962306a36Sopenharmony_ci /* check ICB busy bit */ 87062306a36Sopenharmony_ci if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { 87162306a36Sopenharmony_ci /* Clear IRV valid bit */ 87262306a36Sopenharmony_ci azx_writew(chip, IRS, azx_readw(chip, IRS) | 87362306a36Sopenharmony_ci AZX_IRS_VALID); 87462306a36Sopenharmony_ci azx_writel(chip, IC, val); 87562306a36Sopenharmony_ci azx_writew(chip, IRS, azx_readw(chip, IRS) | 87662306a36Sopenharmony_ci AZX_IRS_BUSY); 87762306a36Sopenharmony_ci return azx_single_wait_for_response(chip, addr); 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci udelay(1); 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci if (printk_ratelimit()) 88262306a36Sopenharmony_ci dev_dbg(chip->card->dev, 88362306a36Sopenharmony_ci "send_cmd timeout: IRS=0x%x, val=0x%x\n", 88462306a36Sopenharmony_ci azx_readw(chip, IRS), val); 88562306a36Sopenharmony_ci return -EIO; 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci/* receive a response */ 88962306a36Sopenharmony_cistatic int azx_single_get_response(struct hdac_bus *bus, unsigned int addr, 89062306a36Sopenharmony_ci unsigned int *res) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci if (res) 89362306a36Sopenharmony_ci *res = bus->rirb.res[addr]; 89462306a36Sopenharmony_ci return 0; 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci/* 89862306a36Sopenharmony_ci * The below are the main callbacks from hda_codec. 89962306a36Sopenharmony_ci * 90062306a36Sopenharmony_ci * They are just the skeleton to call sub-callbacks according to the 90162306a36Sopenharmony_ci * current setting of chip->single_cmd. 90262306a36Sopenharmony_ci */ 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci/* send a command */ 90562306a36Sopenharmony_cistatic int azx_send_cmd(struct hdac_bus *bus, unsigned int val) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (chip->disabled) 91062306a36Sopenharmony_ci return 0; 91162306a36Sopenharmony_ci if (chip->single_cmd) 91262306a36Sopenharmony_ci return azx_single_send_cmd(bus, val); 91362306a36Sopenharmony_ci else 91462306a36Sopenharmony_ci return snd_hdac_bus_send_cmd(bus, val); 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci/* get a response */ 91862306a36Sopenharmony_cistatic int azx_get_response(struct hdac_bus *bus, unsigned int addr, 91962306a36Sopenharmony_ci unsigned int *res) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (chip->disabled) 92462306a36Sopenharmony_ci return 0; 92562306a36Sopenharmony_ci if (chip->single_cmd) 92662306a36Sopenharmony_ci return azx_single_get_response(bus, addr, res); 92762306a36Sopenharmony_ci else 92862306a36Sopenharmony_ci return azx_rirb_get_response(bus, addr, res); 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic const struct hdac_bus_ops bus_core_ops = { 93262306a36Sopenharmony_ci .command = azx_send_cmd, 93362306a36Sopenharmony_ci .get_response = azx_get_response, 93462306a36Sopenharmony_ci}; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci#ifdef CONFIG_SND_HDA_DSP_LOADER 93762306a36Sopenharmony_ci/* 93862306a36Sopenharmony_ci * DSP loading code (e.g. for CA0132) 93962306a36Sopenharmony_ci */ 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci/* use the first stream for loading DSP */ 94262306a36Sopenharmony_cistatic struct azx_dev * 94362306a36Sopenharmony_ciazx_get_dsp_loader_dev(struct azx *chip) 94462306a36Sopenharmony_ci{ 94562306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 94662306a36Sopenharmony_ci struct hdac_stream *s; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci list_for_each_entry(s, &bus->stream_list, list) 94962306a36Sopenharmony_ci if (s->index == chip->playback_index_offset) 95062306a36Sopenharmony_ci return stream_to_azx_dev(s); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci return NULL; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ciint snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, 95662306a36Sopenharmony_ci unsigned int byte_size, 95762306a36Sopenharmony_ci struct snd_dma_buffer *bufp) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci struct hdac_bus *bus = &codec->bus->core; 96062306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 96162306a36Sopenharmony_ci struct azx_dev *azx_dev; 96262306a36Sopenharmony_ci struct hdac_stream *hstr; 96362306a36Sopenharmony_ci bool saved = false; 96462306a36Sopenharmony_ci int err; 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci azx_dev = azx_get_dsp_loader_dev(chip); 96762306a36Sopenharmony_ci hstr = azx_stream(azx_dev); 96862306a36Sopenharmony_ci spin_lock_irq(&bus->reg_lock); 96962306a36Sopenharmony_ci if (hstr->opened) { 97062306a36Sopenharmony_ci chip->saved_azx_dev = *azx_dev; 97162306a36Sopenharmony_ci saved = true; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci spin_unlock_irq(&bus->reg_lock); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp); 97662306a36Sopenharmony_ci if (err < 0) { 97762306a36Sopenharmony_ci spin_lock_irq(&bus->reg_lock); 97862306a36Sopenharmony_ci if (saved) 97962306a36Sopenharmony_ci *azx_dev = chip->saved_azx_dev; 98062306a36Sopenharmony_ci spin_unlock_irq(&bus->reg_lock); 98162306a36Sopenharmony_ci return err; 98262306a36Sopenharmony_ci } 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci hstr->prepared = 0; 98562306a36Sopenharmony_ci return err; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_prepare); 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_civoid snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci struct hdac_bus *bus = &codec->bus->core; 99262306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 99362306a36Sopenharmony_ci struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci snd_hdac_dsp_trigger(azx_stream(azx_dev), start); 99662306a36Sopenharmony_ci} 99762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_trigger); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_civoid snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, 100062306a36Sopenharmony_ci struct snd_dma_buffer *dmab) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci struct hdac_bus *bus = &codec->bus->core; 100362306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 100462306a36Sopenharmony_ci struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); 100562306a36Sopenharmony_ci struct hdac_stream *hstr = azx_stream(azx_dev); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (!dmab->area || !hstr->locked) 100862306a36Sopenharmony_ci return; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci snd_hdac_dsp_cleanup(hstr, dmab); 101162306a36Sopenharmony_ci spin_lock_irq(&bus->reg_lock); 101262306a36Sopenharmony_ci if (hstr->opened) 101362306a36Sopenharmony_ci *azx_dev = chip->saved_azx_dev; 101462306a36Sopenharmony_ci hstr->locked = false; 101562306a36Sopenharmony_ci spin_unlock_irq(&bus->reg_lock); 101662306a36Sopenharmony_ci} 101762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_cleanup); 101862306a36Sopenharmony_ci#endif /* CONFIG_SND_HDA_DSP_LOADER */ 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci/* 102162306a36Sopenharmony_ci * reset and start the controller registers 102262306a36Sopenharmony_ci */ 102362306a36Sopenharmony_civoid azx_init_chip(struct azx *chip, bool full_reset) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci if (snd_hdac_bus_init_chip(azx_bus(chip), full_reset)) { 102662306a36Sopenharmony_ci /* correct RINTCNT for CXT */ 102762306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) 102862306a36Sopenharmony_ci azx_writew(chip, RINTCNT, 0xc0); 102962306a36Sopenharmony_ci } 103062306a36Sopenharmony_ci} 103162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_init_chip); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_civoid azx_stop_all_streams(struct azx *chip) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci snd_hdac_stop_streams(bus); 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_stop_all_streams); 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_civoid azx_stop_chip(struct azx *chip) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci snd_hdac_bus_stop_chip(azx_bus(chip)); 104462306a36Sopenharmony_ci} 104562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_stop_chip); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci/* 104862306a36Sopenharmony_ci * interrupt handler 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_cistatic void stream_update(struct hdac_bus *bus, struct hdac_stream *s) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci struct azx *chip = bus_to_azx(bus); 105362306a36Sopenharmony_ci struct azx_dev *azx_dev = stream_to_azx_dev(s); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci /* check whether this IRQ is really acceptable */ 105662306a36Sopenharmony_ci if (!chip->ops->position_check || 105762306a36Sopenharmony_ci chip->ops->position_check(chip, azx_dev)) { 105862306a36Sopenharmony_ci spin_unlock(&bus->reg_lock); 105962306a36Sopenharmony_ci snd_pcm_period_elapsed(azx_stream(azx_dev)->substream); 106062306a36Sopenharmony_ci spin_lock(&bus->reg_lock); 106162306a36Sopenharmony_ci } 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ciirqreturn_t azx_interrupt(int irq, void *dev_id) 106562306a36Sopenharmony_ci{ 106662306a36Sopenharmony_ci struct azx *chip = dev_id; 106762306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 106862306a36Sopenharmony_ci u32 status; 106962306a36Sopenharmony_ci bool active, handled = false; 107062306a36Sopenharmony_ci int repeat = 0; /* count for avoiding endless loop */ 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci#ifdef CONFIG_PM 107362306a36Sopenharmony_ci if (azx_has_pm_runtime(chip)) 107462306a36Sopenharmony_ci if (!pm_runtime_active(chip->card->dev)) 107562306a36Sopenharmony_ci return IRQ_NONE; 107662306a36Sopenharmony_ci#endif 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci spin_lock(&bus->reg_lock); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci if (chip->disabled) 108162306a36Sopenharmony_ci goto unlock; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci do { 108462306a36Sopenharmony_ci status = azx_readl(chip, INTSTS); 108562306a36Sopenharmony_ci if (status == 0 || status == 0xffffffff) 108662306a36Sopenharmony_ci break; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci handled = true; 108962306a36Sopenharmony_ci active = false; 109062306a36Sopenharmony_ci if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update)) 109162306a36Sopenharmony_ci active = true; 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci status = azx_readb(chip, RIRBSTS); 109462306a36Sopenharmony_ci if (status & RIRB_INT_MASK) { 109562306a36Sopenharmony_ci /* 109662306a36Sopenharmony_ci * Clearing the interrupt status here ensures that no 109762306a36Sopenharmony_ci * interrupt gets masked after the RIRB wp is read in 109862306a36Sopenharmony_ci * snd_hdac_bus_update_rirb. This avoids a possible 109962306a36Sopenharmony_ci * race condition where codec response in RIRB may 110062306a36Sopenharmony_ci * remain unserviced by IRQ, eventually falling back 110162306a36Sopenharmony_ci * to polling mode in azx_rirb_get_response. 110262306a36Sopenharmony_ci */ 110362306a36Sopenharmony_ci azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); 110462306a36Sopenharmony_ci active = true; 110562306a36Sopenharmony_ci if (status & RIRB_INT_RESPONSE) { 110662306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) 110762306a36Sopenharmony_ci udelay(80); 110862306a36Sopenharmony_ci snd_hdac_bus_update_rirb(bus); 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci } 111162306a36Sopenharmony_ci } while (active && ++repeat < 10); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci unlock: 111462306a36Sopenharmony_ci spin_unlock(&bus->reg_lock); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci return IRQ_RETVAL(handled); 111762306a36Sopenharmony_ci} 111862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_interrupt); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci/* 112162306a36Sopenharmony_ci * Codec initerface 112262306a36Sopenharmony_ci */ 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci/* 112562306a36Sopenharmony_ci * Probe the given codec address 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_cistatic int probe_codec(struct azx *chip, int addr) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | 113062306a36Sopenharmony_ci (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; 113162306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 113262306a36Sopenharmony_ci int err; 113362306a36Sopenharmony_ci unsigned int res = -1; 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci mutex_lock(&bus->cmd_mutex); 113662306a36Sopenharmony_ci chip->probing = 1; 113762306a36Sopenharmony_ci azx_send_cmd(bus, cmd); 113862306a36Sopenharmony_ci err = azx_get_response(bus, addr, &res); 113962306a36Sopenharmony_ci chip->probing = 0; 114062306a36Sopenharmony_ci mutex_unlock(&bus->cmd_mutex); 114162306a36Sopenharmony_ci if (err < 0 || res == -1) 114262306a36Sopenharmony_ci return -EIO; 114362306a36Sopenharmony_ci dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr); 114462306a36Sopenharmony_ci return 0; 114562306a36Sopenharmony_ci} 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_civoid snd_hda_bus_reset(struct hda_bus *bus) 114862306a36Sopenharmony_ci{ 114962306a36Sopenharmony_ci struct azx *chip = bus_to_azx(&bus->core); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci bus->in_reset = 1; 115262306a36Sopenharmony_ci azx_stop_chip(chip); 115362306a36Sopenharmony_ci azx_init_chip(chip, true); 115462306a36Sopenharmony_ci if (bus->core.chip_init) 115562306a36Sopenharmony_ci snd_hda_bus_reset_codecs(bus); 115662306a36Sopenharmony_ci bus->in_reset = 0; 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci/* HD-audio bus initialization */ 116062306a36Sopenharmony_ciint azx_bus_init(struct azx *chip, const char *model) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci struct hda_bus *bus = &chip->bus; 116362306a36Sopenharmony_ci int err; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops); 116662306a36Sopenharmony_ci if (err < 0) 116762306a36Sopenharmony_ci return err; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci bus->card = chip->card; 117062306a36Sopenharmony_ci mutex_init(&bus->prepare_mutex); 117162306a36Sopenharmony_ci bus->pci = chip->pci; 117262306a36Sopenharmony_ci bus->modelname = model; 117362306a36Sopenharmony_ci bus->mixer_assigned = -1; 117462306a36Sopenharmony_ci bus->core.snoop = azx_snoop(chip); 117562306a36Sopenharmony_ci if (chip->get_position[0] != azx_get_pos_lpib || 117662306a36Sopenharmony_ci chip->get_position[1] != azx_get_pos_lpib) 117762306a36Sopenharmony_ci bus->core.use_posbuf = true; 117862306a36Sopenharmony_ci bus->core.bdl_pos_adj = chip->bdl_pos_adj; 117962306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR) 118062306a36Sopenharmony_ci bus->core.corbrp_self_clear = true; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) 118362306a36Sopenharmony_ci bus->core.align_bdle_4k = true; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci /* enable sync_write flag for stable communication as default */ 118662306a36Sopenharmony_ci bus->core.sync_write = 1; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci return 0; 118962306a36Sopenharmony_ci} 119062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_bus_init); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci/* Probe codecs */ 119362306a36Sopenharmony_ciint azx_probe_codecs(struct azx *chip, unsigned int max_slots) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 119662306a36Sopenharmony_ci int c, codecs, err; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci codecs = 0; 119962306a36Sopenharmony_ci if (!max_slots) 120062306a36Sopenharmony_ci max_slots = AZX_DEFAULT_CODECS; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci /* First try to probe all given codec slots */ 120362306a36Sopenharmony_ci for (c = 0; c < max_slots; c++) { 120462306a36Sopenharmony_ci if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { 120562306a36Sopenharmony_ci if (probe_codec(chip, c) < 0) { 120662306a36Sopenharmony_ci /* Some BIOSen give you wrong codec addresses 120762306a36Sopenharmony_ci * that don't exist 120862306a36Sopenharmony_ci */ 120962306a36Sopenharmony_ci dev_warn(chip->card->dev, 121062306a36Sopenharmony_ci "Codec #%d probe error; disabling it...\n", c); 121162306a36Sopenharmony_ci bus->codec_mask &= ~(1 << c); 121262306a36Sopenharmony_ci /* More badly, accessing to a non-existing 121362306a36Sopenharmony_ci * codec often screws up the controller chip, 121462306a36Sopenharmony_ci * and disturbs the further communications. 121562306a36Sopenharmony_ci * Thus if an error occurs during probing, 121662306a36Sopenharmony_ci * better to reset the controller chip to 121762306a36Sopenharmony_ci * get back to the sanity state. 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci azx_stop_chip(chip); 122062306a36Sopenharmony_ci azx_init_chip(chip, true); 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci } 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* Then create codec instances */ 122662306a36Sopenharmony_ci for (c = 0; c < max_slots; c++) { 122762306a36Sopenharmony_ci if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { 122862306a36Sopenharmony_ci struct hda_codec *codec; 122962306a36Sopenharmony_ci err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); 123062306a36Sopenharmony_ci if (err < 0) 123162306a36Sopenharmony_ci continue; 123262306a36Sopenharmony_ci codec->jackpoll_interval = chip->jackpoll_interval; 123362306a36Sopenharmony_ci codec->beep_mode = chip->beep_mode; 123462306a36Sopenharmony_ci codec->ctl_dev_id = chip->ctl_dev_id; 123562306a36Sopenharmony_ci codecs++; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci if (!codecs) { 123962306a36Sopenharmony_ci dev_err(chip->card->dev, "no codecs initialized\n"); 124062306a36Sopenharmony_ci return -ENXIO; 124162306a36Sopenharmony_ci } 124262306a36Sopenharmony_ci return 0; 124362306a36Sopenharmony_ci} 124462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_probe_codecs); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci/* configure each codec instance */ 124762306a36Sopenharmony_ciint azx_codec_configure(struct azx *chip) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct hda_codec *codec, *next; 125062306a36Sopenharmony_ci int success = 0; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci list_for_each_codec(codec, &chip->bus) { 125362306a36Sopenharmony_ci if (!snd_hda_codec_configure(codec)) 125462306a36Sopenharmony_ci success++; 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci if (success) { 125862306a36Sopenharmony_ci /* unregister failed codecs if any codec has been probed */ 125962306a36Sopenharmony_ci list_for_each_codec_safe(codec, next, &chip->bus) { 126062306a36Sopenharmony_ci if (!codec->configured) { 126162306a36Sopenharmony_ci codec_err(codec, "Unable to configure, disabling\n"); 126262306a36Sopenharmony_ci snd_hdac_device_unregister(&codec->core); 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci } 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci return success ? 0 : -ENODEV; 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_codec_configure); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_cistatic int stream_direction(struct azx *chip, unsigned char index) 127262306a36Sopenharmony_ci{ 127362306a36Sopenharmony_ci if (index >= chip->capture_index_offset && 127462306a36Sopenharmony_ci index < chip->capture_index_offset + chip->capture_streams) 127562306a36Sopenharmony_ci return SNDRV_PCM_STREAM_CAPTURE; 127662306a36Sopenharmony_ci return SNDRV_PCM_STREAM_PLAYBACK; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci/* initialize SD streams */ 128062306a36Sopenharmony_ciint azx_init_streams(struct azx *chip) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci int i; 128362306a36Sopenharmony_ci int stream_tags[2] = { 0, 0 }; 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci /* initialize each stream (aka device) 128662306a36Sopenharmony_ci * assign the starting bdl address to each stream (device) 128762306a36Sopenharmony_ci * and initialize 128862306a36Sopenharmony_ci */ 128962306a36Sopenharmony_ci for (i = 0; i < chip->num_streams; i++) { 129062306a36Sopenharmony_ci struct azx_dev *azx_dev = kzalloc(sizeof(*azx_dev), GFP_KERNEL); 129162306a36Sopenharmony_ci int dir, tag; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci if (!azx_dev) 129462306a36Sopenharmony_ci return -ENOMEM; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci dir = stream_direction(chip, i); 129762306a36Sopenharmony_ci /* stream tag must be unique throughout 129862306a36Sopenharmony_ci * the stream direction group, 129962306a36Sopenharmony_ci * valid values 1...15 130062306a36Sopenharmony_ci * use separate stream tag if the flag 130162306a36Sopenharmony_ci * AZX_DCAPS_SEPARATE_STREAM_TAG is used 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_ci if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) 130462306a36Sopenharmony_ci tag = ++stream_tags[dir]; 130562306a36Sopenharmony_ci else 130662306a36Sopenharmony_ci tag = i + 1; 130762306a36Sopenharmony_ci snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev), 130862306a36Sopenharmony_ci i, dir, tag); 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci return 0; 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_init_streams); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_civoid azx_free_streams(struct azx *chip) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci struct hdac_bus *bus = azx_bus(chip); 131862306a36Sopenharmony_ci struct hdac_stream *s; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci while (!list_empty(&bus->stream_list)) { 132162306a36Sopenharmony_ci s = list_first_entry(&bus->stream_list, struct hdac_stream, list); 132262306a36Sopenharmony_ci list_del(&s->list); 132362306a36Sopenharmony_ci kfree(stream_to_azx_dev(s)); 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci} 132662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(azx_free_streams); 1327