Discussion:
[PATCH 1/2] ALSA: hda - Move the function "check_amp_caps" to hda_codec.c
David Henningsson
2014-09-23 08:38:17 UTC
Permalink
The next patch will use it, so make it visible across modules.

Signed-off-by: David Henningsson <***@canonical.com>
---
sound/pci/hda/hda_codec.c | 20 ++++++++++++++++++++
sound/pci/hda/hda_generic.c | 17 -----------------
sound/pci/hda/hda_local.h | 8 ++++++++
3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0aa2e1e..15e0089 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2002,6 +2002,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
EXPORT_SYMBOL_GPL(query_amp_caps);

/**
+ * snd_hda_check_amp_caps - query AMP capabilities
+ * @codec: the HD-audio codec
+ * @nid: the NID to query
+ * @dir: either #HDA_INPUT or #HDA_OUTPUT
+ *
+ * Check whether the widget has the given amp capability for the direction.
+ */
+bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
+ int dir, unsigned int bits)
+{
+ if (!nid)
+ return false;
+ if (get_wcaps(codec, nid) & (1 << (dir + 1)))
+ if (query_amp_caps(codec, nid, dir) & bits)
+ return true;
+ return false;
+}
+EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
+
+/**
* snd_hda_override_amp_caps - Override the AMP capabilities
* @codec: the CODEC to clean up
* @nid: the NID to clean up
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 32a85f9..64220c0 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -519,18 +519,6 @@ static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
return val;
}

-/* check whether the widget has the given amp capability for the direction */
-static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int bits)
-{
- if (!nid)
- return false;
- if (get_wcaps(codec, nid) & (1 << (dir + 1)))
- if (query_amp_caps(codec, nid, dir) & bits)
- return true;
- return false;
-}
-
static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
hda_nid_t nid2, int dir)
{
@@ -540,11 +528,6 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
query_amp_caps(codec, nid2, dir));
}

-#define nid_has_mute(codec, nid, dir) \
- check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
-#define nid_has_volume(codec, nid, dir) \
- check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
-
/* look for a widget suitable for assigning a mute switch in the path */
static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
struct nid_path *path)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8a018d4..7eb44e7 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -603,6 +603,14 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
unsigned int caps);
+bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
+ int dir, unsigned int bits);
+
+#define nid_has_mute(codec, nid, dir) \
+ snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
+#define nid_has_volume(codec, nid, dir) \
+ snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
+

/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
--
1.9.1
David Henningsson
2014-09-23 08:38:18 UTC
Permalink
If one input has a boost and another one has not, and they're equal
otherwise, it's more likely you want to use the input with the boost
as your primary input.

See hda-emu.git/codecs/canonical/cx20590-lenovo-20b2z00bus-ccert-201305-13496
for an example.

Signed-off-by: David Henningsson <***@canonical.com>
---
sound/pci/hda/hda_auto_parser.c | 21 ++++++++++++++-------
sound/pci/hda/hda_auto_parser.h | 1 +
2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 51dea49..fcc5e47 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -57,12 +57,14 @@ static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,


/* add the found input-pin to the cfg->inputs[] table */
-static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
- int type)
+static void add_auto_cfg_input_pin(struct hda_codec *codec, struct auto_pin_cfg *cfg,
+ hda_nid_t nid, int type)
{
if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
cfg->inputs[cfg->num_inputs].pin = nid;
cfg->inputs[cfg->num_inputs].type = type;
+ cfg->inputs[cfg->num_inputs].has_boost_on_pin =
+ nid_has_volume(codec, nid, HDA_INPUT);
cfg->num_inputs++;
}
}
@@ -71,7 +73,12 @@ static int compare_input_type(const void *ap, const void *bp)
{
const struct auto_pin_cfg_item *a = ap;
const struct auto_pin_cfg_item *b = bp;
- return (int)(a->type - b->type);
+ if (a->type != b->type)
+ return (int)(a->type - b->type);
+
+ /* In case one has boost and the other one has not,
+ pick the one with boost first. */
+ return (int)(b->has_boost_on_pin - a->has_boost_on_pin);
}

/* Reorder the surround channels
@@ -268,16 +275,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
cfg->hp_outs++;
break;
case AC_JACK_MIC_IN:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
+ add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_MIC);
break;
case AC_JACK_LINE_IN:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
+ add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_LINE_IN);
break;
case AC_JACK_CD:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
+ add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_CD);
break;
case AC_JACK_AUX:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
+ add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_AUX);
break;
case AC_JACK_SPDIF_OUT:
case AC_JACK_DIG_OTHER_OUT:
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
index e941f60..2b8e29f 100644
--- a/sound/pci/hda/hda_auto_parser.h
+++ b/sound/pci/hda/hda_auto_parser.h
@@ -38,6 +38,7 @@ struct auto_pin_cfg_item {
int type;
unsigned int is_headset_mic:1;
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
+ unsigned int has_boost_on_pin:1;
};

struct auto_pin_cfg;
--
1.9.1
Raymond Yau
2014-09-24 03:31:04 UTC
Permalink
Post by David Henningsson
If one input has a boost and another one has not, and they're equal
otherwise, it's more likely you want to use the input with the boost
as your primary input.
See
hda-emu.git/codecs/canonical/cx20590-lenovo-20b2z00bus-ccert-201305-13496
Post by David Henningsson
for an example.
Is this a firmware bug since your firmware 1.02 have two internal Mic 0x1e
and 0x23 but firmware 1.09 only have one internal mic 0x23

http://www.alsa-project.org/db/?f=a265ed3ac422c0ea77b0ada8596338c6421b4de1

Cannot detect the codec with firmware 1.10

http://www.alsa-project.org/db/?f=a60449e5a19b3dbb7a422defd5a9d51f56216693

The proper fix is remove the redundant internal Mic since auto Mic is
disabled
David Henningsson
2014-09-24 06:33:17 UTC
Permalink
Post by David Henningsson
Post by David Henningsson
If one input has a boost and another one has not, and they're equal
otherwise, it's more likely you want to use the input with the boost
as your primary input.
See
hda-emu.git/codecs/canonical/cx20590-lenovo-20b2z00bus-ccert-201305-13496
Post by David Henningsson
for an example.
Is this a firmware bug since your firmware 1.02 have two internal Mic
0x1e and 0x23 but firmware 1.09 only have one internal mic 0x23
http://www.alsa-project.org/db/?f=a265ed3ac422c0ea77b0ada8596338c6421b4de1
Cannot detect the codec with firmware 1.10
http://www.alsa-project.org/db/?f=a60449e5a19b3dbb7a422defd5a9d51f56216693
The proper fix is remove the redundant internal Mic since auto Mic is
disabled
The E545 has dual-array mics, so probably both pins are actual internal
mics.
It seems reasonable that upgrading the firmware would also resolve this
problem, but either way I believe this is a good patch for potentially
future codecs in the same situation.
--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
Raymond Yau
2014-09-24 08:59:36 UTC
Permalink
Post by David Henningsson
Post by David Henningsson
Post by David Henningsson
If one input has a boost and another one has not, and they're equal
otherwise, it's more likely you want to use the input with the boost
as your primary input.
See
hda-emu.git/codecs/canonical/cx20590-lenovo-20b2z00bus-ccert-201305-13496
Post by David Henningsson
for an example.
Is this a firmware bug since your firmware 1.02 have two internal Mic
0x1e and 0x23 but firmware 1.09 only have one internal mic 0x23
http://www.alsa-project.org/db/?f=a265ed3ac422c0ea77b0ada8596338c6421b4de1
Post by David Henningsson
Post by David Henningsson
Cannot detect the codec with firmware 1.10
http://www.alsa-project.org/db/?f=a60449e5a19b3dbb7a422defd5a9d51f56216693
Post by David Henningsson
Post by David Henningsson
The proper fix is remove the redundant internal Mic since auto Mic is
disabled
The E545 has dual-array mics, so probably both pins are actual internal
mics.
Post by David Henningsson
It seems reasonable that upgrading the firmware would also resolve this
problem, but either way I believe this is a good patch for potentially
future codecs in the same situation.
If dual array mic use two nodes and you can record from any one of the
internal mic using the capture source control

Need to implement multi channel capture if you need to record with both mic
Takashi Iwai
2014-09-23 13:58:12 UTC
Permalink
At Tue, 23 Sep 2014 10:38:17 +0200,
Post by David Henningsson
The next patch will use it, so make it visible across modules.
Applied both patches. Thanks.


Takashi
Post by David Henningsson
---
sound/pci/hda/hda_codec.c | 20 ++++++++++++++++++++
sound/pci/hda/hda_generic.c | 17 -----------------
sound/pci/hda/hda_local.h | 8 ++++++++
3 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0aa2e1e..15e0089 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2002,6 +2002,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
EXPORT_SYMBOL_GPL(query_amp_caps);
/**
+ * snd_hda_check_amp_caps - query AMP capabilities
+ *
+ * Check whether the widget has the given amp capability for the direction.
+ */
+bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
+ int dir, unsigned int bits)
+{
+ if (!nid)
+ return false;
+ if (get_wcaps(codec, nid) & (1 << (dir + 1)))
+ if (query_amp_caps(codec, nid, dir) & bits)
+ return true;
+ return false;
+}
+EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
+
+/**
* snd_hda_override_amp_caps - Override the AMP capabilities
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 32a85f9..64220c0 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -519,18 +519,6 @@ static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
return val;
}
-/* check whether the widget has the given amp capability for the direction */
-static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int bits)
-{
- if (!nid)
- return false;
- if (get_wcaps(codec, nid) & (1 << (dir + 1)))
- if (query_amp_caps(codec, nid, dir) & bits)
- return true;
- return false;
-}
-
static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
hda_nid_t nid2, int dir)
{
@@ -540,11 +528,6 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
query_amp_caps(codec, nid2, dir));
}
-#define nid_has_mute(codec, nid, dir) \
- check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
-#define nid_has_volume(codec, nid, dir) \
- check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
-
/* look for a widget suitable for assigning a mute switch in the path */
static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
struct nid_path *path)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8a018d4..7eb44e7 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -603,6 +603,14 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
unsigned int caps);
+bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
+ int dir, unsigned int bits);
+
+#define nid_has_mute(codec, nid, dir) \
+ snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
+#define nid_has_volume(codec, nid, dir) \
+ snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
+
/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
--
1.9.1
Loading...