linux/sound/pci/ac97/ac97_codec.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (c) by Jaroslav Kysela <[email protected]>
 *  Universal interface for Audio Codec '97
 *
 *  For more details look to AC '97 component specification revision 2.2
 *  by Intel Corporation (http://developer.intel.com).
 */

#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/tlv.h>
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
#include "ac97_id.h"

#include "ac97_patch.c"

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

static bool enable_loopback;

module_param(enable_loopback, bool, 0444);
MODULE_PARM_DESC();

#ifdef CONFIG_SND_AC97_POWER_SAVE
static int power_save =;
module_param(power_save, int, 0644);
MODULE_PARM_DESC();
#endif
/*

 */

struct ac97_codec_id {};

static const struct ac97_codec_id snd_ac97_codec_id_vendors[] =;

static const struct ac97_codec_id snd_ac97_codec_ids[] =;


static void update_power_regs(struct snd_ac97 *ac97);
#ifdef CONFIG_SND_AC97_POWER_SAVE
#define ac97_is_power_save_mode(ac97)
#else
#define ac97_is_power_save_mode
#endif

#define ac97_err(ac97, fmt, args...)
#define ac97_warn(ac97, fmt, args...)
#define ac97_dbg(ac97, fmt, args...)

/*
 *  I/O routines
 */

static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg)
{}

/**
 * snd_ac97_write - write a value on the given register
 * @ac97: the ac97 instance
 * @reg: the register to change
 * @value: the value to set
 *
 * Writes a value on the given register.  This will invoke the write
 * callback directly after the register check.
 * This function doesn't change the register cache unlike
 * #snd_ca97_write_cache(), so use this only when you don't want to
 * reflect the change to the suspend/resume state.
 */
void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{}

EXPORT_SYMBOL();

/**
 * snd_ac97_read - read a value from the given register
 * 
 * @ac97: the ac97 instance
 * @reg: the register to read
 *
 * Reads a value from the given register.  This will invoke the read
 * callback directly after the register check.
 *
 * Return: The read value.
 */
unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{}

/* read a register - return the cached value if already read */
static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned short reg)
{}

EXPORT_SYMBOL();

/**
 * snd_ac97_write_cache - write a value on the given register and update the cache
 * @ac97: the ac97 instance
 * @reg: the register to change
 * @value: the value to set
 *
 * Writes a value on the given register and updates the register
 * cache.  The cached values are used for the cached-read and the
 * suspend/resume.
 */
void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{}

EXPORT_SYMBOL();

/**
 * snd_ac97_update - update the value on the given register
 * @ac97: the ac97 instance
 * @reg: the register to change
 * @value: the value to set
 *
 * Compares the value with the register cache and updates the value
 * only when the value is changed.
 *
 * Return: 1 if the value is changed, 0 if no change, or a negative
 * code on failure.
 */
int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{}

EXPORT_SYMBOL();

/**
 * snd_ac97_update_bits - update the bits on the given register
 * @ac97: the ac97 instance
 * @reg: the register to change
 * @mask: the bit-mask to change
 * @value: the value to set
 *
 * Updates the masked-bits on the given register only when the value
 * is changed.
 *
 * Return: 1 if the bits are changed, 0 if no change, or a negative
 * code on failure.
 */
int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
{}

EXPORT_SYMBOL();

/* no lock version - see snd_ac97_update_bits() */
int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
				unsigned short mask, unsigned short value)
{}

static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, unsigned short mask, unsigned short value)
{}

/*
 * Controls
 */

static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_info *uinfo)
{}

static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{}

/* save/restore ac97 v2.3 paging */
static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontrol *kcontrol)
{}

static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save)
{}

/* volume and switch controls */
static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_info *uinfo)
{}

static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new snd_ac97_controls_tone[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =;


static const char* std_rec_sel[] =;
static const char* std_3d_path[] =;
static const char* std_mix[] =;
static const char* std_mic[] =;

static const struct ac97_enum std_enum[] =;

static const struct snd_kcontrol_new snd_ac97_control_capture_src =; 

static const struct snd_kcontrol_new snd_ac97_control_capture_vol =;

static const struct snd_kcontrol_new snd_ac97_controls_mic_capture[2] =;

enum {};

static const struct snd_kcontrol_new snd_ac97_controls_general[7] =;

static const struct snd_kcontrol_new snd_ac97_controls_3d[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_center[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_lfe[2] =;

static const struct snd_kcontrol_new snd_ac97_control_eapd =;

static const struct snd_kcontrol_new snd_ac97_controls_modem_switches[2] =;

/* change the existing EAPD control as inverted */
static void set_inv_eapd(struct snd_ac97 *ac97, struct snd_kcontrol *kctl)
{}

static int snd_ac97_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{}
                        
static int snd_ac97_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}
                        
static int snd_ac97_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}
                        
static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] =;

#define AD18XX_PCM_BITS(xname, codec, lshift, rshift, mask)

static int snd_ac97_ad18xx_pcm_info_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{}

static int snd_ac97_ad18xx_pcm_get_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_ad18xx_pcm_put_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

#define AD18XX_PCM_VOLUME(xname, codec)

static int snd_ac97_ad18xx_pcm_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{}

static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static int snd_ac97_ad18xx_pcm_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_pcm[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_surround[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_center[2] =;

static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_lfe[2] =;

/*
 *
 */

static void snd_ac97_powerdown(struct snd_ac97 *ac97);

static int snd_ac97_bus_free(struct snd_ac97_bus *bus)
{}

static int snd_ac97_bus_dev_free(struct snd_device *device)
{}

static int snd_ac97_free(struct snd_ac97 *ac97)
{}

static int snd_ac97_dev_free(struct snd_device *device)
{}

static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
{}

static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max)
{}

static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit)
{}

/* check the volume resolution of center/lfe */
static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int shift, unsigned char *max)
{}

static inline int printable(unsigned int x)
{}

static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template,
					  struct snd_ac97 * ac97)
{}

/*
 * create mute switch(es) for normal stereo controls
 */
static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg,
				     int check_stereo, int check_amix,
				     struct snd_ac97 *ac97)
{}

/*
 * set dB information
 */
static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);

static const unsigned int *find_db_scale(unsigned int maxval)
{}

static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv)
{}

/*
 * create a volume for normal stereo/mono controls
 */
static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max,
			     unsigned int hi_max, struct snd_ac97 *ac97)
{}

/*
 * create a mute-switch and a volume for normal stereo/mono controls
 */
static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx,
				    int reg, int check_stereo, int check_amix,
				    struct snd_ac97 *ac97)
{}

#define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97)
#define snd_ac97_cmute_new(card, name, reg, acheck, ac97)

static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97);

static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
{}

static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97)
{}

static int snd_ac97_test_rate(struct snd_ac97 *ac97, int reg, int shadow_reg, int rate)
{}

static void snd_ac97_determine_rates(struct snd_ac97 *ac97, int reg, int shadow_reg, unsigned int *r_result)
{}

/* check AC97_SPDIF register to accept which sample rates */
static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97)
{}

/* look for the codec id table matching with the given id */
static const struct ac97_codec_id *look_for_codec_id(const struct ac97_codec_id *table,
						     unsigned int id)
{}

void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem)
{}

/**
 * snd_ac97_get_short_name - retrieve codec name
 * @ac97: the codec instance
 *
 * Return: The short identifying name of the codec.
 */
const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
{}

EXPORT_SYMBOL();

/* wait for a while until registers are accessible after RESET
 * return 0 if ok, negative not ready
 */
static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
{}

/**
 * snd_ac97_bus - create an AC97 bus component
 * @card: the card instance
 * @num: the bus number
 * @ops: the bus callbacks table
 * @private_data: private data pointer for the new instance
 * @rbus: the pointer to store the new AC97 bus instance.
 *
 * Creates an AC97 bus component.  An struct snd_ac97_bus instance is newly
 * allocated and initialized.
 *
 * The ops table must include valid callbacks (at least read and
 * write).  The other callbacks, wait and reset, are not mandatory.
 * 
 * The clock is set to 48000.  If another clock is needed, set
 * ``(*rbus)->clock`` manually.
 *
 * The AC97 bus instance is registered as a low-level device, so you don't
 * have to release it manually.
 *
 * Return: Zero if successful, or a negative error code on failure.
 */
int snd_ac97_bus(struct snd_card *card, int num,
		 const struct snd_ac97_bus_ops *ops,
		 void *private_data, struct snd_ac97_bus **rbus)
{}

EXPORT_SYMBOL();

/* stop no dev release warning */
static void ac97_device_release(struct device * dev)
{}

/* register ac97 codec to bus */
static int snd_ac97_dev_register(struct snd_device *device)
{}

/* disconnect ac97 codec */
static int snd_ac97_dev_disconnect(struct snd_device *device)
{}

/* build_ops to do nothing */
static const struct snd_ac97_build_ops null_build_ops;

#ifdef CONFIG_SND_AC97_POWER_SAVE
static void do_update_power(struct work_struct *work)
{}
#endif

/**
 * snd_ac97_mixer - create an Codec97 component
 * @bus: the AC97 bus which codec is attached to
 * @template: the template of ac97, including index, callbacks and
 *         the private data.
 * @rac97: the pointer to store the new ac97 instance.
 *
 * Creates an Codec97 component.  An struct snd_ac97 instance is newly
 * allocated and initialized from the template.  The codec
 * is then initialized by the standard procedure.
 *
 * The template must include the codec number (num) and address (addr),
 * and the private data (private_data).
 * 
 * The ac97 instance is registered as a low-level device, so you don't
 * have to release it manually.
 *
 * Return: Zero if successful, or a negative error code on failure.
 */
int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
{}

EXPORT_SYMBOL();

/*
 * Power down the chip.
 *
 * MASTER and HEADPHONE registers are muted but the register cache values
 * are not changed, so that the values can be restored in snd_ac97_resume().
 */
static void snd_ac97_powerdown(struct snd_ac97 *ac97)
{}


struct ac97_power_reg {};

enum {};

static const struct ac97_power_reg power_regs[PWIDX_SIZE] =;

#ifdef CONFIG_SND_AC97_POWER_SAVE
/**
 * snd_ac97_update_power - update the powerdown register
 * @ac97: the codec instance
 * @reg: the rate register, e.g. AC97_PCM_FRONT_DAC_RATE
 * @powerup: non-zero when power up the part
 *
 * Update the AC97 powerdown register bits of the given part.
 *
 * Return: Zero.
 */
int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
{}

EXPORT_SYMBOL();
#endif /* CONFIG_SND_AC97_POWER_SAVE */

static void update_power_regs(struct snd_ac97 *ac97)
{}


#ifdef CONFIG_PM
/**
 * snd_ac97_suspend - General suspend function for AC97 codec
 * @ac97: the ac97 instance
 *
 * Suspends the codec, power down the chip.
 */
void snd_ac97_suspend(struct snd_ac97 *ac97)
{}

EXPORT_SYMBOL();

/*
 * restore ac97 status
 */
static void snd_ac97_restore_status(struct snd_ac97 *ac97)
{}

/*
 * restore IEC958 status
 */
static void snd_ac97_restore_iec958(struct snd_ac97 *ac97)
{}

/**
 * snd_ac97_resume - General resume function for AC97 codec
 * @ac97: the ac97 instance
 *
 * Do the standard resume procedure, power up and restoring the
 * old register values.
 */
void snd_ac97_resume(struct snd_ac97 *ac97)
{}

EXPORT_SYMBOL();
#endif


/*
 * Hardware tuning
 */
static void set_ctl_name(char *dst, const char *src, const char *suffix)
{}

/* remove the control with the given name and optional suffix */
static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name,
			       const char *suffix)
{}

static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, const char *suffix)
{}

/* rename the control with the given name and optional suffix */
static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src,
			       const char *dst, const char *suffix)
{}

/* rename both Volume and Switch controls - don't check the return value */
static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src,
				    const char *dst)
{}

/* swap controls */
static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1,
			     const char *s2, const char *suffix)
{}

#if 1
/* bind hp and master controls instead of using only hp control */
static int bind_hp_volsw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

/* ac97 tune: bind Master and Headphone controls */
static int tune_hp_only(struct snd_ac97 *ac97)
{}

#else
/* ac97 tune: use Headphone control as master */
static int tune_hp_only(struct snd_ac97 *ac97)
{
	if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
		return -ENOENT;
	snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
	snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
	return 0;
}
#endif

/* ac97 tune: swap Headphone and Master controls */
static int tune_swap_hp(struct snd_ac97 *ac97)
{}

/* ac97 tune: swap Surround and Master controls */
static int tune_swap_surround(struct snd_ac97 *ac97)
{}

/* ac97 tune: set up mic sharing for AD codecs */
static int tune_ad_sharing(struct snd_ac97 *ac97)
{}

static const struct snd_kcontrol_new snd_ac97_alc_jack_detect =;

/* ac97 tune: set up ALC jack-select */
static int tune_alc_jack(struct snd_ac97 *ac97)
{}

/* ac97 tune: inversed EAPD bit */
static int tune_inv_eapd(struct snd_ac97 *ac97)
{}

static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

/* ac97 tune: EAPD controls mute LED bound with the master mute */
static int tune_mute_led(struct snd_ac97 *ac97)
{}

static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{}

static int tune_hp_mute_led(struct snd_ac97 *ac97)
{}

struct quirk_table {};

static const struct quirk_table applicable_quirks[] =;

/* apply the quirk with the given type */
static int apply_quirk(struct snd_ac97 *ac97, int type)
{}

/* apply the quirk with the given name */
static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
{}

/**
 * snd_ac97_tune_hardware - tune up the hardware
 * @ac97: the ac97 instance
 * @quirk: quirk list
 * @override: explicit quirk value (overrides the list if non-NULL)
 *
 * Do some workaround for each pci device, such as renaming of the
 * headphone (true line-out) control as "Master".
 * The quirk-list must be terminated with a zero-filled entry.
 *
 * Return: Zero if successful, or a negative error code on failure.
 */

int snd_ac97_tune_hardware(struct snd_ac97 *ac97,
			   const struct ac97_quirk *quirk, const char *override)
{}

EXPORT_SYMBOL();