/* execute pin sense measurement */ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) { u32 pincap; if (!codec->no_trigger_sense) { pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); } return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); }
static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) { snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, AC_VERB_SET_COEF_INDEX, idx); return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0, AC_VERB_GET_PROC_COEF, 0); }
/* execute pin sense measurement */ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) { u32 pincap; u32 val; if (!codec->no_trigger_sense) { pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); } val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); if (codec->inv_jack_detect) val ^= AC_PINSENSE_PRESENCE; return val; }
static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) { struct cs_spec *spec = codec->spec; snd_hda_codec_write(codec, spec->vendor_nid, 0, AC_VERB_SET_COEF_INDEX, idx); return snd_hda_codec_read(codec, spec->vendor_nid, 0, AC_VERB_GET_PROC_COEF, 0); }
/* mute internal speaker if HP is plugged */ static void cxt5045_hp_automute(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; unsigned int bits; spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); }
static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, int byte_index) { unsigned int val; val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, byte_index); #ifdef BE_PARANOID printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); #endif return val; }
static void cs_automic(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid; unsigned int caps, present; nid = cfg->input_pins[spec->automic_idx]; caps = snd_hda_query_pin_caps(codec, nid); if (caps & AC_PINCAP_TRIG_REQ) snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); present = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); if (present & AC_PINSENSE_PRESENCE) change_cur_input(codec, spec->automic_idx, 0); else { unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC; change_cur_input(codec, imic, 0); } }
static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long *valp = ucontrol->value.integer.value; unsigned int val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0x00); *valp = (val & mask) != 0; return 0; }
static void cs_automute(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int caps, present, hp_present; hda_nid_t nid; int i; hp_present = 0; for (i = 0; i < cfg->hp_outs; i++) { nid = cfg->hp_pins[i]; caps = snd_hda_query_pin_caps(codec, nid); if (!(caps & AC_PINCAP_PRES_DETECT)) continue; if (caps & AC_PINCAP_TRIG_REQ) snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); present = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); hp_present |= (present & AC_PINSENSE_PRESENCE) != 0; if (hp_present) break; } for (i = 0; i < cfg->speaker_outs; i++) { nid = cfg->speaker_pins[i]; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, hp_present ? 0 : PIN_OUT); } if (spec->board_config == CS420X_MBP53 || spec->board_config == CS420X_MBP55 || spec->board_config == CS420X_IMAC27) { unsigned int gpio = hp_present ? 0x02 : 0x08; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); } }
/* Chip access helper function */ static int chipio_send(struct hda_codec *codec, unsigned int reg, unsigned int data) { unsigned int res; int retry = 50; /* send bits of data specified by reg */ do { res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, reg, data); if (res == VENDOR_STATUS_CHIPIO_OK) return 0; } while (--retry); return -EIO; }
static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid, int byte_index) { unsigned int val; val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, byte_index); #ifdef BE_PARANOID printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); #endif if ((val & AC_ELDD_ELD_VALID) == 0) { snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", byte_index); val = 0; } return val & AC_ELDD_ELD_DATA; }
/* toggle input of built-in and mic jack appropriately */ static void cxt5045_hp_automic(struct hda_codec *codec) { static struct hda_verb mic_jack_on[] = { {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, {} }; static struct hda_verb mic_jack_off[] = { {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, {} }; unsigned int present; present = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; if (present) snd_hda_sequence_write(codec, mic_jack_on); else snd_hda_sequence_write(codec, mic_jack_off); }
static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long val = *ucontrol->value.integer.value; unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_GPIO_DATA, 0x00); unsigned int old_data = gpio_data; /* Set/unset the masked GPIO bit(s) as needed */ if (val == 0) gpio_data &= ~mask; else gpio_data |= mask; if (gpio_data == old_data && !codec->in_resume) return 0; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); return 1; }
static int patch_cmi9880(struct hda_codec *codec) { struct cmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, cmi9880_models, cmi9880_cfg_tbl); if (spec->board_config < 0) { snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); spec->board_config = CMI_AUTO; /* try everything */ } /* copy default DAC NIDs */ memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); spec->num_dacs = 4; switch (spec->board_config) { case CMI_MINIMAL: case CMI_MIN_FP: spec->channel_modes = cmi9880_channel_modes; if (spec->board_config == CMI_MINIMAL) spec->num_channel_modes = 2; else { spec->front_panel = 1; spec->num_channel_modes = 3; } spec->multiout.max_channels = cmi9880_channel_modes[0].channels; spec->input_mux = &cmi9880_basic_mux; break; case CMI_FULL: case CMI_FULL_DIG: spec->front_panel = 1; spec->multiout.max_channels = 8; spec->input_mux = &cmi9880_basic_mux; if (spec->board_config == CMI_FULL_DIG) { spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; spec->dig_in_nid = CMI_DIG_IN_NID; } break; case CMI_ALLOUT: spec->front_panel = 1; spec->multiout.max_channels = 8; spec->no_line_in = 1; spec->input_mux = &cmi9880_no_line_mux; spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; break; case CMI_AUTO: { unsigned int port_e, port_f, port_g, port_h; unsigned int port_spdifi, port_spdifo; struct auto_pin_cfg cfg; /* collect pin default configuration */ port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); spec->front_panel = 1; if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); spec->channel_modes = cmi9880_channel_modes; /* no front panel */ if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { /* no optional rear panel */ spec->board_config = CMI_MINIMAL; spec->front_panel = 0; spec->num_channel_modes = 2; } else { spec->board_config = CMI_MIN_FP; spec->num_channel_modes = 3; } spec->input_mux = &cmi9880_basic_mux; spec->multiout.max_channels = cmi9880_channel_modes[0].channels; } else { spec->input_mux = &cmi9880_basic_mux; port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) spec->dig_in_nid = CMI_DIG_IN_NID; spec->multiout.max_channels = 8; } snd_hda_parse_pin_def_config(codec, &cfg, NULL); if (cfg.line_outs) { spec->multiout.max_channels = cfg.line_outs * 2; cmi9880_fill_multi_dac_nids(codec, &cfg); cmi9880_fill_multi_init(codec, &cfg); } else snd_printd("patch_cmedia: cannot detect association in defcfg\n"); break; } } spec->multiout.num_dacs = spec->num_dacs; spec->multiout.dac_nids = spec->dac_nids; spec->adc_nids = cmi9880_adc_nids; codec->patch_ops = cmi9880_patch_ops; return 0; }
int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) { return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, AC_DIPSIZE_ELD_BUF); }
static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid) { return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); }