When select 2.1 profile in pulseaudio, how do pulseaudio select notebook 's internal subwoofer or 5.1 external speaker ?
diff mbox

Message ID CAN8ccia43iJJOkB9w=XOxHBNtaO52ExJ4brKZCFGT=sxcik0VA@mail.gmail.com
State New
Headers show

Commit Message

Raymond Yau July 12, 2015, 2:16 a.m. UTC
> >
> > Are you sure that it is alsa driver bug since pulseaudio seem not using
> > line out jack to mute internal speakers ?
>
> No, I'm not. I set all my jacks to line out and it works now.
>

Do pulseaudio 2.1 profile select the internal subwoofer or your 5.1
external speaker ?

  * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
@@ -2048,12 +2104,8 @@ static const struct hda_fixup alc882_fixups[] = {
         .v.func = alc889_fixup_coef,
     },
     [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
-        .type = HDA_FIXUP_PINS,
-        .v.pins = (const struct hda_pintbl[]) {
-            { 0x16, 0x99130111 }, /* CLFE speaker */
-            { 0x17, 0x99130112 }, /* surround speaker */
-            { }
-        },
+        .type = HDA_FIXUP_FUNC,
+        .v.func = alc888_fixup_acer_aspire_4930g,
         .chained = true,
         .chain_id = ALC882_FIXUP_GPIO1,
     },

Comments

Raymond Yau July 12, 2015, 9:17 a.m. UTC | #1
> >
> > Do pulseaudio 2.1 profile select the internal subwoofer or your 5.1
> > external speaker ?
>
> My external speaker (i.e not subwoofer but center). It always was so.
>

https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda?id=ee81abb623cb5e03c182d16871bb4fb34fdc9b4f

+/* default channel maps for 2.1 speakers;
+ * since HD-audio supports only stereo, odd number channels are omitted
+ */
+const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
+ { .channels = 2,
+   .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+ { .channels = 4,
+   .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+    SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
+ { }
+};

The default 2.1 channel map for internal subwoofer does not has 5.1 channel
map

But your notebook have three jacks at ext front which support 5.1
In your case,there is no default 2.1 channel map when the current model has
three speaker pins

after remove the not exist internal surround speakers,


     [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
-        .type = HDA_FIXUP_PINS,
-        .v.pins = (const struct hda_pintbl[]) {
-            { 0x16, 0x99130111 }, /* CLFE speaker */
-            { 0x17, 0x99130112 }, /* surround speaker */
-            { }
-        },


you need to use the left channel version of  2.1 channel and 5.1 channel map

+static const struct snd_pcm_chmap_elem acer_pcm_chmaps[] = {

+ { .channels = 2, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, + {
.channels = 4, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,

+ SNDRV_CHMAP_LFE, SNDRV_CHMAP_NA } }, /* LFE only on left */

+ { .channels = 4, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,

+ SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },

+ { .channels = 6,

+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,

+ SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,

+ SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },

+ { }

+};


http://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=48f1b308cc66152eb6db66742dd0d08d888cda8d;hp=5c4cd46810cef8850b037fca9e38ffd43b0bff2
<http://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=48f1b308cc66152eb6db66742dd0d08d888cda8d;hp=5c4cd46810cef8850b037fca9e38ffd43b0bff22>

conf: Allow 2.1 surround to use different number of channels

This way, cards that support LFE on four channels (e g laptop with
internal subwoofer) can do that, and other cards on a six channel setup
can use that as well.


which channel map is used by alsa lib when you open surround21 pcm device
since your notebook will have both channel maps ?
Raymond Yau Aug. 5, 2015, 2:51 a.m. UTC | #2
>
> +static const struct snd_pcm_chmap_elem acer_pcm_chmaps[] = {
>
> + { .channels = 2, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, + {
.channels = 4, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
>
> + SNDRV_CHMAP_LFE, SNDRV_CHMAP_NA } }, /* LFE only on left */
>
> + { .channels = 4, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
>
> + SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
>
> + { .channels = 6,
>
> + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
>
> + SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
>
> + SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
>
> + { }
>
> +};

After testing with ubuntu 15.10 alpha and modified snd-dummy

alsa-lib seem using the first channel map which has FL, FR and LFE , this
mean that 2.1 profile always use your notebook internal speaker/subwoofer
even when your notebook support 5.1 external speakers

this behaviour is different from those desktop with external 5.1 speakers
using 2.1 profile


you may need to implement dynamic channel map which change when line out
jack is plugged if you want to use 2.1 profile with external 5.1 speakers

Patch
diff mbox

diff --git a/sound/pci/hda/hda_auto_parser.c
b/sound/pci/hda/hda_auto_parser.c
index 03b7399..c9e45e7 100644
@@ -952,6 +960,7 @@  void snd_hda_pick_fixup(struct hda_codec *codec,
     const struct snd_pci_quirk *q;
     int id = HDA_FIXUP_ID_NOT_SET;
     const char *name = NULL;
+    int i;

     if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
         return;
@@ -966,6 +975,9 @@  void snd_hda_pick_fixup(struct hda_codec *codec,
         return;
     }

+    if (!snd_hda_get_int_hint(codec, "alt_config", &i))
+        codec->alt_config = i;
+
     if (codec->modelname && models) {
         while (models->name) {
             if (!strcmp(codec->modelname, models->name)) {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 12837ab..38841db 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -283,6 +283,8 @@  struct hda_codec {

     /* additional init verbs */
     struct snd_array verbs;
+    int alt_config;
+    int combo_jack;
 };

 #define dev_to_hda_codec(_dev)    container_of(_dev, struct hda_codec,
core.dev)
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index ac0db16..12ee7f7 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -39,7 +39,6 @@ 
 #include "hda_beep.h"
 #include "hda_generic.h"

-
 /**
  * snd_hda_gen_spec_init - initialize hda_gen_spec struct
  * @spec: hda_gen_spec object to initialize
@@ -180,10 +179,10 @@  static void parse_user_hints(struct hda_codec *codec)
     /* the following two are just for compatibility */
     val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
     if (val >= 0)
-        spec->add_jack_modes = !!val;
+        spec->add_out_jack_modes = !!val;
     val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
     if (val >= 0)
-        spec->add_jack_modes = !!val;
+        spec->add_in_jack_modes = !!val;
     val = snd_hda_get_bool_hint(codec, "add_jack_modes");
     if (val >= 0)
         spec->add_jack_modes = !!val;
@@ -2648,7 +2720,7 @@  static void get_jack_mode_name(struct hda_codec
*codec, hda_nid_t pin,
 static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
 {
     struct hda_gen_spec *spec = codec->spec;
-    if (spec->add_jack_modes) {
+    if (spec->add_jack_modes || spec->add_out_jack_modes) {
         unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
         if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
             return 2;
@@ -2791,7 +2863,7 @@  static int get_in_jack_num_items(struct hda_codec
*codec, hda_nid_t pin)
 {
     struct hda_gen_spec *spec = codec->spec;
     int nitems = 0;
-    if (spec->add_jack_modes)
+    if (spec->add_jack_modes || spec->add_in_jack_modes)
         nitems = hweight32(get_vref_caps(codec, pin));
     return nitems ? nitems : 1;
 }
@@ -3287,7 +3359,7 @@  static int create_input_ctls(struct hda_codec *codec)
         if (err < 0)
             return err;

-        if (spec->add_jack_modes) {
+        if (spec->add_jack_modes || spec->add_in_jack_modes) {
             err = create_in_jack_mode(codec, pin);
             if (err < 0)
                 return err;
@@ -4895,13 +4971,13 @@  int snd_hda_gen_parse_auto_config(struct hda_codec
*codec,
      */
     if (spec->hp_mic_pin &&
         (spec->auto_mic || spec->input_mux.num_items == 1 ||
-         spec->add_jack_modes)) {
+         spec->add_jack_modes || spec->add_in_jack_modes)) {
         err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
         if (err < 0)
             return err;
     }

-    if (spec->add_jack_modes) {
+    if (spec->add_jack_modes || spec->add_out_jack_modes) {
         if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
             err = create_out_jack_modes(codec, cfg->line_outs,
                             cfg->line_out_pins);
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 56e4139..f10c55b 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -227,6 +229,8 @@  struct hda_gen_spec {
     unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
     unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */
     unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
+    unsigned int add_in_jack_modes:1; /* add in jack mode enum ctls */
+    unsigned int add_out_jack_modes:1; /* add out jack mode enum ctls */
     unsigned int power_down_unused:1; /* power down unused widgets */
     unsigned int dac_min_mute:1; /* minimal = mute for DACs */

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8e02cdf..b13f588 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1914,6 +1914,62 @@  static void alc889_fixup_mba21_vref(struct hda_codec
*codec,
         alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
 }

+static const struct snd_pcm_chmap_elem acer_pcm_chmaps[] = {
+    { .channels = 2,
+      .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+    { .channels = 4,
+      .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+           SNDRV_CHMAP_LFE, SNDRV_CHMAP_NA } }, /* LFE only on left */
+    { .channels = 4,
+      .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+           SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+    { .channels = 6,
+      .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+           SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
+           SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
+    { }
+};
+
+static void alc888_fixup_acer_aspire_4930g(struct hda_codec *codec,
+                    const struct hda_fixup *fix, int action)
+{
+    static const struct hda_pintbl subwoofer_cfg[] = {
+        { 0x16, 0x90170111 }, /* internal subwoofer */
+        {}
+    };
+    static const struct hda_pintbl front_cfg[] = {
+        { 0x15, 0x02014010},
+        {}
+    };
+    static const struct hda_pintbl rear_cfg[] = {
+        { 0x1a, 0x02014011},
+        {}
+    };
+    static const struct hda_pintbl clfe_cfg[] = {
+        { 0x18, 0x02014012},
+        {}
+    };
+    struct alc_spec *spec = codec->spec;
+    switch(action){
+    case HDA_FIXUP_ACT_PRE_PROBE:
+        snd_hda_apply_pincfgs(codec, subwoofer_cfg);
+        spec->gen.add_out_jack_modes = true;
+        switch(codec->alt_config){
+        case 3:
+            snd_hda_apply_pincfgs(codec, clfe_cfg);
+        case 2:
+            snd_hda_apply_pincfgs(codec, rear_cfg);
+        case 1:
+            snd_hda_apply_pincfgs(codec, front_cfg);
+            break;
+        }
+        break;
+    case HDA_FIXUP_ACT_BUILD:
+        spec->gen.pcm_rec[0]->stream[0].chmap = acer_pcm_chmaps;
+        break;
+    }
+}
+
 /* Don't take HP output as primary
  * Strangely, the speaker output doesn't work on Vaio Z and some Vaio