diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ee958a7d1647..2da787519513 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2166,12 +2166,12 @@ EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv); | |||
2166 | 2166 | ||
2167 | /* find a mixer control element with the given name */ | 2167 | /* find a mixer control element with the given name */ |
2168 | static struct snd_kcontrol * | 2168 | static struct snd_kcontrol * |
2169 | _snd_hda_find_mixer_ctl(struct hda_codec *codec, | 2169 | find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx) |
2170 | const char *name, int idx) | ||
2171 | { | 2170 | { |
2172 | struct snd_ctl_elem_id id; | 2171 | struct snd_ctl_elem_id id; |
2173 | memset(&id, 0, sizeof(id)); | 2172 | memset(&id, 0, sizeof(id)); |
2174 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 2173 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
2174 | id.device = dev; | ||
2175 | id.index = idx; | 2175 | id.index = idx; |
2176 | if (snd_BUG_ON(strlen(name) >= sizeof(id.name))) | 2176 | if (snd_BUG_ON(strlen(name) >= sizeof(id.name))) |
2177 | return NULL; | 2177 | return NULL; |
@@ -2189,15 +2189,16 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
2189 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 2189 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, |
2190 | const char *name) | 2190 | const char *name) |
2191 | { | 2191 | { |
2192 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 2192 | return find_mixer_ctl(codec, name, 0, 0); |
2193 | } | 2193 | } |
2194 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | 2194 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); |
2195 | 2195 | ||
2196 | static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name) | 2196 | static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name, |
2197 | int dev) | ||
2197 | { | 2198 | { |
2198 | int idx; | 2199 | int idx; |
2199 | for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ | 2200 | for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ |
2200 | if (!_snd_hda_find_mixer_ctl(codec, name, idx)) | 2201 | if (!find_mixer_ctl(codec, name, dev, idx)) |
2201 | return idx; | 2202 | return idx; |
2202 | } | 2203 | } |
2203 | return -EBUSY; | 2204 | return -EBUSY; |
@@ -3148,26 +3149,48 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
3148 | }; | 3149 | }; |
3149 | 3150 | ||
3150 | /** | 3151 | /** |
3151 | * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls | 3152 | * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls |
3152 | * @codec: the HDA codec | 3153 | * @codec: the HDA codec |
3153 | * @nid: audio out widget NID | 3154 | * @associated_nid: NID that new ctls associated with |
3154 | * | 3155 | * @cvt_nid: converter NID |
3155 | * Creates controls related with the SPDIF output. | 3156 | * @type: HDA_PCM_TYPE_* |
3156 | * Called from each patch supporting the SPDIF out. | 3157 | * Creates controls related with the digital output. |
3158 | * Called from each patch supporting the digital out. | ||
3157 | * | 3159 | * |
3158 | * Returns 0 if successful, or a negative error code. | 3160 | * Returns 0 if successful, or a negative error code. |
3159 | */ | 3161 | */ |
3160 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, | 3162 | int snd_hda_create_dig_out_ctls(struct hda_codec *codec, |
3161 | hda_nid_t associated_nid, | 3163 | hda_nid_t associated_nid, |
3162 | hda_nid_t cvt_nid) | 3164 | hda_nid_t cvt_nid, |
3165 | int type) | ||
3163 | { | 3166 | { |
3164 | int err; | 3167 | int err; |
3165 | struct snd_kcontrol *kctl; | 3168 | struct snd_kcontrol *kctl; |
3166 | struct snd_kcontrol_new *dig_mix; | 3169 | struct snd_kcontrol_new *dig_mix; |
3167 | int idx; | 3170 | int idx, dev = 0; |
3171 | const int spdif_pcm_dev = 1; | ||
3168 | struct hda_spdif_out *spdif; | 3172 | struct hda_spdif_out *spdif; |
3169 | 3173 | ||
3170 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); | 3174 | if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI && |
3175 | type == HDA_PCM_TYPE_SPDIF) { | ||
3176 | dev = spdif_pcm_dev; | ||
3177 | } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF && | ||
3178 | type == HDA_PCM_TYPE_HDMI) { | ||
3179 | for (idx = 0; idx < codec->spdif_out.used; idx++) { | ||
3180 | spdif = snd_array_elem(&codec->spdif_out, idx); | ||
3181 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { | ||
3182 | kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx); | ||
3183 | if (!kctl) | ||
3184 | break; | ||
3185 | kctl->id.device = spdif_pcm_dev; | ||
3186 | } | ||
3187 | } | ||
3188 | codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI; | ||
3189 | } | ||
3190 | if (!codec->primary_dig_out_type) | ||
3191 | codec->primary_dig_out_type = type; | ||
3192 | |||
3193 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev); | ||
3171 | if (idx < 0) { | 3194 | if (idx < 0) { |
3172 | printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); | 3195 | printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); |
3173 | return -EBUSY; | 3196 | return -EBUSY; |
@@ -3177,6 +3200,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, | |||
3177 | kctl = snd_ctl_new1(dig_mix, codec); | 3200 | kctl = snd_ctl_new1(dig_mix, codec); |
3178 | if (!kctl) | 3201 | if (!kctl) |
3179 | return -ENOMEM; | 3202 | return -ENOMEM; |
3203 | kctl->id.device = dev; | ||
3180 | kctl->id.index = idx; | 3204 | kctl->id.index = idx; |
3181 | kctl->private_value = codec->spdif_out.used - 1; | 3205 | kctl->private_value = codec->spdif_out.used - 1; |
3182 | err = snd_hda_ctl_add(codec, associated_nid, kctl); | 3206 | err = snd_hda_ctl_add(codec, associated_nid, kctl); |
@@ -3189,7 +3213,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, | |||
3189 | spdif->status = convert_to_spdif_status(spdif->ctls); | 3213 | spdif->status = convert_to_spdif_status(spdif->ctls); |
3190 | return 0; | 3214 | return 0; |
3191 | } | 3215 | } |
3192 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); | 3216 | EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls); |
3193 | 3217 | ||
3194 | /* get the hda_spdif_out entry from the given NID | 3218 | /* get the hda_spdif_out entry from the given NID |
3195 | * call within spdif_mutex lock | 3219 | * call within spdif_mutex lock |
@@ -3364,7 +3388,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
3364 | struct snd_kcontrol_new *dig_mix; | 3388 | struct snd_kcontrol_new *dig_mix; |
3365 | int idx; | 3389 | int idx; |
3366 | 3390 | ||
3367 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch"); | 3391 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0); |
3368 | if (idx < 0) { | 3392 | if (idx < 0) { |
3369 | printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); | 3393 | printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); |
3370 | return -EBUSY; | 3394 | return -EBUSY; |
@@ -4472,7 +4496,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, | |||
4472 | addr = codec->addr; | 4496 | addr = codec->addr; |
4473 | else if (!idx && !knew->index) { | 4497 | else if (!idx && !knew->index) { |
4474 | idx = find_empty_mixer_ctl_idx(codec, | 4498 | idx = find_empty_mixer_ctl_idx(codec, |
4475 | knew->name); | 4499 | knew->name, 0); |
4476 | if (idx <= 0) | 4500 | if (idx <= 0) |
4477 | return err; | 4501 | return err; |
4478 | } else | 4502 | } else |