ALSA: hda - Update to use the new jack kctls method
Jack snd_kcontrols can now be created during snd_jack_new() or by later calling snd_jack_add_new_kctls(). This patch creates the jacks during the initialisation stage for both phantom and non phantom jacks. Signed-off-by: Jie Yang <yang.jie@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
					parent
					
						
							
								4e3f0dc658
							
						
					
				
			
			
				commit
				
					
						2ba2dfa1fc
					
				
			
		
					 6 changed files with 31 additions and 74 deletions
				
			
		|  | @ -252,7 +252,7 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); | ||||||
|  * Helper functions for jack-detection controls |  * Helper functions for jack-detection controls | ||||||
|  */ |  */ | ||||||
| struct snd_kcontrol * | struct snd_kcontrol * | ||||||
| snd_kctl_jack_new(const char *name, void *private_data, struct snd_card *card); | snd_kctl_jack_new(const char *name, struct snd_card *card); | ||||||
| void snd_kctl_jack_report(struct snd_card *card, | void snd_kctl_jack_report(struct snd_card *card, | ||||||
| 			  struct snd_kcontrol *kctl, bool status); | 			  struct snd_kcontrol *kctl, bool status); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -61,11 +61,11 @@ static void jack_kctl_name_gen(char *name, const char *src_name, int size) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct snd_kcontrol * | struct snd_kcontrol * | ||||||
| snd_kctl_jack_new(const char *name, void *private_data, struct snd_card *card) | snd_kctl_jack_new(const char *name, struct snd_card *card) | ||||||
| { | { | ||||||
| 	struct snd_kcontrol *kctl; | 	struct snd_kcontrol *kctl; | ||||||
| 
 | 
 | ||||||
| 	kctl = snd_ctl_new1(&jack_detect_kctl, private_data); | 	kctl = snd_ctl_new1(&jack_detect_kctl, NULL); | ||||||
| 	if (!kctl) | 	if (!kctl) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const cha | ||||||
| 	struct snd_jack_kctl *jack_kctl; | 	struct snd_jack_kctl *jack_kctl; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	kctl = snd_kctl_jack_new(name, card, card); | 	kctl = snd_kctl_jack_new(name, card); | ||||||
| 	if (!kctl) | 	if (!kctl) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -132,11 +132,11 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < codec->jacktbl.used; i++, jack++) { | 	for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||||||
| 		struct hda_jack_callback *cb, *next; | 		struct hda_jack_callback *cb, *next; | ||||||
| #ifdef CONFIG_SND_HDA_INPUT_JACK | 
 | ||||||
| 		/* free jack instances manually when clearing/reconfiguring */ | 		/* free jack instances manually when clearing/reconfiguring */ | ||||||
| 		if (!codec->bus->shutdown && jack->jack) | 		if (!codec->bus->shutdown && jack->jack) | ||||||
| 			snd_device_free(codec->card, jack->jack); | 			snd_device_free(codec->card, jack->jack); | ||||||
| #endif | 
 | ||||||
| 		for (cb = jack->callback; cb; cb = next) { | 		for (cb = jack->callback; cb; cb = next) { | ||||||
| 			next = cb->next; | 			next = cb->next; | ||||||
| 			kfree(cb); | 			kfree(cb); | ||||||
|  | @ -337,20 +337,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec) | ||||||
| 	jack = codec->jacktbl.list; | 	jack = codec->jacktbl.list; | ||||||
| 	for (i = 0; i < codec->jacktbl.used; i++, jack++) | 	for (i = 0; i < codec->jacktbl.used; i++, jack++) | ||||||
| 		if (jack->nid) { | 		if (jack->nid) { | ||||||
| 			if (!jack->kctl || jack->block_report) | 			if (!jack->jack || jack->block_report) | ||||||
| 				continue; | 				continue; | ||||||
| 			state = get_jack_plug_state(jack->pin_sense); | 			state = get_jack_plug_state(jack->pin_sense); | ||||||
| 			snd_kctl_jack_report(codec->card, jack->kctl, state); | 			snd_jack_report(jack->jack, | ||||||
| #ifdef CONFIG_SND_HDA_INPUT_JACK | 					state ? jack->type : 0); | ||||||
| 			if (jack->jack) |  | ||||||
| 				snd_jack_report(jack->jack, |  | ||||||
| 						state ? jack->type : 0); |  | ||||||
| #endif |  | ||||||
| 		} | 		} | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync); | EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SND_HDA_INPUT_JACK |  | ||||||
| /* guess the jack type from the pin-config */ | /* guess the jack type from the pin-config */ | ||||||
| static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) | static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) | ||||||
| { | { | ||||||
|  | @ -377,54 +372,42 @@ static void hda_free_jack_priv(struct snd_jack *jack) | ||||||
| 	jacks->nid = 0; | 	jacks->nid = 0; | ||||||
| 	jacks->jack = NULL; | 	jacks->jack = NULL; | ||||||
| } | } | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * snd_hda_jack_add_kctl - Add a kctl for the given pin |  * snd_hda_jack_add_kctl - Add a kctl for the given pin | ||||||
|  * @codec: the HDA codec |  * @codec: the HDA codec | ||||||
|  * @nid: pin NID to assign |  * @nid: pin NID to assign | ||||||
|  * @name: string name for the jack |  * @name: string name for the jack | ||||||
|  * @idx: index number for the jack |  | ||||||
|  * @phantom_jack: flag to deal as a phantom jack |  * @phantom_jack: flag to deal as a phantom jack | ||||||
|  * |  * | ||||||
|  * This assigns a jack-detection kctl to the given pin.  The kcontrol |  * This assigns a jack-detection kctl to the given pin.  The kcontrol | ||||||
|  * will have the given name and index. |  * will have the given name and index. | ||||||
|  */ |  */ | ||||||
| static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
| 			  const char *name, int idx, bool phantom_jack) | 			  const char *name, bool phantom_jack) | ||||||
| { | { | ||||||
| 	struct hda_jack_tbl *jack; | 	struct hda_jack_tbl *jack; | ||||||
| 	struct snd_kcontrol *kctl; | 	int err, state, type; | ||||||
| 	int err, state; |  | ||||||
| 
 | 
 | ||||||
| 	jack = snd_hda_jack_tbl_new(codec, nid); | 	jack = snd_hda_jack_tbl_new(codec, nid); | ||||||
| 	if (!jack) | 	if (!jack) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	if (jack->kctl) | 	if (jack->jack) | ||||||
| 		return 0; /* already created */ | 		return 0; /* already created */ | ||||||
| 	kctl = snd_kctl_jack_new(name, codec, codec->card); | 
 | ||||||
| 	if (!kctl) | 	type = get_input_jack_type(codec, nid); | ||||||
| 		return -ENOMEM; | 	err = snd_jack_new(codec->card, name, type, | ||||||
| 	err = snd_hda_ctl_add(codec, nid, kctl); | 			   &jack->jack, true, phantom_jack); | ||||||
| 	if (err < 0) | 	if (err < 0) | ||||||
| 		return err; | 		return err; | ||||||
| 	jack->kctl = kctl; |  | ||||||
| 	jack->phantom_jack = !!phantom_jack; |  | ||||||
| 
 | 
 | ||||||
|  | 	jack->phantom_jack = !!phantom_jack; | ||||||
|  | 	jack->type = type; | ||||||
|  | 	jack->jack->private_data = jack; | ||||||
|  | 	jack->jack->private_free = hda_free_jack_priv; | ||||||
| 	state = snd_hda_jack_detect(codec, nid); | 	state = snd_hda_jack_detect(codec, nid); | ||||||
| 	snd_kctl_jack_report(codec->card, kctl, state); | 	snd_jack_report(jack->jack, state ? jack->type : 0); | ||||||
| #ifdef CONFIG_SND_HDA_INPUT_JACK | 
 | ||||||
| 	if (!phantom_jack) { |  | ||||||
| 		jack->type = get_input_jack_type(codec, nid); |  | ||||||
| 		err = snd_jack_new(codec->card, name, jack->type, |  | ||||||
| 				   &jack->jack, false, false); |  | ||||||
| 		if (err < 0) |  | ||||||
| 			return err; |  | ||||||
| 		jack->jack->private_data = jack; |  | ||||||
| 		jack->jack->private_free = hda_free_jack_priv; |  | ||||||
| 		snd_jack_report(jack->jack, state ? jack->type : 0); |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -433,44 +416,23 @@ static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
|  * @codec: the HDA codec |  * @codec: the HDA codec | ||||||
|  * @nid: pin NID |  * @nid: pin NID | ||||||
|  * @name: the name string for the jack ctl |  * @name: the name string for the jack ctl | ||||||
|  * @idx: the ctl index for the jack ctl |  | ||||||
|  * |  * | ||||||
|  * This is a simple helper calling __snd_hda_jack_add_kctl(). |  * This is a simple helper calling __snd_hda_jack_add_kctl(). | ||||||
|  */ |  */ | ||||||
| int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
| 			  const char *name, int idx) | 			  const char *name) | ||||||
| { | { | ||||||
| 	return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); | 	return __snd_hda_jack_add_kctl(codec, nid, name, false); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl); | EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl); | ||||||
| 
 | 
 | ||||||
| /* get the unique index number for the given kctl name */ |  | ||||||
| static int get_unique_index(struct hda_codec *codec, const char *name, int idx) |  | ||||||
| { |  | ||||||
| 	struct hda_jack_tbl *jack; |  | ||||||
| 	int i, len = strlen(name); |  | ||||||
|  again: |  | ||||||
| 	jack = codec->jacktbl.list; |  | ||||||
| 	for (i = 0; i < codec->jacktbl.used; i++, jack++) { |  | ||||||
| 		/* jack->kctl.id contains "XXX Jack" name string with index */ |  | ||||||
| 		if (jack->kctl && |  | ||||||
| 		    !strncmp(name, jack->kctl->id.name, len) && |  | ||||||
| 		    !strcmp(" Jack", jack->kctl->id.name + len) && |  | ||||||
| 		    jack->kctl->id.index == idx) { |  | ||||||
| 			idx++; |  | ||||||
| 			goto again; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return idx; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
| 			 const struct auto_pin_cfg *cfg, | 			 const struct auto_pin_cfg *cfg, | ||||||
| 			 const char *base_name) | 			 const char *base_name) | ||||||
| { | { | ||||||
| 	unsigned int def_conf, conn; | 	unsigned int def_conf, conn; | ||||||
| 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||||||
| 	int idx, err; | 	int err; | ||||||
| 	bool phantom_jack; | 	bool phantom_jack; | ||||||
| 
 | 
 | ||||||
| 	if (!nid) | 	if (!nid) | ||||||
|  | @ -482,16 +444,14 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
| 	phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | 	phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | ||||||
| 		       !is_jack_detectable(codec, nid); | 		       !is_jack_detectable(codec, nid); | ||||||
| 
 | 
 | ||||||
| 	if (base_name) { | 	if (base_name) | ||||||
| 		strlcpy(name, base_name, sizeof(name)); | 		strlcpy(name, base_name, sizeof(name)); | ||||||
| 		idx = 0; | 	else | ||||||
| 	} else | 		snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL); | ||||||
| 		snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); |  | ||||||
| 	if (phantom_jack) | 	if (phantom_jack) | ||||||
| 		/* Example final name: "Internal Mic Phantom Jack" */ | 		/* Example final name: "Internal Mic Phantom Jack" */ | ||||||
| 		strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | 		strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | ||||||
| 	idx = get_unique_index(codec, name, idx); | 	err = __snd_hda_jack_add_kctl(codec, nid, name, phantom_jack); | ||||||
| 	err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); |  | ||||||
| 	if (err < 0) | 	if (err < 0) | ||||||
| 		return err; | 		return err; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,11 +39,8 @@ struct hda_jack_tbl { | ||||||
| 	unsigned int block_report:1;    /* in a transitional state - do not report to userspace */ | 	unsigned int block_report:1;    /* in a transitional state - do not report to userspace */ | ||||||
| 	hda_nid_t gating_jack;		/* valid when gating jack plugged */ | 	hda_nid_t gating_jack;		/* valid when gating jack plugged */ | ||||||
| 	hda_nid_t gated_jack;		/* gated is dependent on this jack */ | 	hda_nid_t gated_jack;		/* gated is dependent on this jack */ | ||||||
| 	struct snd_kcontrol *kctl;	/* assigned kctl for jack-detection */ |  | ||||||
| #ifdef CONFIG_SND_HDA_INPUT_JACK |  | ||||||
| 	int type; | 	int type; | ||||||
| 	struct snd_jack *jack; | 	struct snd_jack *jack; | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct hda_jack_tbl * | struct hda_jack_tbl * | ||||||
|  | @ -85,7 +82,7 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | ||||||
| bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); | ||||||
| 
 | 
 | ||||||
| int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||||||
| 			  const char *name, int idx); | 			  const char *name); | ||||||
| int snd_hda_jack_add_kctls(struct hda_codec *codec, | int snd_hda_jack_add_kctls(struct hda_codec *codec, | ||||||
| 			   const struct auto_pin_cfg *cfg); | 			   const struct auto_pin_cfg *cfg); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2081,7 +2081,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | ||||||
| 		strncat(hdmi_str, " Phantom", | 		strncat(hdmi_str, " Phantom", | ||||||
| 			sizeof(hdmi_str) - strlen(hdmi_str) - 1); | 			sizeof(hdmi_str) - strlen(hdmi_str) - 1); | ||||||
| 
 | 
 | ||||||
| 	return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); | 	return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int generic_hdmi_build_controls(struct hda_codec *codec) | static int generic_hdmi_build_controls(struct hda_codec *codec) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jie Yang
				Jie Yang