Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353103
b: refs/heads/master
c: a07a949
h: refs/heads/master
i:
  353101: ca1350c
  353099: 4914264
  353095: 16a67a4
  353087: d767105
v: v3
  • Loading branch information
Takashi Iwai committed Jan 12, 2013
1 parent 3774a30 commit cf0a821
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: affdb62b815b38261f09f9d4ec210a35c7ffb1f3
refs/heads/master: a07a949be6eb1c9aab06adaadce72dbd27b7d9cb
92 changes: 62 additions & 30 deletions trunk/sound/pci/hda/hda_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,25 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
return snd_hda_get_path_idx(codec, path);
}

/* fill the empty entries in the dac array for speaker/hp with the
* shared dac pointed by the paths
*/
static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
hda_nid_t *dacs, int *path_idx)
{
struct nid_path *path;
int i;

for (i = 0; i < num_outs; i++) {
if (dacs[i])
continue;
path = snd_hda_get_path_from_idx(codec, path_idx[i]);
if (!path)
continue;
dacs[i] = path->path[0];
}
}

/* fill in the dac_nids table from the parsed pin configuration */
static int fill_and_eval_dacs(struct hda_codec *codec,
bool fill_hardwired,
Expand Down Expand Up @@ -1183,19 +1202,6 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
spec->private_dac_nids, spec->out_paths,
&main_out_badness);

/* re-count num_dacs and squash invalid entries */
spec->multiout.num_dacs = 0;
for (i = 0; i < cfg->line_outs; i++) {
if (spec->private_dac_nids[i])
spec->multiout.num_dacs++;
else {
memmove(spec->private_dac_nids + i,
spec->private_dac_nids + i + 1,
sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
spec->private_dac_nids[cfg->line_outs - 1] = 0;
}
}

if (fill_mio_first &&
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
/* try to fill multi-io first */
Expand Down Expand Up @@ -1246,16 +1252,41 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
spec->multi_ios = 1; /* give badness */

/* re-count num_dacs and squash invalid entries */
spec->multiout.num_dacs = 0;
for (i = 0; i < cfg->line_outs; i++) {
if (spec->private_dac_nids[i])
spec->multiout.num_dacs++;
else {
memmove(spec->private_dac_nids + i,
spec->private_dac_nids + i + 1,
sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
spec->private_dac_nids[cfg->line_outs - 1] = 0;
}
}

spec->ext_channel_count = spec->min_channel_count =
spec->multiout.num_dacs;

if (spec->multi_ios == 2) {
for (i = 0; i < 2; i++)
spec->private_dac_nids[spec->multiout.num_dacs++] =
spec->multi_io[i].dac;
spec->ext_channel_count = 2;
} else if (spec->multi_ios) {
spec->multi_ios = 0;
badness += BAD_MULTI_IO;
}

/* re-fill the shared DAC for speaker / headphone */
if (cfg->line_out_type != AUTO_PIN_HP_OUT)
refill_shared_dacs(codec, cfg->hp_outs,
spec->multiout.hp_out_nid,
spec->hp_paths);
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
refill_shared_dacs(codec, cfg->speaker_outs,
spec->multiout.extra_out_nid,
spec->speaker_paths);

return badness;
}

Expand Down Expand Up @@ -1610,14 +1641,15 @@ static int ch_mode_info(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gen_spec *spec = codec->spec;
int chs;

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = spec->multi_ios + 1;
if (uinfo->value.enumerated.item > spec->multi_ios)
uinfo->value.enumerated.item = spec->multi_ios;
sprintf(uinfo->value.enumerated.name, "%dch",
(uinfo->value.enumerated.item + 1) * 2);
chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
sprintf(uinfo->value.enumerated.name, "%dch", chs);
return 0;
}

Expand All @@ -1626,7 +1658,8 @@ static int ch_mode_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gen_spec *spec = codec->spec;
ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
ucontrol->value.enumerated.item[0] =
(spec->ext_channel_count - spec->min_channel_count) / 2;
return 0;
}

Expand Down Expand Up @@ -1674,9 +1707,9 @@ static int ch_mode_put(struct snd_kcontrol *kcontrol,
ch = ucontrol->value.enumerated.item[0];
if (ch < 0 || ch > spec->multi_ios)
return -EINVAL;
if (ch == (spec->ext_channel_count - 1) / 2)
if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
return 0;
spec->ext_channel_count = (ch + 1) * 2;
spec->ext_channel_count = ch * 2 + spec->min_channel_count;
for (i = 0; i < spec->multi_ios; i++)
set_multi_io(codec, i, i < ch);
spec->multiout.max_channels = max(spec->ext_channel_count,
Expand Down Expand Up @@ -3127,17 +3160,16 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
if (err < 0)
return err;

/* check the multiple speaker pins */
if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
spec->const_channel_count = cfg->line_outs * 2;
else
spec->const_channel_count = cfg->speaker_outs * 2;

if (spec->multi_ios > 0)
spec->multiout.max_channels = max(spec->ext_channel_count,
spec->const_channel_count);
else
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
spec->const_channel_count = spec->ext_channel_count;
/* check the multiple speaker and headphone pins */
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
spec->const_channel_count = max(spec->const_channel_count,
cfg->speaker_outs * 2);
if (cfg->line_out_type != AUTO_PIN_HP_OUT)
spec->const_channel_count = max(spec->const_channel_count,
cfg->hp_outs * 2);
spec->multiout.max_channels = max(spec->ext_channel_count,
spec->const_channel_count);

err = check_auto_mute_availability(codec);
if (err < 0)
Expand Down
16 changes: 14 additions & 2 deletions trunk/sound/pci/hda/hda_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,20 @@ struct hda_gen_spec {
unsigned int cur_mux[3];

/* channel model */
int const_channel_count; /* min. channel count (for speakers) */
int ext_channel_count; /* current channel count for multi-io */
/* min_channel_count contains the minimum channel count for primary
* outputs. When multi_ios is set, the channels can be configured
* between min_channel_count and (min_channel_count + multi_ios * 2).
*
* ext_channel_count contains the current channel count of the primary
* out. This varies in the range above.
*
* Meanwhile, const_channel_count is the channel count for all outputs
* including headphone and speakers. It's a constant value, and the
* PCM is set up as max(ext_channel_count, const_channel_count).
*/
int min_channel_count; /* min. channel count for primary out */
int ext_channel_count; /* current channel count for primary */
int const_channel_count; /* channel count for all */

/* PCM information */
struct hda_pcm pcm_rec[3]; /* used in build_pcms() */
Expand Down

0 comments on commit cf0a821

Please sign in to comment.