Mercurial > illumos > illumos-gate
changeset 10413:63f6889c8957
PSARC 2009/466 AC'97 DDI Update
6877310 Deliver PSARC 2009/466 AC'97 DDI Updates
author | Garrett D'Amore <Garrett.Damore@Sun.COM> |
---|---|
date | Sun, 30 Aug 2009 15:32:09 -0700 |
parents | 270d6665fb95 |
children | dc0ac18317a0 |
files | usr/src/uts/common/io/audio/ac97/ac97.c usr/src/uts/common/io/audio/ac97/ac97_ad.c usr/src/uts/common/io/audio/ac97/ac97_alc.c usr/src/uts/common/io/audio/ac97/ac97_cmi.c usr/src/uts/common/io/audio/ac97/ac97_impl.h usr/src/uts/common/sys/audio/ac97.h |
diffstat | 6 files changed, 468 insertions(+), 352 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/audio/ac97/ac97.c Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/io/audio/ac97/ac97.c Sun Aug 30 15:32:09 2009 -0700 @@ -76,7 +76,7 @@ #define INPUT_MONOMIX 6 #define INPUT_PHONE 7 -static const char *ac97_insrcs[] = { +static const char *ac_insrcs[] = { AUDIO_PORT_MIC, AUDIO_PORT_CD, AUDIO_PORT_VIDEO, @@ -221,7 +221,7 @@ * ( each channel is "bits" wide ) */ uint16_t -ac97_val_scale(int left, int right, int bits) +ac_val_scale(int left, int right, int bits) { ASSERT(left <= 100); ASSERT(right <= 100); @@ -257,7 +257,7 @@ } uint16_t -ac97_mono_scale(int val, int bits) +ac_mono_scale(int val, int bits) { ASSERT(val <= 100); @@ -269,15 +269,14 @@ return (val * ((1 << bits) - 1) / 100); } - audio_dev_t * -ac97_get_dev(ac97_t *ac) +ac_get_dev(ac97_t *ac) { return (ac->d); } int -ac97_get_prop(ac97_t *ac, char *prop, int defval) +ac_get_prop(ac97_t *ac, char *prop, int defval) { int rv; @@ -313,7 +312,7 @@ * detection.) */ static int -ac97_probe_reg(ac97_t *ac, uint8_t reg) +ac_probe_reg(ac97_t *ac, uint8_t reg) { uint16_t val; int rv = 0; @@ -333,7 +332,7 @@ * Does this device have bass/treble controls? */ static int -ac97_probe_tone(ac97_t *ac) +ac_probe_tone(ac97_t *ac) { /* Bass/Treble contols present */ if (ac->caps & RR_BASS_TREBLE) @@ -346,7 +345,7 @@ * If there is a loudness switch? */ static int -ac97_probe_loud(ac97_t *ac) +ac_probe_loud(ac97_t *ac) { /* loudness contol present */ if (ac->caps & RR_LOUDNESS_SUPPORT) @@ -359,7 +358,7 @@ * Does this device have a mono-mic input volume control? */ static int -ac97_probe_mmic(ac97_t *ac) +ac_probe_mmic(ac97_t *ac) { /* mono mic present */ if (ac->caps & RR_DEDICATED_MIC) @@ -372,7 +371,7 @@ * Does this device have a simulated stereo switch? */ static int -ac97_probe_stsim(ac97_t *ac) +ac_probe_stsim(ac97_t *ac) { /* simulated stereocontol present */ if (ac->caps & RR_PSEUDO_STEREO) @@ -385,16 +384,16 @@ * Does this device have a PC beeper input volume control? */ static int -ac97_probe_pcbeep(ac97_t *ac) +ac_probe_pcbeep(ac97_t *ac) { - return (ac97_probe_reg(ac, AC97_PC_BEEP_REGISTER)); + return (ac_probe_reg(ac, AC97_PC_BEEP_REGISTER)); } /* * Does this device have AUX output port volume control? */ static int -ac97_probe_rear(ac97_t *ac) +ac_probe_rear(ac97_t *ac) { if (ac->flags & AC97_FLAG_AUX_4CH) return (1); @@ -407,10 +406,10 @@ * Does this device have a mic? */ static int -ac97_probe_mic(ac97_t *ac) +ac_probe_mic(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_MIC)) && - (ac97_probe_reg(ac, AC97_MIC_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_MIC_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_MIC); return (1); } @@ -421,7 +420,7 @@ * If this device has an AUX output port is it used for headphones? */ static int -ac97_probe_headphone(ac97_t *ac) +ac_probe_headphone(ac97_t *ac) { /* headphone control present */ if ((ac->flags & AC97_FLAG_AUX_HP) && @@ -435,7 +434,7 @@ * Does this device have AUX output port volume control? */ static int -ac97_probe_auxout(ac97_t *ac) +ac_probe_auxout(ac97_t *ac) { /* ALT PCM control present */ if ((ac->flags & AC97_FLAG_AUX_LVL) && @@ -449,10 +448,10 @@ * Does this device have an AUX input port volume control? */ static int -ac97_probe_auxin(ac97_t *ac) +ac_probe_auxin(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_AUXIN)) && - (ac97_probe_reg(ac, AC97_AUX_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_AUX_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_AUXIN); return (1); } @@ -463,10 +462,10 @@ * Does this device have a phone input port with a volume control? */ static int -ac97_probe_phone(ac97_t *ac) +ac_probe_phone(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_PHONE)) && - (ac97_probe_reg(ac, AC97_PHONE_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_PHONE_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_PHONE); return (1); } @@ -477,12 +476,12 @@ * Does this device have a mono output port with volume control? */ static int -ac97_probe_mono(ac97_t *ac) +ac_probe_mono(ac97_t *ac) { if (!(ac->flags & AC97_FLAG_SPEAKER_OK)) { return (0); } - if (ac97_probe_reg(ac, AC97_MONO_MASTER_VOLUME_REGISTER)) { + if (ac_probe_reg(ac, AC97_MONO_MASTER_VOLUME_REGISTER)) { return (1); } return (0); @@ -492,10 +491,10 @@ * Does this device have a line input port with volume control? */ static int -ac97_probe_linein(ac97_t *ac) +ac_probe_linein(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_LINEIN)) && - (ac97_probe_reg(ac, AC97_LINE_IN_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_LINE_IN_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_LINEIN); return (1); } @@ -506,10 +505,10 @@ * Does this device have a cdrom input port with volume control? */ static int -ac97_probe_cdrom(ac97_t *ac) +ac_probe_cdrom(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_CDROM)) && - (ac97_probe_reg(ac, AC97_CD_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_CD_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_CD); return (1); } @@ -520,10 +519,10 @@ * Does this device have a video input port with volume control? */ static int -ac97_probe_video(ac97_t *ac) +ac_probe_video(ac97_t *ac) { if ((!(ac->flags & AC97_FLAG_NO_VIDEO)) && - (ac97_probe_reg(ac, AC97_VIDEO_VOLUME_REGISTER))) { + (ac_probe_reg(ac, AC97_VIDEO_VOLUME_REGISTER))) { ac->inputs |= (1U << INPUT_VIDEO); return (1); } @@ -534,7 +533,7 @@ * Does this device have a 3D sound enhancement? */ static int -ac97_probe_3d(ac97_t *ac) +ac_probe_3d(ac97_t *ac) { /* 3D control present */ if (ac->caps & RR_3D_STEREO_ENHANCE_MASK) @@ -544,7 +543,7 @@ } static int -ac97_probe_3d_impl(ac97_t *ac, uint16_t mask) +ac_probe_3d_impl(ac97_t *ac, uint16_t mask) { int rv = 0; uint16_t val; @@ -564,22 +563,22 @@ } static int -ac97_probe_3d_depth(ac97_t *ac) +ac_probe_3d_depth(ac97_t *ac) { - return (ac97_probe_3d_impl(ac, TDCR_DEPTH_MASK)); + return (ac_probe_3d_impl(ac, TDCR_DEPTH_MASK)); } static int -ac97_probe_3d_center(ac97_t *ac) +ac_probe_3d_center(ac97_t *ac) { - return (ac97_probe_3d_impl(ac, TDCR_CENTER_MASK)); + return (ac_probe_3d_impl(ac, TDCR_CENTER_MASK)); } /* * Does this device have a center output port with volume control? */ static int -ac97_probe_center(ac97_t *ac) +ac_probe_center(ac97_t *ac) { uint16_t val; @@ -597,7 +596,7 @@ * a volume control? */ static int -ac97_probe_lfe(ac97_t *ac) +ac_probe_lfe(ac97_t *ac) { uint16_t val; @@ -615,7 +614,7 @@ * Are we a multichannel codec? */ static int -ac97_probe_front(ac97_t *ac) +ac_probe_front(ac97_t *ac) { uint16_t val; @@ -629,19 +628,19 @@ } static int -ac97_probe_lineout(ac97_t *ac) +ac_probe_lineout(ac97_t *ac) { /* if not multichannel, then use "lineout" instead of "front" label */ - return (!ac97_probe_front(ac)); + return (!ac_probe_front(ac)); } -static const char *ac97_mics[] = { +static const char *ac_mics[] = { AUDIO_PORT_MIC1, AUDIO_PORT_MIC2, NULL, }; -static const char *ac97_monos[] = { +static const char *ac_monos[] = { AUDIO_PORT_MONOMIX, AUDIO_PORT_MIC, NULL @@ -652,7 +651,7 @@ * to write to a device register. */ void -ac97_wr(ac97_t *ac, uint8_t reg, uint16_t val) +ac_wr(ac97_t *ac, uint8_t reg, uint16_t val) { if ((reg < LAST_SHADOW_REG) && (reg > 0)) { SHADOW(ac, reg) = val; @@ -674,7 +673,7 @@ * To read a hardware register, use the RD() macro above. */ uint16_t -ac97_rd(ac97_t *ac, uint8_t reg) +ac_rd(ac97_t *ac, uint8_t reg) { if ((reg < LAST_SHADOW_REG) && (reg > 0)) { return (SHADOW(ac, reg)); @@ -690,9 +689,9 @@ * to set bits in a device register. */ void -ac97_set(ac97_t *ac, uint8_t reg, uint16_t val) +ac_set(ac97_t *ac, uint8_t reg, uint16_t val) { - ac97_wr(ac, reg, ac->rd(ac->private, reg) | val); + ac_wr(ac, reg, ac->rd(ac->private, reg) | val); } /* @@ -700,9 +699,9 @@ * to clear bits in a device register. */ void -ac97_clr(ac97_t *ac, uint8_t reg, uint16_t val) +ac_clr(ac97_t *ac, uint8_t reg, uint16_t val) { - ac97_wr(ac, reg, ac->rd(ac->private, reg) & ~val); + ac_wr(ac, reg, ac->rd(ac->private, reg) & ~val); } /* @@ -719,14 +718,11 @@ list_t *l = &ac->ctrls; /* Validate that ctrlnum is real and usable */ - mutex_enter(&ac->ac_lock); for (ctrl = list_head(l); ctrl; ctrl = list_next(l, ctrl)) { if (strcmp(ctrl->actrl_name, name) == 0) { - mutex_exit(&ac->ac_lock); return (ctrl); } } - mutex_exit(&ac->ac_lock); return (NULL); } @@ -734,7 +730,7 @@ * This will update all the codec registers from the shadow table. */ static void -ac97_restore(ac97_t *ac) +ac_restore(ac97_t *ac) { /* * If we are restoring previous settings, just reload from the @@ -760,7 +756,7 @@ * start of day. */ static void -ac97_init_values(ac97_t *ac) +ac_init_values(ac97_t *ac) { ac97_ctrl_t *ctrl; @@ -778,7 +774,7 @@ * for the control AUDIO_CONTROL_INPUTS. */ static void -ac97_insrc_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_insrc_set(ac97_ctrl_t *ctrl, uint64_t value) { ac97_t *ac = ctrl->actrl_ac97; uint16_t set_val; @@ -786,13 +782,13 @@ set_val = ddi_ffs(value & 0xffff); if ((set_val > 0) && (set_val <= 8)) { set_val--; - ac97_wr(ac, AC97_RECORD_SELECT_CTRL_REGISTER, + ac_wr(ac, AC97_RECORD_SELECT_CTRL_REGISTER, set_val | (set_val << 8)); } } static void -ac97_gpr_toggle(ac97_ctrl_t *ctrl, int bit, uint64_t onoff) +ac_gpr_toggle(ac97_ctrl_t *ctrl, int bit, uint64_t onoff) { ac97_t *ac = ctrl->actrl_ac97; uint16_t v; @@ -803,56 +799,56 @@ } else { v &= ~bit; } - ac97_wr(ac, AC97_GENERAL_PURPOSE_REGISTER, v); + ac_wr(ac, AC97_GENERAL_PURPOSE_REGISTER, v); } static void -ac97_3donoff_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_3donoff_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_3D_STEREO_ENHANCE, value); + ac_gpr_toggle(ctrl, GPR_3D_STEREO_ENHANCE, value); } static void -ac97_loudness_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_loudness_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_BASS_BOOST, value); + ac_gpr_toggle(ctrl, GPR_BASS_BOOST, value); } static void -ac97_loopback_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_loopback_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_LPBK, value); + ac_gpr_toggle(ctrl, GPR_LPBK, value); } /* * This will set simulated stereo control to on or off. */ static void -ac97_stsim_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_stsim_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_ST, value); + ac_gpr_toggle(ctrl, GPR_ST, value); } /* * This will set mic select control to mic1=0 or mic2=1. */ static void -ac97_selmic_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_selmic_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_MS_MIC2, value & 2); + ac_gpr_toggle(ctrl, GPR_MS_MIC2, value & 2); } /* * This will set mono source select control to mix=0 or mic=1. */ static void -ac97_monosrc_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_monosrc_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_gpr_toggle(ctrl, GPR_MONO_MIC_IN, value & 2); + ac_gpr_toggle(ctrl, GPR_MONO_MIC_IN, value & 2); } static void -ac97_stereo_set(ac97_ctrl_t *ctrl, uint64_t value, uint8_t reg) +ac_stereo_set(ac97_ctrl_t *ctrl, uint64_t value, uint8_t reg) { ac97_t *ac = ctrl->actrl_ac97; uint8_t left, right; @@ -862,11 +858,11 @@ right = value & 0xff; mute = value ? 0 : ctrl->actrl_muteable; - ac97_wr(ac, reg, ac97_val_scale(left, right, ctrl->actrl_bits) | mute); + ac_wr(ac, reg, ac_val_scale(left, right, ctrl->actrl_bits) | mute); } static void -ac97_mono_set(ac97_ctrl_t *ctrl, uint64_t value, uint8_t reg, int shift) +ac_mono_set(ac97_ctrl_t *ctrl, uint64_t value, uint8_t reg, int shift) { ac97_t *ac = ctrl->actrl_ac97; uint8_t val; @@ -884,131 +880,131 @@ /* now set the mute bit, and volume bits */ v |= mute; - v |= (ac97_mono_scale(val, ctrl->actrl_bits) << shift); + v |= (ac_mono_scale(val, ctrl->actrl_bits) << shift); - ac97_wr(ac, reg, v); + ac_wr(ac, reg, v); } static void ac97_master_set(ac97_ctrl_t *ctrl, uint64_t value) { value = value | (value << 8); - ac97_stereo_set(ctrl, value, AC97_PCM_OUT_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_PCM_OUT_VOLUME_REGISTER); } static void ac97_lineout_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_MASTER_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_MASTER_VOLUME_REGISTER); } static void ac97_surround_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_EXTENDED_LRS_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_EXTENDED_LRS_VOLUME_REGISTER); } static void ac97_aux1out_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_HEADPHONE_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_HEADPHONE_VOLUME_REGISTER); } static void ac97_headphone_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_HEADPHONE_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_HEADPHONE_VOLUME_REGISTER); } static void -ac97_cd_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_cd_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_CD_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_CD_VOLUME_REGISTER); } static void -ac97_video_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_video_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_VIDEO_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_VIDEO_VOLUME_REGISTER); } static void -ac97_auxin_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_auxin_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_AUX_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_AUX_VOLUME_REGISTER); } static void -ac97_linein_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_linein_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_LINE_IN_VOLUME_REGISTER); + ac_stereo_set(ctrl, value, AC97_LINE_IN_VOLUME_REGISTER); } /* * This will set mono mic gain control. */ static void -ac97_monomic_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_monomic_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_RECORD_GAIN_MIC_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_RECORD_GAIN_MIC_REGISTER, 0); } static void -ac97_phone_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_phone_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_PHONE_VOLUME_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_PHONE_VOLUME_REGISTER, 0); } static void -ac97_mic_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_mic_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_MIC_VOLUME_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_MIC_VOLUME_REGISTER, 0); } static void -ac97_speaker_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_speaker_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_MONO_MASTER_VOLUME_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_MONO_MASTER_VOLUME_REGISTER, 0); } static void -ac97_pcbeep_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_pcbeep_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_PC_BEEP_REGISTER, 1); + ac_mono_set(ctrl, value, AC97_PC_BEEP_REGISTER, 1); } static void -ac97_recgain_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_recgain_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_stereo_set(ctrl, value, AC97_RECORD_GAIN_REGISTER); + ac_stereo_set(ctrl, value, AC97_RECORD_GAIN_REGISTER); } static void -ac97_center_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_center_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 0); } static void -ac97_lfe_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_lfe_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 8); + ac_mono_set(ctrl, value, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 8); } static void -ac97_bass_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_bass_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_MASTER_TONE_CONTROL_REGISTER, 8); + ac_mono_set(ctrl, value, AC97_MASTER_TONE_CONTROL_REGISTER, 8); } static void -ac97_treble_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_treble_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_mono_set(ctrl, value, AC97_MASTER_TONE_CONTROL_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_MASTER_TONE_CONTROL_REGISTER, 0); } static void -ac97_3ddepth_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_3ddepth_set(ac97_ctrl_t *ctrl, uint64_t value) { /* * XXX: This is all wrong... 3D depth/center cannot necessarily @@ -1016,11 +1012,11 @@ * need more information about each of the options available * to do the right thing. */ - ac97_mono_set(ctrl, value, AC97_THREE_D_CONTROL_REGISTER, 0); + ac_mono_set(ctrl, value, AC97_THREE_D_CONTROL_REGISTER, 0); } static void -ac97_3dcent_set(ac97_ctrl_t *ctrl, uint64_t value) +ac_3dcent_set(ac97_ctrl_t *ctrl, uint64_t value) { /* * XXX: This is all wrong... 3D depth/center cannot necessarily @@ -1028,7 +1024,7 @@ * need more information about each of the options available * to do the right thing. */ - ac97_mono_set(ctrl, value, AC97_THREE_D_CONTROL_REGISTER, 8); + ac_mono_set(ctrl, value, AC97_THREE_D_CONTROL_REGISTER, 8); } static void @@ -1043,7 +1039,7 @@ } else { v &= ~MICVR_20dB_BOOST; } - ac97_wr(ac, AC97_MIC_VOLUME_REGISTER, v); + ac_wr(ac, AC97_MIC_VOLUME_REGISTER, v); } /* @@ -1058,10 +1054,9 @@ * * On success zero is returned. */ -static int -ac97_control_get(void *arg, uint64_t *value) +int +ac97_control_get(ac97_ctrl_t *ctrl, uint64_t *value) { - ac97_ctrl_t *ctrl = arg; ac97_t *ac = ctrl->actrl_ac97; mutex_enter(&ac->ac_lock); @@ -1071,10 +1066,9 @@ return (0); } -static int -ac97_control_set(void *arg, uint64_t value) +int +ac97_control_set(ac97_ctrl_t *ctrl, uint64_t value) { - ac97_ctrl_t *ctrl = arg; ac97_t *ac = ctrl->actrl_ac97; uint8_t v1, v2; @@ -1114,6 +1108,18 @@ return (0); } +static int +ac_get_value(void *arg, uint64_t *value) +{ + return (ac97_control_get(arg, value)); +} + +static int +ac_set_value(void *arg, uint64_t value) +{ + return (ac97_control_set(arg, value)); +} + /* * This simply sets a flag to block calls to the underlying * hardware driver to get or set hardware controls. This is usually @@ -1143,7 +1149,7 @@ * Wait a resonable amount of time for hardware to become ready. */ static void -ac97_analog_reset(ac97_t *ac) +ac_analog_reset(ac97_t *ac) { uint16_t tmp; int wait = 1000; /* delay for up to 1s */ @@ -1171,7 +1177,7 @@ } } - audio_dev_warn(ac->d, "AC'97 analog powerup timed out"); + audio_dev_warn(ac->d, "AC'97 analog power up timed out"); } /* @@ -1187,33 +1193,33 @@ * last updated versions. */ static void -ac97_hw_reset(ac97_t *ac) +ac_hw_reset(ac97_t *ac) { /* * Fully Power up the device */ if (ac->flags & AC97_FLAG_AMPLIFIER) { /* power up - external amp powerd up */ - ac97_wr(ac, AC97_POWERDOWN_CTRL_STAT_REGISTER, 0); + ac_wr(ac, AC97_POWERDOWN_CTRL_STAT_REGISTER, 0); } else { /* power up - external amp powered down */ - ac97_wr(ac, AC97_POWERDOWN_CTRL_STAT_REGISTER, PCSR_EAPD); + ac_wr(ac, AC97_POWERDOWN_CTRL_STAT_REGISTER, PCSR_EAPD); } - ac97_wr(ac, AC97_GENERAL_PURPOSE_REGISTER, 0); + ac_wr(ac, AC97_GENERAL_PURPOSE_REGISTER, 0); switch (ac->vid) { case AC97_CODEC_STAC9708: #if 0 /* non-inverted phase */ - /* ac97_rd(ac, AC97_VENDOR_REGISTER_11) & ~0x8); */ + /* ac_rd(ac, AC97_VENDOR_REGISTER_11) & ~0x8); */ #endif WR(AC97_VENDOR_REGISTER_11, 8); break; case AC97_CODEC_EM28028: - ac97_wr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, - (ac97_rd(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER) & + ac_wr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, + (ac_rd(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER) & ~3800) | 0xE0); break; @@ -1228,7 +1234,7 @@ #if 0 /* GED: This looks fishy to me, so I'm nuking it for now */ /* headphone/aux volume (?) */ - ac97_wr(ac, AC97_HEADPHONE_VOLUME_REGISTER, 0x0808); + ac_wr(ac, AC97_HEADPHONE_VOLUME_REGISTER, 0x0808); #endif break; @@ -1254,7 +1260,7 @@ case AC97_CODEC_VT1617A: case AC97_CODEC_VT1616: /* Turn off Center, Surround, and LFE DACs */ - ac97_clr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, + ac_clr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, EASCR_PRI | EASCR_PRJ | EASCR_PRK); WR(AC97_VENDOR_REGISTER_01, 0x0230); break; @@ -1274,7 +1280,7 @@ } /* Turn off variable sampling rate support */ - ac97_clr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, EASCR_VRA); + ac_clr(ac, AC97_EXTENDED_AUDIO_STAT_CTRL_REGISTER, EASCR_VRA); } /* @@ -1298,9 +1304,9 @@ mutex_exit(&ac->ac_lock); return; } - ac97_analog_reset(ac); - ac97_hw_reset(ac); - ac97_restore(ac); + ac_analog_reset(ac); + ac_hw_reset(ac); + ac_restore(ac); mutex_exit(&ac->ac_lock); } @@ -1324,9 +1330,9 @@ ac->resumer = ddi_get_kt_did(); /* We simply call reset since the operation is the same */ - ac97_analog_reset(ac); - ac97_hw_reset(ac); - ac97_restore(ac); + ac_analog_reset(ac); + ac_hw_reset(ac); + ac_restore(ac); ac->resumer = 0; ac->suspended = B_FALSE; @@ -1345,82 +1351,134 @@ /* * Register a control -- if it fails, it will generate a message to * syslog, but the driver muddles on. (Failure to register a control - * should never occur, and is generally benign if it happens.) + * should never occur, but is generally benign if it happens.) */ void -ac97_alloc_control(ac97_t *ac, ac97_ctrl_probe_t *cpt) +ac97_control_register(ac97_ctrl_t *ctrl) +{ + ac97_t *ac = ctrl->actrl_ac97; + ASSERT(ac->d != NULL); + + ctrl->actrl_suppress = B_FALSE; + + /* Register control with framework */ + ctrl->actrl_ctrl = audio_dev_add_control(ac->d, &ctrl->actrl_desc, + ac_get_value, ac_set_value, ctrl); + if (ctrl->actrl_ctrl == NULL) { + audio_dev_warn(ac->d, "AC97 %s alloc failed", + ctrl->actrl_name); + } +} + +void +ac97_control_unregister(ac97_ctrl_t *ctrl) +{ + ctrl->actrl_suppress = B_TRUE; + + if (ctrl->actrl_ctrl != NULL) { + audio_dev_del_control(ctrl->actrl_ctrl); + ctrl->actrl_ctrl = NULL; + } +} + +const char * +ac97_control_name(ac97_ctrl_t *ctrl) +{ + return (ctrl->actrl_name); +} + +const audio_ctrl_desc_t * +ac97_control_desc(ac97_ctrl_t *ctrl) +{ + return (&ctrl->actrl_desc); +} + +void +ac97_register_controls(ac97_t *ac) +{ + ac97_ctrl_t *ctrl; + + for (ctrl = list_head(&ac->ctrls); ctrl; + ctrl = list_next(&ac->ctrls, ctrl)) { + if (ctrl->actrl_suppress) + continue; + ac97_control_register(ctrl); + } +} + +void +ac97_walk_controls(ac97_t *ac, ac97_ctrl_walk_t walker, void *arg) +{ + ac97_ctrl_t *ctrl; + + for (ctrl = list_head(&ac->ctrls); ctrl; + ctrl = list_next(&ac->ctrls, ctrl)) { + if (!(*walker)(ctrl, arg)) { + break; + } + } +} + +void +ac_add_control(ac97_t *ac, ac97_ctrl_probe_t *cpt) { ac97_ctrl_t *ctrl; - audio_ctrl_desc_t ctrl_des; + boolean_t is_new; ASSERT(ac); ASSERT(ac->d); - ctrl = kmem_zalloc(sizeof (ac97_ctrl_t), KM_SLEEP); - - bzero(&ctrl_des, sizeof (ctrl_des)); - ctrl_des.acd_name = cpt->cp_name; - ctrl_des.acd_minvalue = cpt->cp_minval; - ctrl_des.acd_maxvalue = cpt->cp_maxval; - ctrl_des.acd_type = cpt->cp_type; - ctrl_des.acd_flags = cpt->cp_flags; + ctrl = ac97_control_find(ac, cpt->cp_name); + if (ctrl != NULL) { + is_new = B_FALSE; + } else { + ctrl = kmem_zalloc(sizeof (ac97_ctrl_t), KM_SLEEP); + is_new = B_TRUE; + } + ctrl->actrl_ac97 = ac; + ctrl->actrl_minval = cpt->cp_minval; + ctrl->actrl_maxval = cpt->cp_maxval; + ctrl->actrl_type = cpt->cp_type; + ctrl->actrl_name = cpt->cp_name; + ctrl->actrl_flags = cpt->cp_flags; if (cpt->cp_enum) { for (int e = 0; e < 64; e++) { if (cpt->cp_enum[e] == NULL) break; - ctrl_des.acd_enum[e] = cpt->cp_enum[e]; + ctrl->actrl_enum[e] = cpt->cp_enum[e]; } } - ctrl->actrl_ac97 = ac; /* * Warning for extended controls this field gets changed * by audio_dev_add_control() to be a unique value. */ - ctrl->actrl_minval = cpt->cp_minval; - ctrl->actrl_maxval = cpt->cp_maxval; ctrl->actrl_initval = cpt->cp_initval; ctrl->actrl_muteable = cpt->cp_muteable; ctrl->actrl_write_fn = cpt->cp_write_fn; ctrl->actrl_bits = cpt->cp_bits; - ctrl->actrl_type = cpt->cp_type; - ctrl->actrl_name = cpt->cp_name; - - /* Register control with framework */ - ctrl->actrl_ctrl = audio_dev_add_control(ac->d, &ctrl_des, - ac97_control_get, ac97_control_set, ctrl); - if (!ctrl->actrl_ctrl) { - audio_dev_warn(ac->d, "AC97 %s alloc failed", cpt->cp_name); - kmem_free(ctrl, sizeof (ac97_ctrl_t)); - return; - } /* - * Not that it can not be referenced until in is in the + * Not that it can not be referenced until it is in the * list. So again by adding to the list last we avoid the need - * for control locks. + * for locks. */ - mutex_enter(&ac->ac_lock); - list_insert_tail(&ac->ctrls, ctrl); - mutex_exit(&ac->ac_lock); + if (is_new) + list_insert_tail(&ac->ctrls, ctrl); } /* * De-Register and free up a control - * - * Note ctrl_lock read write must be held for writing when calling - * this function */ void -ac97_free_control(ac97_ctrl_t *ctrl) +ac97_control_remove(ac97_ctrl_t *ctrl) { ac97_t *ac = ctrl->actrl_ac97; - mutex_enter(&ac->ac_lock); list_remove(&ac->ctrls, ctrl); - mutex_exit(&ac->ac_lock); - audio_dev_del_control(ctrl->actrl_ctrl); + if (ctrl->actrl_ctrl != NULL) + audio_dev_del_control(ctrl->actrl_ctrl); kmem_free(ctrl, sizeof (ac97_ctrl_t)); } @@ -1452,99 +1510,99 @@ /* LINE out volume */ {AUDIO_CTRL_ID_LINEOUT, INIT_VAL_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MAINVOL, 0x8080, ac97_lineout_set, ac97_probe_lineout, 6}, + MAINVOL, 0x8080, ac97_lineout_set, ac_probe_lineout, 6}, /* Front volume */ {AUDIO_CTRL_ID_FRONT, INIT_VAL_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MAINVOL, 0x8080, ac97_lineout_set, ac97_probe_front, 6}, + MAINVOL, 0x8080, ac97_lineout_set, ac_probe_front, 6}, /* 4CH out volume (has one of three possible uses, first use) */ {AUDIO_CTRL_ID_SURROUND, INIT_VAL_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MAINVOL, 0x8080, ac97_surround_set, ac97_probe_rear, 6}, + MAINVOL, 0x8080, ac97_surround_set, ac_probe_rear, 6}, /* ALT out volume (has one of three possible uses, second use) */ {AUDIO_CTRL_ID_HEADPHONE, INIT_VAL_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MAINVOL, 0x8080, ac97_headphone_set, ac97_probe_headphone, 6}, + MAINVOL, 0x8080, ac97_headphone_set, ac_probe_headphone, 6}, /* ALT out volume (has one of three possible uses, third use) */ {AUDIO_CTRL_ID_AUX1OUT, INIT_VAL_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MAINVOL, 0x8080, ac97_aux1out_set, ac97_probe_auxout, 6}, + MAINVOL, 0x8080, ac97_aux1out_set, ac_probe_auxout, 6}, /* center out volume */ {AUDIO_CTRL_ID_CENTER, INIT_VAL_MN, 0, 100, AUDIO_CTRL_TYPE_MONO, - MAINVOL, EXLFEVR_CENTER_MUTE, ac97_center_set, ac97_probe_center, 6}, + MAINVOL, EXLFEVR_CENTER_MUTE, ac_center_set, ac_probe_center, 6}, /* LFE out volume (sub-woofer) */ {AUDIO_CTRL_ID_LFE, INIT_VAL_MN, 0, 100, AUDIO_CTRL_TYPE_MONO, - MAINVOL, EXLFEVR_LFE_MUTE, ac97_lfe_set, ac97_probe_lfe, 6}, + MAINVOL, EXLFEVR_LFE_MUTE, ac_lfe_set, ac_probe_lfe, 6}, /* MONO out volume */ {AUDIO_CTRL_ID_SPEAKER, INIT_VAL_MN, 0, 100, AUDIO_CTRL_TYPE_MONO, - MAINVOL, MMVR_MUTE, ac97_speaker_set, ac97_probe_mono, 6}, + MAINVOL, MMVR_MUTE, ac_speaker_set, ac_probe_mono, 6}, /* Record in GAIN */ {AUDIO_CTRL_ID_RECGAIN, INIT_IGAIN_ST, 0, 100, AUDIO_CTRL_TYPE_STEREO, - RECVOL, RGR_MUTE, ac97_recgain_set, NULL, -4}, + RECVOL, RGR_MUTE, ac_recgain_set, NULL, -4}, /* MIC in volume */ {AUDIO_CTRL_ID_MIC, 0, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MONVOL, MICVR_MUTE, ac97_mic_set, ac97_probe_mic, 5}, + MONVOL, MICVR_MUTE, ac_mic_set, ac_probe_mic, 5}, /* LINE in volume */ {AUDIO_CTRL_ID_LINEIN, 0, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MONVOL, LIVR_MUTE, ac97_linein_set, ac97_probe_linein, 5}, + MONVOL, LIVR_MUTE, ac_linein_set, ac_probe_linein, 5}, /* CD in volume */ {AUDIO_CTRL_ID_CD, 0, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MONVOL, CDVR_MUTE, ac97_cd_set, ac97_probe_cdrom, 5}, + MONVOL, CDVR_MUTE, ac_cd_set, ac_probe_cdrom, 5}, /* VIDEO in volume */ {AUDIO_CTRL_ID_VIDEO, 0, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MONVOL, VIDVR_MUTE, ac97_video_set, ac97_probe_video, 5}, + MONVOL, VIDVR_MUTE, ac_video_set, ac_probe_video, 5}, /* AUX in volume */ {AUDIO_CTRL_ID_AUX1IN, 0, 0, 100, AUDIO_CTRL_TYPE_STEREO, - MONVOL, AUXVR_MUTE, ac97_auxin_set, ac97_probe_auxin, 5}, + MONVOL, AUXVR_MUTE, ac_auxin_set, ac_probe_auxin, 5}, /* PHONE in volume */ {AUDIO_CTRL_ID_PHONE, 0, 0, 100, AUDIO_CTRL_TYPE_MONO, - MONVOL, PVR_MUTE, ac97_phone_set, ac97_probe_phone, 5}, + MONVOL, PVR_MUTE, ac_phone_set, ac_probe_phone, 5}, /* PC BEEPER in volume (motherboard speaker pins) */ {AUDIO_CTRL_ID_BEEP, INIT_VAL_MN, 0, 100, AUDIO_CTRL_TYPE_MONO, - AC97_RW, PCBR_MUTE, ac97_pcbeep_set, ac97_probe_pcbeep, 4}, + AC97_RW, PCBR_MUTE, ac_pcbeep_set, ac_probe_pcbeep, 4}, /* BASS out level (note, zero is hardware bypass) */ {AUDIO_CTRL_ID_BASS, 0, 0, 100, AUDIO_CTRL_TYPE_MONO, - TONECTL, 0, ac97_bass_set, ac97_probe_tone, 4}, + TONECTL, 0, ac_bass_set, ac_probe_tone, 4}, /* TREBLE out level (note, zero is hardware bypass) */ {AUDIO_CTRL_ID_TREBLE, 0, 0, 100, AUDIO_CTRL_TYPE_MONO, - TONECTL, 0, ac97_treble_set, ac97_probe_tone, 4}, + TONECTL, 0, ac_treble_set, ac_probe_tone, 4}, /* Loudness on/off switch */ {AUDIO_CTRL_ID_LOUDNESS, 0, 0, 1, AUDIO_CTRL_TYPE_BOOLEAN, - TONECTL, 0, ac97_loudness_set, ac97_probe_loud, 0}, + TONECTL, 0, ac_loudness_set, ac_probe_loud, 0}, /* 3D depth out level */ {AUDIO_CTRL_ID_3DDEPTH, 0, 0, 100, AUDIO_CTRL_TYPE_MONO, - T3DCTL, 0, ac97_3ddepth_set, ac97_probe_3d_depth, 4}, + T3DCTL, 0, ac_3ddepth_set, ac_probe_3d_depth, 4}, /* 3D center out level */ {AUDIO_CTRL_ID_3DCENT, 0, 0, 100, AUDIO_CTRL_TYPE_MONO, - T3DCTL, 0, ac97_3dcent_set, ac97_probe_3d_center, 4}, + T3DCTL, 0, ac_3dcent_set, ac_probe_3d_center, 4}, /* 3D enhance on/off switch */ {AUDIO_CTRL_ID_3DENHANCE, 0, 0, 1, AUDIO_CTRL_TYPE_BOOLEAN, - T3DCTL, 0, ac97_3donoff_set, ac97_probe_3d, 0}, + T3DCTL, 0, ac_3donoff_set, ac_probe_3d, 0}, /* MIC BOOST switch */ {AUDIO_CTRL_ID_MICBOOST, 0, 0, 1, AUDIO_CTRL_TYPE_BOOLEAN, - RECCTL, 0, ac97_micboost_set, ac97_probe_mic, 0}, + RECCTL, 0, ac97_micboost_set, ac_probe_mic, 0}, /* Loopback on/off switch */ {AUDIO_CTRL_ID_LOOPBACK, 0, 0, 1, AUDIO_CTRL_TYPE_BOOLEAN, - AC97_RW, 0, ac97_loopback_set, NULL, 0}, + AC97_RW, 0, ac_loopback_set, NULL, 0}, /* * The following selectors *must* come after the others, as they rely @@ -1552,25 +1610,25 @@ */ /* record src select (only one port at a time) */ {AUDIO_CTRL_ID_RECSRC, (1U << INPUT_MIC), 0, 0, AUDIO_CTRL_TYPE_ENUM, - RECCTL, 0, ac97_insrc_set, NULL, 0, ac97_insrcs}, + RECCTL, 0, ac_insrc_set, NULL, 0, ac_insrcs}, /* Start of non-standard private controls */ /* Simulated stereo on/off switch */ {AUDIO_CTRL_ID_STEREOSIM, 0, 0, 1, AUDIO_CTRL_TYPE_BOOLEAN, - AC97_RW, 0, ac97_stsim_set, ac97_probe_stsim, 0}, + AC97_RW, 0, ac_stsim_set, ac_probe_stsim, 0}, /* mono MIC GAIN */ {AUDIO_CTRL_ID_MICGAIN, INIT_IGAIN_MN, 0, 100, AUDIO_CTRL_TYPE_MONO, - RECCTL, RGMR_MUTE, ac97_monomic_set, ac97_probe_mmic, -4}, + RECCTL, RGMR_MUTE, ac_monomic_set, ac_probe_mmic, -4}, /* MIC select switch 0=mic1 1=mic2 */ {AUDIO_CTRL_ID_MICSRC, 1, 3, 3, AUDIO_CTRL_TYPE_ENUM, - RECCTL, 0, ac97_selmic_set, ac97_probe_mic, 0, ac97_mics}, + RECCTL, 0, ac_selmic_set, ac_probe_mic, 0, ac_mics}, /* MONO out src select 0=mix 1=mic */ {AUDIO_CTRL_ID_SPKSRC, 1, 3, 3, AUDIO_CTRL_TYPE_ENUM, - AC97_RW, 0, ac97_monosrc_set, ac97_probe_mono, 0, ac97_monos}, + AC97_RW, 0, ac_monosrc_set, ac_probe_mono, 0, ac_monos}, {NULL} }; @@ -1581,8 +1639,8 @@ * * Returns zero on success */ -static int -ac97_probeinit_ctrls(ac97_t *ac, int vol_bits, int enh_bits) +static void +ac_probeinit_ctrls(ac97_t *ac, int vol_bits, int enh_bits) { ac97_ctrl_probe_t *cpt; ac97_ctrl_probe_t my_cpt; @@ -1619,15 +1677,13 @@ } if (!my_cpt.cp_probe || my_cpt.cp_probe(ac)) { - ac97_alloc_control(ac, &my_cpt); + ac_add_control(ac, &my_cpt); } } if (ac->codec_init != NULL) { ac->codec_init(ac); } - - return (0); } /* @@ -1726,6 +1782,23 @@ return (ac); } +/* + * Allocate an AC97 instance for use by a hardware driver. + * + * returns an allocated and initialize ac97 structure. + */ +ac97_t * +ac97_allocate(audio_dev_t *adev, dev_info_t *dip, ac97_rd_t rd, ac97_wr_t wr, + void *priv) +{ + ac97_t *ac; + + ac = ac97_alloc(dip, rd, wr, priv); + if (ac != NULL) { + ac->d = adev; + } + return (ac); +} /* * Free an AC97 instance. @@ -1737,7 +1810,7 @@ /* Clear out any controls that are still attached */ while ((ctrl = list_head(&ac->ctrls)) != NULL) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } list_destroy(&ac->ctrls); @@ -1846,14 +1919,8 @@ { 0, NULL } }; -/* - * Init the actual hardware related to a previously - * allocated instance of an AC97 device. - * - * Return zero on success. - */ -int -ac97_init(ac97_t *ac, struct audio_dev *d) +void +ac97_probe_controls(ac97_t *ac) { uint32_t vid1, vid2; uint16_t ear; @@ -1865,17 +1932,17 @@ char nmbuf[128]; char buf[128]; - /* Save audio framework instance structure */ - ac->d = d; + /* This is only valid when used with new style ac97_allocate(). */ + ASSERT(ac->d); - ac97_analog_reset(ac); + ac_analog_reset(ac); vid1 = RD(AC97_VENDOR_ID1_REGISTER); vid2 = RD(AC97_VENDOR_ID2_REGISTER); if (vid1 == 0xffff) { - audio_dev_warn(d, "AC'97 codec unresponsive"); - return (-1); + audio_dev_warn(ac->d, "AC'97 codec unresponsive"); + return; } ac->vid = (vid1 << 16) | vid2; @@ -1933,7 +2000,7 @@ */ if (ac->caps & RR_HEADPHONE_SUPPORT) { /* it looks like it is probably headphones */ - if (ac97_probe_reg(ac, AC97_HEADPHONE_VOLUME_REGISTER)) { + if (ac_probe_reg(ac, AC97_HEADPHONE_VOLUME_REGISTER)) { /* it is implemented */ ac->flags |= AC97_FLAG_AUX_HP; } @@ -1946,7 +2013,7 @@ * If not a headphone, is it 4CH_OUT (surround?) */ if ((!(ac->flags & AC97_FLAG_AUX_HP)) && (ear & EAR_SDAC)) { - if (ac97_probe_reg(ac, AC97_EXTENDED_LRS_VOLUME_REGISTER)) { + if (ac_probe_reg(ac, AC97_EXTENDED_LRS_VOLUME_REGISTER)) { ac->flags |= AC97_FLAG_AUX_4CH; } } @@ -1955,7 +2022,7 @@ * If neither, then maybe its an auxiliary line level output? */ if (!(ac->flags & (AC97_FLAG_AUX_HP | AC97_FLAG_AUX_4CH))) { - if (ac97_probe_reg(ac, AC97_HEADPHONE_VOLUME_REGISTER)) { + if (ac_probe_reg(ac, AC97_HEADPHONE_VOLUME_REGISTER)) { ac->flags |= AC97_FLAG_AUX_LVL; } } @@ -1975,11 +2042,10 @@ } ac->flags |= flags; - (void) snprintf(ac->name, sizeof (ac->name), "%s %s (%d channels)", - vendor, name, ac->nchan); + (void) snprintf(ac->name, sizeof (ac->name), "%s %s", vendor, name); (void) snprintf(buf, sizeof (buf), "AC'97 codec: %s", ac->name); - audio_dev_add_info(d, buf); + audio_dev_add_info(ac->d, buf); cmn_err(CE_CONT, "?%s#%d: AC'97 codec id %s (%x, %d channels, caps %x)\n", @@ -1989,15 +2055,30 @@ /* * Probe and register all known controls with framework */ - if (ac97_probeinit_ctrls(ac, vol_bits, enh_bits)) { - audio_dev_warn(d, "AC97 controls init failed"); + ac_probeinit_ctrls(ac, vol_bits, enh_bits); + + ac_hw_reset(ac); + ac_init_values(ac); +} - /* XXX - need to free all controls registered? */ - return (-1); - } +/* + * Init the actual hardware related to a previously allocated instance + * of an AC97 device. This is a legacy function and should not be + * used in new code. + * + * Return zero on success. + */ +int +ac97_init(ac97_t *ac, struct audio_dev *d) +{ + /* Make sure we aren't using this with new style ac97_allocate(). */ + ASSERT(ac->d == NULL); - ac97_hw_reset(ac); - ac97_init_values(ac); + /* Save audio framework instance structure */ + ac->d = d; + + ac97_probe_controls(ac); + ac97_register_controls(ac); return (0); }
--- a/usr/src/uts/common/io/audio/ac97/ac97_ad.c Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/io/audio/ac97/ac97_ad.c Sun Aug 30 15:32:09 2009 -0700 @@ -136,35 +136,35 @@ ac97_t *ac = actrl->actrl_ac97; uint16_t v; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ switch (value) { case 0x1: /* 0db */ - ac97_clr(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); + ac_clr(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); break; case 0x2: /* 10dB */ - ac97_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - v = ac97_rd(ac, ADS_MISC_CFG_REGISTER); + 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; - ac97_wr(ac, ADS_MISC_CFG_REGISTER, v); + ac_wr(ac, ADS_MISC_CFG_REGISTER, v); break; case 0x4: /* 20dB */ - ac97_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - v = ac97_rd(ac, ADS_MISC_CFG_REGISTER); + 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; - ac97_wr(ac, ADS_MISC_CFG_REGISTER, v); + ac_wr(ac, ADS_MISC_CFG_REGISTER, v); break; case 0x8: /* 30dB */ - ac97_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - v = ac97_rd(ac, ADS_MISC_CFG_REGISTER); + 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; - ac97_wr(ac, ADS_MISC_CFG_REGISTER, v); + ac_wr(ac, ADS_MISC_CFG_REGISTER, v); break; } } @@ -174,19 +174,19 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ switch (value) { case 0x1: /* mic1 */ - ac97_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); - ac97_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); + ac_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); + ac_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); break; case 0x2: /* mic2 */ - ac97_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); - ac97_set(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); + ac_clr(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); + ac_set(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); break; case 0x4: /* stereo - ms bit clear to allow MIC1 to be mixed */ - ac97_set(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); - ac97_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); + ac_set(ac, ADS_MISC_CFG_REGISTER, AMCR_2CMIC); + ac_clr(ac, AC97_GENERAL_PURPOSE_REGISTER, GPR_MS_MIC2); break; } } @@ -194,7 +194,6 @@ static void ads_setup_micsrc(ac97_t *ac) { - ac97_ctrl_t *ctrl; static const char *values[] = { AUDIO_PORT_MIC1, AUDIO_PORT_MIC2, @@ -206,12 +205,7 @@ AC97_FLAGS | AUDIO_CTRL_FLAG_REC, 0, ads_set_micsrc, NULL, 0, values }; - ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_MICSRC); - if (ctrl) { - ac97_free_control(ctrl); - } - - ac97_alloc_control(ac, &cpt); + ac_add_control(ac, &cpt); } static void @@ -237,10 +231,9 @@ /* 20dB by default */ cpt.cp_initval = 2; } - ac97_free_control(ctrl); } - ac97_alloc_control(ac, &cpt); + ac_add_control(ac, &cpt); } void
--- a/usr/src/uts/common/io/audio/ac97/ac97_alc.c Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/io/audio/ac97/ac97_alc.c Sun Aug 30 15:32:09 2009 -0700 @@ -78,11 +78,11 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ if (value & 2) { - ac97_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_SURROUND); + ac_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_SURROUND); } else { - ac97_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_SURROUND); + ac_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_SURROUND); } } @@ -91,13 +91,13 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ if (value & 2) { - ac97_set(ac, ALC_MISC_CTRL_REGISTER, AMC_VREFOUT_DIS); - ac97_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_CENTER_LFE); + ac_set(ac, ALC_MISC_CTRL_REGISTER, AMC_VREFOUT_DIS); + ac_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_CENTER_LFE); } else { - ac97_clr(ac, ALC_MISC_CTRL_REGISTER, AMC_VREFOUT_DIS); - ac97_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_CENTER_LFE); + ac_clr(ac, ALC_MISC_CTRL_REGISTER, AMC_VREFOUT_DIS); + ac_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_CENTER_LFE); } } @@ -107,11 +107,11 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ if (value & 2) { - ac97_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_BACK_SURROUND); + ac_set(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_BACK_SURROUND); } else { - ac97_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_BACK_SURROUND); + ac_clr(ac, ALC_DATA_FLOW_CTRL_REGISTER, ADFC_BACK_SURROUND); } } #endif @@ -129,14 +129,14 @@ /* If this control is mute-able than set as muted if needed */ mute = vol ? 0 : ASD_SURROUND_MUTE; - adj_value = ac97_val_scale(vol, vol, 5) | mute; + adj_value = ac_val_scale(vol, vol, 5) | mute; /* select page 0 */ - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* adjust all three PCM volumes */ - ac97_wr(ac, AC97_PCM_OUT_VOLUME_REGISTER, adj_value); - ac97_wr(ac, ALC_SURROUND_DAC_REGISTER, adj_value); - ac97_wr(ac, ALC_CEN_LFE_DAC_REGISTER, adj_value); + ac_wr(ac, AC97_PCM_OUT_VOLUME_REGISTER, adj_value); + ac_wr(ac, ALC_SURROUND_DAC_REGISTER, adj_value); + ac_wr(ac, ALC_CEN_LFE_DAC_REGISTER, adj_value); } static const char *alc_linein_funcs[] = { @@ -179,18 +179,18 @@ int ival; bcopy(&alc650_linein_func_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); + ival = ac_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); if ((ival >= 1) && (ival <= 2)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); bcopy(&alc650_mic_func_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_MIC_FUNC, 0); + ival = ac_get_prop(ac, AC97_PROP_MIC_FUNC, 0); if ((ival >= 1) && (ival <= 2)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); alc_pcm_override(ac); }
--- a/usr/src/uts/common/io/audio/ac97/ac97_cmi.c Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/io/audio/ac97/ac97_cmi.c Sun Aug 30 15:32:09 2009 -0700 @@ -71,22 +71,22 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ switch (value) { case 0x1: /* 0db */ - ac97_clr(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - ac97_clr(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); + ac_clr(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); + ac_clr(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); break; case 0x2: /* 20dB */ - ac97_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - ac97_clr(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); + ac_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); + ac_clr(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); break; case 0x4: /* 30dB */ - ac97_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); - ac97_set(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); + ac_set(ac, AC97_MIC_VOLUME_REGISTER, MICVR_20dB_BOOST); + ac_set(ac, CMI_MULTICH_REGISTER, CMR_BSTSEL); break; } } @@ -96,11 +96,11 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ if (value & 2) { - ac97_set(ac, CMI_MULTICH_REGISTER, CMR_S2LNI); + ac_set(ac, CMI_MULTICH_REGISTER, CMR_S2LNI); } else { - ac97_clr(ac, CMI_MULTICH_REGISTER, CMR_S2LNI); + ac_clr(ac, CMI_MULTICH_REGISTER, CMR_S2LNI); } } @@ -109,11 +109,11 @@ { ac97_t *ac = actrl->actrl_ac97; - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ if (value & 2) { - ac97_set(ac, CMI_MULTICH_REGISTER, CMR_CLCTL); + ac_set(ac, CMI_MULTICH_REGISTER, CMR_CLCTL); } else { - ac97_clr(ac, CMI_MULTICH_REGISTER, CMR_CLCTL); + ac_clr(ac, CMI_MULTICH_REGISTER, CMR_CLCTL); } } @@ -139,10 +139,9 @@ /* 20dB by default */ cpt.cp_initval = 1; } - ac97_free_control(ctrl); } - ac97_alloc_control(ac, &cpt); + ac_add_control(ac, &cpt); } static const char *cmi_linein_funcs[] = { @@ -173,18 +172,18 @@ }; bcopy(&linein_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); + ival = ac_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); if ((ival >= 1) && (ival <= 2)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); bcopy(&mic_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_MIC_FUNC, 0); + ival = ac_get_prop(ac, AC97_PROP_MIC_FUNC, 0); if ((ival >= 1) && (ival <= 2)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); } static void @@ -193,9 +192,9 @@ ac97_t *ac = actrl->actrl_ac97; if (value & 2) { - ac97_set(ac, CMI_TASK_REGISTER, CTR_S2LNI); + ac_set(ac, CMI_TASK_REGISTER, CTR_S2LNI); } else { - ac97_clr(ac, CMI_TASK_REGISTER, CTR_S2LNI); + ac_clr(ac, CMI_TASK_REGISTER, CTR_S2LNI); } } @@ -205,9 +204,9 @@ ac97_t *ac = actrl->actrl_ac97; if (value) { - ac97_set(ac, CMI_TASK_REGISTER, CTR_F2R); + ac_set(ac, CMI_TASK_REGISTER, CTR_F2R); } else { - ac97_clr(ac, CMI_TASK_REGISTER, CTR_F2R); + ac_clr(ac, CMI_TASK_REGISTER, CTR_F2R); } } @@ -227,18 +226,18 @@ }; bcopy(&linein_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); + ival = ac_get_prop(ac, AC97_PROP_LINEIN_FUNC, 0); if ((ival >= 1) && (ival <= 2)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); bcopy(&spread_cpt, &cp, sizeof (cp)); - ival = ac97_get_prop(ac, AC97_PROP_SPREAD, -1); + ival = ac_get_prop(ac, AC97_PROP_SPREAD, -1); if ((ival >= 0) && (ival <= 1)) { cp.cp_initval = ival; } - ac97_alloc_control(ac, &cp); + ac_add_control(ac, &cp); } @@ -258,33 +257,40 @@ */ ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_VOLUME); if (ctrl) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_FRONT); if (ctrl) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_SURROUND); if (ctrl) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_CENTER); if (ctrl) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } ctrl = ac97_control_find(ac, AUDIO_CTRL_ID_LFE); if (ctrl) { - ac97_free_control(ctrl); + ac97_control_remove(ctrl); } /* make sure we have disabled mute and attenuation on physical ctrls */ - ac97_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ - ac97_wr(ac, AC97_PCM_OUT_VOLUME_REGISTER, 0); - ac97_wr(ac, AC97_MASTER_VOLUME_REGISTER, 0); - ac97_wr(ac, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 0); - ac97_wr(ac, AC97_EXTENDED_LRS_VOLUME_REGISTER, 0); + ac_wr(ac, AC97_INTERRUPT_PAGING_REGISTER, 0); /* select page 0 */ + ac_wr(ac, AC97_PCM_OUT_VOLUME_REGISTER, 0); + ac_wr(ac, AC97_MASTER_VOLUME_REGISTER, 0); + ac_wr(ac, AC97_EXTENDED_C_LFE_VOLUME_REGISTER, 0); + ac_wr(ac, AC97_EXTENDED_LRS_VOLUME_REGISTER, 0); - (void) audio_dev_add_soft_volume(ac97_get_dev(ac)); + /* + * NB: This is probably not the best way to do this, because + * it will make overriding this hard for drivers that desire + * to. Fortunately, we don't think any drivers that want to + * override or fine tune AC'97 controls (i.e. creative cards) + * use these C-Media codecs. + */ + (void) audio_dev_add_soft_volume(ac_get_dev(ac)); } void
--- a/usr/src/uts/common/io/audio/ac97/ac97_impl.h Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/io/audio/ac97/ac97_impl.h Sun Aug 30 15:32:09 2009 -0700 @@ -27,25 +27,28 @@ #ifndef _SYS_AC97_IMPL_H #define _SYS_AC97_IMPL_H -typedef struct ac97_ctrl ac97_ctrl_t; typedef void (*ac97_set_t)(ac97_ctrl_t *, uint64_t); /* * Per control state */ struct ac97_ctrl { - list_node_t actrl_linkage; /* For private cntrls list */ - struct ac97 *actrl_ac97; - int actrl_bits; /* Port width */ - uint32_t actrl_type; /* control type */ - const char *actrl_name; /* control's name */ - audio_ctrl_t *actrl_ctrl; /* control framework handle */ - ac97_set_t actrl_write_fn; /* control write function */ - uint64_t actrl_minval; /* MIN value for control */ - uint64_t actrl_maxval; /* MAX value for control */ - uint64_t actrl_value; /* current value in port */ - uint64_t actrl_initval; /* initial value in port */ - uint16_t actrl_muteable; /* if muteable, bits to do it */ + list_node_t actrl_linkage; /* For private cntrls list */ + struct ac97 *actrl_ac97; + int actrl_bits; /* Port width */ + audio_ctrl_t *actrl_ctrl; /* control framework handle */ + ac97_set_t actrl_write_fn; /* control write function */ + uint64_t actrl_value; /* current value in port */ + uint64_t actrl_initval; /* initial value in port */ + uint16_t actrl_muteable; /* if muteable, bits for it */ + boolean_t actrl_suppress; /* if true, do not register */ + audio_ctrl_desc_t actrl_desc; /* ctrl desc structure */ +#define actrl_name actrl_desc.acd_name +#define actrl_minval actrl_desc.acd_minvalue +#define actrl_maxval actrl_desc.acd_maxvalue +#define actrl_type actrl_desc.acd_type +#define actrl_flags actrl_desc.acd_flags +#define actrl_enum actrl_desc.acd_enum }; /* @@ -74,29 +77,21 @@ const char **cp_enum; /* Enumeration value */ } ac97_ctrl_probe_t; -typedef struct ac97_hooks { - void (*h_detach)(ac97_t *); - void (*h_reset)(ac97_t *); - void (*h_restore)(ac97_t *); -} ac97_hooks_t; - /* * These are the flags for most of our controls */ #define AC97_RW (AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE) #define AC97_FLAGS (AC97_RW | AUDIO_CTRL_FLAG_POLL) -void ac97_wr(ac97_t *, uint8_t, uint16_t); -uint16_t ac97_rd(ac97_t *, uint8_t); -void ac97_clr(ac97_t *, uint8_t, uint16_t); -void ac97_set(ac97_t *, uint8_t, uint16_t); -void ac97_alloc_control(ac97_t *, ac97_ctrl_probe_t *); -void ac97_free_control(ac97_ctrl_t *); -ac97_ctrl_t *ac97_control_find(ac97_t *, const char *); -uint16_t ac97_val_scale(int left, int right, int bits); -uint16_t ac97_mono_scale(int val, int bits); -audio_dev_t *ac97_get_dev(ac97_t *); -int ac97_get_prop(ac97_t *, char *, int); +void ac_wr(ac97_t *, uint8_t, uint16_t); +uint16_t ac_rd(ac97_t *, uint8_t); +void ac_clr(ac97_t *, uint8_t, uint16_t); +void ac_set(ac97_t *, uint8_t, uint16_t); +void ac_add_control(ac97_t *, ac97_ctrl_probe_t *); +uint16_t ac_val_scale(int left, int right, int bits); +uint16_t ac_mono_scale(int val, int bits); +audio_dev_t *ac_get_dev(ac97_t *); +int ac_get_prop(ac97_t *, char *, int); /* Codec specific initializations */
--- a/usr/src/uts/common/sys/audio/ac97.h Sun Aug 30 11:07:50 2009 -0700 +++ b/usr/src/uts/common/sys/audio/ac97.h Sun Aug 30 15:32:09 2009 -0700 @@ -601,10 +601,51 @@ typedef struct ac97 ac97_t; typedef void (*ac97_wr_t)(void *, uint8_t, uint16_t); typedef uint16_t (*ac97_rd_t)(void *, uint8_t); +typedef struct ac97_ctrl ac97_ctrl_t; +typedef boolean_t (*ac97_ctrl_walk_t)(ac97_ctrl_t *, void *); +/* + * Old style initialization. The driver simply calls ac97_alloc() + * followed by ac97_init(). These interfaces should not be used in + * new drivers. + */ ac97_t *ac97_alloc(dev_info_t *, ac97_rd_t, ac97_wr_t, void *); +int ac97_init(ac97_t *, audio_dev_t *); + +/* + * New style initialization. The driver will call ac97_allocate(), + * then it can call ac97_register_controls() to register controls. + * Or, if it doesn't want all controls registered, it can find + * controls with ac97_find_control(), and register them individually + * with ac97_register_control(). ac97_alloc() + * + * Note that adjusting the set of controls should only be performed + * while the driver is single threaded, during attach or detach + * processing. The AC'97 framework does not provide any locks + * surrounding its internal list of controls. Note however that + * changes to the controls made from within the framework (e.g. by + * someone accessing the control via the audio framework) are safe. + */ +ac97_t *ac97_allocate(audio_dev_t *, dev_info_t *, ac97_rd_t, ac97_wr_t, + void *); +void ac97_probe_controls(ac97_t *); +void ac97_register_controls(ac97_t *); +void ac97_unregister_controls(ac97_t *); + +void ac97_walk_controls(ac97_t *, ac97_ctrl_walk_t, void *); +ac97_ctrl_t *ac97_control_find(ac97_t *, const char *); +void ac97_control_register(ac97_ctrl_t *); +void ac97_control_unregister(ac97_ctrl_t *); +void ac97_control_remove(ac97_ctrl_t *); +const char *ac97_control_name(ac97_ctrl_t *); +const audio_ctrl_desc_t *ac97_control_desc(ac97_ctrl_t *); +int ac97_control_get(ac97_ctrl_t *, uint64_t *); +int ac97_control_set(ac97_ctrl_t *, uint64_t); + +/* + * Bits common to both new style and old style initialization. + */ void ac97_free(ac97_t *); -int ac97_init(ac97_t *, audio_dev_t *); void ac97_suspend(ac97_t *); void ac97_resume(ac97_t *); void ac97_reset(ac97_t *);