mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
ALSA: hda - pin-adc-mux-dmic auto-configuration of 92HD8X codecs
This patch replaces use of the harcoded arrays of pins, muxes, digital mics and adcs with the auto-generated ones using codec parsing and auto-discovers all actually connected digital mic pins on 92HD8X-like codecs This patch also adds the support for d-mic on pin 0x20. Signed-off-by: Vitaliy Kulikov <Vitaliy.Kulikov@idt.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
094a42452a
commit
699d899560
@ -186,6 +186,10 @@ struct sigmatel_mic_route {
|
||||
signed char dmux_idx;
|
||||
};
|
||||
|
||||
#define MAX_PINS_NUM 16
|
||||
#define MAX_ADCS_NUM 4
|
||||
#define MAX_DMICS_NUM 4
|
||||
|
||||
struct sigmatel_spec {
|
||||
struct snd_kcontrol_new *mixers[4];
|
||||
unsigned int num_mixers;
|
||||
@ -300,6 +304,17 @@ struct sigmatel_spec {
|
||||
struct hda_input_mux private_imux;
|
||||
struct hda_input_mux private_smux;
|
||||
struct hda_input_mux private_mono_mux;
|
||||
|
||||
/* auto spec */
|
||||
unsigned auto_pin_cnt;
|
||||
hda_nid_t auto_pin_nids[MAX_PINS_NUM];
|
||||
unsigned auto_adc_cnt;
|
||||
hda_nid_t auto_adc_nids[MAX_ADCS_NUM];
|
||||
hda_nid_t auto_mux_nids[MAX_ADCS_NUM];
|
||||
hda_nid_t auto_dmux_nids[MAX_ADCS_NUM];
|
||||
unsigned long auto_capvols[MAX_ADCS_NUM];
|
||||
unsigned auto_dmic_cnt;
|
||||
hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
|
||||
};
|
||||
|
||||
static hda_nid_t stac9200_adc_nids[1] = {
|
||||
@ -355,14 +370,6 @@ static unsigned long stac92hd73xx_capvols[] = {
|
||||
|
||||
#define STAC92HD83_DAC_COUNT 3
|
||||
|
||||
static hda_nid_t stac92hd83xxx_mux_nids[2] = {
|
||||
0x17, 0x18,
|
||||
};
|
||||
|
||||
static hda_nid_t stac92hd83xxx_adc_nids[2] = {
|
||||
0x15, 0x16,
|
||||
};
|
||||
|
||||
static hda_nid_t stac92hd83xxx_pwr_nids[4] = {
|
||||
0xa, 0xb, 0xd, 0xe,
|
||||
};
|
||||
@ -375,26 +382,10 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = {
|
||||
0x03, 0x0c, 0x20, 0x40,
|
||||
};
|
||||
|
||||
#define STAC92HD83XXX_NUM_DMICS 2
|
||||
static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
|
||||
0x11, 0x20, 0
|
||||
static hda_nid_t stac92hd83xxx_dmic_nids[] = {
|
||||
0x11, 0x20,
|
||||
};
|
||||
|
||||
#define STAC92HD88XXX_NUM_DMICS STAC92HD83XXX_NUM_DMICS
|
||||
#define stac92hd88xxx_dmic_nids stac92hd83xxx_dmic_nids
|
||||
|
||||
#define STAC92HD87B_NUM_DMICS 1
|
||||
static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = {
|
||||
0x11, 0
|
||||
};
|
||||
|
||||
#define STAC92HD83XXX_NUM_CAPS 2
|
||||
static unsigned long stac92hd83xxx_capvols[] = {
|
||||
HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
|
||||
HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT),
|
||||
};
|
||||
#define stac92hd83xxx_capsws stac92hd83xxx_capvols
|
||||
|
||||
static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
|
||||
0x0a, 0x0d, 0x0f
|
||||
};
|
||||
@ -572,21 +563,6 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = {
|
||||
0x14, 0x22, 0x23
|
||||
};
|
||||
|
||||
static hda_nid_t stac92hd83xxx_pin_nids[10] = {
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x1f, 0x20,
|
||||
};
|
||||
|
||||
static hda_nid_t stac92hd87xxx_pin_nids[6] = {
|
||||
0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0f, 0x11,
|
||||
};
|
||||
|
||||
static hda_nid_t stac92hd88xxx_pin_nids[8] = {
|
||||
0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0f, 0x11, 0x1f, 0x20,
|
||||
};
|
||||
|
||||
#define STAC92HD71BXX_NUM_PINS 13
|
||||
static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x00,
|
||||
@ -3415,6 +3391,17 @@ static const char * const stac92xx_dmic_labels[5] = {
|
||||
"Digital Mic 3", "Digital Mic 4"
|
||||
};
|
||||
|
||||
static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux,
|
||||
int idx)
|
||||
{
|
||||
hda_nid_t conn[HDA_MAX_NUM_INPUTS];
|
||||
int nums;
|
||||
nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
|
||||
if (idx >= 0 && idx < nums)
|
||||
return conn[idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
|
||||
hda_nid_t nid)
|
||||
{
|
||||
@ -3425,6 +3412,15 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
|
||||
for (i = 0; i < nums; i++)
|
||||
if (conn[i] == nid)
|
||||
return i;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
unsigned int wid_caps = get_wcaps(codec, conn[i]);
|
||||
unsigned int wid_type = get_wcaps_type(wid_caps);
|
||||
|
||||
if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX)
|
||||
if (get_connection_index(codec, conn[i], nid) >= 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -3497,6 +3493,16 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
|
||||
type_idx, HDA_OUTPUT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (!err) {
|
||||
nid = get_connected_node(codec,
|
||||
spec->dmux_nids[0], index);
|
||||
if (nid)
|
||||
err = create_elem_capture_vol(codec,
|
||||
nid, label,
|
||||
type_idx, HDA_INPUT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5308,6 +5314,105 @@ static int hp_bnb2011_with_dock(struct hda_codec *codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stac92hd8x_add_pin(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
|
||||
int i;
|
||||
|
||||
spec->auto_pin_nids[spec->auto_pin_cnt] = nid;
|
||||
spec->auto_pin_cnt++;
|
||||
|
||||
if (get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
|
||||
get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) {
|
||||
for (i = 0; i < ARRAY_SIZE(stac92hd83xxx_dmic_nids); i++) {
|
||||
if (nid == stac92hd83xxx_dmic_nids[i]) {
|
||||
spec->auto_dmic_nids[spec->auto_dmic_cnt] = nid;
|
||||
spec->auto_dmic_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stac92hd8x_add_adc(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
|
||||
spec->auto_adc_nids[spec->auto_adc_cnt] = nid;
|
||||
spec->auto_adc_cnt++;
|
||||
}
|
||||
|
||||
static void stac92hd8x_add_mux(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
int i, j;
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
|
||||
for (i = 0; i < spec->auto_adc_cnt; i++) {
|
||||
if (get_connection_index(codec,
|
||||
spec->auto_adc_nids[i], nid) >= 0) {
|
||||
/* mux and volume for adc_nids[i] */
|
||||
if (!spec->auto_mux_nids[i]) {
|
||||
spec->auto_mux_nids[i] = nid;
|
||||
/* 92hd codecs capture volume is in mux */
|
||||
spec->auto_capvols[i] = HDA_COMPOSE_AMP_VAL(nid,
|
||||
3, 0, HDA_OUTPUT);
|
||||
}
|
||||
for (j = 0; j < spec->auto_dmic_cnt; j++) {
|
||||
if (get_connection_index(codec, nid,
|
||||
spec->auto_dmic_nids[j]) >= 0) {
|
||||
/* dmux for adc_nids[i] */
|
||||
if (!spec->auto_dmux_nids[i])
|
||||
spec->auto_dmux_nids[i] = nid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stac92hd8x_fill_auto_spec(struct hda_codec *codec)
|
||||
{
|
||||
hda_nid_t nid, end_nid;
|
||||
unsigned int wid_caps, wid_type;
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
|
||||
end_nid = codec->start_nid + codec->num_nodes;
|
||||
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||
wid_caps = get_wcaps(codec, nid);
|
||||
wid_type = get_wcaps_type(wid_caps);
|
||||
|
||||
if (wid_type == AC_WID_PIN)
|
||||
stac92hd8x_add_pin(codec, nid);
|
||||
|
||||
if (wid_type == AC_WID_AUD_IN && !(wid_caps & AC_WCAP_DIGITAL))
|
||||
stac92hd8x_add_adc(codec, nid);
|
||||
}
|
||||
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||
wid_caps = get_wcaps(codec, nid);
|
||||
wid_type = get_wcaps_type(wid_caps);
|
||||
|
||||
if (wid_type == AC_WID_AUD_SEL)
|
||||
stac92hd8x_add_mux(codec, nid);
|
||||
}
|
||||
|
||||
spec->pin_nids = spec->auto_pin_nids;
|
||||
spec->num_pins = spec->auto_pin_cnt;
|
||||
spec->adc_nids = spec->auto_adc_nids;
|
||||
spec->num_adcs = spec->auto_adc_cnt;
|
||||
spec->capvols = spec->auto_capvols;
|
||||
spec->capsws = spec->auto_capvols;
|
||||
spec->num_caps = spec->auto_adc_cnt;
|
||||
spec->mux_nids = spec->auto_mux_nids;
|
||||
spec->num_muxes = spec->auto_adc_cnt;
|
||||
spec->dmux_nids = spec->auto_dmux_nids;
|
||||
spec->num_dmuxes = spec->auto_adc_cnt;
|
||||
spec->dmic_nids = spec->auto_dmic_nids;
|
||||
spec->num_dmics = spec->auto_dmic_cnt;
|
||||
}
|
||||
|
||||
static int patch_stac92hd83xxx(struct hda_codec *codec)
|
||||
{
|
||||
struct sigmatel_spec *spec;
|
||||
@ -5329,26 +5434,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
|
||||
codec->no_trigger_sense = 1;
|
||||
codec->spec = spec;
|
||||
|
||||
stac92hd8x_fill_auto_spec(codec);
|
||||
|
||||
spec->linear_tone_beep = 0;
|
||||
codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
|
||||
spec->digbeep_nid = 0x21;
|
||||
spec->dmic_nids = stac92hd83xxx_dmic_nids;
|
||||
spec->dmux_nids = stac92hd83xxx_mux_nids;
|
||||
spec->mux_nids = stac92hd83xxx_mux_nids;
|
||||
spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids);
|
||||
spec->adc_nids = stac92hd83xxx_adc_nids;
|
||||
spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids);
|
||||
spec->pwr_nids = stac92hd83xxx_pwr_nids;
|
||||
spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
|
||||
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
|
||||
spec->multiout.dac_nids = spec->dac_nids;
|
||||
|
||||
spec->init = stac92hd83xxx_core_init;
|
||||
spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids);
|
||||
spec->pin_nids = stac92hd83xxx_pin_nids;
|
||||
spec->num_caps = STAC92HD83XXX_NUM_CAPS;
|
||||
spec->capvols = stac92hd83xxx_capvols;
|
||||
spec->capsws = stac92hd83xxx_capsws;
|
||||
|
||||
spec->board_config = snd_hda_check_board_config(codec,
|
||||
STAC_92HD83XXX_MODELS,
|
||||
@ -5366,28 +5462,11 @@ again:
|
||||
case 0x111d76d1:
|
||||
case 0x111d76d9:
|
||||
case 0x111d76e5:
|
||||
spec->dmic_nids = stac92hd87b_dmic_nids;
|
||||
spec->num_dmics = stac92xx_connected_ports(codec,
|
||||
stac92hd87b_dmic_nids,
|
||||
STAC92HD87B_NUM_DMICS);
|
||||
spec->num_pins = ARRAY_SIZE(stac92hd87xxx_pin_nids);
|
||||
spec->pin_nids = stac92hd87xxx_pin_nids;
|
||||
spec->mono_nid = 0;
|
||||
spec->num_pwrs = 0;
|
||||
break;
|
||||
case 0x111d7666:
|
||||
case 0x111d7667:
|
||||
case 0x111d7668:
|
||||
case 0x111d7669:
|
||||
case 0x111d76e3:
|
||||
spec->num_dmics = stac92xx_connected_ports(codec,
|
||||
stac92hd88xxx_dmic_nids,
|
||||
STAC92HD88XXX_NUM_DMICS);
|
||||
spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids);
|
||||
spec->pin_nids = stac92hd88xxx_pin_nids;
|
||||
spec->mono_nid = 0;
|
||||
spec->num_pwrs = 0;
|
||||
break;
|
||||
case 0x111d7604:
|
||||
case 0x111d76d4:
|
||||
case 0x111d7605:
|
||||
@ -5396,9 +5475,6 @@ again:
|
||||
if (spec->board_config == STAC_92HD83XXX_PWR_REF)
|
||||
break;
|
||||
spec->num_pwrs = 0;
|
||||
spec->num_dmics = stac92xx_connected_ports(codec,
|
||||
stac92hd83xxx_dmic_nids,
|
||||
STAC92HD83XXX_NUM_DMICS);
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user