ALSA: hda - Make common input-jack helper functions

Since multiple codec drivers already use the input-jack stuff, let's
make common helper functions to reduce the duplicated codes.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2011-03-03 14:40:14 +01:00
parent d207df2df0
commit cd372fb3be
6 changed files with 165 additions and 272 deletions

View File

@ -29,6 +29,7 @@
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/jack.h>
#include "hda_local.h" #include "hda_local.h"
#include "hda_beep.h" #include "hda_beep.h"
#include <sound/hda_hwdep.h> #include <sound/hda_hwdep.h>
@ -4959,5 +4960,109 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
} }
EXPORT_SYMBOL_HDA(snd_print_pcm_bits); EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
#ifdef CONFIG_SND_HDA_INPUT_JACK
/*
* Input-jack notification support
*/
struct hda_jack_item {
hda_nid_t nid;
int type;
struct snd_jack *jack;
};
static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,
int type)
{
switch (type) {
case SND_JACK_HEADPHONE:
return "Headphone";
case SND_JACK_MICROPHONE:
return "Mic";
case SND_JACK_LINEOUT:
return "Line-out";
case SND_JACK_HEADSET:
return "Headset";
default:
return "Misc";
}
}
static void hda_free_jack_priv(struct snd_jack *jack)
{
struct hda_jack_item *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}
int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
const char *name)
{
struct hda_jack_item *jack;
int err;
snd_array_init(&codec->jacks, sizeof(*jack), 32);
jack = snd_array_new(&codec->jacks);
if (!jack)
return -ENOMEM;
jack->nid = nid;
jack->type = type;
if (!name)
name = get_jack_default_name(codec, nid, type);
err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
if (err < 0) {
jack->nid = 0;
return err;
}
jack->jack->private_data = jack;
jack->jack->private_free = hda_free_jack_priv;
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_item *jacks = codec->jacks.list;
int i;
if (!jacks)
return;
for (i = 0; i < codec->jacks.used; i++, jacks++) {
unsigned int pin_ctl;
unsigned int present;
int type;
if (jacks->nid != nid)
continue;
present = snd_hda_jack_detect(codec, nid);
type = jacks->type;
if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) {
pin_ctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
type = (pin_ctl & AC_PINCTL_HP_EN) ?
SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
}
snd_jack_report(jacks->jack, present ? type : 0);
}
}
EXPORT_SYMBOL_HDA(snd_hda_input_jack_report);
/* free jack instances manually when clearing/reconfiguring */
void snd_hda_input_jack_free(struct hda_codec *codec)
{
if (!codec->bus->shutdown && codec->jacks.list) {
struct hda_jack_item *jacks = codec->jacks.list;
int i;
for (i = 0; i < codec->jacks.used; i++, jacks++) {
if (jacks->jack)
snd_device_free(codec->bus->card, jacks->jack);
}
}
snd_array_free(&codec->jacks);
}
EXPORT_SYMBOL_HDA(snd_hda_input_jack_free);
#endif /* CONFIG_SND_HDA_INPUT_JACK */
MODULE_DESCRIPTION("HDA codec core"); MODULE_DESCRIPTION("HDA codec core");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -866,6 +866,11 @@ struct hda_codec {
/* codec-specific additional proc output */ /* codec-specific additional proc output */
void (*proc_widget_hook)(struct snd_info_buffer *buffer, void (*proc_widget_hook)(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid); struct hda_codec *codec, hda_nid_t nid);
#ifdef CONFIG_SND_HDA_INPUT_JACK
/* jack detection */
struct snd_array jacks;
#endif
}; };
/* direction */ /* direction */

View File

@ -656,4 +656,28 @@ static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
/*
* Input-jack notification support
*/
#ifdef CONFIG_SND_HDA_INPUT_JACK
int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
const char *name);
void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);
void snd_hda_input_jack_free(struct hda_codec *codec);
#else /* CONFIG_SND_HDA_INPUT_JACK */
static inline int snd_hda_input_jack_add(struct hda_codec *codec,
hda_nid_t nid, int type,
const char *name)
{
return 0;
}
static inline void snd_hda_input_jack_report(struct hda_codec *codec,
hda_nid_t nid)
{
}
static inline void snd_hda_input_jack_free(struct hda_codec *codec)
{
}
#endif /* CONFIG_SND_HDA_INPUT_JACK */
#endif /* __SOUND_HDA_LOCAL_H */ #endif /* __SOUND_HDA_LOCAL_H */

View File

@ -49,14 +49,6 @@
#define AUTO_MIC_PORTB (1 << 1) #define AUTO_MIC_PORTB (1 << 1)
#define AUTO_MIC_PORTC (1 << 2) #define AUTO_MIC_PORTC (1 << 2)
struct conexant_jack {
hda_nid_t nid;
int type;
struct snd_jack *jack;
};
struct pin_dac_pair { struct pin_dac_pair {
hda_nid_t pin; hda_nid_t pin;
hda_nid_t dac; hda_nid_t dac;
@ -111,9 +103,6 @@ struct conexant_spec {
unsigned int spdif_route; unsigned int spdif_route;
/* jack detection */
struct snd_array jacks;
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
@ -393,71 +382,9 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
&spec->cur_mux[adc_idx]); &spec->cur_mux[adc_idx]);
} }
#ifdef CONFIG_SND_HDA_INPUT_JACK
static void conexant_free_jack_priv(struct snd_jack *jack)
{
struct conexant_jack *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}
static int conexant_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
struct conexant_spec *spec;
struct conexant_jack *jack;
const char *name;
int i, err;
spec = codec->spec;
snd_array_init(&spec->jacks, sizeof(*jack), 32);
jack = spec->jacks.list;
for (i = 0; i < spec->jacks.used; i++, jack++)
if (jack->nid == nid)
return 0 ; /* already present */
jack = snd_array_new(&spec->jacks);
name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
if (!jack)
return -ENOMEM;
jack->nid = nid;
jack->type = type;
err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
if (err < 0)
return err;
jack->jack->private_data = jack;
jack->jack->private_free = conexant_free_jack_priv;
return 0;
}
static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
{
struct conexant_spec *spec = codec->spec;
struct conexant_jack *jacks = spec->jacks.list;
if (jacks) {
int i;
for (i = 0; i < spec->jacks.used; i++) {
if (jacks->nid == nid) {
unsigned int present;
present = snd_hda_jack_detect(codec, nid);
present = (present) ? jacks->type : 0 ;
snd_jack_report(jacks->jack,
present);
}
jacks++;
}
}
}
static int conexant_init_jacks(struct hda_codec *codec) static int conexant_init_jacks(struct hda_codec *codec)
{ {
#ifdef CONFIG_SND_HDA_INPUT_JACK
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
int i; int i;
@ -469,15 +396,15 @@ static int conexant_init_jacks(struct hda_codec *codec)
int err = 0; int err = 0;
switch (hv->param ^ AC_USRSP_EN) { switch (hv->param ^ AC_USRSP_EN) {
case CONEXANT_HP_EVENT: case CONEXANT_HP_EVENT:
err = conexant_add_jack(codec, hv->nid, err = snd_hda_input_jack_add(codec, hv->nid,
SND_JACK_HEADPHONE); SND_JACK_HEADPHONE, NULL);
conexant_report_jack(codec, hv->nid); snd_hda_input_jack_report(codec, hv->nid);
break; break;
case CXT5051_PORTC_EVENT: case CXT5051_PORTC_EVENT:
case CONEXANT_MIC_EVENT: case CONEXANT_MIC_EVENT:
err = conexant_add_jack(codec, hv->nid, err = snd_hda_input_jack_add(codec, hv->nid,
SND_JACK_MICROPHONE); SND_JACK_MICROPHONE, NULL);
conexant_report_jack(codec, hv->nid); snd_hda_input_jack_report(codec, hv->nid);
break; break;
} }
if (err < 0) if (err < 0)
@ -485,19 +412,9 @@ static int conexant_init_jacks(struct hda_codec *codec)
++hv; ++hv;
} }
} }
return 0; #endif /* CONFIG_SND_HDA_INPUT_JACK */
}
#else
static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
{
}
static inline int conexant_init_jacks(struct hda_codec *codec)
{
return 0; return 0;
} }
#endif
static int conexant_init(struct hda_codec *codec) static int conexant_init(struct hda_codec *codec)
{ {
@ -511,18 +428,7 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec) static void conexant_free(struct hda_codec *codec)
{ {
#ifdef CONFIG_SND_HDA_INPUT_JACK snd_hda_input_jack_free(codec);
struct conexant_spec *spec = codec->spec;
if (spec->jacks.list) {
struct conexant_jack *jacks = spec->jacks.list;
int i;
for (i = 0; i < spec->jacks.used; i++, jacks++) {
if (jacks->jack)
snd_device_free(codec->bus->card, jacks->jack);
}
snd_array_free(&spec->jacks);
}
#endif
snd_hda_detach_beep_device(codec); snd_hda_detach_beep_device(codec);
kfree(codec->spec); kfree(codec->spec);
} }
@ -1787,7 +1693,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
cxt5051_portc_automic(codec); cxt5051_portc_automic(codec);
break; break;
} }
conexant_report_jack(codec, nid); snd_hda_input_jack_report(codec, nid);
} }
static struct snd_kcontrol_new cxt5051_playback_mixers[] = { static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
@ -1959,10 +1865,8 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | event); AC_USRSP_EN | event);
#ifdef CONFIG_SND_HDA_INPUT_JACK snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
conexant_add_jack(codec, nid, SND_JACK_MICROPHONE); snd_hda_input_jack_report(codec, nid);
conexant_report_jack(codec, nid);
#endif
} }
static struct hda_verb cxt5051_ideapad_init_verbs[] = { static struct hda_verb cxt5051_ideapad_init_verbs[] = {
@ -3477,11 +3381,11 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
switch (res >> 26) { switch (res >> 26) {
case CONEXANT_HP_EVENT: case CONEXANT_HP_EVENT:
cx_auto_hp_automute(codec); cx_auto_hp_automute(codec);
conexant_report_jack(codec, nid); snd_hda_input_jack_report(codec, nid);
break; break;
case CONEXANT_MIC_EVENT: case CONEXANT_MIC_EVENT:
cx_auto_automic(codec); cx_auto_automic(codec);
conexant_report_jack(codec, nid); snd_hda_input_jack_report(codec, nid);
break; break;
} }
} }

View File

@ -282,12 +282,6 @@ struct alc_mic_route {
unsigned char amix_idx; unsigned char amix_idx;
}; };
struct alc_jack {
hda_nid_t nid;
int type;
struct snd_jack *jack;
};
#define MUX_IDX_UNDEF ((unsigned char)-1) #define MUX_IDX_UNDEF ((unsigned char)-1)
struct alc_customize_define { struct alc_customize_define {
@ -366,9 +360,6 @@ struct alc_spec {
/* PCM information */ /* PCM information */
struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
/* jack detection */
struct snd_array jacks;
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
struct alc_customize_define cdefine; struct alc_customize_define cdefine;
@ -1032,94 +1023,32 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
alc_fix_pll(codec); alc_fix_pll(codec);
} }
#ifdef CONFIG_SND_HDA_INPUT_JACK
static void alc_free_jack_priv(struct snd_jack *jack)
{
struct alc_jack *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}
static int alc_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
struct alc_spec *spec;
struct alc_jack *jack;
const char *name;
int err;
spec = codec->spec;
snd_array_init(&spec->jacks, sizeof(*jack), 32);
jack = snd_array_new(&spec->jacks);
if (!jack)
return -ENOMEM;
jack->nid = nid;
jack->type = type;
name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
if (err < 0)
return err;
jack->jack->private_data = jack;
jack->jack->private_free = alc_free_jack_priv;
return 0;
}
static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
{
struct alc_spec *spec = codec->spec;
struct alc_jack *jacks = spec->jacks.list;
if (jacks) {
int i;
for (i = 0; i < spec->jacks.used; i++) {
if (jacks->nid == nid) {
unsigned int present;
present = snd_hda_jack_detect(codec, nid);
present = (present) ? jacks->type : 0;
snd_jack_report(jacks->jack, present);
}
jacks++;
}
}
}
static int alc_init_jacks(struct hda_codec *codec) static int alc_init_jacks(struct hda_codec *codec)
{ {
#ifdef CONFIG_SND_HDA_INPUT_JACK
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int err; int err;
unsigned int hp_nid = spec->autocfg.hp_pins[0]; unsigned int hp_nid = spec->autocfg.hp_pins[0];
unsigned int mic_nid = spec->ext_mic.pin; unsigned int mic_nid = spec->ext_mic.pin;
if (hp_nid) { if (hp_nid) {
err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); err = snd_hda_input_jack_add(codec, hp_nid,
SND_JACK_HEADPHONE, NULL);
if (err < 0) if (err < 0)
return err; return err;
alc_report_jack(codec, hp_nid); snd_hda_input_jack_report(codec, hp_nid);
} }
if (mic_nid) { if (mic_nid) {
err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); err = snd_hda_input_jack_add(codec, mic_nid,
SND_JACK_MICROPHONE, NULL);
if (err < 0) if (err < 0)
return err; return err;
alc_report_jack(codec, mic_nid); snd_hda_input_jack_report(codec, mic_nid);
} }
#endif /* CONFIG_SND_HDA_INPUT_JACK */
return 0; return 0;
} }
#else
static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
{
}
static inline int alc_init_jacks(struct hda_codec *codec)
{
return 0;
}
#endif
static void alc_automute_speaker(struct hda_codec *codec, int pinctl) static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
{ {
@ -1133,7 +1062,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
nid = spec->autocfg.hp_pins[i]; nid = spec->autocfg.hp_pins[i];
if (!nid) if (!nid)
break; break;
alc_report_jack(codec, nid); snd_hda_input_jack_report(codec, nid);
spec->jack_present |= snd_hda_jack_detect(codec, nid); spec->jack_present |= snd_hda_jack_detect(codec, nid);
} }
@ -1240,7 +1169,7 @@ static void alc_mic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL, AC_VERB_SET_CONNECT_SEL,
alive->mux_idx); alive->mux_idx);
} }
alc_report_jack(codec, spec->ext_mic.pin); snd_hda_input_jack_report(codec, spec->ext_mic.pin);
/* FIXME: analog mixer */ /* FIXME: analog mixer */
} }
@ -4283,6 +4212,7 @@ static void alc_free(struct hda_codec *codec)
return; return;
alc_shutup(codec); alc_shutup(codec);
snd_hda_input_jack_free(codec);
alc_free_kctls(codec); alc_free_kctls(codec);
kfree(spec); kfree(spec);
snd_hda_detach_beep_device(codec); snd_hda_detach_beep_device(codec);
@ -14494,7 +14424,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
HDA_AMP_MUTE, bits); HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
HDA_AMP_MUTE, bits); HDA_AMP_MUTE, bits);
alc_report_jack(codec, nid); snd_hda_input_jack_report(codec, nid);
} }
/* unsolicited event for HP jack sensing */ /* unsolicited event for HP jack sensing */

View File

@ -180,12 +180,6 @@ struct sigmatel_event {
int data; int data;
}; };
struct sigmatel_jack {
hda_nid_t nid;
int type;
struct snd_jack *jack;
};
struct sigmatel_mic_route { struct sigmatel_mic_route {
hda_nid_t pin; hda_nid_t pin;
signed char mux_idx; signed char mux_idx;
@ -229,9 +223,6 @@ struct sigmatel_spec {
hda_nid_t *pwr_nids; hda_nid_t *pwr_nids;
hda_nid_t *dac_list; hda_nid_t *dac_list;
/* jack detection */
struct snd_array jacks;
/* events */ /* events */
struct snd_array events; struct snd_array events;
@ -4054,21 +4045,10 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
} }
#ifdef CONFIG_SND_HDA_INPUT_JACK
static void stac92xx_free_jack_priv(struct snd_jack *jack)
{
struct sigmatel_jack *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}
#endif
static int stac92xx_add_jack(struct hda_codec *codec, static int stac92xx_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type) hda_nid_t nid, int type)
{ {
#ifdef CONFIG_SND_HDA_INPUT_JACK #ifdef CONFIG_SND_HDA_INPUT_JACK
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_jack *jack;
int def_conf = snd_hda_codec_get_pincfg(codec, nid); int def_conf = snd_hda_codec_get_pincfg(codec, nid);
int connectivity = get_defcfg_connect(def_conf); int connectivity = get_defcfg_connect(def_conf);
char name[32]; char name[32];
@ -4077,26 +4057,15 @@ static int stac92xx_add_jack(struct hda_codec *codec,
if (connectivity && connectivity != AC_JACK_PORT_FIXED) if (connectivity && connectivity != AC_JACK_PORT_FIXED)
return 0; return 0;
snd_array_init(&spec->jacks, sizeof(*jack), 32);
jack = snd_array_new(&spec->jacks);
if (!jack)
return -ENOMEM;
jack->nid = nid;
jack->type = type;
snprintf(name, sizeof(name), "%s at %s %s Jack", snprintf(name, sizeof(name), "%s at %s %s Jack",
snd_hda_get_jack_type(def_conf), snd_hda_get_jack_type(def_conf),
snd_hda_get_jack_connectivity(def_conf), snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf)); snd_hda_get_jack_location(def_conf));
err = snd_jack_new(codec->bus->card, name, type, &jack->jack); err = snd_hda_input_jack_add(codec, nid, type, name);
if (err < 0) { if (err < 0)
jack->nid = 0;
return err; return err;
} #endif /* CONFIG_SND_HDA_INPUT_JACK */
jack->jack->private_data = jack;
jack->jack->private_free = stac92xx_free_jack_priv;
#endif
return 0; return 0;
} }
@ -4399,23 +4368,6 @@ static int stac92xx_init(struct hda_codec *codec)
return 0; return 0;
} }
static void stac92xx_free_jacks(struct hda_codec *codec)
{
#ifdef CONFIG_SND_HDA_INPUT_JACK
/* free jack instances manually when clearing/reconfiguring */
struct sigmatel_spec *spec = codec->spec;
if (!codec->bus->shutdown && spec->jacks.list) {
struct sigmatel_jack *jacks = spec->jacks.list;
int i;
for (i = 0; i < spec->jacks.used; i++, jacks++) {
if (jacks->jack)
snd_device_free(codec->bus->card, jacks->jack);
}
}
snd_array_free(&spec->jacks);
#endif
}
static void stac92xx_free_kctls(struct hda_codec *codec) static void stac92xx_free_kctls(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
@ -4449,7 +4401,7 @@ static void stac92xx_free(struct hda_codec *codec)
return; return;
stac92xx_shutup(codec); stac92xx_shutup(codec);
stac92xx_free_jacks(codec); snd_hda_input_jack_free(codec);
snd_array_free(&spec->events); snd_array_free(&spec->events);
kfree(spec); kfree(spec);
@ -4667,33 +4619,6 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
} }
static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
{
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_jack *jacks = spec->jacks.list;
if (jacks) {
int i;
for (i = 0; i < spec->jacks.used; i++) {
if (jacks->nid == nid) {
unsigned int pin_ctl =
snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL,
0x00);
int type = jacks->type;
if (type == (SND_JACK_LINEOUT
| SND_JACK_HEADPHONE))
type = (pin_ctl & AC_PINCTL_HP_EN)
? SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
snd_jack_report(jacks->jack,
get_pin_presence(codec, nid)
? type : 0);
}
jacks++;
}
}
}
/* get the pin connection (fixed, none, etc) */ /* get the pin connection (fixed, none, etc) */
static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
{ {
@ -4782,7 +4707,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
case STAC_PWR_EVENT: case STAC_PWR_EVENT:
if (spec->num_pwrs > 0) if (spec->num_pwrs > 0)
stac92xx_pin_sense(codec, event->nid); stac92xx_pin_sense(codec, event->nid);
stac92xx_report_jack(codec, event->nid); snd_hda_input_jack_report(codec, event->nid);
switch (codec->subsystem_id) { switch (codec->subsystem_id) {
case 0x103c308f: case 0x103c308f: