Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
63f4b3a4
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
63f4b3a4
编写于
2月 03, 2014
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/hda' into for-next
The updates of HD-audio drivers for 3.15
上级
4fa71c15
3d692451
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
395 addition
and
434 deletion
+395
-434
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.c
+1
-1
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+9
-14
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_conexant.c
+385
-419
未找到文件。
sound/pci/hda/hda_generic.c
浏览文件 @
63f4b3a4
...
...
@@ -762,7 +762,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
AC_PWRST_D0
);
}
if
(
enable
&&
path
->
multi
[
i
])
snd_hda_codec_
wri
te_cache
(
codec
,
nid
,
0
,
snd_hda_codec_
upda
te_cache
(
codec
,
nid
,
0
,
AC_VERB_SET_CONNECT_SEL
,
path
->
idx
[
i
]);
if
(
has_amp_in
(
codec
,
path
,
i
))
...
...
sound/pci/hda/hda_intel.c
浏览文件 @
63f4b3a4
...
...
@@ -834,18 +834,6 @@ static unsigned int azx_command_addr(u32 cmd)
return
addr
;
}
static
unsigned
int
azx_response_addr
(
u32
res
)
{
unsigned
int
addr
=
res
&
0xf
;
if
(
addr
>=
AZX_MAX_CODECS
)
{
snd_BUG
();
addr
=
0
;
}
return
addr
;
}
/* send a command */
static
int
azx_corb_send_cmd
(
struct
hda_bus
*
bus
,
u32
val
)
{
...
...
@@ -907,8 +895,15 @@ static void azx_update_rirb(struct azx *chip)
rp
=
chip
->
rirb
.
rp
<<
1
;
/* an RIRB entry is 8-bytes */
res_ex
=
le32_to_cpu
(
chip
->
rirb
.
buf
[
rp
+
1
]);
res
=
le32_to_cpu
(
chip
->
rirb
.
buf
[
rp
]);
addr
=
azx_response_addr
(
res_ex
);
if
(
res_ex
&
ICH6_RIRB_EX_UNSOL_EV
)
addr
=
res_ex
&
0xf
;
if
((
addr
>=
AZX_MAX_CODECS
)
||
!
(
chip
->
codec_mask
&
(
1
<<
addr
)))
{
snd_printk
(
KERN_ERR
SFX
"%s: spurious response %#x:%#x, rp = %d, wp = %d"
,
pci_name
(
chip
->
pci
),
res
,
res_ex
,
chip
->
rirb
.
rp
,
wp
);
snd_BUG
();
}
else
if
(
res_ex
&
ICH6_RIRB_EX_UNSOL_EV
)
snd_hda_queue_unsol_event
(
chip
->
bus
,
res
,
res_ex
);
else
if
(
chip
->
rirb
.
cmds
[
addr
])
{
chip
->
rirb
.
res
[
addr
]
=
res
;
...
...
sound/pci/hda/patch_conexant.c
浏览文件 @
63f4b3a4
...
...
@@ -35,7 +35,7 @@
#include "hda_jack.h"
#include "hda_generic.h"
#
define
ENABLE_CXT_STATIC_QUIRKS
#
undef
ENABLE_CXT_STATIC_QUIRKS
#define CXT_PIN_DIR_IN 0x00
#define CXT_PIN_DIR_OUT 0x01
...
...
@@ -68,6 +68,12 @@ struct conexant_spec {
unsigned
int
parse_flags
;
/* flag for snd_hda_parse_pin_defcfg() */
/* OPLC XO specific */
bool
recording
;
bool
dc_enable
;
unsigned
int
dc_input_bias
;
/* offset into olpc_xo_dc_bias */
struct
nid_path
*
dc_mode_path
;
#ifdef ENABLE_CXT_STATIC_QUIRKS
const
struct
snd_kcontrol_new
*
mixers
[
5
];
int
num_mixers
;
...
...
@@ -123,19 +129,6 @@ struct conexant_spec {
unsigned
int
hp_laptop
:
1
;
unsigned
int
asus
:
1
;
unsigned
int
ext_mic_present
;
unsigned
int
recording
;
void
(
*
capture_prepare
)(
struct
hda_codec
*
codec
);
void
(
*
capture_cleanup
)(
struct
hda_codec
*
codec
);
/* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors)
* through the microphone jack.
* When the user enables this through a mixer switch, both internal and
* external microphones are disabled. Gain is fixed at 0dB. In this mode,
* we also allow the bias to be configured through a separate mixer
* control. */
unsigned
int
dc_enable
;
unsigned
int
dc_input_bias
;
/* offset into cxt5066_olpc_dc_bias */
unsigned
int
mic_boost
;
/* offset into cxt5066_analog_mic_boost */
#endif
/* ENABLE_CXT_STATIC_QUIRKS */
};
...
...
@@ -253,8 +246,6 @@ static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
struct
snd_pcm_substream
*
substream
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
if
(
spec
->
capture_prepare
)
spec
->
capture_prepare
(
codec
);
snd_hda_codec_setup_stream
(
codec
,
spec
->
adc_nids
[
substream
->
number
],
stream_tag
,
0
,
format
);
return
0
;
...
...
@@ -266,8 +257,6 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
snd_hda_codec_cleanup_stream
(
codec
,
spec
->
adc_nids
[
substream
->
number
]);
if
(
spec
->
capture_cleanup
)
spec
->
capture_cleanup
(
codec
);
return
0
;
}
...
...
@@ -673,14 +662,6 @@ static const struct hda_input_mux cxt5045_capture_source_benq = {
}
};
static
const
struct
hda_input_mux
cxt5045_capture_source_hp530
=
{
.
num_items
=
2
,
.
items
=
{
{
"Mic"
,
0x1
},
{
"Internal Mic"
,
0x2
},
}
};
/* turn on/off EAPD (+ mute HP) as a master switch */
static
int
cxt5045_hp_master_sw_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
...
...
@@ -796,28 +777,6 @@ static const struct snd_kcontrol_new cxt5045_benq_mixers[] = {
{}
};
static
const
struct
snd_kcontrol_new
cxt5045_mixers_hp530
[]
=
{
HDA_CODEC_VOLUME
(
"Capture Volume"
,
0x1a
,
0x00
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"Capture Switch"
,
0x1a
,
0x0
,
HDA_INPUT
),
HDA_CODEC_VOLUME
(
"PCM Playback Volume"
,
0x17
,
0x0
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"PCM Playback Switch"
,
0x17
,
0x0
,
HDA_INPUT
),
HDA_CODEC_VOLUME
(
"Internal Mic Playback Volume"
,
0x17
,
0x2
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"Internal Mic Playback Switch"
,
0x17
,
0x2
,
HDA_INPUT
),
HDA_CODEC_VOLUME
(
"Mic Playback Volume"
,
0x17
,
0x1
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"Mic Playback Switch"
,
0x17
,
0x1
,
HDA_INPUT
),
HDA_BIND_VOL
(
"Master Playback Volume"
,
&
cxt5045_hp_bind_master_vol
),
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Master Playback Switch"
,
.
info
=
cxt_eapd_info
,
.
get
=
cxt_eapd_get
,
.
put
=
cxt5045_hp_master_sw_put
,
.
private_value
=
0x10
,
},
{}
};
static
const
struct
hda_verb
cxt5045_init_verbs
[]
=
{
/* Line in, Mic */
{
0x12
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_IN
|
AC_PINCTL_VREF_80
},
...
...
@@ -1000,7 +959,6 @@ enum {
CXT5045_LAPTOP_MICSENSE
,
CXT5045_LAPTOP_HPMICSENSE
,
CXT5045_BENQ
,
CXT5045_LAPTOP_HP530
,
#ifdef CONFIG_SND_DEBUG
CXT5045_TEST
,
#endif
...
...
@@ -1013,7 +971,6 @@ static const char * const cxt5045_models[CXT5045_MODELS] = {
[
CXT5045_LAPTOP_MICSENSE
]
=
"laptop-micsense"
,
[
CXT5045_LAPTOP_HPMICSENSE
]
=
"laptop-hpmicsense"
,
[
CXT5045_BENQ
]
=
"benq"
,
[
CXT5045_LAPTOP_HP530
]
=
"laptop-hp530"
,
#ifdef CONFIG_SND_DEBUG
[
CXT5045_TEST
]
=
"test"
,
#endif
...
...
@@ -1021,8 +978,6 @@ static const char * const cxt5045_models[CXT5045_MODELS] = {
};
static
const
struct
snd_pci_quirk
cxt5045_cfg_tbl
[]
=
{
SND_PCI_QUIRK
(
0x103c
,
0x30d5
,
"HP 530"
,
CXT5045_LAPTOP_HP530
),
SND_PCI_QUIRK
(
0x1179
,
0xff31
,
"Toshiba P105"
,
CXT5045_LAPTOP_MICSENSE
),
SND_PCI_QUIRK
(
0x152d
,
0x0753
,
"Benq R55E"
,
CXT5045_BENQ
),
SND_PCI_QUIRK
(
0x1734
,
0x10ad
,
"Fujitsu Si1520"
,
CXT5045_LAPTOP_MICSENSE
),
SND_PCI_QUIRK
(
0x1734
,
0x10cb
,
"Fujitsu Si3515"
,
CXT5045_LAPTOP_HPMICSENSE
),
...
...
@@ -1113,14 +1068,6 @@ static int patch_cxt5045(struct hda_codec *codec)
spec
->
num_mixers
=
2
;
codec
->
patch_ops
.
init
=
cxt5045_init
;
break
;
case
CXT5045_LAPTOP_HP530
:
codec
->
patch_ops
.
unsol_event
=
cxt5045_hp_unsol_event
;
spec
->
input_mux
=
&
cxt5045_capture_source_hp530
;
spec
->
num_init_verbs
=
2
;
spec
->
init_verbs
[
1
]
=
cxt5045_hp_sense_init_verbs
;
spec
->
mixers
[
0
]
=
cxt5045_mixers_hp530
;
codec
->
patch_ops
.
init
=
cxt5045_init
;
break
;
#ifdef CONFIG_SND_DEBUG
case
CXT5045_TEST
:
spec
->
input_mux
=
&
cxt5045_test_capture_source
;
...
...
@@ -1940,11 +1887,6 @@ static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
static
const
hda_nid_t
cxt5066_capsrc_nids
[
1
]
=
{
0x17
};
static
const
hda_nid_t
cxt5066_digout_pin_nids
[
2
]
=
{
0x20
,
0x22
};
/* OLPC's microphone port is DC coupled for use with external sensors,
* therefore we use a 50% mic bias in order to center the input signal with
* the DC input range of the codec. */
#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
static
const
struct
hda_channel_mode
cxt5066_modes
[
1
]
=
{
{
2
,
NULL
},
};
...
...
@@ -1997,88 +1939,6 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return
1
;
}
static
const
struct
hda_input_mux
cxt5066_olpc_dc_bias
=
{
.
num_items
=
3
,
.
items
=
{
{
"Off"
,
PIN_IN
},
{
"50%"
,
PIN_VREF50
},
{
"80%"
,
PIN_VREF80
},
},
};
static
int
cxt5066_set_olpc_dc_bias
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
/* Even though port F is the DC input, the bias is controlled on port B.
* we also leave that port as an active input (but unselected) in DC mode
* just in case that is necessary to make the bias setting take effect. */
return
snd_hda_set_pin_ctl_cache
(
codec
,
0x1a
,
cxt5066_olpc_dc_bias
.
items
[
spec
->
dc_input_bias
].
index
);
}
/* OLPC defers mic widget control until when capture is started because the
* microphone LED comes on as soon as these settings are put in place. if we
* did this before recording, it would give the false indication that recording
* is happening when it is not. */
static
void
cxt5066_olpc_select_mic
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
if
(
!
spec
->
recording
)
return
;
if
(
spec
->
dc_enable
)
{
/* in DC mode we ignore presence detection and just use the jack
* through our special DC port */
const
struct
hda_verb
enable_dc_mode
[]
=
{
/* disble internal mic, port C */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* enable DC capture, port F */
{
0x1e
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_IN
},
{},
};
snd_hda_sequence_write
(
codec
,
enable_dc_mode
);
/* port B input disabled (and bias set) through the following call */
cxt5066_set_olpc_dc_bias
(
codec
);
return
;
}
/* disable DC (port F) */
snd_hda_set_pin_ctl
(
codec
,
0x1e
,
0
);
/* external mic, port B */
snd_hda_set_pin_ctl
(
codec
,
0x1a
,
spec
->
ext_mic_present
?
CXT5066_OLPC_EXT_MIC_BIAS
:
0
);
/* internal mic, port C */
snd_hda_set_pin_ctl
(
codec
,
0x1b
,
spec
->
ext_mic_present
?
0
:
PIN_VREF80
);
}
/* toggle input of built-in and mic jack appropriately */
static
void
cxt5066_olpc_automic
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
unsigned
int
present
;
if
(
spec
->
dc_enable
)
/* don't do presence detection in DC mode */
return
;
present
=
snd_hda_codec_read
(
codec
,
0x1a
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
;
if
(
present
)
snd_printdd
(
"CXT5066: external microphone detected
\n
"
);
else
snd_printdd
(
"CXT5066: external microphone absent
\n
"
);
snd_hda_codec_write
(
codec
,
0x17
,
0
,
AC_VERB_SET_CONNECT_SEL
,
present
?
0
:
1
);
spec
->
ext_mic_present
=
!!
present
;
cxt5066_olpc_select_mic
(
codec
);
}
/* toggle input of built-in digital mic and mic jack appropriately */
static
void
cxt5066_vostro_automic
(
struct
hda_codec
*
codec
)
{
...
...
@@ -2251,23 +2111,6 @@ static void cxt5066_automic(struct hda_codec *codec)
cxt5066_asus_automic
(
codec
);
}
/* unsolicited event for jack sensing */
static
void
cxt5066_olpc_unsol_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
snd_printdd
(
"CXT5066: unsol event %x (%x)
\n
"
,
res
,
res
>>
26
);
switch
(
res
>>
26
)
{
case
CONEXANT_HP_EVENT
:
cxt5066_hp_automute
(
codec
);
break
;
case
CONEXANT_MIC_EVENT
:
/* ignore mic events in DC mode; we're always using the jack */
if
(
!
spec
->
dc_enable
)
cxt5066_olpc_automic
(
codec
);
break
;
}
}
/* unsolicited event for jack sensing */
static
void
cxt5066_unsol_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
{
...
...
@@ -2338,124 +2181,10 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
idx
=
imux
->
num_items
-
1
;
spec
->
mic_boost
=
idx
;
if
(
!
spec
->
dc_enable
)
cxt5066_set_mic_boost
(
codec
);
return
1
;
}
static
void
cxt5066_enable_dc
(
struct
hda_codec
*
codec
)
{
const
struct
hda_verb
enable_dc_mode
[]
=
{
/* disable gain */
{
0x17
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
},
/* switch to DC input */
{
0x17
,
AC_VERB_SET_CONNECT_SEL
,
3
},
{}
};
/* configure as input source */
snd_hda_sequence_write
(
codec
,
enable_dc_mode
);
cxt5066_olpc_select_mic
(
codec
);
/* also sets configured bias */
}
static
void
cxt5066_disable_dc
(
struct
hda_codec
*
codec
)
{
/* reconfigure input source */
cxt5066_set_mic_boost
(
codec
);
/* automic also selects the right mic if we're recording */
cxt5066_olpc_automic
(
codec
);
}
static
int
cxt5066_olpc_dc_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
spec
->
dc_enable
;
return
0
;
}
static
int
cxt5066_olpc_dc_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
dc_enable
=
!!
ucontrol
->
value
.
integer
.
value
[
0
];
if
(
dc_enable
==
spec
->
dc_enable
)
return
0
;
spec
->
dc_enable
=
dc_enable
;
if
(
dc_enable
)
cxt5066_enable_dc
(
codec
);
else
cxt5066_disable_dc
(
codec
);
return
1
;
}
static
int
cxt5066_olpc_dc_bias_enum_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
return
snd_hda_input_mux_info
(
&
cxt5066_olpc_dc_bias
,
uinfo
);
}
static
int
cxt5066_olpc_dc_bias_enum_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
spec
->
dc_input_bias
;
return
0
;
}
static
int
cxt5066_olpc_dc_bias_enum_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
const
struct
hda_input_mux
*
imux
=
&
cxt5066_analog_mic_boost
;
unsigned
int
idx
;
idx
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
idx
>=
imux
->
num_items
)
idx
=
imux
->
num_items
-
1
;
spec
->
dc_input_bias
=
idx
;
if
(
spec
->
dc_enable
)
cxt5066_set_olpc_dc_bias
(
codec
);
return
1
;
}
static
void
cxt5066_olpc_capture_prepare
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
/* mark as recording and configure the microphone widget so that the
* recording LED comes on. */
spec
->
recording
=
1
;
cxt5066_olpc_select_mic
(
codec
);
}
static
void
cxt5066_olpc_capture_cleanup
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
const
struct
hda_verb
disable_mics
[]
=
{
/* disable external mic, port B */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* disble internal mic, port C */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* disable DC capture, port F */
{
0x1e
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{},
};
snd_hda_sequence_write
(
codec
,
disable_mics
);
spec
->
recording
=
0
;
}
static
void
conexant_check_dig_outs
(
struct
hda_codec
*
codec
,
const
hda_nid_t
*
dig_pins
,
int
num_pins
)
...
...
@@ -2506,43 +2235,6 @@ static const struct snd_kcontrol_new cxt5066_mixer_master[] = {
{}
};
static
const
struct
snd_kcontrol_new
cxt5066_mixer_master_olpc
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Master Playback Volume"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READWRITE
|
SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
,
.
subdevice
=
HDA_SUBDEV_AMP_FLAG
,
.
info
=
snd_hda_mixer_amp_volume_info
,
.
get
=
snd_hda_mixer_amp_volume_get
,
.
put
=
snd_hda_mixer_amp_volume_put
,
.
tlv
=
{
.
c
=
snd_hda_mixer_amp_tlv
},
/* offset by 28 volume steps to limit minimum gain to -46dB */
.
private_value
=
HDA_COMPOSE_AMP_VAL_OFS
(
0x10
,
3
,
0
,
HDA_OUTPUT
,
28
),
},
{}
};
static
const
struct
snd_kcontrol_new
cxt5066_mixer_olpc_dc
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"DC Mode Enable Switch"
,
.
info
=
snd_ctl_boolean_mono_info
,
.
get
=
cxt5066_olpc_dc_get
,
.
put
=
cxt5066_olpc_dc_put
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"DC Input Bias Enum"
,
.
info
=
cxt5066_olpc_dc_bias_enum_info
,
.
get
=
cxt5066_olpc_dc_bias_enum_get
,
.
put
=
cxt5066_olpc_dc_bias_enum_put
,
},
{}
};
static
const
struct
snd_kcontrol_new
cxt5066_mixers
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
...
...
@@ -2633,67 +2325,6 @@ static const struct hda_verb cxt5066_init_verbs[] = {
{
}
/* end */
};
static
const
struct
hda_verb
cxt5066_init_verbs_olpc
[]
=
{
/* Port A: headphones */
{
0x19
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_HP
},
{
0x19
,
AC_VERB_SET_CONNECT_SEL
,
0x00
},
/* DAC1 */
/* Port B: external microphone */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port C: internal microphone */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port D: unused */
{
0x1c
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port E: unused, but has primary EAPD */
{
0x1d
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{
0x1d
,
AC_VERB_SET_EAPD_BTLENABLE
,
0x2
},
/* default on */
/* Port F: external DC input through microphone port */
{
0x1e
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port G: internal speakers */
{
0x1f
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_OUT
},
{
0x1f
,
AC_VERB_SET_CONNECT_SEL
,
0x00
},
/* DAC1 */
/* DAC1 */
{
0x10
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
},
/* DAC2: unused */
{
0x11
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
{
0x14
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
0
)
|
0x50
},
{
0x14
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
1
)},
{
0x14
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
2
)},
{
0x14
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
3
)},
{
0x15
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
0
)},
{
0x15
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
1
)},
{
0x15
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
2
)},
{
0x15
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
3
)},
{
0x16
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
0
)},
{
0x16
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
1
)},
{
0x16
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
2
)},
{
0x16
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_MUTE
(
3
)},
/* Disable digital microphone port */
{
0x23
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Audio input selectors */
{
0x17
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
|
0x3
},
{
0x18
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_MUTE
},
/* Disable SPDIF */
{
0x20
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{
0x22
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* enable unsolicited events for Port A and B */
{
0x19
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
CONEXANT_HP_EVENT
},
{
0x1a
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
CONEXANT_MIC_EVENT
},
{
}
/* end */
};
static
const
struct
hda_verb
cxt5066_init_verbs_vostro
[]
=
{
/* Port A: headphones */
{
0x19
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
...
...
@@ -2889,25 +2520,9 @@ static int cxt5066_init(struct hda_codec *codec)
return
0
;
}
static
int
cxt5066_olpc_init
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
snd_printdd
(
"CXT5066: init
\n
"
);
conexant_init
(
codec
);
cxt5066_hp_automute
(
codec
);
if
(
!
spec
->
dc_enable
)
{
cxt5066_set_mic_boost
(
codec
);
cxt5066_olpc_automic
(
codec
);
}
else
{
cxt5066_enable_dc
(
codec
);
}
return
0
;
}
enum
{
CXT5066_LAPTOP
,
/* Laptops w/ EAPD support */
CXT5066_DELL_LAPTOP
,
/* Dell Laptop */
CXT5066_OLPC_XO_1_5
,
/* OLPC XO 1.5 */
CXT5066_DELL_VOSTRO
,
/* Dell Vostro 1015i */
CXT5066_IDEAPAD
,
/* Lenovo IdeaPad U150 */
CXT5066_THINKPAD
,
/* Lenovo ThinkPad T410s, others? */
...
...
@@ -2920,7 +2535,6 @@ enum {
static
const
char
*
const
cxt5066_models
[
CXT5066_MODELS
]
=
{
[
CXT5066_LAPTOP
]
=
"laptop"
,
[
CXT5066_DELL_LAPTOP
]
=
"dell-laptop"
,
[
CXT5066_OLPC_XO_1_5
]
=
"olpc-xo-1_5"
,
[
CXT5066_DELL_VOSTRO
]
=
"dell-vostro"
,
[
CXT5066_IDEAPAD
]
=
"ideapad"
,
[
CXT5066_THINKPAD
]
=
"thinkpad"
,
...
...
@@ -2941,10 +2555,8 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK
(
0x1043
,
0x1643
,
"Asus K52JU"
,
CXT5066_ASUS
),
SND_PCI_QUIRK
(
0x1043
,
0x1993
,
"Asus U50F"
,
CXT5066_ASUS
),
SND_PCI_QUIRK
(
0x1179
,
0xff1e
,
"Toshiba Satellite C650D"
,
CXT5066_IDEAPAD
),
SND_PCI_QUIRK
(
0x1179
,
0xff50
,
"Toshiba Satellite P500-PSPGSC-01800T"
,
CXT5066_OLPC_XO_1_5
),
SND_PCI_QUIRK
(
0x14f1
,
0x0101
,
"Conexant Reference board"
,
CXT5066_LAPTOP
),
SND_PCI_QUIRK
(
0x152d
,
0x0833
,
"OLPC XO-1.5"
,
CXT5066_OLPC_XO_1_5
),
SND_PCI_QUIRK
(
0x17aa
,
0x20f2
,
"Lenovo T400s"
,
CXT5066_THINKPAD
),
SND_PCI_QUIRK
(
0x17aa
,
0x21c5
,
"Thinkpad Edge 13"
,
CXT5066_THINKPAD
),
SND_PCI_QUIRK
(
0x17aa
,
0x21c6
,
"Thinkpad Edge 13"
,
CXT5066_ASUS
),
...
...
@@ -3030,32 +2642,11 @@ static int patch_cxt5066(struct hda_codec *codec)
spec
->
mic_boost
=
3
;
/* default 30dB gain */
break
;
case
CXT5066_OLPC_XO_1_5
:
codec
->
patch_ops
.
init
=
cxt5066_olpc_init
;
codec
->
patch_ops
.
unsol_event
=
cxt5066_olpc_unsol_event
;
spec
->
init_verbs
[
0
]
=
cxt5066_init_verbs_olpc
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixer_master_olpc
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixer_olpc_dc
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixers
;
spec
->
port_d_mode
=
0
;
spec
->
mic_boost
=
3
;
/* default 30dB gain */
/* no S/PDIF out */
spec
->
multiout
.
dig_out_nid
=
0
;
/* input source automatically selected */
spec
->
input_mux
=
NULL
;
/* our capture hooks which allow us to turn on the microphone LED
* at the right time */
spec
->
capture_prepare
=
cxt5066_olpc_capture_prepare
;
spec
->
capture_cleanup
=
cxt5066_olpc_capture_cleanup
;
break
;
case
CXT5066_DELL_VOSTRO
:
codec
->
patch_ops
.
init
=
cxt5066_init
;
codec
->
patch_ops
.
unsol_event
=
cxt5066_unsol_event
;
spec
->
init_verbs
[
0
]
=
cxt5066_init_verbs_vostro
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixer_master
_olpc
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixer_master
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixers
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_vostro_mixers
;
spec
->
port_d_mode
=
0
;
...
...
@@ -3238,6 +2829,11 @@ enum {
CXT_FIXUP_HEADPHONE_MIC
,
CXT_FIXUP_GPIO1
,
CXT_FIXUP_THINKPAD_ACPI
,
CXT_FIXUP_OLPC_XO
,
CXT_FIXUP_CAP_MIX_AMP
,
CXT_FIXUP_TOSHIBA_P105
,
CXT_FIXUP_HP_530
,
CXT_FIXUP_CAP_MIX_AMP_5047
,
};
/* for hda_fixup_thinkpad_acpi() */
...
...
@@ -3315,6 +2911,288 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec,
}
}
/* OPLC XO 1.5 fixup */
/* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors)
* through the microphone jack.
* When the user enables this through a mixer switch, both internal and
* external microphones are disabled. Gain is fixed at 0dB. In this mode,
* we also allow the bias to be configured through a separate mixer
* control. */
#define update_mic_pin(codec, nid, val) \
snd_hda_codec_update_cache(codec, nid, 0, \
AC_VERB_SET_PIN_WIDGET_CONTROL, val)
static
const
struct
hda_input_mux
olpc_xo_dc_bias
=
{
.
num_items
=
3
,
.
items
=
{
{
"Off"
,
PIN_IN
},
{
"50%"
,
PIN_VREF50
},
{
"80%"
,
PIN_VREF80
},
},
};
static
void
olpc_xo_update_mic_boost
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
ch
,
val
;
for
(
ch
=
0
;
ch
<
2
;
ch
++
)
{
val
=
AC_AMP_SET_OUTPUT
|
(
ch
?
AC_AMP_SET_RIGHT
:
AC_AMP_SET_LEFT
);
if
(
!
spec
->
dc_enable
)
val
|=
snd_hda_codec_amp_read
(
codec
,
0x17
,
ch
,
HDA_OUTPUT
,
0
);
snd_hda_codec_write
(
codec
,
0x17
,
0
,
AC_VERB_SET_AMP_GAIN_MUTE
,
val
);
}
}
static
void
olpc_xo_update_mic_pins
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
cur_input
,
val
;
struct
nid_path
*
path
;
cur_input
=
spec
->
gen
.
input_paths
[
0
][
spec
->
gen
.
cur_mux
[
0
]];
/* Set up mic pins for port-B, C and F dynamically as the recording
* LED is turned on/off by these pin controls
*/
if
(
!
spec
->
dc_enable
)
{
/* disable DC bias path and pin for port F */
update_mic_pin
(
codec
,
0x1e
,
0
);
snd_hda_activate_path
(
codec
,
spec
->
dc_mode_path
,
false
,
false
);
/* update port B (ext mic) and C (int mic) */
/* OLPC defers mic widget control until when capture is
* started because the microphone LED comes on as soon as
* these settings are put in place. if we did this before
* recording, it would give the false indication that
* recording is happening when it is not.
*/
update_mic_pin
(
codec
,
0x1a
,
spec
->
recording
?
snd_hda_codec_get_pin_target
(
codec
,
0x1a
)
:
0
);
update_mic_pin
(
codec
,
0x1b
,
spec
->
recording
?
snd_hda_codec_get_pin_target
(
codec
,
0x1b
)
:
0
);
/* enable normal mic path */
path
=
snd_hda_get_path_from_idx
(
codec
,
cur_input
);
if
(
path
)
snd_hda_activate_path
(
codec
,
path
,
true
,
false
);
}
else
{
/* disable normal mic path */
path
=
snd_hda_get_path_from_idx
(
codec
,
cur_input
);
if
(
path
)
snd_hda_activate_path
(
codec
,
path
,
false
,
false
);
/* Even though port F is the DC input, the bias is controlled
* on port B. We also leave that port as an active input (but
* unselected) in DC mode just in case that is necessary to
* make the bias setting take effect.
*/
if
(
spec
->
recording
)
val
=
olpc_xo_dc_bias
.
items
[
spec
->
dc_input_bias
].
index
;
else
val
=
0
;
update_mic_pin
(
codec
,
0x1a
,
val
);
update_mic_pin
(
codec
,
0x1b
,
0
);
/* enable DC bias path and pin */
update_mic_pin
(
codec
,
0x1e
,
spec
->
recording
?
PIN_IN
:
0
);
snd_hda_activate_path
(
codec
,
spec
->
dc_mode_path
,
true
,
false
);
}
}
/* mic_autoswitch hook */
static
void
olpc_xo_automic
(
struct
hda_codec
*
codec
,
struct
hda_jack_tbl
*
jack
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
saved_cached_write
=
codec
->
cached_write
;
codec
->
cached_write
=
1
;
/* in DC mode, we don't handle automic */
if
(
!
spec
->
dc_enable
)
snd_hda_gen_mic_autoswitch
(
codec
,
jack
);
olpc_xo_update_mic_pins
(
codec
);
snd_hda_codec_flush_cache
(
codec
);
codec
->
cached_write
=
saved_cached_write
;
if
(
spec
->
dc_enable
)
olpc_xo_update_mic_boost
(
codec
);
}
/* pcm_capture hook */
static
void
olpc_xo_capture_hook
(
struct
hda_pcm_stream
*
hinfo
,
struct
hda_codec
*
codec
,
struct
snd_pcm_substream
*
substream
,
int
action
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
/* toggle spec->recording flag and update mic pins accordingly
* for turning on/off LED
*/
switch
(
action
)
{
case
HDA_GEN_PCM_ACT_PREPARE
:
spec
->
recording
=
1
;
olpc_xo_update_mic_pins
(
codec
);
break
;
case
HDA_GEN_PCM_ACT_CLEANUP
:
spec
->
recording
=
0
;
olpc_xo_update_mic_pins
(
codec
);
break
;
}
}
static
int
olpc_xo_dc_mode_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
spec
->
dc_enable
;
return
0
;
}
static
int
olpc_xo_dc_mode_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
dc_enable
=
!!
ucontrol
->
value
.
integer
.
value
[
0
];
if
(
dc_enable
==
spec
->
dc_enable
)
return
0
;
spec
->
dc_enable
=
dc_enable
;
olpc_xo_update_mic_pins
(
codec
);
olpc_xo_update_mic_boost
(
codec
);
return
1
;
}
static
int
olpc_xo_dc_bias_enum_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
spec
->
dc_input_bias
;
return
0
;
}
static
int
olpc_xo_dc_bias_enum_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
return
snd_hda_input_mux_info
(
&
olpc_xo_dc_bias
,
uinfo
);
}
static
int
olpc_xo_dc_bias_enum_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
const
struct
hda_input_mux
*
imux
=
&
olpc_xo_dc_bias
;
unsigned
int
idx
;
idx
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
idx
>=
imux
->
num_items
)
idx
=
imux
->
num_items
-
1
;
if
(
spec
->
dc_input_bias
==
idx
)
return
0
;
spec
->
dc_input_bias
=
idx
;
if
(
spec
->
dc_enable
)
olpc_xo_update_mic_pins
(
codec
);
return
1
;
}
static
const
struct
snd_kcontrol_new
olpc_xo_mixers
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"DC Mode Enable Switch"
,
.
info
=
snd_ctl_boolean_mono_info
,
.
get
=
olpc_xo_dc_mode_get
,
.
put
=
olpc_xo_dc_mode_put
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"DC Input Bias Enum"
,
.
info
=
olpc_xo_dc_bias_enum_info
,
.
get
=
olpc_xo_dc_bias_enum_get
,
.
put
=
olpc_xo_dc_bias_enum_put
,
},
{}
};
/* overriding mic boost put callback; update mic boost volume only when
* DC mode is disabled
*/
static
int
olpc_xo_mic_boost_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
ret
=
snd_hda_mixer_amp_volume_put
(
kcontrol
,
ucontrol
);
if
(
ret
>
0
&&
spec
->
dc_enable
)
olpc_xo_update_mic_boost
(
codec
);
return
ret
;
}
static
void
cxt_fixup_olpc_xo
(
struct
hda_codec
*
codec
,
const
struct
hda_fixup
*
fix
,
int
action
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
int
i
;
if
(
action
!=
HDA_FIXUP_ACT_PROBE
)
return
;
spec
->
gen
.
mic_autoswitch_hook
=
olpc_xo_automic
;
spec
->
gen
.
pcm_capture_hook
=
olpc_xo_capture_hook
;
spec
->
dc_mode_path
=
snd_hda_add_new_path
(
codec
,
0x1e
,
0x14
,
0
);
snd_hda_add_new_ctls
(
codec
,
olpc_xo_mixers
);
/* OLPC's microphone port is DC coupled for use with external sensors,
* therefore we use a 50% mic bias in order to center the input signal
* with the DC input range of the codec.
*/
snd_hda_codec_set_pin_target
(
codec
,
0x1a
,
PIN_VREF50
);
/* override mic boost control */
for
(
i
=
0
;
i
<
spec
->
gen
.
kctls
.
used
;
i
++
)
{
struct
snd_kcontrol_new
*
kctl
=
snd_array_elem
(
&
spec
->
gen
.
kctls
,
i
);
if
(
!
strcmp
(
kctl
->
name
,
"Mic Boost Volume"
))
{
kctl
->
put
=
olpc_xo_mic_boost_put
;
break
;
}
}
}
/*
* Fix max input level on mixer widget to 0dB
* (originally it has 0x2b steps with 0dB offset 0x14)
*/
static
void
cxt_fixup_cap_mix_amp
(
struct
hda_codec
*
codec
,
const
struct
hda_fixup
*
fix
,
int
action
)
{
snd_hda_override_amp_caps
(
codec
,
0x17
,
HDA_INPUT
,
(
0x14
<<
AC_AMPCAP_OFFSET_SHIFT
)
|
(
0x14
<<
AC_AMPCAP_NUM_STEPS_SHIFT
)
|
(
0x05
<<
AC_AMPCAP_STEP_SIZE_SHIFT
)
|
(
1
<<
AC_AMPCAP_MUTE_SHIFT
));
}
/*
* Fix max input level on mixer widget to 0dB
* (originally it has 0x1e steps with 0 dB offset 0x17)
*/
static
void
cxt_fixup_cap_mix_amp_5047
(
struct
hda_codec
*
codec
,
const
struct
hda_fixup
*
fix
,
int
action
)
{
snd_hda_override_amp_caps
(
codec
,
0x10
,
HDA_INPUT
,
(
0x17
<<
AC_AMPCAP_OFFSET_SHIFT
)
|
(
0x17
<<
AC_AMPCAP_NUM_STEPS_SHIFT
)
|
(
0x05
<<
AC_AMPCAP_STEP_SIZE_SHIFT
)
|
(
1
<<
AC_AMPCAP_MUTE_SHIFT
));
}
/* ThinkPad X200 & co with cxt5051 */
static
const
struct
hda_pintbl
cxt_pincfg_lenovo_x200
[]
=
{
...
...
@@ -3400,6 +3278,68 @@ static const struct hda_fixup cxt_fixups[] = {
.
type
=
HDA_FIXUP_FUNC
,
.
v
.
func
=
hda_fixup_thinkpad_acpi
,
},
[
CXT_FIXUP_OLPC_XO
]
=
{
.
type
=
HDA_FIXUP_FUNC
,
.
v
.
func
=
cxt_fixup_olpc_xo
,
},
[
CXT_FIXUP_CAP_MIX_AMP
]
=
{
.
type
=
HDA_FIXUP_FUNC
,
.
v
.
func
=
cxt_fixup_cap_mix_amp
,
},
[
CXT_FIXUP_TOSHIBA_P105
]
=
{
.
type
=
HDA_FIXUP_PINS
,
.
v
.
pins
=
(
const
struct
hda_pintbl
[])
{
{
0x10
,
0x961701f0
},
/* speaker/hp */
{
0x12
,
0x02a1901e
},
/* ext mic */
{
0x14
,
0x95a70110
},
/* int mic */
{}
},
},
[
CXT_FIXUP_HP_530
]
=
{
.
type
=
HDA_FIXUP_PINS
,
.
v
.
pins
=
(
const
struct
hda_pintbl
[])
{
{
0x12
,
0x90a60160
},
/* int mic */
{}
},
.
chained
=
true
,
.
chain_id
=
CXT_FIXUP_CAP_MIX_AMP
,
},
[
CXT_FIXUP_CAP_MIX_AMP_5047
]
=
{
.
type
=
HDA_FIXUP_FUNC
,
.
v
.
func
=
cxt_fixup_cap_mix_amp_5047
,
},
};
static
const
struct
snd_pci_quirk
cxt5045_fixups
[]
=
{
SND_PCI_QUIRK
(
0x103c
,
0x30d5
,
"HP 530"
,
CXT_FIXUP_HP_530
),
SND_PCI_QUIRK
(
0x1179
,
0xff31
,
"Toshiba P105"
,
CXT_FIXUP_TOSHIBA_P105
),
/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
* really bad sound over 0dB on NID 0x17.
*/
SND_PCI_QUIRK_VENDOR
(
0x103c
,
"HP"
,
CXT_FIXUP_CAP_MIX_AMP
),
SND_PCI_QUIRK_VENDOR
(
0x1631
,
"Packard Bell"
,
CXT_FIXUP_CAP_MIX_AMP
),
SND_PCI_QUIRK_VENDOR
(
0x1734
,
"Fujitsu"
,
CXT_FIXUP_CAP_MIX_AMP
),
SND_PCI_QUIRK_VENDOR
(
0x17aa
,
"Lenovo"
,
CXT_FIXUP_CAP_MIX_AMP
),
{}
};
static
const
struct
hda_model_fixup
cxt5045_fixup_models
[]
=
{
{
.
id
=
CXT_FIXUP_CAP_MIX_AMP
,
.
name
=
"cap-mix-amp"
},
{
.
id
=
CXT_FIXUP_TOSHIBA_P105
,
.
name
=
"toshiba-p105"
},
{
.
id
=
CXT_FIXUP_HP_530
,
.
name
=
"hp-530"
},
{}
};
static
const
struct
snd_pci_quirk
cxt5047_fixups
[]
=
{
/* HP laptops have really bad sound over 0 dB on NID 0x10.
*/
SND_PCI_QUIRK_VENDOR
(
0x103c
,
"HP"
,
CXT_FIXUP_CAP_MIX_AMP_5047
),
{}
};
static
const
struct
hda_model_fixup
cxt5047_fixup_models
[]
=
{
{
.
id
=
CXT_FIXUP_CAP_MIX_AMP_5047
,
.
name
=
"cap-mix-amp"
},
{}
};
static
const
struct
snd_pci_quirk
cxt5051_fixups
[]
=
{
...
...
@@ -3407,10 +3347,16 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
{}
};
static
const
struct
hda_model_fixup
cxt5051_fixup_models
[]
=
{
{
.
id
=
CXT_PINCFG_LENOVO_X200
,
.
name
=
"lenovo-x200"
},
{}
};
static
const
struct
snd_pci_quirk
cxt5066_fixups
[]
=
{
SND_PCI_QUIRK
(
0x1025
,
0x0543
,
"Acer Aspire One 522"
,
CXT_FIXUP_STEREO_DMIC
),
SND_PCI_QUIRK
(
0x1025
,
0x054c
,
"Acer Aspire 3830TG"
,
CXT_FIXUP_GPIO1
),
SND_PCI_QUIRK
(
0x1043
,
0x138d
,
"Asus"
,
CXT_FIXUP_HEADPHONE_MIC_PIN
),
SND_PCI_QUIRK
(
0x152d
,
0x0833
,
"OLPC XO-1.5"
,
CXT_FIXUP_OLPC_XO
),
SND_PCI_QUIRK
(
0x17aa
,
0x20f2
,
"Lenovo T400"
,
CXT_PINCFG_LENOVO_TP410
),
SND_PCI_QUIRK
(
0x17aa
,
0x215e
,
"Lenovo T410"
,
CXT_PINCFG_LENOVO_TP410
),
SND_PCI_QUIRK
(
0x17aa
,
0x215f
,
"Lenovo T510"
,
CXT_PINCFG_LENOVO_TP410
),
...
...
@@ -3427,6 +3373,17 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
{}
};
static
const
struct
hda_model_fixup
cxt5066_fixup_models
[]
=
{
{
.
id
=
CXT_FIXUP_STEREO_DMIC
,
.
name
=
"stereo-dmic"
},
{
.
id
=
CXT_FIXUP_GPIO1
,
.
name
=
"gpio1"
},
{
.
id
=
CXT_FIXUP_HEADPHONE_MIC_PIN
,
.
name
=
"headphone-mic-pin"
},
{
.
id
=
CXT_PINCFG_LENOVO_TP410
,
.
name
=
"tp410"
},
{
.
id
=
CXT_FIXUP_THINKPAD_ACPI
,
.
name
=
"thinkpad"
},
{
.
id
=
CXT_PINCFG_LEMOTE_A1004
,
.
name
=
"lemote-a1004"
},
{
.
id
=
CXT_FIXUP_OLPC_XO
,
.
name
=
"olpc-xo"
},
{}
};
/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
* can be created (bko#42825)
*/
...
...
@@ -3466,19 +3423,28 @@ static int patch_conexant_auto(struct hda_codec *codec)
switch
(
codec
->
vendor_id
)
{
case
0x14f15045
:
codec
->
single_adc_amp
=
1
;
spec
->
gen
.
mixer_nid
=
0x17
;
spec
->
gen
.
add_stereo_mix_input
=
1
;
snd_hda_pick_fixup
(
codec
,
cxt5045_fixup_models
,
cxt5045_fixups
,
cxt_fixups
);
break
;
case
0x14f15047
:
codec
->
pin_amp_workaround
=
1
;
spec
->
gen
.
mixer_nid
=
0x19
;
spec
->
gen
.
add_stereo_mix_input
=
1
;
snd_hda_pick_fixup
(
codec
,
cxt5047_fixup_models
,
cxt5047_fixups
,
cxt_fixups
);
break
;
case
0x14f15051
:
add_cx5051_fake_mutes
(
codec
);
codec
->
pin_amp_workaround
=
1
;
snd_hda_pick_fixup
(
codec
,
NULL
,
cxt5051_fixups
,
cxt_fixups
);
snd_hda_pick_fixup
(
codec
,
cxt5051_fixup_models
,
cxt5051_fixups
,
cxt_fixups
);
break
;
default:
codec
->
pin_amp_workaround
=
1
;
snd_hda_pick_fixup
(
codec
,
NULL
,
cxt5066_fixups
,
cxt_fixups
);
snd_hda_pick_fixup
(
codec
,
cxt5066_fixup_models
,
cxt5066_fixups
,
cxt_fixups
);
break
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录