linux/sound/pci/hda/hda_controller.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *
 *  Implementation of primary alsa driver code base for Intel HD Audio.
 *
 *  Copyright(c) 2004 Intel Corporation
 *
 *  Copyright (c) 2004 Takashi Iwai <[email protected]>
 *                     PeiSen Hou <[email protected]>
 */

#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>

#ifdef CONFIG_X86
/* for art-tsc conversion */
#include <asm/tsc.h>
#endif

#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include "hda_controller.h"
#include "hda_local.h"

#define CREATE_TRACE_POINTS
#include "hda_controller_trace.h"

/* DSP lock helpers */
#define dsp_lock(dev)
#define dsp_unlock(dev)
#define dsp_is_locked(dev)

/* assign a stream for the PCM */
static inline struct azx_dev *
azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
{}

/* release the assigned stream */
static inline void azx_release_device(struct azx_dev *azx_dev)
{}

static inline struct hda_pcm_stream *
to_hda_pcm_stream(struct snd_pcm_substream *substream)
{}

static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
				u64 nsec)
{}

/*
 * PCM ops
 */

static int azx_pcm_close(struct snd_pcm_substream *substream)
{}

static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *hw_params)
{}

static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
{}

static int azx_pcm_prepare(struct snd_pcm_substream *substream)
{}

static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{}

unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
{}
EXPORT_SYMBOL_GPL();

unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
{}
EXPORT_SYMBOL_GPL();

unsigned int azx_get_position(struct azx *chip,
			      struct azx_dev *azx_dev)
{}
EXPORT_SYMBOL_GPL();

static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
{}

/*
 * azx_scale64: Scale base by mult/div while not overflowing sanely
 *
 * Derived from scale64_check_overflow in kernel/time/timekeeping.c
 *
 * The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which
 * is about 384307 ie ~4.5 days.
 *
 * This scales the calculation so that overflow will happen but after 2^64 /
 * 48000 secs, which is pretty large!
 *
 * In caln below:
 *	base may overflow, but since there isn’t any additional division
 *	performed on base it’s OK
 *	rem can’t overflow because both are 32-bit values
 */

#ifdef CONFIG_X86
static u64 azx_scale64(u64 base, u32 num, u32 den)
{}

static int azx_get_sync_time(ktime_t *device,
		struct system_counterval_t *system, void *ctx)
{}

#else
static int azx_get_sync_time(ktime_t *device,
		struct system_counterval_t *system, void *ctx)
{
	return -ENXIO;
}
#endif

static int azx_get_crosststamp(struct snd_pcm_substream *substream,
			      struct system_device_crosststamp *xtstamp)
{}

static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime,
				struct snd_pcm_audio_tstamp_config *ts)
{}

static int 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)
{}

static const struct snd_pcm_hardware azx_pcm_hw =;

static int azx_pcm_open(struct snd_pcm_substream *substream)
{}

static const struct snd_pcm_ops azx_pcm_ops =;

static void azx_pcm_free(struct snd_pcm *pcm)
{}

#define MAX_PREALLOC_SIZE

int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
			      struct hda_pcm *cpcm)
{}

static unsigned int azx_command_addr(u32 cmd)
{}

/* receive a response */
static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
				 unsigned int *res)
{}

/*
 * Use the single immediate command instead of CORB/RIRB for simplicity
 *
 * Note: according to Intel, this is not preferred use.  The command was
 *       intended for the BIOS only, and may get confused with unsolicited
 *       responses.  So, we shouldn't use it for normal operation from the
 *       driver.
 *       I left the codes, however, for debugging/testing purposes.
 */

/* receive a response */
static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
{}

/* send a command */
static int azx_single_send_cmd(struct hdac_bus *bus, u32 val)
{}

/* receive a response */
static int azx_single_get_response(struct hdac_bus *bus, unsigned int addr,
				   unsigned int *res)
{}

/*
 * The below are the main callbacks from hda_codec.
 *
 * They are just the skeleton to call sub-callbacks according to the
 * current setting of chip->single_cmd.
 */

/* send a command */
static int azx_send_cmd(struct hdac_bus *bus, unsigned int val)
{}

/* get a response */
static int azx_get_response(struct hdac_bus *bus, unsigned int addr,
			    unsigned int *res)
{}

static const struct hdac_bus_ops bus_core_ops =;

#ifdef CONFIG_SND_HDA_DSP_LOADER
/*
 * DSP loading code (e.g. for CA0132)
 */

/* use the first stream for loading DSP */
static struct azx_dev *
azx_get_dsp_loader_dev(struct azx *chip)
{}

int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format,
				   unsigned int byte_size,
				   struct snd_dma_buffer *bufp)
{}
EXPORT_SYMBOL_GPL();

void snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start)
{}
EXPORT_SYMBOL_GPL();

void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
				    struct snd_dma_buffer *dmab)
{}
EXPORT_SYMBOL_GPL();
#endif /* CONFIG_SND_HDA_DSP_LOADER */

/*
 * reset and start the controller registers
 */
void azx_init_chip(struct azx *chip, bool full_reset)
{}
EXPORT_SYMBOL_GPL();

void azx_stop_all_streams(struct azx *chip)
{}
EXPORT_SYMBOL_GPL();

void azx_stop_chip(struct azx *chip)
{}
EXPORT_SYMBOL_GPL();

/*
 * interrupt handler
 */
static void stream_update(struct hdac_bus *bus, struct hdac_stream *s)
{}

irqreturn_t azx_interrupt(int irq, void *dev_id)
{}
EXPORT_SYMBOL_GPL();

/*
 * Codec initerface
 */

/*
 * Probe the given codec address
 */
static int probe_codec(struct azx *chip, int addr)
{}

void snd_hda_bus_reset(struct hda_bus *bus)
{}

/* HD-audio bus initialization */
int azx_bus_init(struct azx *chip, const char *model)
{}
EXPORT_SYMBOL_GPL();

/* Probe codecs */
int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
{}
EXPORT_SYMBOL_GPL();

/* configure each codec instance */
int azx_codec_configure(struct azx *chip)
{}
EXPORT_SYMBOL_GPL();

static int stream_direction(struct azx *chip, unsigned char index)
{}

/* initialize SD streams */
int azx_init_streams(struct azx *chip)
{}
EXPORT_SYMBOL_GPL();

void azx_free_streams(struct azx *chip)
{}
EXPORT_SYMBOL_GPL();