Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270371
b: refs/heads/master
c: 3458870
h: refs/heads/master
i:
  270369: 605e135
  270367: 6841ffa
v: v3
  • Loading branch information
Raymond Yau authored and Takashi Iwai committed Sep 23, 2011
1 parent aeaea1b commit e4361b8
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 20 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: 0b6c49b59fb272c1a20f79202693ed1072e9548c
refs/heads/master: 34588709af61be1550b4e2bcee5c85d0ac4f34d4
150 changes: 131 additions & 19 deletions trunk/sound/pci/hda/patch_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct ad198x_spec {

const hda_nid_t *alt_dac_nid;
const struct hda_pcm_stream *stream_analog_alt_playback;
int independent_hp;
int num_active_streams;

/* capture */
unsigned int num_adc_nids;
Expand Down Expand Up @@ -302,6 +304,72 @@ static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
}
#endif

static void activate_ctl(struct hda_codec *codec, const char *name, int active)
{
struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
if (ctl) {
ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
ctl->vd[0].access |= active ? 0 :
SNDRV_CTL_ELEM_ACCESS_INACTIVE;
ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl->vd[0].access |= active ?
SNDRV_CTL_ELEM_ACCESS_WRITE : 0;
snd_ctl_notify(codec->bus->card,
SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
}
}

static void set_stream_active(struct hda_codec *codec, bool active)
{
struct ad198x_spec *spec = codec->spec;
if (active)
spec->num_active_streams++;
else
spec->num_active_streams--;
activate_ctl(codec, "Independent HP", spec->num_active_streams == 0);
}

static int ad1988_independent_hp_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static const char * const texts[] = { "OFF", "ON", NULL};
int index;
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 2;
index = uinfo->value.enumerated.item;
if (index >= 2)
index = 1;
strcpy(uinfo->value.enumerated.name, texts[index]);
return 0;
}

static int ad1988_independent_hp_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
ucontrol->value.enumerated.item[0] = spec->independent_hp;
return 0;
}

static int ad1988_independent_hp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
unsigned int select = ucontrol->value.enumerated.item[0];
if (spec->independent_hp != select) {
spec->independent_hp = select;
if (spec->independent_hp)
spec->multiout.hp_nid = 0;
else
spec->multiout.hp_nid = spec->alt_dac_nid[0];
return 1;
}
return 0;
}

/*
* Analog playback callbacks
*/
Expand All @@ -310,8 +378,15 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
int err;
set_stream_active(codec, true);
err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
hinfo);
if (err < 0) {
set_stream_active(codec, false);
return err;
}
return 0;
}

static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Expand All @@ -333,11 +408,41 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
}

static int ad198x_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
set_stream_active(codec, false);
return 0;
}

static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
if (!spec->independent_hp)
return -EBUSY;
set_stream_active(codec, true);
return 0;
}

static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
set_stream_active(codec, false);
return 0;
}

static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in ad198x_build_pcms */
.ops = {
.open = ad1988_alt_playback_pcm_open,
.close = ad1988_alt_playback_pcm_close
},
};

/*
Expand Down Expand Up @@ -402,7 +507,6 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}


/*
*/
static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
Expand All @@ -413,7 +517,8 @@ static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
.ops = {
.open = ad198x_playback_pcm_open,
.prepare = ad198x_playback_pcm_prepare,
.cleanup = ad198x_playback_pcm_cleanup
.cleanup = ad198x_playback_pcm_cleanup,
.close = ad198x_playback_pcm_close
},
};

Expand Down Expand Up @@ -2058,7 +2163,6 @@ static int patch_ad1981(struct hda_codec *codec)
enum {
AD1988_6STACK,
AD1988_6STACK_DIG,
AD1988_6STACK_DIG_FP,
AD1988_3STACK,
AD1988_3STACK_DIG,
AD1988_LAPTOP,
Expand Down Expand Up @@ -2168,6 +2272,17 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
return err;
}

static const struct snd_kcontrol_new ad1988_hp_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Independent HP",
.info = ad1988_independent_hp_info,
.get = ad1988_independent_hp_get,
.put = ad1988_independent_hp_put,
},
{ } /* end */
};

/* 6-stack mode */
static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
Expand Down Expand Up @@ -2211,7 +2326,6 @@ static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {

HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),

{ } /* end */
};

Expand Down Expand Up @@ -3147,7 +3261,6 @@ static int ad1988_auto_init(struct hda_codec *codec)
static const char * const ad1988_models[AD1988_MODEL_LAST] = {
[AD1988_6STACK] = "6stack",
[AD1988_6STACK_DIG] = "6stack-dig",
[AD1988_6STACK_DIG_FP] = "6stack-dig-fp",
[AD1988_3STACK] = "3stack",
[AD1988_3STACK_DIG] = "3stack-dig",
[AD1988_LAPTOP] = "laptop",
Expand Down Expand Up @@ -3206,11 +3319,10 @@ static int patch_ad1988(struct hda_codec *codec)
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);

if (!spec->multiout.hp_nid)
spec->multiout.hp_nid = 0x03;
spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
switch (board_config) {
case AD1988_6STACK:
case AD1988_6STACK_DIG:
case AD1988_6STACK_DIG_FP:
spec->multiout.max_channels = 8;
spec->multiout.num_dacs = 4;
if (is_rev2(codec))
Expand All @@ -3226,16 +3338,7 @@ static int patch_ad1988(struct hda_codec *codec)
spec->mixers[1] = ad1988_6stack_mixers2;
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1988_6stack_init_verbs;
if (board_config == AD1988_6STACK_DIG_FP) {
spec->multiout.hp_nid = 0;
spec->slave_vols = ad1988_6stack_fp_slave_vols;
spec->slave_sws = ad1988_6stack_fp_slave_sws;
spec->alt_dac_nid = ad1988_alt_dac_nid;
spec->stream_analog_alt_playback =
&ad198x_pcm_analog_alt_playback;
}
if ((board_config == AD1988_6STACK_DIG) ||
(board_config == AD1988_6STACK_DIG_FP)) {
if (board_config == AD1988_6STACK_DIG) {
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
spec->dig_in_nid = AD1988_SPDIF_IN;
}
Expand Down Expand Up @@ -3278,6 +3381,15 @@ static int patch_ad1988(struct hda_codec *codec)
break;
}

if (spec->autocfg.hp_pins[0]) {
spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
spec->slave_vols = ad1988_6stack_fp_slave_vols;
spec->slave_sws = ad1988_6stack_fp_slave_sws;
spec->alt_dac_nid = ad1988_alt_dac_nid;
spec->stream_analog_alt_playback =
&ad198x_pcm_analog_alt_playback;
}

spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
spec->adc_nids = ad1988_adc_nids;
spec->capsrc_nids = ad1988_capsrc_nids;
Expand Down

0 comments on commit e4361b8

Please sign in to comment.