Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
081a8c45
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
081a8c45
编写于
10月 02, 2009
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'fix/hda' into topic/hda
上级
71623855
7085ec12
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
311 addition
and
93 deletion
+311
-93
Documentation/sound/alsa/HD-Audio-Models.txt
Documentation/sound/alsa/HD-Audio-Models.txt
+1
-0
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_analog.c
+139
-0
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_realtek.c
+157
-87
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_sigmatel.c
+14
-6
未找到文件。
Documentation/sound/alsa/HD-Audio-Models.txt
浏览文件 @
081a8c45
...
@@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B
...
@@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B
laptop laptop with HP jack sensing
laptop laptop with HP jack sensing
mobile mobile devices with HP jack sensing
mobile mobile devices with HP jack sensing
thinkpad Lenovo Thinkpad X300
thinkpad Lenovo Thinkpad X300
touchsmart HP Touchsmart
AD1884
AD1884
======
======
...
...
sound/pci/hda/patch_analog.c
浏览文件 @
081a8c45
...
@@ -4031,6 +4031,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
...
@@ -4031,6 +4031,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
return
0
;
return
0
;
}
}
/*
* HP Touchsmart
* port-A (0x11) - front hp-out
* port-B (0x14) - unused
* port-C (0x15) - unused
* port-D (0x12) - rear line out
* port-E (0x1c) - front mic-in
* port-F (0x16) - Internal speakers
* digital-mic (0x17) - Internal mic
*/
static
struct
hda_verb
ad1984a_touchsmart_verbs
[]
=
{
/* DACs; unmute as default */
{
0x03
,
AC_VERB_SET_AMP_GAIN_MUTE
,
0x27
},
/* 0dB */
{
0x04
,
AC_VERB_SET_AMP_GAIN_MUTE
,
0x27
},
/* 0dB */
/* Port-A (HP) mixer - route only from analog mixer */
{
0x07
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
0
)},
{
0x07
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
1
)},
/* Port-A pin */
{
0x11
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_HP
},
/* Port-A (HP) pin - always unmuted */
{
0x11
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
},
/* Port-E (int speaker) mixer - route only from analog mixer */
{
0x25
,
AC_VERB_SET_AMP_GAIN_MUTE
,
0x03
},
/* Port-E pin */
{
0x1c
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_IN
},
{
0x1c
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
},
{
0x1c
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_VREF80
},
/* Port-F (int speaker) mixer - route only from analog mixer */
{
0x0b
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
0
)},
{
0x0b
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
1
)},
/* Port-F pin */
{
0x16
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_HP
},
{
0x16
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
/* Analog mixer; mute as default */
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
0
)},
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
1
)},
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
2
)},
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
3
)},
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
4
)},
{
0x20
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
5
)},
/* Analog Mix output amp */
{
0x21
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
/* capture sources */
/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */
/* set via unsol */
{
0x0c
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
{
0x0d
,
AC_VERB_SET_CONNECT_SEL
,
0x0
},
{
0x0d
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
/* unsolicited event for pin-sense */
{
0x11
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
AD1884A_HP_EVENT
},
{
0x1c
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
AD1884A_MIC_EVENT
},
/* allow to touch GPIO1 (for mute control) */
{
0x01
,
AC_VERB_SET_GPIO_MASK
,
0x02
},
{
0x01
,
AC_VERB_SET_GPIO_DIRECTION
,
0x02
},
{
0x01
,
AC_VERB_SET_GPIO_DATA
,
0x02
},
/* first muted */
/* internal mic - dmic */
{
0x17
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_IN
},
/* set magic COEFs for dmic */
{
0x01
,
AC_VERB_SET_COEF_INDEX
,
0x13f7
},
{
0x01
,
AC_VERB_SET_PROC_COEF
,
0x08
},
{
}
/* end */
};
static
struct
snd_kcontrol_new
ad1984a_touchsmart_mixers
[]
=
{
HDA_CODEC_VOLUME
(
"Master Playback Volume"
,
0x21
,
0x0
,
HDA_OUTPUT
),
/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Master Playback Switch"
,
.
info
=
snd_hda_mixer_amp_switch_info
,
.
get
=
snd_hda_mixer_amp_switch_get
,
.
put
=
ad1884a_mobile_master_sw_put
,
.
private_value
=
HDA_COMPOSE_AMP_VAL
(
0x21
,
3
,
0
,
HDA_OUTPUT
),
},
HDA_CODEC_VOLUME
(
"PCM Playback Volume"
,
0x20
,
0x5
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"PCM Playback Switch"
,
0x20
,
0x5
,
HDA_INPUT
),
HDA_CODEC_VOLUME
(
"Capture Volume"
,
0x0c
,
0x0
,
HDA_OUTPUT
),
HDA_CODEC_MUTE
(
"Capture Switch"
,
0x0c
,
0x0
,
HDA_OUTPUT
),
HDA_CODEC_VOLUME
(
"Mic Boost"
,
0x25
,
0x0
,
HDA_OUTPUT
),
HDA_CODEC_VOLUME
(
"Internal Mic Boost"
,
0x17
,
0x0
,
HDA_INPUT
),
{
}
/* end */
};
/* switch to external mic if plugged */
static
void
ad1984a_touchsmart_automic
(
struct
hda_codec
*
codec
)
{
if
(
snd_hda_codec_read
(
codec
,
0x1c
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
)
{
snd_hda_codec_write
(
codec
,
0x0c
,
0
,
AC_VERB_SET_CONNECT_SEL
,
0x4
);
}
else
{
snd_hda_codec_write
(
codec
,
0x0c
,
0
,
AC_VERB_SET_CONNECT_SEL
,
0x5
);
}
}
/* unsolicited event for HP jack sensing */
static
void
ad1984a_touchsmart_unsol_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
{
switch
(
res
>>
26
)
{
case
AD1884A_HP_EVENT
:
ad1884a_hp_automute
(
codec
);
break
;
case
AD1884A_MIC_EVENT
:
ad1984a_touchsmart_automic
(
codec
);
break
;
}
}
/* initialize jack-sensing, too */
static
int
ad1984a_touchsmart_init
(
struct
hda_codec
*
codec
)
{
ad198x_init
(
codec
);
ad1884a_hp_automute
(
codec
);
ad1984a_touchsmart_automic
(
codec
);
return
0
;
}
/*
/*
*/
*/
...
@@ -4039,6 +4160,7 @@ enum {
...
@@ -4039,6 +4160,7 @@ enum {
AD1884A_LAPTOP
,
AD1884A_LAPTOP
,
AD1884A_MOBILE
,
AD1884A_MOBILE
,
AD1884A_THINKPAD
,
AD1884A_THINKPAD
,
AD1984A_TOUCHSMART
,
AD1884A_MODELS
AD1884A_MODELS
};
};
...
@@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
...
@@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
[
AD1884A_LAPTOP
]
=
"laptop"
,
[
AD1884A_LAPTOP
]
=
"laptop"
,
[
AD1884A_MOBILE
]
=
"mobile"
,
[
AD1884A_MOBILE
]
=
"mobile"
,
[
AD1884A_THINKPAD
]
=
"thinkpad"
,
[
AD1884A_THINKPAD
]
=
"thinkpad"
,
[
AD1984A_TOUCHSMART
]
=
"touchsmart"
,
};
};
static
struct
snd_pci_quirk
ad1884a_cfg_tbl
[]
=
{
static
struct
snd_pci_quirk
ad1884a_cfg_tbl
[]
=
{
...
@@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
...
@@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
SND_PCI_QUIRK_MASK
(
0x103c
,
0xff00
,
0x3600
,
"HP laptop"
,
AD1884A_LAPTOP
),
SND_PCI_QUIRK_MASK
(
0x103c
,
0xff00
,
0x3600
,
"HP laptop"
,
AD1884A_LAPTOP
),
SND_PCI_QUIRK_MASK
(
0x103c
,
0xfff0
,
0x7010
,
"HP laptop"
,
AD1884A_MOBILE
),
SND_PCI_QUIRK_MASK
(
0x103c
,
0xfff0
,
0x7010
,
"HP laptop"
,
AD1884A_MOBILE
),
SND_PCI_QUIRK
(
0x17aa
,
0x20ac
,
"Thinkpad X300"
,
AD1884A_THINKPAD
),
SND_PCI_QUIRK
(
0x17aa
,
0x20ac
,
"Thinkpad X300"
,
AD1884A_THINKPAD
),
SND_PCI_QUIRK
(
0x103c
,
0x2a82
,
"Touchsmart"
,
AD1984A_TOUCHSMART
),
{}
{}
};
};
...
@@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec)
...
@@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec)
codec
->
patch_ops
.
unsol_event
=
ad1984a_thinkpad_unsol_event
;
codec
->
patch_ops
.
unsol_event
=
ad1984a_thinkpad_unsol_event
;
codec
->
patch_ops
.
init
=
ad1984a_thinkpad_init
;
codec
->
patch_ops
.
init
=
ad1984a_thinkpad_init
;
break
;
break
;
case
AD1984A_TOUCHSMART
:
spec
->
mixers
[
0
]
=
ad1984a_touchsmart_mixers
;
spec
->
init_verbs
[
0
]
=
ad1984a_touchsmart_verbs
;
spec
->
multiout
.
dig_out_nid
=
0
;
codec
->
patch_ops
.
unsol_event
=
ad1984a_touchsmart_unsol_event
;
codec
->
patch_ops
.
init
=
ad1984a_touchsmart_init
;
/* set the upper-limit for mixer amp to 0dB for avoiding the
* possible damage by overloading
*/
snd_hda_override_amp_caps
(
codec
,
0x20
,
HDA_INPUT
,
(
0x17
<<
AC_AMPCAP_OFFSET_SHIFT
)
|
(
0x17
<<
AC_AMPCAP_NUM_STEPS_SHIFT
)
|
(
0x05
<<
AC_AMPCAP_STEP_SIZE_SHIFT
)
|
(
1
<<
AC_AMPCAP_MUTE_SHIFT
));
break
;
}
}
return
0
;
return
0
;
...
...
sound/pci/hda/patch_realtek.c
浏览文件 @
081a8c45
...
@@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = {
...
@@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = {
.init_hook = alc268_toshiba_automute,
.init_hook = alc268_toshiba_automute,
},
},
[ALC268_ACER] = {
[ALC268_ACER] = {
.mixers = { alc268_acer_mixer, alc268_capture_
nosrc
_mixer,
.mixers = { alc268_acer_mixer, alc268_capture_
alt
_mixer,
alc268_beep_mixer },
alc268_beep_mixer },
.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
alc268_acer_verbs },
alc268_acer_verbs },
...
@@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
...
@@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
ALC662_3ST_6ch_DIG),
ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4),
SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
ALC662_3ST_6ch_DIG),
ALC662_3ST_6ch_DIG),
...
@@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = {
...
@@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = {
* BIOS auto configuration
* BIOS auto configuration
*/
*/
/* convert from MIX nid to DAC */
static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
{
if (nid == 0x0f)
return 0x02;
else if (nid >= 0x0c && nid <= 0x0e)
return nid - 0x0c + 0x02;
else
return 0;
}
/* get MIX nid connected to the given pin targeted to DAC */
static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
hda_nid_t mix[4];
int i, num;
num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
for (i = 0; i < num; i++) {
if (alc662_mix_to_dac(mix[i]) == dac)
return mix[i];
}
return 0;
}
/* look for an empty DAC slot */
static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
{
struct alc_spec *spec = codec->spec;
hda_nid_t srcs[5];
int i, j, num;
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
if (num < 0)
return 0;
for (i = 0; i < num; i++) {
hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
if (!nid)
continue;
for (j = 0; j < spec->multiout.num_dacs; j++)
if (spec->multiout.dac_nids[j] == nid)
break;
if (j >= spec->multiout.num_dacs)
return nid;
}
return 0;
}
/* fill in the dac_nids table from the parsed pin configuration */
static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
struct alc_spec *spec = codec->spec;
int i;
hda_nid_t dac;
spec->multiout.dac_nids = spec->private_dac_nids;
for (i = 0; i < cfg->line_outs; i++) {
dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
if (!dac)
continue;
spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
}
return 0;
}
static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
hda_nid_t nid, unsigned int chs)
{
char name[32];
sprintf(name, "%s Playback Volume", pfx);
return add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
}
static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
hda_nid_t nid, unsigned int chs)
{
char name[32];
sprintf(name, "%s Playback Switch", pfx);
return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
}
#define alc662_add_stereo_vol(spec, pfx, nid) \
alc662_add_vol_ctl(spec, pfx, nid, 3)
#define alc662_add_stereo_sw(spec, pfx, nid) \
alc662_add_sw_ctl(spec, pfx, nid, 3)
/* add playback controls from the parsed DAC table */
/* add playback controls from the parsed DAC table */
static int alc662_auto_create_multi_out_ctls(struct
alc_spec *sp
ec,
static int alc662_auto_create_multi_out_ctls(struct
hda_codec *cod
ec,
const struct auto_pin_cfg *cfg)
const struct auto_pin_cfg *cfg)
{
{
char name[32]
;
struct alc_spec *spec = codec->spec
;
static const char *chname[4] = {
static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
"Front", "Surround", NULL /*CLFE*/, "Side"
};
};
hda_nid_t nid;
hda_nid_t nid
, mix
;
int i, err;
int i, err;
for (i = 0; i < cfg->line_outs; i++) {
for (i = 0; i < cfg->line_outs; i++) {
if (!spec->multiout.dac_nids[i])
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
if (!mix)
continue;
continue;
nid = alc880_idx_to_dac(i);
if (i == 2) {
if (i == 2) {
/* Center/LFE */
/* Center/LFE */
err = add_control(spec, ALC_CTL_WIDGET_VOL,
err = alc662_add_vol_ctl(spec, "Center", nid, 1);
"Center Playback Volume",
HDA_COMPOSE_AMP_VAL(nid, 1, 0,
HDA_OUTPUT));
if (err < 0)
if (err < 0)
return err;
return err;
err = add_control(spec, ALC_CTL_WIDGET_VOL,
err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
"LFE Playback Volume",
HDA_COMPOSE_AMP_VAL(nid, 2, 0,
HDA_OUTPUT));
if (err < 0)
if (err < 0)
return err;
return err;
err = add_control(spec, ALC_CTL_WIDGET_MUTE,
err = alc662_add_sw_ctl(spec, "Center", mix, 1);
"Center Playback Switch",
HDA_COMPOSE_AMP_VAL(0x0e, 1, 0,
HDA_INPUT));
if (err < 0)
if (err < 0)
return err;
return err;
err = add_control(spec, ALC_CTL_WIDGET_MUTE,
err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
"LFE Playback Switch",
HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
HDA_INPUT));
if (err < 0)
if (err < 0)
return err;
return err;
} else {
} else {
const char *pfx;
const char *pfx;
if (cfg->line_outs == 1 &&
if (cfg->line_outs == 1 &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
if (
!cfg->hp_pin
s)
if (
cfg->hp_out
s)
pfx = "Speaker";
pfx = "Speaker";
else
else
pfx = "PCM";
pfx = "PCM";
} else
} else
pfx = chname[i];
pfx = chname[i];
sprintf(name, "%s Playback Volume", pfx);
err = alc662_add_vol_ctl(spec, pfx, nid, 3);
err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0,
HDA_OUTPUT));
if (err < 0)
if (err < 0)
return err;
return err;
if (cfg->line_outs == 1 &&
if (cfg->line_outs == 1 &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
pfx = "Speaker";
pfx = "Speaker";
sprintf(name, "%s Playback Switch", pfx);
err = alc662_add_sw_ctl(spec, pfx, mix, 3);
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i),
3, 0, HDA_INPUT));
if (err < 0)
if (err < 0)
return err;
return err;
}
}
...
@@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
...
@@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
}
}
/* add playback controls for speaker and HP outputs */
/* add playback controls for speaker and HP outputs */
static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
/* return DAC nid if any new DAC is assigned */
static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
const char *pfx)
const char *pfx)
{
{
hda_nid_t nid;
struct alc_spec *spec = codec->spec;
hda_nid_t nid, mix;
int err;
int err;
char name[32];
if (!pin)
if (!pin)
return 0;
return 0;
nid = alc662_look_for_dac(codec, pin);
if (pin == 0x17) {
if (!nid) {
/* ALC663 has a mono output pin on 0x17 */
char name[32];
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
return 0; /* no way */
/* create a switch only */
sprintf(name, "%s Playback Switch", pfx);
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT));
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
return err;
}
}
if (alc880_is_fixed_pin(pin)) {
mix = alc662_dac_to_mix(codec, pin, nid);
nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
if (!mix)
/* printk(KERN_DEBUG "DAC nid=%x\n",nid); */
return 0;
/* specify the DAC as the extra output */
err = alc662_add_vol_ctl(spec, pfx, nid, 3);
if (!spec->multiout.hp_nid)
if (err < 0)
spec->multiout.hp_nid = nid;
return err;
else
err = alc662_add_sw_ctl(spec, pfx, mix, 3);
spec->multiout.extra_out_nid[0] = nid;
if (err < 0)
/* control HP volume/switch on the output mixer amp */
return err;
nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
return nid;
sprintf(name, "%s Playback Volume", pfx);
err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_BIND_MUTE, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
if (err < 0)
return err;
} else if (alc880_is_multi_pin(pin)) {
/* set manual connection */
/* we have only a switch on HP-out PIN */
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
}
return 0;
}
}
/* create playback/capture controls for input pins */
/* create playback/capture controls for input pins */
...
@@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
...
@@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid, int pin_type,
hda_nid_t nid, int pin_type,
int dac_idx
)
hda_nid_t dac
)
{
{
int i, num;
hda_nid_t srcs[4];
alc_set_pin_output(codec, nid, pin_type);
alc_set_pin_output(codec, nid, pin_type);
/* need the manual connection? */
/* need the manual connection? */
if (alc880_is_multi_pin(nid)) {
num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
struct alc_spec *spec = codec->spec;
if (num <= 1)
int idx = alc880_multi_pin_idx(nid);
return;
snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
for (i = 0; i < num; i++) {
AC_VERB_SET_CONNECT_SEL,
if (alc662_mix_to_dac(srcs[i]) != dac)
alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
continue;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
return;
}
}
}
}
static void alc662_auto_init_multi_out(struct hda_codec *codec)
static void alc662_auto_init_multi_out(struct hda_codec *codec)
{
{
struct alc_spec *spec = codec->spec;
struct alc_spec *spec = codec->spec;
int pin_type = get_pin_type(spec->autocfg.line_out_type);
int i;
int i;
for (i = 0; i <= HDA_SIDE; i++) {
for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
if (nid)
if (nid)
alc662_auto_set_output_and_unmute(codec, nid, pin_type,
alc662_auto_set_output_and_unmute(codec, nid, pin_type,
i
);
spec->multiout.dac_nids[i]
);
}
}
}
}
...
@@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
...
@@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
hda_nid_t pin;
hda_nid_t pin;
pin = spec->autocfg.hp_pins[0];
pin = spec->autocfg.hp_pins[0];
if (pin)
/* connect to front */
if (pin)
/* use dac 0 */
alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0
);
spec->multiout.hp_nid
);
pin = spec->autocfg.speaker_pins[0];
pin = spec->autocfg.speaker_pins[0];
if (pin)
if (pin)
alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
spec->multiout.extra_out_nid[0]);
}
}
#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
...
@@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
...
@@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (!spec->autocfg.line_outs)
if (!spec->autocfg.line_outs)
return 0; /* can't find valid BIOS pin config */
return 0; /* can't find valid BIOS pin config */
err = alc
880_auto_fill_dac_nids(sp
ec, &spec->autocfg);
err = alc
662_auto_fill_dac_nids(cod
ec, &spec->autocfg);
if (err < 0)
if (err < 0)
return err;
return err;
err = alc662_auto_create_multi_out_ctls(
sp
ec, &spec->autocfg);
err = alc662_auto_create_multi_out_ctls(
cod
ec, &spec->autocfg);
if (err < 0)
if (err < 0)
return err;
return err;
err = alc662_auto_create_extra_out(
sp
ec,
err = alc662_auto_create_extra_out(
cod
ec,
spec->autocfg.speaker_pins[0],
spec->autocfg.speaker_pins[0],
"Speaker");
"Speaker");
if (err < 0)
if (err < 0)
return err;
return err;
err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
if (err)
spec->multiout.extra_out_nid[0] = err;
err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
"Headphone");
"Headphone");
if (err < 0)
if (err < 0)
return err;
return err;
if (err)
spec->multiout.hp_nid = err;
err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
if (err < 0)
if (err < 0)
return err;
return err;
...
...
sound/pci/hda/patch_sigmatel.c
浏览文件 @
081a8c45
...
@@ -182,8 +182,8 @@ struct sigmatel_jack {
...
@@ -182,8 +182,8 @@ struct sigmatel_jack {
struct
sigmatel_mic_route
{
struct
sigmatel_mic_route
{
hda_nid_t
pin
;
hda_nid_t
pin
;
un
signed
char
mux_idx
;
signed
char
mux_idx
;
un
signed
char
dmux_idx
;
signed
char
dmux_idx
;
};
};
struct
sigmatel_spec
{
struct
sigmatel_spec
{
...
@@ -3469,18 +3469,26 @@ static int set_mic_route(struct hda_codec *codec,
...
@@ -3469,18 +3469,26 @@ static int set_mic_route(struct hda_codec *codec,
break
;
break
;
if
(
i
<=
AUTO_PIN_FRONT_MIC
)
{
if
(
i
<=
AUTO_PIN_FRONT_MIC
)
{
/* analog pin */
/* analog pin */
mic
->
dmux_idx
=
0
;
i
=
get_connection_index
(
codec
,
spec
->
mux_nids
[
0
],
pin
);
i
=
get_connection_index
(
codec
,
spec
->
mux_nids
[
0
],
pin
);
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
mic
->
mux_idx
=
i
;
mic
->
mux_idx
=
i
;
mic
->
dmux_idx
=
-
1
;
if
(
spec
->
dmux_nids
)
mic
->
dmux_idx
=
get_connection_index
(
codec
,
spec
->
dmux_nids
[
0
],
spec
->
mux_nids
[
0
]);
}
else
if
(
spec
->
dmux_nids
)
{
}
else
if
(
spec
->
dmux_nids
)
{
/* digital pin */
/* digital pin */
mic
->
mux_idx
=
0
;
i
=
get_connection_index
(
codec
,
spec
->
dmux_nids
[
0
],
pin
);
i
=
get_connection_index
(
codec
,
spec
->
dmux_nids
[
0
],
pin
);
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
mic
->
dmux_idx
=
i
;
mic
->
dmux_idx
=
i
;
mic
->
mux_idx
=
-
1
;
if
(
spec
->
mux_nids
)
mic
->
mux_idx
=
get_connection_index
(
codec
,
spec
->
mux_nids
[
0
],
spec
->
dmux_nids
[
0
]);
}
}
return
0
;
return
0
;
}
}
...
@@ -4557,11 +4565,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
...
@@ -4557,11 +4565,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
mic
=
&
spec
->
ext_mic
;
mic
=
&
spec
->
ext_mic
;
else
else
mic
=
&
spec
->
int_mic
;
mic
=
&
spec
->
int_mic
;
if
(
mic
->
dmux_idx
)
if
(
mic
->
dmux_idx
>=
0
)
snd_hda_codec_write_cache
(
codec
,
spec
->
dmux_nids
[
0
],
0
,
snd_hda_codec_write_cache
(
codec
,
spec
->
dmux_nids
[
0
],
0
,
AC_VERB_SET_CONNECT_SEL
,
AC_VERB_SET_CONNECT_SEL
,
mic
->
dmux_idx
);
mic
->
dmux_idx
);
else
if
(
mic
->
mux_idx
>=
0
)
snd_hda_codec_write_cache
(
codec
,
spec
->
mux_nids
[
0
],
0
,
snd_hda_codec_write_cache
(
codec
,
spec
->
mux_nids
[
0
],
0
,
AC_VERB_SET_CONNECT_SEL
,
AC_VERB_SET_CONNECT_SEL
,
mic
->
mux_idx
);
mic
->
mux_idx
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录