/* * Universal Interface for Intel High Definition Audio Codec * * HD audio interface patch for Conexant HDA audio codec * * Copyright (c) 2006 Pototskiy Akex * * * NO LICENSE NO WARRANTY * */ #include #include #include #include #include #include #include "hda_codec.h" #include "hda_local.h" #define MAIN_MUX 0x1A #define DAC 0x10 #define ADC 0x12 struct conexant_spec { unsigned int cur_mux; struct hda_pcm pcm; }; static struct hda_pcm_stream conexant_pcm_analog_playback = { .substreams = 1, .channels_min = 2, .channels_max = 2, .nid = DAC, /* NID to query formats and rates */ }; static struct hda_pcm_stream conexant_pcm_analog_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, .nid = ADC, /* NID to query formats and rates */ }; static int conexant_build_pcms(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; struct hda_pcm *info = &spec->pcm; codec->num_pcms = 1; codec->pcm_info = info; info->name = "CONEXANT"; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; info->stream[SNDRV_PCM_STREAM_CAPTURE] = conexant_pcm_analog_capture; return 0; } static struct hda_input_mux conexant_basic_mux = { .num_items = 2, .items = { {"ExtMic",0x01}, {"IntMic",0x02}, } }; static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { return snd_hda_input_mux_info(&conexant_basic_mux, uinfo); } static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct conexant_spec * spec = codec->spec; ucontrol->value.enumerated.item[0] = spec->cur_mux; return 0; } static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct conexant_spec *spec = codec->spec; return snd_hda_input_mux_put(codec, &conexant_basic_mux, ucontrol, MAIN_MUX, &spec->cur_mux); } static struct snd_kcontrol_new conexant_basic_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = conexant_mux_enum_info, .get = conexant_mux_enum_get, .put = conexant_mux_enum_put }, HDA_CODEC_VOLUME("Mic Bypass Capture Volume",0x19,0x02,HDA_INPUT), HDA_CODEC_MUTE("Mic Bypass Capture Switch",0x19,0x02,HDA_INPUT), HDA_CODEC_MUTE("Capture Switch",0x12,0x03,HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume",0x12,0x03,HDA_INPUT), HDA_CODEC_VOLUME("PCM Volume",0x10,0x00,HDA_OUTPUT), HDA_CODEC_MUTE("PCM Switch",0x10,0x00,HDA_OUTPUT), HDA_CODEC_VOLUME("Playback Volume",0x13,0x00,HDA_OUTPUT), HDA_CODEC_MUTE("Playback Switch",0x13,0x00,HDA_OUTPUT), {} }; static int conexant_build_controls(struct hda_codec *codec) { int err; err = snd_hda_add_new_ctls(codec,conexant_basic_mixer); if ( err < 0 ) return err; return 0; } static struct hda_verb conexant_basic_init[] = { {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, {0x1A, AC_VERB_SET_CONNECT_SEL,0x01}, {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, {} }; static int conexant_init(struct hda_codec *codec) { snd_hda_sequence_write(codec,conexant_basic_init); return 0; } static void conexant_free(struct hda_codec *codec) { kfree(codec->spec); return; } static struct hda_codec_ops conexant_patch_ops = { .build_controls = conexant_build_controls, .build_pcms = conexant_build_pcms, .init = conexant_init, .free = conexant_free }; static int patch_conexant(struct hda_codec *codec) { struct conexant_spec *spec; spec = kzalloc(sizeof(*spec),GFP_KERNEL); if ( !spec ) return -ENOMEM; codec->spec = spec; spec->cur_mux = 0; codec->patch_ops = conexant_patch_ops; return 0; } struct hda_codec_preset snd_hda_preset_conexant[] = { { .id = 0x14f15047, .name = "CONEXANT", .patch = patch_conexant }, {} /* terminator */ };