422 lines · c
1/* SPDX-License-Identifier: GPL-2.0+2 *3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>4 * Universal interface for Audio Codec '975 *6 * For more details look to AC '97 component specification revision 2.17 * by Intel Corporation (http://developer.intel.com).8 */9 10#ifndef __SOUND_AC97_CODEC_H11#define __SOUND_AC97_CODEC_H12 13#include <linux/bitops.h>14#include <linux/device.h>15#include <linux/workqueue.h>16#include <sound/ac97/regs.h>17#include <sound/pcm.h>18#include <sound/control.h>19#include <sound/info.h>20 21/* maximum number of devices on the AC97 bus */22#define AC97_BUS_MAX_DEVICES 423 24/* specific - SigmaTel */25#define AC97_SIGMATEL_OUTSEL 0x64 /* Output Select, STAC9758 */26#define AC97_SIGMATEL_INSEL 0x66 /* Input Select, STAC9758 */27#define AC97_SIGMATEL_IOMISC 0x68 /* STAC9758 */28#define AC97_SIGMATEL_ANALOG 0x6c /* Analog Special */29#define AC97_SIGMATEL_DAC2INVERT 0x6e30#define AC97_SIGMATEL_BIAS1 0x7031#define AC97_SIGMATEL_BIAS2 0x7232#define AC97_SIGMATEL_VARIOUS 0x72 /* STAC9758 */33#define AC97_SIGMATEL_MULTICHN 0x74 /* Multi-Channel programming */34#define AC97_SIGMATEL_CIC1 0x7635#define AC97_SIGMATEL_CIC2 0x7836 37/* specific - Analog Devices */38#define AC97_AD_TEST 0x5a /* test register */39#define AC97_AD_TEST2 0x5c /* undocumented test register 2 */40#define AC97_AD_HPFD_SHIFT 12 /* High Pass Filter Disable */41#define AC97_AD_CODEC_CFG 0x70 /* codec configuration */42#define AC97_AD_JACK_SPDIF 0x72 /* Jack Sense & S/PDIF */43#define AC97_AD_SERIAL_CFG 0x74 /* Serial Configuration */44#define AC97_AD_MISC 0x76 /* Misc Control Bits */45#define AC97_AD_VREFD_SHIFT 2 /* V_REFOUT Disable (AD1888) */46 47/* specific - Cirrus Logic */48#define AC97_CSR_ACMODE 0x5e /* AC Mode Register */49#define AC97_CSR_MISC_CRYSTAL 0x60 /* Misc Crystal Control */50#define AC97_CSR_SPDIF 0x68 /* S/PDIF Register */51#define AC97_CSR_SERIAL 0x6a /* Serial Port Control */52#define AC97_CSR_SPECF_ADDR 0x6c /* Special Feature Address */53#define AC97_CSR_SPECF_DATA 0x6e /* Special Feature Data */54#define AC97_CSR_BDI_STATUS 0x7a /* BDI Status */55 56/* specific - Conexant */57#define AC97_CXR_AUDIO_MISC 0x5c58#define AC97_CXR_SPDIFEN (1<<3)59#define AC97_CXR_COPYRGT (1<<2)60#define AC97_CXR_SPDIF_MASK (3<<0)61#define AC97_CXR_SPDIF_PCM 0x062#define AC97_CXR_SPDIF_AC3 0x263 64/* specific - ALC */65#define AC97_ALC650_SPDIF_INPUT_STATUS1 0x6066/* S/PDIF input status 1 bit defines */67#define AC97_ALC650_PRO 0x0001 /* Professional status */68#define AC97_ALC650_NAUDIO 0x0002 /* Non audio stream */69#define AC97_ALC650_COPY 0x0004 /* Copyright status */70#define AC97_ALC650_PRE 0x0038 /* Preemphasis status */71#define AC97_ALC650_PRE_SHIFT 372#define AC97_ALC650_MODE 0x00C0 /* Preemphasis status */73#define AC97_ALC650_MODE_SHIFT 674#define AC97_ALC650_CC_MASK 0x7f00 /* Category Code mask */75#define AC97_ALC650_CC_SHIFT 876#define AC97_ALC650_L 0x8000 /* Generation Level status */77 78#define AC97_ALC650_SPDIF_INPUT_STATUS2 0x6279/* S/PDIF input status 2 bit defines */80#define AC97_ALC650_SOUCE_MASK 0x000f /* Source number */81#define AC97_ALC650_CHANNEL_MASK 0x00f0 /* Channel number */82#define AC97_ALC650_CHANNEL_SHIFT 4 83#define AC97_ALC650_SPSR_MASK 0x0f00 /* S/PDIF Sample Rate bits */84#define AC97_ALC650_SPSR_SHIFT 885#define AC97_ALC650_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */86#define AC97_ALC650_SPSR_48K 0x0200 /* Use 48kHz Sample rate */87#define AC97_ALC650_SPSR_32K 0x0300 /* Use 32kHz Sample rate */88#define AC97_ALC650_CLOCK_ACCURACY 0x3000 /* Clock accuracy */89#define AC97_ALC650_CLOCK_SHIFT 1290#define AC97_ALC650_CLOCK_LOCK 0x4000 /* Clock locked status */91#define AC97_ALC650_V 0x8000 /* Validity status */92 93#define AC97_ALC650_SURR_DAC_VOL 0x6494#define AC97_ALC650_LFE_DAC_VOL 0x6695#define AC97_ALC650_UNKNOWN1 0x6896#define AC97_ALC650_MULTICH 0x6a97#define AC97_ALC650_UNKNOWN2 0x6c98#define AC97_ALC650_REVISION 0x6e99#define AC97_ALC650_UNKNOWN3 0x70100#define AC97_ALC650_UNKNOWN4 0x72101#define AC97_ALC650_MISC 0x74102#define AC97_ALC650_GPIO_SETUP 0x76103#define AC97_ALC650_GPIO_STATUS 0x78104#define AC97_ALC650_CLOCK 0x7a105 106/* specific - Yamaha YMF7x3 */107#define AC97_YMF7X3_DIT_CTRL 0x66 /* DIT Control (YMF743) / 2 (YMF753) */108#define AC97_YMF7X3_3D_MODE_SEL 0x68 /* 3D Mode Select */109 110/* specific - C-Media */111#define AC97_CM9738_VENDOR_CTRL 0x5a112#define AC97_CM9739_MULTI_CHAN 0x64113#define AC97_CM9739_SPDIF_IN_STATUS 0x68 /* 32bit */114#define AC97_CM9739_SPDIF_CTRL 0x6c115 116/* specific - wolfson */117#define AC97_WM97XX_FMIXER_VOL 0x72118#define AC97_WM9704_RMIXER_VOL 0x74119#define AC97_WM9704_TEST 0x5a120#define AC97_WM9704_RPCM_VOL 0x70121#define AC97_WM9711_OUT3VOL 0x16122 123 124/* ac97->scaps */125#define AC97_SCAP_AUDIO (1<<0) /* audio codec 97 */126#define AC97_SCAP_MODEM (1<<1) /* modem codec 97 */127#define AC97_SCAP_SURROUND_DAC (1<<2) /* surround L&R DACs are present */128#define AC97_SCAP_CENTER_LFE_DAC (1<<3) /* center and LFE DACs are present */129#define AC97_SCAP_SKIP_AUDIO (1<<4) /* skip audio part of codec */130#define AC97_SCAP_SKIP_MODEM (1<<5) /* skip modem part of codec */131#define AC97_SCAP_INDEP_SDIN (1<<6) /* independent SDIN */132#define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */133#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */134#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */135#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */136#define AC97_SCAP_POWER_SAVE (1<<11) /* capable for aggressive power-saving */137 138/* ac97->flags */139#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */140#define AC97_AD_MULTI (1<<1) /* Analog Devices - multi codecs */141#define AC97_CS_SPDIF (1<<2) /* Cirrus Logic uses funky SPDIF */142#define AC97_CX_SPDIF (1<<3) /* Conexant's spdif interface */143#define AC97_STEREO_MUTES (1<<4) /* has stereo mute bits */144#define AC97_DOUBLE_RATE (1<<5) /* supports double rate playback */145#define AC97_HAS_NO_MASTER_VOL (1<<6) /* no Master volume */146#define AC97_HAS_NO_PCM_VOL (1<<7) /* no PCM volume */147#define AC97_DEFAULT_POWER_OFF (1<<8) /* no RESET write */148#define AC97_MODEM_PATCH (1<<9) /* modem patch */149#define AC97_HAS_NO_REC_GAIN (1<<10) /* no Record gain */150#define AC97_HAS_NO_PHONE (1<<11) /* no PHONE volume */151#define AC97_HAS_NO_PC_BEEP (1<<12) /* no PC Beep volume */152#define AC97_HAS_NO_VIDEO (1<<13) /* no Video volume */153#define AC97_HAS_NO_CD (1<<14) /* no CD volume */154#define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */155#define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */156#define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */157#define AC97_HAS_NO_AUX (1<<18) /* no standard AC97 AUX volume and mute */158#define AC97_HAS_8CH (1<<19) /* supports 8-channel output */159 160/* rates indexes */161#define AC97_RATES_FRONT_DAC 0162#define AC97_RATES_SURR_DAC 1163#define AC97_RATES_LFE_DAC 2164#define AC97_RATES_ADC 3165#define AC97_RATES_MIC_ADC 4166#define AC97_RATES_SPDIF 5167 168#define AC97_NUM_GPIOS 16169/*170 *171 */172 173struct snd_ac97;174struct snd_ac97_gpio_priv;175struct snd_pcm_chmap;176 177struct snd_ac97_build_ops {178 int (*build_3d) (struct snd_ac97 *ac97);179 int (*build_specific) (struct snd_ac97 *ac97);180 int (*build_spdif) (struct snd_ac97 *ac97);181 int (*build_post_spdif) (struct snd_ac97 *ac97);182#ifdef CONFIG_PM183 void (*suspend) (struct snd_ac97 *ac97);184 void (*resume) (struct snd_ac97 *ac97);185#endif186 void (*update_jacks) (struct snd_ac97 *ac97); /* for jack-sharing */187};188 189struct snd_ac97_bus_ops {190 void (*reset) (struct snd_ac97 *ac97);191 void (*warm_reset)(struct snd_ac97 *ac97);192 void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);193 unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);194 void (*wait) (struct snd_ac97 *ac97);195 void (*init) (struct snd_ac97 *ac97);196};197 198struct snd_ac97_bus {199 /* -- lowlevel (hardware) driver specific -- */200 const struct snd_ac97_bus_ops *ops;201 void *private_data;202 void (*private_free) (struct snd_ac97_bus *bus);203 /* --- */204 struct snd_card *card;205 unsigned short num; /* bus number */206 unsigned short no_vra: 1, /* bridge doesn't support VRA */207 dra: 1, /* bridge supports double rate */208 isdin: 1;/* independent SDIN */209 unsigned int clock; /* AC'97 base clock (usually 48000Hz) */210 spinlock_t bus_lock; /* used mainly for slot allocation */211 unsigned short used_slots[2][4]; /* actually used PCM slots */212 unsigned short pcms_count; /* count of PCMs */213 struct ac97_pcm *pcms;214 struct snd_ac97 *codec[4];215 struct snd_info_entry *proc;216};217 218/* static resolution table */219struct snd_ac97_res_table {220 unsigned short reg; /* register */221 unsigned short bits; /* resolution bitmask */222};223 224struct snd_ac97_template {225 void *private_data;226 void (*private_free) (struct snd_ac97 *ac97);227 struct pci_dev *pci; /* assigned PCI device - used for quirks */228 unsigned short num; /* number of codec: 0 = primary, 1 = secondary */229 unsigned short addr; /* physical address of codec [0-3] */230 unsigned int scaps; /* driver capabilities */231 const struct snd_ac97_res_table *res_table; /* static resolution */232};233 234struct snd_ac97 {235 /* -- lowlevel (hardware) driver specific -- */236 const struct snd_ac97_build_ops *build_ops;237 void *private_data;238 void (*private_free) (struct snd_ac97 *ac97);239 /* --- */240 struct snd_ac97_bus *bus;241 struct pci_dev *pci; /* assigned PCI device - used for quirks */242 struct snd_info_entry *proc;243 struct snd_info_entry *proc_regs;244 unsigned short subsystem_vendor;245 unsigned short subsystem_device;246 struct mutex reg_mutex;247 struct mutex page_mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */248 unsigned short num; /* number of codec: 0 = primary, 1 = secondary */249 unsigned short addr; /* physical address of codec [0-3] */250 unsigned int id; /* identification of codec */251 unsigned short caps; /* capabilities (register 0) */252 unsigned short ext_id; /* extended feature identification (register 28) */253 unsigned short ext_mid; /* extended modem ID (register 3C) */254 const struct snd_ac97_res_table *res_table; /* static resolution */255 unsigned int scaps; /* driver capabilities */256 unsigned int flags; /* specific code */257 unsigned int rates[6]; /* see AC97_RATES_* defines */258 unsigned int spdif_status;259 unsigned short regs[0x80]; /* register cache */260 DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */261 union { /* vendor specific code */262 struct {263 unsigned short unchained[3]; // 0 = C34, 1 = C79, 2 = C69264 unsigned short chained[3]; // 0 = C34, 1 = C79, 2 = C69265 unsigned short id[3]; // codec IDs (lower 16-bit word)266 unsigned short pcmreg[3]; // PCM registers267 unsigned short codec_cfg[3]; // CODEC_CFG bits268 unsigned char swap_mic_linein; // AD1986/AD1986A only269 unsigned char lo_as_master; /* LO as master */270 } ad18xx;271 unsigned int dev_flags; /* device specific */272 } spec;273 /* jack-sharing info */274 unsigned char indep_surround;275 unsigned char channel_mode;276 277#ifdef CONFIG_SND_AC97_POWER_SAVE278 unsigned int power_up; /* power states */279 struct delayed_work power_work;280#endif281 struct device dev;282 struct snd_ac97_gpio_priv *gpio_priv;283 284 struct snd_pcm_chmap *chmaps[2]; /* channel-maps (optional) */285};286 287#define to_ac97_t(d) container_of(d, struct snd_ac97, dev)288 289/* conditions */290static inline int ac97_is_audio(struct snd_ac97 * ac97)291{292 return (ac97->scaps & AC97_SCAP_AUDIO);293}294static inline int ac97_is_modem(struct snd_ac97 * ac97)295{296 return (ac97->scaps & AC97_SCAP_MODEM);297}298static inline int ac97_is_rev22(struct snd_ac97 * ac97)299{300 return (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_22;301}302static inline int ac97_can_amap(struct snd_ac97 * ac97)303{304 return (ac97->ext_id & AC97_EI_AMAP) != 0;305}306static inline int ac97_can_spdif(struct snd_ac97 * ac97)307{308 return (ac97->ext_id & AC97_EI_SPDIF) != 0;309}310 311/* functions */312/* create new AC97 bus */313int snd_ac97_bus(struct snd_card *card, int num,314 const struct snd_ac97_bus_ops *ops,315 void *private_data, struct snd_ac97_bus **rbus);316/* create mixer controls */317int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,318 struct snd_ac97 **rac97);319const char *snd_ac97_get_short_name(struct snd_ac97 *ac97);320 321void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);322unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg);323void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);324int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);325int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value);326#ifdef CONFIG_SND_AC97_POWER_SAVE327int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup);328#else329static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg,330 int powerup)331{332 return 0;333}334#endif335#ifdef CONFIG_PM336void snd_ac97_suspend(struct snd_ac97 *ac97);337void snd_ac97_resume(struct snd_ac97 *ac97);338#else339static inline void snd_ac97_suspend(struct snd_ac97 *ac97) {}340static inline void snd_ac97_resume(struct snd_ac97 *ac97) {}341#endif342int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,343 unsigned int id_mask);344 345/* quirk types */346enum {347 AC97_TUNE_DEFAULT = -1, /* use default from quirk list (not valid in list) */348 AC97_TUNE_NONE = 0, /* nothing extra to do */349 AC97_TUNE_HP_ONLY, /* headphone (true line-out) control as master only */350 AC97_TUNE_SWAP_HP, /* swap headphone and master controls */351 AC97_TUNE_SWAP_SURROUND, /* swap master and surround controls */352 AC97_TUNE_AD_SHARING, /* for AD1985, turn on OMS bit and use headphone */353 AC97_TUNE_ALC_JACK, /* for Realtek, enable JACK detection */354 AC97_TUNE_INV_EAPD, /* inverted EAPD implementation */355 AC97_TUNE_MUTE_LED, /* EAPD bit works as mute LED */356 AC97_TUNE_HP_MUTE_LED, /* EAPD bit works as mute LED, use headphone control as master */357};358 359struct ac97_quirk {360 unsigned short subvendor; /* PCI subsystem vendor id */361 unsigned short subdevice; /* PCI subsystem device id */362 unsigned short mask; /* device id bit mask, 0 = accept all */363 unsigned int codec_id; /* codec id (if any), 0 = accept all */364 const char *name; /* name shown as info */365 int type; /* quirk type above */366};367 368int snd_ac97_tune_hardware(struct snd_ac97 *ac97,369 const struct ac97_quirk *quirk,370 const char *override);371int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate);372 373/*374 * PCM allocation375 */376 377enum ac97_pcm_cfg {378 AC97_PCM_CFG_FRONT = 2,379 AC97_PCM_CFG_REAR = 10, /* alias surround */380 AC97_PCM_CFG_LFE = 11, /* center + lfe */381 AC97_PCM_CFG_40 = 4, /* front + rear */382 AC97_PCM_CFG_51 = 6, /* front + rear + center/lfe */383 AC97_PCM_CFG_SPDIF = 20384};385 386struct ac97_pcm {387 struct snd_ac97_bus *bus;388 unsigned int stream: 1, /* stream type: 1 = capture */389 exclusive: 1, /* exclusive mode, don't override with other pcms */390 copy_flag: 1, /* lowlevel driver must fill all entries */391 spdif: 1; /* spdif pcm */392 unsigned short aslots; /* active slots */393 unsigned short cur_dbl; /* current double-rate state */394 unsigned int rates; /* available rates */395 struct {396 unsigned short slots; /* driver input: requested AC97 slot numbers */397 unsigned short rslots[4]; /* allocated slots per codecs */398 unsigned char rate_table[4];399 struct snd_ac97 *codec[4]; /* allocated codecs */400 } r[2]; /* 0 = standard rates, 1 = double rates */401 unsigned long private_value; /* used by the hardware driver */402};403 404int snd_ac97_pcm_assign(struct snd_ac97_bus *ac97,405 unsigned short pcms_count,406 const struct ac97_pcm *pcms);407int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,408 enum ac97_pcm_cfg cfg, unsigned short slots);409int snd_ac97_pcm_close(struct ac97_pcm *pcm);410int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime);411 412/* ad hoc AC97 device driver access */413extern const struct bus_type ac97_bus_type;414 415/* AC97 platform_data adding function */416static inline void snd_ac97_dev_add_pdata(struct snd_ac97 *ac97, void *data)417{418 ac97->dev.platform_data = data;419}420 421#endif /* __SOUND_AC97_CODEC_H */422