mirror of https://gitee.com/openkylin/linux.git
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:
parent
d207df2df0
commit
cd372fb3be
|
@ -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");
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue