At Fri, 07 Oct 2011 13:49:46 +0200, David Henningsson wrote:
So, this is what I had in mind for 3.2. Assuming positive feedback from Takashi I'll go ahead and make a real patch out of this, and to clean up the Realtek implementation, as well as probably add this method for more codecs.
Thoughts:
- The unsol event tags vary wildly between different vendors. How about
standardising that as well?
Generalization is good. But tags aren't always constant. It'd be better to assign each tag dynamically like in patch_sigmatel.c. The reason is that you'd need to know the pin NID from the unsol event, so the tag has to be unique even for the same purpose. E.g. if a machine has two headphones, both are the same type but they should issue unsol events with different tags.
- If alc_init_jacks would call the new method, that might regress
model-based (non auto) parsers. Is that a big deal these days?
I don't think so. And most of all model-based entries will vanish in 3.3. In 3.2, already a half of realtek quirks are gone.
- Todo for realtek parser is to clean up all other calls to
snd_input_jack_report so that jacks are not reported twice.
thanks,
Takashi
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e9b039c..69390fd 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -5284,6 +5284,142 @@ int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, } EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
+/**
- snd_hda_input_auto_jack_add - Add relevant input jacks based on
- auto pin configuration.
- @param unsol_tags lists of jack types to enable, terminate with
- list entry with jack_type set to 0. If unsol_tag is set to 0,
- unsol events will not be enabled for that jack type.
- @return 0 or error code
- */
+int snd_hda_input_auto_jack_add(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
const struct hda_unsol_jack_tag* unsol_tags)
+{
- for (; unsol_tags->jack_type; unsol_tags++) {
hda_nid_t nid_list_storage[AUTO_CFG_MAX_INS];
const hda_nid_t *nid_list;
int nid_count = 0;
int i;
int input_match = AUTO_PIN_MIC;
switch (unsol_tags->jack_type) {
case SND_JACK_LINEIN:
input_match = AUTO_PIN_LINE_IN;
/* Fall through */
case SND_JACK_MICROPHONE:
for (i = 0; i < cfg->num_inputs; i++) {
if (cfg->inputs[i].type == input_match)
nid_list_storage[nid_count++] = cfg->inputs[i].pin;
}
nid_list = nid_list_storage;
break;
case SND_JACK_HEADPHONE:
if (cfg->line_out_type == AUTO_PIN_HP_OUT) {
nid_list = cfg->line_out_pins;
nid_count = cfg->line_outs;
} else {
nid_list = cfg->hp_pins;
nid_count = cfg->hp_outs;
}
break;
case SND_JACK_LINEOUT:
if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
nid_list = cfg->line_out_pins;
nid_count = cfg->line_outs;
}
break;
}
for (i = 0; i < nid_count; i++) {
int pin = nid_list[i];
int err;
if (!is_jack_detectable(codec, pin))
continue;
if (unsol_tags->unsol_tag) {
err = snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | unsol_tags->unsol_tag);
if (err)
return err;
}
err = snd_hda_input_jack_add(codec, pin,
unsol_tags->jack_type, NULL);
if (err)
return err;
snd_hda_input_jack_report(codec, pin);
}
- }
- return 0;
+} +EXPORT_SYMBOL_HDA(snd_hda_input_auto_jack_add);
+void snd_hda_input_jack_report_type(struct hda_codec *codec, int jack_type) +{
- struct hda_jack_item *jacks = codec->jacks.list;
- int i;
- if (!jacks)
return;
- for (i = 0; i < codec->jacks.used; i++, jacks++)
if (jacks->type == jack_type)
snd_hda_input_jack_report(codec, jacks->nid);
+} +EXPORT_SYMBOL_HDA(snd_hda_input_jack_report_type);
- void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) { struct hda_jack_item *jacks = codec->jacks.list;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 46c581c..bb59a3f 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -678,11 +678,21 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); /*
- Input-jack notification support
*/
+struct hda_unsol_jack_tag {
- int jack_type; /* SND_JACK_xxx constant */
- int unsol_tag; /* event tag */
+};
- #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_report_type(struct hda_codec *codec, int jack_type); void snd_hda_input_jack_free(struct hda_codec *codec); +int snd_hda_input_auto_jack_add(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
#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 struct hda_unsol_jack_tag *unsol_tags);
@@ -694,9 +704,19 @@ static inline void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) { } +static inline void snd_hda_input_jack_report_type(struct hda_codec *codec,
int jack_type)
+{ +} static inline void snd_hda_input_jack_free(struct hda_codec *codec) { } +static inline int snd_hda_input_auto_jack_add(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
const struct hda_unsol_jack_tag *unsol_tags)
+{
- return 0;
+} #endif /* CONFIG_SND_HDA_INPUT_JACK */
#endif /* __SOUND_HDA_LOCAL_H */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bf53663..90cdd6c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -38,6 +38,7 @@ #define ALC_DCVOL_EVENT 0x02 #define ALC_HP_EVENT 0x04 #define ALC_MIC_EVENT 0x08 +#define ALC_LINEIN_EVENT 0x10
/* for GPIO Poll */ #define GPIO_MASK 0x03 @@ -441,11 +442,21 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
- Jack-reporting via input-jack layer
*/
+static const struct hda_unsol_jack_tag unsol_tags[] = {
- {.jack_type = SND_JACK_HEADPHONE, .unsol_tag = ALC_HP_EVENT },
- {.jack_type = SND_JACK_LINEOUT, .unsol_tag = ALC_FRONT_EVENT },
- {.jack_type = SND_JACK_MICROPHONE, .unsol_tag = ALC_MIC_EVENT },
- {.jack_type = SND_JACK_LINEIN, .unsol_tag = ALC_LINEIN_EVENT },
- {} /* Zero terminator */
+};
- /* initialization of jacks; currently checks only a few known pins */ static int alc_init_jacks(struct hda_codec *codec) { #ifdef CONFIG_SND_HDA_INPUT_JACK struct alc_spec *spec = codec->spec;
- snd_hda_input_auto_jack_add(codec, &spec->autocfg, unsol_tags);
+/* ; int err; unsigned int hp_nid = spec->autocfg.hp_pins[0]; unsigned int mic_nid = spec->ext_mic_pin; @@ -472,7 +483,7 @@ static int alc_init_jacks(struct hda_codec *codec) if (err < 0) return err; snd_hda_input_jack_report(codec, dock_nid);
- }
- }*/ #endif /* CONFIG_SND_HDA_INPUT_JACK */ return 0; }
@@ -645,12 +656,18 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) switch (res) { case ALC_HP_EVENT: alc_hp_automute(codec);
break; case ALC_FRONT_EVENT: alc_line_automute(codec);snd_hda_input_jack_report_type(codec, SND_JACK_HEADPHONE);
break; case ALC_MIC_EVENT: alc_mic_automute(codec);snd_hda_input_jack_report_type(codec, SND_JACK_LINEOUT);
snd_hda_input_jack_report_type(codec, SND_JACK_MICROPHONE);
break;
- case ALC_LINEIN_EVENT:
break; } }snd_hda_input_jack_report_type(codec, SND_JACK_LINEIN);
-- David Henningsson, Canonical Ltd. http://launchpad.net/~diwic