#include <sys/types.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/audio/audio_driver.h>
#include <sys/audio/ac97.h>
#include <sys/note.h>
#include "ac97_impl.h"
#define ADS_EQ_CTRL_REGISTER 0x60
#define AECR_EQM 0x8000
#define AECR_SYM 0x0080
#define ADS_EQ_DATA_REGISTER 0x62
#define ADS_MIXER_ADC_IGAIN_REGISTER 0x64
#define AMADIR_LEFT_MASK 0x0f00
#define AMADIR_RIGHT_MASK 0x000f
#define AMADIR_MXM 0x8000
#define ADS_JS_INTS_STATUS_REGISTER 0x72
#define AJISR_JS0INT 0x0001
#define AJISR_JS1INT 0x0002
#define AJISR_JS0ST 0x0004
#define AJISR_JS1ST 0x0008
#define AJISR_JS0MD 0x0010
#define AJISR_JS1MD 0x0020
#define AJISR_JS0TMR 0x0040
#define AJISR_JS1TMR 0x0080
#define AJISR_JS0EQB 0x0100
#define AJISR_JS1EQB 0x0200
#define AJISR_JSMT_MASK 0x1c00
#define AJISR_JSMT_NONE 0x0000
#define AJISR_JSMT_HP_LNOUT 0x0400
#define AJISR_JSMT_HP_BOTH 0x0800
#define AJISR_JSMT_LNOUT_MONO 0x1000
#define AJISR_JSMT_ALL 0x1800
#define ADS_SERIAL_CFG_REGISTER 0x74
#define ASCR_SPLNK 0x0001
#define ASCR_SPDZ 0x0002
#define ASCR_SPAL 0x0004
#define ASCR_INTS 0x0010
#define ASCR_CHEN 0x0100
#define ASCR_REGM0 0x1000
#define ASCR_REGM1 0x2000
#define ASCR_REGM2 0x4000
#define ASCR_SLOT16 0x8000
#define ADS_MISC_CFG_REGISTER 0x76
#define AMCR_MBG_MASK 0x0003
#define AMCR_MBG_20dB 0x0000
#define AMCR_MBG_10dB 0x0001
#define AMCR_MBG_30dB 0x0002
#define AMCR_VREFD 0x0004
#define AMCR_VREFH 0x0008
#define AMCR_MADST 0x0010
#define AMCR_SRU 0x0010
#define AMCR_LOSEL 0x0020
#define AMCR_2CMIC 0x0040
#define AMCR_MADPD 0x0080
#define AMCR_SPRD 0x0080
#define AMCR_DMIX_6TO2 0x0100
#define AMCR_DMIX_FORCE 0x0200
#define AMCR_FMXE 0x0200
#define AMCR_HPSEL 0x0400
#define AMCR_CLDIS 0x0800
#define AMCR_LODIS 0x1000
#define AMCR_DAM 0x0800
#define AMCR_MSPLT 0x2000
#define AMCR_AC97NC 0x4000
#define AMCR_DACZ 0x8000
static void
ads_set_micboost(ac97_ctrl_t *actrl, uint64_t value)
{
ac97_t *ac = actrl->actrl_ac97;
uint16_t v;
ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0);
switch (value) {
case 0x1:
ac_clr(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST);
break;
case 0x2:
ac_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST);
v = ac_rd(ac, ADS_MISC_CFG_REGISTER);
v &= ~AMCR_MBG_MASK;
v |= AMCR_MBG_10dB;
ac_wr(ac, ADS_MISC_CFG_REGISTER, v);
break;
case 0x4:
ac_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST);
v = ac_rd(ac, ADS_MISC_CFG_REGISTER);
v &= ~AMCR_MBG_MASK;
v |= AMCR_MBG_20dB;
ac_wr(ac, ADS_MISC_CFG_REGISTER, v);
break;
case 0x8:
ac_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST);
v = ac_rd(ac, ADS_MISC_CFG_REGISTER);
v &= ~AMCR_MBG_MASK;
v |= AMCR_MBG_30dB;
ac_wr(ac, ADS_MISC_CFG_REGISTER, v);
break;
}
}
static void
ads_set_micsrc(ac97_ctrl_t *actrl, uint64_t value)
{
ac97_t *ac = actrl->actrl_ac97;
ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0);
switch (value) {
case 0x1:
ac_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC);
ac_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2);
break;
case 0x2:
ac_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC);
ac_set(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2);
break;
case 0x4:
ac_set(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC);
ac_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2);
break;
}
}
static void
ads_setup_micsrc(ac97_t *ac)
{
static const char *values[] = {
AUDIO_PORT_MIC1,
AUDIO_PORT_MIC2,
AUDIO_PORT_STEREO,
NULL
};
ac97_ctrl_probe_t cpt = {
AUDIO_CTRL_ID_MICSRC, 1, 0x7, 0x7, AUDIO_CTRL_TYPE_ENUM,
AC97_FLAGS | AUDIO_CTRL_FLAG_REC, 0, ads_set_micsrc,
NULL, 0, values };
ac_add_control(ac, &cpt);
}
static void
ads_setup_micboost(ac97_t *ac)
{
ac97_ctrl_t *ctrl;
static const char *values[] = {
AUDIO_VALUE_OFF,
AUDIO_VALUE_LOW,
AUDIO_VALUE_MEDIUM,
AUDIO_VALUE_HIGH,
NULL
};
ac97_ctrl_probe_t cpt = {
AUDIO_CTRL_ID_MICBOOST, 1, 0xf, 0xf, AUDIO_CTRL_TYPE_ENUM,
AC97_FLAGS | AUDIO_CTRL_FLAG_REC, 0, ads_set_micboost,
NULL, 0, values };
ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_MICBOOST);
if (ctrl) {
if (ctrl->actrl_initval) {
cpt.cp_initval = 2;
}
}
ac_add_control(ac, &cpt);
}
void
ad1981a_init(ac97_t *ac)
{
ads_setup_micboost(ac);
}
void
ad1981b_init(ac97_t *ac)
{
ads_setup_micboost(ac);
ads_setup_micsrc(ac);
}