210 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2#ifndef __SOUND_WM8776_H3#define __SOUND_WM8776_H4 5/*6 * ALSA driver for ICEnsemble VT17xx7 *8 * Lowlevel functions for WM8776 codec9 *10 * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>11 */12 13#define WM8776_REG_HPLVOL 0x0014#define WM8776_REG_HPRVOL 0x0115#define WM8776_REG_HPMASTER 0x0216#define WM8776_HPVOL_MASK 0x17f /* incl. update bit */17#define WM8776_VOL_HPZCEN (1 << 7) /* zero cross detect */18#define WM8776_VOL_UPDATE (1 << 8) /* update volume */19#define WM8776_REG_DACLVOL 0x0320#define WM8776_REG_DACRVOL 0x0421#define WM8776_REG_DACMASTER 0x0522#define WM8776_DACVOL_MASK 0x1ff /* incl. update bit */23#define WM8776_REG_PHASESWAP 0x0624#define WM8776_PHASE_INVERTL (1 << 0)25#define WM8776_PHASE_INVERTR (1 << 1)26#define WM8776_REG_DACCTRL1 0x0727#define WM8776_DAC_DZCEN (1 << 0)28#define WM8776_DAC_ATC (1 << 1)29#define WM8776_DAC_IZD (1 << 2)30#define WM8776_DAC_TOD (1 << 3)31#define WM8776_DAC_PL_MASK 0xf032#define WM8776_DAC_PL_LL (1 << 4) /* L chan: L signal */33#define WM8776_DAC_PL_LR (2 << 4) /* L chan: R signal */34#define WM8776_DAC_PL_LB (3 << 4) /* L chan: both */35#define WM8776_DAC_PL_RL (1 << 6) /* R chan: L signal */36#define WM8776_DAC_PL_RR (2 << 6) /* R chan: R signal */37#define WM8776_DAC_PL_RB (3 << 6) /* R chan: both */38#define WM8776_REG_DACMUTE 0x0839#define WM8776_DACMUTE (1 << 0)40#define WM8776_REG_DACCTRL2 0x0941#define WM8776_DAC2_DEEMPH (1 << 0)42#define WM8776_DAC2_ZFLAG_DISABLE (0 << 1)43#define WM8776_DAC2_ZFLAG_OWN (1 << 1)44#define WM8776_DAC2_ZFLAG_BOTH (2 << 1)45#define WM8776_DAC2_ZFLAG_EITHER (3 << 1)46#define WM8776_REG_DACIFCTRL 0x0a47#define WM8776_FMT_RIGHTJ (0 << 0)48#define WM8776_FMT_LEFTJ (1 << 0)49#define WM8776_FMT_I2S (2 << 0)50#define WM8776_FMT_DSP (3 << 0)51#define WM8776_FMT_DSP_LATE (1 << 2) /* in DSP mode */52#define WM8776_FMT_LRC_INVERTED (1 << 2) /* in other modes */53#define WM8776_FMT_BCLK_INVERTED (1 << 3)54#define WM8776_FMT_16BIT (0 << 4)55#define WM8776_FMT_20BIT (1 << 4)56#define WM8776_FMT_24BIT (2 << 4)57#define WM8776_FMT_32BIT (3 << 4)58#define WM8776_REG_ADCIFCTRL 0x0b59#define WM8776_FMT_ADCMCLK_INVERTED (1 << 6)60#define WM8776_FMT_ADCHPD (1 << 8)61#define WM8776_REG_MSTRCTRL 0x0c62#define WM8776_IF_ADC256FS (2 << 0)63#define WM8776_IF_ADC384FS (3 << 0)64#define WM8776_IF_ADC512FS (4 << 0)65#define WM8776_IF_ADC768FS (5 << 0)66#define WM8776_IF_OVERSAMP64 (1 << 3)67#define WM8776_IF_DAC128FS (0 << 4)68#define WM8776_IF_DAC192FS (1 << 4)69#define WM8776_IF_DAC256FS (2 << 4)70#define WM8776_IF_DAC384FS (3 << 4)71#define WM8776_IF_DAC512FS (4 << 4)72#define WM8776_IF_DAC768FS (5 << 4)73#define WM8776_IF_DAC_MASTER (1 << 7)74#define WM8776_IF_ADC_MASTER (1 << 8)75#define WM8776_REG_PWRDOWN 0x0d76#define WM8776_PWR_PDWN (1 << 0)77#define WM8776_PWR_ADCPD (1 << 1)78#define WM8776_PWR_DACPD (1 << 2)79#define WM8776_PWR_HPPD (1 << 3)80#define WM8776_PWR_AINPD (1 << 6)81#define WM8776_REG_ADCLVOL 0x0e82#define WM8776_REG_ADCRVOL 0x0f83#define WM8776_ADC_GAIN_MASK 0xff84#define WM8776_ADC_ZCEN (1 << 8)85#define WM8776_REG_ALCCTRL1 0x1086#define WM8776_ALC1_LCT_MASK 0x0f /* 0=-16dB, 1=-15dB..15=-1dB */87#define WM8776_ALC1_MAXGAIN_MASK 0x70 /* 0,1=0dB, 2=+4dB...7=+24dB */88#define WM8776_ALC1_LCSEL_MASK 0x18089#define WM8776_ALC1_LCSEL_LIMITER (0 << 7)90#define WM8776_ALC1_LCSEL_ALCR (1 << 7)91#define WM8776_ALC1_LCSEL_ALCL (2 << 7)92#define WM8776_ALC1_LCSEL_ALCSTEREO (3 << 7)93#define WM8776_REG_ALCCTRL2 0x1194#define WM8776_ALC2_HOLD_MASK 0x0f /*0=0ms, 1=2.67ms, 2=5.33ms.. */95#define WM8776_ALC2_ZCEN (1 << 7)96#define WM8776_ALC2_LCEN (1 << 8)97#define WM8776_REG_ALCCTRL3 0x1298#define WM8776_ALC3_ATK_MASK 0x0f99#define WM8776_ALC3_DCY_MASK 0xf0100#define WM8776_ALC3_FDECAY (1 << 8)101#define WM8776_REG_NOISEGATE 0x13102#define WM8776_NGAT_ENABLE (1 << 0)103#define WM8776_NGAT_THR_MASK 0x1c /*0=-78dB, 1=-72dB...7=-36dB */104#define WM8776_REG_LIMITER 0x14105#define WM8776_LIM_MAXATTEN_MASK 0x0f106#define WM8776_LIM_TRANWIN_MASK 0x70 /*0=0us, 1=62.5us, 2=125us.. */107#define WM8776_REG_ADCMUX 0x15108#define WM8776_ADC_MUX_AIN1 (1 << 0)109#define WM8776_ADC_MUX_AIN2 (1 << 1)110#define WM8776_ADC_MUX_AIN3 (1 << 2)111#define WM8776_ADC_MUX_AIN4 (1 << 3)112#define WM8776_ADC_MUX_AIN5 (1 << 4)113#define WM8776_ADC_MUTER (1 << 6)114#define WM8776_ADC_MUTEL (1 << 7)115#define WM8776_ADC_LRBOTH (1 << 8)116#define WM8776_REG_OUTMUX 0x16117#define WM8776_OUTMUX_DAC (1 << 0)118#define WM8776_OUTMUX_AUX (1 << 1)119#define WM8776_OUTMUX_BYPASS (1 << 2)120#define WM8776_REG_RESET 0x17121 122#define WM8776_REG_COUNT 0x17 /* don't cache the RESET register */123 124struct snd_wm8776;125 126struct snd_wm8776_ops {127 void (*write)(struct snd_wm8776 *wm, u8 addr, u8 data);128};129 130enum snd_wm8776_ctl_id {131 WM8776_CTL_DAC_VOL,132 WM8776_CTL_DAC_SW,133 WM8776_CTL_DAC_ZC_SW,134 WM8776_CTL_HP_VOL,135 WM8776_CTL_HP_SW,136 WM8776_CTL_HP_ZC_SW,137 WM8776_CTL_AUX_SW,138 WM8776_CTL_BYPASS_SW,139 WM8776_CTL_DAC_IZD_SW,140 WM8776_CTL_PHASE_SW,141 WM8776_CTL_DEEMPH_SW,142 WM8776_CTL_ADC_VOL,143 WM8776_CTL_ADC_SW,144 WM8776_CTL_INPUT1_SW,145 WM8776_CTL_INPUT2_SW,146 WM8776_CTL_INPUT3_SW,147 WM8776_CTL_INPUT4_SW,148 WM8776_CTL_INPUT5_SW,149 WM8776_CTL_AGC_SEL,150 WM8776_CTL_LIM_THR,151 WM8776_CTL_LIM_ATK,152 WM8776_CTL_LIM_DCY,153 WM8776_CTL_LIM_TRANWIN,154 WM8776_CTL_LIM_MAXATTN,155 WM8776_CTL_ALC_TGT,156 WM8776_CTL_ALC_ATK,157 WM8776_CTL_ALC_DCY,158 WM8776_CTL_ALC_MAXGAIN,159 WM8776_CTL_ALC_MAXATTN,160 WM8776_CTL_ALC_HLD,161 WM8776_CTL_NGT_SW,162 WM8776_CTL_NGT_THR,163 164 WM8776_CTL_COUNT,165};166 167#define WM8776_ENUM_MAX 16168 169#define WM8776_FLAG_STEREO (1 << 0)170#define WM8776_FLAG_VOL_UPDATE (1 << 1)171#define WM8776_FLAG_INVERT (1 << 2)172#define WM8776_FLAG_LIM (1 << 3)173#define WM8776_FLAG_ALC (1 << 4)174 175struct snd_wm8776_ctl {176 const char *name;177 snd_ctl_elem_type_t type;178 const char *const enum_names[WM8776_ENUM_MAX];179 const unsigned int *tlv;180 u16 reg1, reg2, mask1, mask2, min, max, flags;181 void (*set)(struct snd_wm8776 *wm, u16 ch1, u16 ch2);182 void (*get)(struct snd_wm8776 *wm, u16 *ch1, u16 *ch2);183};184 185enum snd_wm8776_agc_mode {186 WM8776_AGC_OFF,187 WM8776_AGC_LIM,188 WM8776_AGC_ALC_R,189 WM8776_AGC_ALC_L,190 WM8776_AGC_ALC_STEREO191};192 193struct snd_wm8776 {194 struct snd_card *card;195 struct snd_wm8776_ctl ctl[WM8776_CTL_COUNT];196 enum snd_wm8776_agc_mode agc_mode;197 struct snd_wm8776_ops ops;198 u16 regs[WM8776_REG_COUNT]; /* 9-bit registers */199};200 201 202 203void snd_wm8776_init(struct snd_wm8776 *wm);204void snd_wm8776_resume(struct snd_wm8776 *wm);205void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power);206void snd_wm8776_volume_restore(struct snd_wm8776 *wm);207int snd_wm8776_build_controls(struct snd_wm8776 *wm);208 209#endif /* __SOUND_WM8776_H */210