Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gsplhtlxg
clone-Linux
提交
47e91348
C
clone-Linux
项目概览
gsplhtlxg
/
clone-Linux
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
clone-Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
47e91348
编写于
1月 13, 2010
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'devel' of git.alsa-project.org:alsa-kernel into topic/misc
上级
6b98515a
ed69c6a8
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
591 addition
and
183 deletion
+591
-183
sound/core/pcm_lib.c
sound/core/pcm_lib.c
+5
-3
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.c
+22
-26
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+1
-0
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_hwdep.c
+5
-2
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+19
-32
sound/pci/hda/hda_local.h
sound/pci/hda/hda_local.h
+0
-2
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_analog.c
+69
-2
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_cirrus.c
+8
-4
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_cmedia.c
+1
-2
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_conexant.c
+322
-60
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_realtek.c
+49
-24
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_sigmatel.c
+89
-24
sound/pci/hda/patch_via.c
sound/pci/hda/patch_via.c
+1
-2
未找到文件。
sound/core/pcm_lib.c
浏览文件 @
47e91348
...
...
@@ -394,6 +394,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
+
HZ
/
100
);
/* move new_hw_ptr according jiffies not pos variable */
new_hw_ptr
=
old_hw_ptr
;
hw_base
=
delta
;
/* use loop to avoid checks for delta overflows */
/* the delta value is small or zero in most cases */
while
(
delta
>
0
)
{
...
...
@@ -403,8 +404,6 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
delta
--
;
}
/* align hw_base to buffer_size */
hw_base
=
new_hw_ptr
-
(
new_hw_ptr
%
runtime
->
buffer_size
);
delta
=
0
;
hw_ptr_error
(
substream
,
"hw_ptr skipping! %s"
"(pos=%ld, delta=%ld, period=%ld, "
...
...
@@ -412,9 +411,12 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
in_interrupt
?
"[Q] "
:
""
,
(
long
)
pos
,
(
long
)
hdelta
,
(
long
)
runtime
->
period_size
,
jdelta
,
((
hdelta
*
HZ
)
/
runtime
->
rate
),
delta
,
((
hdelta
*
HZ
)
/
runtime
->
rate
),
hw_base
,
(
unsigned
long
)
old_hw_ptr
,
(
unsigned
long
)
new_hw_ptr
);
/* reset values to proper state */
delta
=
0
;
hw_base
=
new_hw_ptr
-
(
new_hw_ptr
%
runtime
->
buffer_size
);
}
no_jiffies_check:
if
(
delta
>
runtime
->
period_size
+
runtime
->
period_size
/
2
)
{
...
...
sound/pci/hda/hda_codec.c
浏览文件 @
47e91348
...
...
@@ -824,6 +824,9 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
struct
hda_pincfg
*
pin
;
unsigned
int
oldcfg
;
if
(
get_wcaps_type
(
get_wcaps
(
codec
,
nid
))
!=
AC_WID_PIN
)
return
-
EINVAL
;
oldcfg
=
snd_hda_codec_get_pincfg
(
codec
,
nid
);
pin
=
look_up_pincfg
(
codec
,
list
,
nid
);
if
(
!
pin
)
{
...
...
@@ -899,6 +902,25 @@ static void restore_pincfgs(struct hda_codec *codec)
}
}
/**
* snd_hda_shutup_pins - Shut up all pins
* @codec: the HDA codec
*
* Clear all pin controls to shup up before suspend for avoiding click noise.
* The controls aren't cached so that they can be resumed properly.
*/
void
snd_hda_shutup_pins
(
struct
hda_codec
*
codec
)
{
int
i
;
for
(
i
=
0
;
i
<
codec
->
init_pins
.
used
;
i
++
)
{
struct
hda_pincfg
*
pin
=
snd_array_elem
(
&
codec
->
init_pins
,
i
);
/* use read here for syncing after issuing each verb */
snd_hda_codec_read
(
codec
,
pin
->
nid
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
);
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_shutup_pins
);
static
void
init_hda_cache
(
struct
hda_cache_rec
*
cache
,
unsigned
int
record_size
);
static
void
free_hda_cache
(
struct
hda_cache_rec
*
cache
);
...
...
@@ -3537,32 +3559,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
}
EXPORT_SYMBOL_HDA
(
snd_hda_add_new_ctls
);
/**
* snd_hda_add_nids - assign nids to controls from the array
* @codec: the HDA codec
* @kctl: struct snd_kcontrol
* @index: index to kctl
* @nids: the array of hda_nid_t
* @size: count of hda_nid_t items
*
* This helper function assigns NIDs in the given array to a control element.
*
* Returns 0 if successful, or a negative error code.
*/
int
snd_hda_add_nids
(
struct
hda_codec
*
codec
,
struct
snd_kcontrol
*
kctl
,
unsigned
int
index
,
hda_nid_t
*
nids
,
unsigned
int
size
)
{
int
err
;
for
(
;
size
>
0
;
size
--
,
nids
++
)
{
err
=
snd_hda_add_nid
(
codec
,
kctl
,
index
,
*
nids
);
if
(
err
<
0
)
return
err
;
}
return
0
;
}
EXPORT_SYMBOL_HDA
(
snd_hda_add_nids
);
#ifdef CONFIG_SND_HDA_POWER_SAVE
static
void
hda_set_power_state
(
struct
hda_codec
*
codec
,
hda_nid_t
fg
,
unsigned
int
power_state
);
...
...
sound/pci/hda/hda_codec.h
浏览文件 @
47e91348
...
...
@@ -898,6 +898,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid,
unsigned
int
cfg
);
int
snd_hda_add_pincfg
(
struct
hda_codec
*
codec
,
struct
snd_array
*
list
,
hda_nid_t
nid
,
unsigned
int
cfg
);
/* for hwdep */
void
snd_hda_shutup_pins
(
struct
hda_codec
*
codec
);
/*
* Mixer
...
...
sound/pci/hda/hda_hwdep.c
浏览文件 @
47e91348
...
...
@@ -293,8 +293,11 @@ static ssize_t type##_store(struct device *dev, \
{ \
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
struct hda_codec *codec = hwdep->private_data; \
char *after; \
codec->type = simple_strtoul(buf, &after, 0); \
unsigned long val; \
int err = strict_strtoul(buf, 0, &val); \
if (err < 0) \
return err; \
codec->type = val; \
return count; \
}
...
...
sound/pci/hda/hda_intel.c
浏览文件 @
47e91348
...
...
@@ -356,6 +356,7 @@ struct azx_dev {
*/
unsigned
char
stream_tag
;
/* assigned stream */
unsigned
char
index
;
/* stream index */
int
device
;
/* last device number assigned to */
unsigned
int
opened
:
1
;
unsigned
int
running
:
1
;
...
...
@@ -1441,10 +1442,13 @@ static int __devinit azx_codec_configure(struct azx *chip)
*/
/* assign a stream for the PCM */
static
inline
struct
azx_dev
*
azx_assign_device
(
struct
azx
*
chip
,
int
stream
)
static
inline
struct
azx_dev
*
azx_assign_device
(
struct
azx
*
chip
,
struct
snd_pcm_substream
*
substream
)
{
int
dev
,
i
,
nums
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
struct
azx_dev
*
res
=
NULL
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
dev
=
chip
->
playback_index_offset
;
nums
=
chip
->
playback_streams
;
}
else
{
...
...
@@ -1453,10 +1457,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
}
for
(
i
=
0
;
i
<
nums
;
i
++
,
dev
++
)
if
(
!
chip
->
azx_dev
[
dev
].
opened
)
{
chip
->
azx_dev
[
dev
].
opened
=
1
;
return
&
chip
->
azx_dev
[
dev
];
res
=
&
chip
->
azx_dev
[
dev
];
if
(
res
->
device
==
substream
->
pcm
->
device
)
break
;
}
return
NULL
;
if
(
res
)
{
res
->
opened
=
1
;
res
->
device
=
substream
->
pcm
->
device
;
}
return
res
;
}
/* release the assigned stream */
...
...
@@ -1505,7 +1514,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
int
err
;
mutex_lock
(
&
chip
->
open_mutex
);
azx_dev
=
azx_assign_device
(
chip
,
substream
->
stream
);
azx_dev
=
azx_assign_device
(
chip
,
substream
);
if
(
azx_dev
==
NULL
)
{
mutex_unlock
(
&
chip
->
open_mutex
);
return
-
EBUSY
;
...
...
@@ -2695,32 +2704,10 @@ static struct pci_device_id azx_ids[] = {
/* ULI M5461 */
{
PCI_DEVICE
(
0x10b9
,
0x5461
),
.
driver_data
=
AZX_DRIVER_ULI
},
/* NVIDIA MCP */
{
PCI_DEVICE
(
0x10de
,
0x026c
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0371
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x03e4
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x03f0
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x044a
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x044b
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x055c
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x055d
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0590
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0774
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0775
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0776
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0777
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x07fc
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x07fd
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0ac0
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0ac1
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0ac2
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0ac3
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0be2
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0be3
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0be4
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0d94
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0d95
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0d96
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
0x10de
,
0x0d97
),
.
driver_data
=
AZX_DRIVER_NVIDIA
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_NVIDIA
,
PCI_ANY_ID
),
.
class
=
PCI_CLASS_MULTIMEDIA_HD_AUDIO
<<
8
,
.
class_mask
=
0xffffff
,
.
driver_data
=
AZX_DRIVER_NVIDIA
},
/* Teradici */
{
PCI_DEVICE
(
0x6549
,
0x1200
),
.
driver_data
=
AZX_DRIVER_TERA
},
/* Creative X-Fi (CA0110-IBG) */
...
...
sound/pci/hda/hda_local.h
浏览文件 @
47e91348
...
...
@@ -343,8 +343,6 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
const
struct
snd_pci_quirk
*
tbl
);
int
snd_hda_add_new_ctls
(
struct
hda_codec
*
codec
,
struct
snd_kcontrol_new
*
knew
);
int
snd_hda_add_nids
(
struct
hda_codec
*
codec
,
struct
snd_kcontrol
*
kctl
,
unsigned
int
index
,
hda_nid_t
*
nids
,
unsigned
int
size
);
/*
* unsolicited event handler
...
...
sound/pci/hda/patch_analog.c
浏览文件 @
47e91348
...
...
@@ -244,8 +244,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
if
(
!
kctl
)
kctl
=
snd_hda_find_mixer_ctl
(
codec
,
"Input Source"
);
for
(
i
=
0
;
kctl
&&
i
<
kctl
->
count
;
i
++
)
{
err
=
snd_hda_add_nids
(
codec
,
kctl
,
i
,
spec
->
capsrc_nids
,
spec
->
input_mux
->
num_items
);
err
=
snd_hda_add_nid
(
codec
,
kctl
,
i
,
spec
->
capsrc_nids
[
i
]);
if
(
err
<
0
)
return
err
;
}
...
...
@@ -442,6 +441,11 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return
0
;
}
static
inline
void
ad198x_shutup
(
struct
hda_codec
*
codec
)
{
snd_hda_shutup_pins
(
codec
);
}
static
void
ad198x_free_kctls
(
struct
hda_codec
*
codec
)
{
struct
ad198x_spec
*
spec
=
codec
->
spec
;
...
...
@@ -455,6 +459,46 @@ static void ad198x_free_kctls(struct hda_codec *codec)
snd_array_free
(
&
spec
->
kctls
);
}
static
void
ad198x_power_eapd_write
(
struct
hda_codec
*
codec
,
hda_nid_t
front
,
hda_nid_t
hp
)
{
struct
ad198x_spec
*
spec
=
codec
->
spec
;
snd_hda_codec_write
(
codec
,
front
,
0
,
AC_VERB_SET_EAPD_BTLENABLE
,
!
spec
->
inv_eapd
?
0x00
:
0x02
);
snd_hda_codec_write
(
codec
,
hp
,
0
,
AC_VERB_SET_EAPD_BTLENABLE
,
!
spec
->
inv_eapd
?
0x00
:
0x02
);
}
static
void
ad198x_power_eapd
(
struct
hda_codec
*
codec
)
{
/* We currently only handle front, HP */
switch
(
codec
->
vendor_id
)
{
case
0x11d41882
:
case
0x11d4882a
:
case
0x11d41884
:
case
0x11d41984
:
case
0x11d41883
:
case
0x11d4184a
:
case
0x11d4194a
:
case
0x11d4194b
:
ad198x_power_eapd_write
(
codec
,
0x12
,
0x11
);
break
;
case
0x11d41981
:
case
0x11d41983
:
ad198x_power_eapd_write
(
codec
,
0x05
,
0x06
);
break
;
case
0x11d41986
:
ad198x_power_eapd_write
(
codec
,
0x1b
,
0x1a
);
break
;
case
0x11d41988
:
case
0x11d4198b
:
case
0x11d4989a
:
case
0x11d4989b
:
ad198x_power_eapd_write
(
codec
,
0x29
,
0x22
);
break
;
}
}
static
void
ad198x_free
(
struct
hda_codec
*
codec
)
{
struct
ad198x_spec
*
spec
=
codec
->
spec
;
...
...
@@ -462,11 +506,29 @@ static void ad198x_free(struct hda_codec *codec)
if
(
!
spec
)
return
;
ad198x_shutup
(
codec
);
ad198x_free_kctls
(
codec
);
kfree
(
spec
);
snd_hda_detach_beep_device
(
codec
);
}
#ifdef SND_HDA_NEEDS_RESUME
static
int
ad198x_suspend
(
struct
hda_codec
*
codec
,
pm_message_t
state
)
{
ad198x_shutup
(
codec
);
ad198x_power_eapd
(
codec
);
return
0
;
}
static
int
ad198x_resume
(
struct
hda_codec
*
codec
)
{
ad198x_init
(
codec
);
snd_hda_codec_resume_amp
(
codec
);
snd_hda_codec_resume_cache
(
codec
);
return
0
;
}
#endif
static
struct
hda_codec_ops
ad198x_patch_ops
=
{
.
build_controls
=
ad198x_build_controls
,
.
build_pcms
=
ad198x_build_pcms
,
...
...
@@ -475,6 +537,11 @@ static struct hda_codec_ops ad198x_patch_ops = {
#ifdef CONFIG_SND_HDA_POWER_SAVE
.
check_power_status
=
ad198x_check_power_status
,
#endif
#ifdef SND_HDA_NEEDS_RESUME
.
suspend
=
ad198x_suspend
,
.
resume
=
ad198x_resume
,
#endif
.
reboot_notify
=
ad198x_shutup
,
};
...
...
sound/pci/hda/patch_cirrus.c
浏览文件 @
47e91348
...
...
@@ -753,6 +753,7 @@ static int build_input(struct hda_codec *codec)
spec
->
capture_bind
[
1
]
=
make_bind_capture
(
codec
,
&
snd_hda_bind_vol
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
struct
snd_kcontrol
*
kctl
;
int
n
;
if
(
!
spec
->
capture_bind
[
i
])
return
-
ENOMEM
;
kctl
=
snd_ctl_new1
(
&
cs_capture_ctls
[
i
],
codec
);
...
...
@@ -762,10 +763,13 @@ static int build_input(struct hda_codec *codec)
err
=
snd_hda_ctl_add
(
codec
,
0
,
kctl
);
if
(
err
<
0
)
return
err
;
err
=
snd_hda_add_nids
(
codec
,
kctl
,
0
,
spec
->
adc_nid
,
spec
->
num_inputs
);
if
(
err
<
0
)
return
err
;
for
(
n
=
0
;
n
<
AUTO_PIN_LAST
;
n
++
)
{
if
(
!
spec
->
adc_nid
[
n
])
continue
;
err
=
snd_hda_add_nid
(
codec
,
kctl
,
0
,
spec
->
adc_nid
[
i
]);
if
(
err
<
0
)
return
err
;
}
}
if
(
spec
->
num_inputs
>
1
&&
!
spec
->
mic_detect
)
{
...
...
sound/pci/hda/patch_cmedia.c
浏览文件 @
47e91348
...
...
@@ -345,8 +345,7 @@ static int cmi9880_build_controls(struct hda_codec *codec)
/* assign Capture Source enums to NID */
kctl
=
snd_hda_find_mixer_ctl
(
codec
,
"Capture Source"
);
for
(
i
=
0
;
kctl
&&
i
<
kctl
->
count
;
i
++
)
{
err
=
snd_hda_add_nids
(
codec
,
kctl
,
i
,
spec
->
adc_nids
,
spec
->
input_mux
->
num_items
);
err
=
snd_hda_add_nid
(
codec
,
kctl
,
i
,
spec
->
adc_nids
[
i
]);
if
(
err
<
0
)
return
err
;
}
...
...
sound/pci/hda/patch_conexant.c
浏览文件 @
47e91348
...
...
@@ -111,8 +111,22 @@ struct conexant_spec {
unsigned
int
dell_automute
;
unsigned
int
port_d_mode
;
unsigned
char
ext_mic_bias
;
unsigned
int
dell_vostro
;
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 */
};
static
int
conexant_playback_pcm_open
(
struct
hda_pcm_stream
*
hinfo
,
...
...
@@ -185,6 +199,8 @@ 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
;
...
...
@@ -196,6 +212,8 @@ 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
;
}
...
...
@@ -1723,6 +1741,22 @@ static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
{}
};
static
struct
snd_kcontrol_new
cxt5051_f700_mixers
[]
=
{
HDA_CODEC_VOLUME
(
"Mic Volume"
,
0x14
,
0x01
,
HDA_INPUT
),
HDA_CODEC_MUTE
(
"Mic Switch"
,
0x14
,
0x01
,
HDA_INPUT
),
HDA_CODEC_VOLUME
(
"Master Playback Volume"
,
0x10
,
0x00
,
HDA_OUTPUT
),
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Master Playback Switch"
,
.
info
=
cxt_eapd_info
,
.
get
=
cxt_eapd_get
,
.
put
=
cxt5051_hp_master_sw_put
,
.
private_value
=
0x1a
,
},
{}
};
static
struct
hda_verb
cxt5051_init_verbs
[]
=
{
/* Line in, Mic */
{
0x17
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
0
)
|
0x03
},
...
...
@@ -1813,6 +1847,32 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
{
}
/* end */
};
static
struct
hda_verb
cxt5051_f700_init_verbs
[]
=
{
/* Line in, Mic */
{
0x17
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
1
)
|
0x03
},
{
0x17
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_VREF80
},
{
0x18
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0x0
},
{
0x1d
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0x0
},
/* SPK */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_OUT
},
{
0x1a
,
AC_VERB_SET_CONNECT_SEL
,
0x00
},
/* HP, Amp */
{
0x16
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_HP
},
{
0x16
,
AC_VERB_SET_CONNECT_SEL
,
0x00
},
/* DAC1 */
{
0x10
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_OUT_UNMUTE
},
/* Record selector: Int mic */
{
0x14
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AMP_IN_UNMUTE
(
1
)
|
0x44
},
{
0x14
,
AC_VERB_SET_CONNECT_SEL
,
0x1
},
/* SPDIF route: PCM */
{
0x1c
,
AC_VERB_SET_CONNECT_SEL
,
0x0
},
/* EAPD */
{
0x1a
,
AC_VERB_SET_EAPD_BTLENABLE
,
0x2
},
/* default on */
{
0x16
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
CONEXANT_HP_EVENT
},
{
0x17
,
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
CXT5051_PORTB_EVENT
},
{
}
/* end */
};
/* initialize jack-sensing, too */
static
int
cxt5051_init
(
struct
hda_codec
*
codec
)
{
...
...
@@ -1832,6 +1892,7 @@ enum {
CXT5051_HP
,
/* no docking */
CXT5051_HP_DV6736
,
/* HP without mic switch */
CXT5051_LENOVO_X200
,
/* Lenovo X200 laptop */
CXT5051_F700
,
/* HP Compaq Presario F700 */
CXT5051_MODELS
};
...
...
@@ -1840,6 +1901,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
[
CXT5051_HP
]
=
"hp"
,
[
CXT5051_HP_DV6736
]
=
"hp-dv6736"
,
[
CXT5051_LENOVO_X200
]
=
"lenovo-x200"
,
[
CXT5051_F700
]
=
"hp 700"
};
static
struct
snd_pci_quirk
cxt5051_cfg_tbl
[]
=
{
...
...
@@ -1849,6 +1911,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
CXT5051_LAPTOP
),
SND_PCI_QUIRK
(
0x14f1
,
0x5051
,
"HP Spartan 1.1"
,
CXT5051_HP
),
SND_PCI_QUIRK
(
0x17aa
,
0x20f2
,
"Lenovo X200"
,
CXT5051_LENOVO_X200
),
SND_PCI_QUIRK
(
0x103c
,
0x30ea
,
"Compaq Presario F700"
,
CXT5051_F700
),
{}
};
...
...
@@ -1899,6 +1962,11 @@ static int patch_cxt5051(struct hda_codec *codec)
case
CXT5051_LENOVO_X200
:
spec
->
init_verbs
[
0
]
=
cxt5051_lenovo_x200_init_verbs
;
break
;
case
CXT5051_F700
:
spec
->
init_verbs
[
0
]
=
cxt5051_f700_init_verbs
;
spec
->
mixers
[
0
]
=
cxt5051_f700_mixers
;
spec
->
no_auto_mic
=
1
;
break
;
}
return
0
;
...
...
@@ -1966,53 +2034,97 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return
1
;
}
/* toggle input of built-in and mic jack appropriately */
static
void
cxt5066_automic
(
struct
hda_codec
*
codec
)
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
;
struct
hda_verb
ext_mic_present
[]
=
{
/* enable external mic, port B */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
spec
->
ext_mic_bias
},
/* 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_codec_write_cache
(
codec
,
0x1a
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
cxt5066_olpc_dc_bias
.
items
[
spec
->
dc_input_bias
].
index
);
}
/* switch to external mic input */
{
0x17
,
AC_VERB_SET_CONNECT_SEL
,
0
},
/* 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
;
/* disable internal mic, port C */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{}
};
static
struct
hda_verb
ext_mic_absent
[]
=
{
/* enable internal mic, port C */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_VREF80
},
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
;
}
/* switch to internal mic input
*/
{
0x17
,
AC_VERB_SET_CONNECT_SEL
,
1
},
/* disable DC (port F)
*/
snd_hda_codec_write
(
codec
,
0x1e
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
);
/* disable external mic, port B */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{}
};
/* external mic, port B */
snd_hda_codec_write
(
codec
,
0x1a
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
spec
->
ext_mic_present
?
CXT5066_OLPC_EXT_MIC_BIAS
:
0
);
/* internal mic, port C */
snd_hda_codec_write
(
codec
,
0x1b
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
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
;
present
=
snd_hda_jack_detect
(
codec
,
0x1a
);
if
(
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
"
);
snd_hda_sequence_write
(
codec
,
ext_mic_present
);
}
else
{
else
snd_printdd
(
"CXT5066: external microphone absent
\n
"
);
snd_hda_sequence_write
(
codec
,
ext_mic_absent
);
}
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
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
unsigned
int
present
;
struct
hda_verb
ext_mic_present
[]
=
{
/* enable external mic, port B */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
spec
->
ext_mic_bias
},
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_VREF80
},
/* switch to external mic input */
{
0x17
,
AC_VERB_SET_CONNECT_SEL
,
0
},
...
...
@@ -2063,15 +2175,18 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
}
/* unsolicited event for jack sensing */
static
void
cxt5066_unsol_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
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
:
cxt5066_automic
(
codec
);
/* ignore mic events in DC mode; we're always using the jack */
if
(
!
spec
->
dc_enable
)
cxt5066_olpc_automic
(
codec
);
break
;
}
}
...
...
@@ -2101,6 +2216,15 @@ static const struct hda_input_mux cxt5066_analog_mic_boost = {
},
};
static
int
cxt5066_set_mic_boost
(
struct
hda_codec
*
codec
)
{
struct
conexant_spec
*
spec
=
codec
->
spec
;
return
snd_hda_codec_write_cache
(
codec
,
0x17
,
0
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AC_AMP_SET_RIGHT
|
AC_AMP_SET_LEFT
|
AC_AMP_SET_OUTPUT
|
cxt5066_analog_mic_boost
.
items
[
spec
->
mic_boost
].
index
);
}
static
int
cxt5066_mic_boost_mux_enum_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
...
...
@@ -2111,15 +2235,8 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
int
val
;
hda_nid_t
nid
=
kcontrol
->
private_value
&
0xff
;
int
inout
=
(
kcontrol
->
private_value
&
0x100
)
?
AC_AMP_GET_INPUT
:
AC_AMP_GET_OUTPUT
;
val
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_AMP_GAIN_MUTE
,
inout
);
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
val
&
AC_AMP_GAIN
;
struct
conexant_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
spec
->
mic_boost
;
return
0
;
}
...
...
@@ -2127,26 +2244,132 @@ static int cxt5066_mic_boost_mux_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
;
hda_nid_t
nid
=
kcontrol
->
private_value
&
0xff
;
int
inout
=
(
kcontrol
->
private_value
&
0x100
)
?
AC_AMP_SET_INPUT
:
AC_AMP_SET_OUTPUT
;
idx
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
idx
>=
imux
->
num_items
)
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
(
!
imux
->
num_items
)
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
;
snd_hda_codec_write_cache
(
codec
,
nid
,
0
,
AC_VERB_SET_AMP_GAIN_MUTE
,
AC_AMP_SET_RIGHT
|
AC_AMP_SET_LEFT
|
inout
|
imux
->
items
[
idx
].
index
);
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
struct
hda_input_mux
cxt5066_capture_source
=
{
.
num_items
=
4
,
.
items
=
{
...
...
@@ -2199,6 +2422,24 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
{}
};
static
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
struct
snd_kcontrol_new
cxt5066_mixers
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
...
...
@@ -2211,11 +2452,10 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"
Ext
Mic Boost Capture Enum"
,
.
name
=
"
Analog
Mic Boost Capture Enum"
,
.
info
=
cxt5066_mic_boost_mux_enum_info
,
.
get
=
cxt5066_mic_boost_mux_enum_get
,
.
put
=
cxt5066_mic_boost_mux_enum_put
,
.
private_value
=
0x17
,
},
HDA_BIND_VOL
(
"Capture Volume"
,
&
cxt5066_bind_capture_vol_others
),
...
...
@@ -2297,10 +2537,10 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
{
0x19
,
AC_VERB_SET_CONNECT_SEL
,
0x00
},
/* DAC1 */
/* Port B: external microphone */
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
CXT5066_OLPC_EXT_MIC_BIAS
},
{
0x1a
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port C: internal microphone */
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_VREF8
0
},
{
0x1b
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port D: unused */
{
0x1c
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
...
...
@@ -2309,7 +2549,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
{
0x1d
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
{
0x1d
,
AC_VERB_SET_EAPD_BTLENABLE
,
0x2
},
/* default on */
/* Port F:
unused
*/
/* Port F:
external DC input through microphone port
*/
{
0x1e
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
},
/* Port G: internal speakers */
...
...
@@ -2429,8 +2669,22 @@ static int cxt5066_init(struct hda_codec *codec)
cxt5066_hp_automute
(
codec
);
if
(
spec
->
dell_vostro
)
cxt5066_vostro_automic
(
codec
);
else
cxt5066_automic
(
codec
);
}
cxt5066_set_mic_boost
(
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
;
}
...
...
@@ -2471,7 +2725,7 @@ static int patch_cxt5066(struct hda_codec *codec)
codec
->
spec
=
spec
;
codec
->
patch_ops
=
conexant_patch_ops
;
codec
->
patch_ops
.
init
=
c
xt5066
_init
;
codec
->
patch_ops
.
init
=
c
onexant
_init
;
spec
->
dell_automute
=
0
;
spec
->
multiout
.
max_channels
=
2
;
...
...
@@ -2484,7 +2738,6 @@ static int patch_cxt5066(struct hda_codec *codec)
spec
->
input_mux
=
&
cxt5066_capture_source
;
spec
->
port_d_mode
=
PIN_HP
;
spec
->
ext_mic_bias
=
PIN_VREF80
;
spec
->
num_init_verbs
=
1
;
spec
->
init_verbs
[
0
]
=
cxt5066_init_verbs
;
...
...
@@ -2511,20 +2764,28 @@ static int patch_cxt5066(struct hda_codec *codec)
spec
->
dell_automute
=
1
;
break
;
case
CXT5066_OLPC_XO_1_5
:
codec
->
patch_ops
.
unsol_event
=
cxt5066_unsol_event
;
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
->
ext_mic_bias
=
CXT5066_OLPC_EXT_MIC_BIAS
;
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_VOSTO
:
codec
->
patch_ops
.
init
=
cxt5066_init
;
codec
->
patch_ops
.
unsol_event
=
cxt5066_vostro_event
;
spec
->
init_verbs
[
0
]
=
cxt5066_init_verbs_vostro
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_mixer_master_olpc
;
...
...
@@ -2532,6 +2793,7 @@ static int patch_cxt5066(struct hda_codec *codec)
spec
->
mixers
[
spec
->
num_mixers
++
]
=
cxt5066_vostro_mixers
;
spec
->
port_d_mode
=
0
;
spec
->
dell_vostro
=
1
;
spec
->
mic_boost
=
3
;
/* default 30dB gain */
snd_hda_attach_beep_device
(
codec
,
0x13
);
/* no S/PDIF out */
...
...
sound/pci/hda/patch_realtek.c
浏览文件 @
47e91348
...
...
@@ -338,7 +338,7 @@ struct alc_spec {
void (*init_hook)(struct hda_codec *codec);
void (*unsol_event)(struct hda_codec *codec, unsigned int res);
#ifdef CONFIG_SND_HDA_POWER_SAVE
void (*power_hook)(struct hda_codec *codec
, int power
);
void (*power_hook)(struct hda_codec *codec);
#endif
/* for pin sensing */
...
...
@@ -391,7 +391,7 @@ struct alc_config_preset {
void (*init_hook)(struct hda_codec *);
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_amp_list *loopbacks;
void (*power_hook)(struct hda_codec *codec
, int power
);
void (*power_hook)(struct hda_codec *codec);
#endif
};
...
...
@@ -1835,16 +1835,6 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x1b;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void alc889_power_eapd(struct hda_codec *codec, int power)
{
snd_hda_codec_write(codec, 0x14, 0,
AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
snd_hda_codec_write(codec, 0x15, 0,
AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
}
#endif
/*
* ALC880 3-stack model
*
...
...
@@ -2548,8 +2538,10 @@ static int alc_build_controls(struct hda_codec *codec)
if (!kctl)
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids,
spec->input_mux->num_items);
hda_nid_t *nids = spec->capsrc_nids;
if (!nids)
nids = spec->adc_nids;
err = snd_hda_add_nid(codec, kctl, i, nids[i]);
if (err < 0)
return err;
}
...
...
@@ -3691,6 +3683,11 @@ static int alc_build_pcms(struct hda_codec *codec)
return 0;
}
static inline void alc_shutup(struct hda_codec *codec)
{
snd_hda_shutup_pins(codec);
}
static void alc_free_kctls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
...
...
@@ -3711,17 +3708,47 @@ static void alc_free(struct hda_codec *codec)
if (!spec)
return;
alc_shutup(codec);
alc_free_kctls(codec);
kfree(spec);
snd_hda_detach_beep_device(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void alc_power_eapd(struct hda_codec *codec)
{
/* We currently only handle front, HP */
switch (codec->vendor_id) {
case 0x10ec0260:
snd_hda_codec_write(codec, 0x0f, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
snd_hda_codec_write(codec, 0x10, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
break;
case 0x10ec0262:
case 0x10ec0267:
case 0x10ec0268:
case 0x10ec0269:
case 0x10ec0272:
case 0x10ec0660:
case 0x10ec0662:
case 0x10ec0663:
case 0x10ec0862:
case 0x10ec0889:
snd_hda_codec_write(codec, 0x14, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
snd_hda_codec_write(codec, 0x15, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
break;
}
}
static int alc_suspend(struct hda_codec *codec, pm_message_t state)
{
struct alc_spec *spec = codec->spec;
alc_shutup(codec);
if (spec && spec->power_hook)
spec->power_hook(codec
, 0
);
spec->power_hook(codec);
return 0;
}
#endif
...
...
@@ -3729,16 +3756,9 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
#ifdef SND_HDA_NEEDS_RESUME
static int alc_resume(struct hda_codec *codec)
{
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct alc_spec *spec = codec->spec;
#endif
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec && spec->power_hook)
spec->power_hook(codec, 1);
#endif
return 0;
}
#endif
...
...
@@ -3758,6 +3778,7 @@ static struct hda_codec_ops alc_patch_ops = {
.suspend = alc_suspend,
.check_power_status = alc_check_power_status,
#endif
.reboot_notify = alc_shutup,
};
...
...
@@ -9538,7 +9559,7 @@ static struct alc_config_preset alc882_presets[] = {
.setup = alc889_acer_aspire_8930g_setup,
.init_hook = alc_automute_amp,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.power_hook = alc
889
_power_eapd,
.power_hook = alc_power_eapd,
#endif
},
[ALC888_ACER_ASPIRE_7730G] = {
...
...
@@ -14975,8 +14996,12 @@ static int patch_alc861(struct hda_codec *codec)
spec->vmaster_nid = 0x03;
codec->patch_ops = alc_patch_ops;
if (board_config == ALC861_AUTO)
if (board_config == ALC861_AUTO)
{
spec->init_hook = alc861_auto_init;
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->power_hook = alc_power_eapd;
#endif
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861_loopbacks;
...
...
sound/pci/hda/patch_sigmatel.c
浏览文件 @
47e91348
...
...
@@ -4159,34 +4159,52 @@ static void stac92xx_power_down(struct hda_codec *codec)
static
void
stac_toggle_power_map
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
enable
);
static
inline
int
get_int_hint
(
struct
hda_codec
*
codec
,
const
char
*
key
,
int
*
valp
)
{
const
char
*
p
;
p
=
snd_hda_get_hint
(
codec
,
key
);
if
(
p
)
{
unsigned
long
val
;
if
(
!
strict_strtoul
(
p
,
0
,
&
val
))
{
*
valp
=
val
;
return
1
;
}
}
return
0
;
}
/* override some hints from the hwdep entry */
static
void
stac_store_hints
(
struct
hda_codec
*
codec
)
{
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
const
char
*
p
;
int
val
;
val
=
snd_hda_get_bool_hint
(
codec
,
"hp_detect"
);
if
(
val
>=
0
)
spec
->
hp_detect
=
val
;
p
=
snd_hda_get_hint
(
codec
,
"gpio_mask"
);
if
(
p
)
{
spec
->
gpio_mask
=
simple_strtoul
(
p
,
NULL
,
0
);
if
(
get_int_hint
(
codec
,
"gpio_mask"
,
&
spec
->
gpio_mask
))
{
spec
->
eapd_mask
=
spec
->
gpio_dir
=
spec
->
gpio_data
=
spec
->
gpio_mask
;
}
p
=
snd_hda_get_hint
(
codec
,
"gpio_dir"
);
if
(
p
)
spec
->
gpio_dir
=
simple_strtoul
(
p
,
NULL
,
0
)
&
spec
->
gpio_mask
;
p
=
snd_hda_get_hint
(
codec
,
"gpio_data"
);
if
(
p
)
spec
->
gpio_data
=
simple_strtoul
(
p
,
NULL
,
0
)
&
spec
->
gpio_mask
;
p
=
snd_hda_get_hint
(
codec
,
"eapd_mask"
);
if
(
p
)
spec
->
eapd_mask
=
simple_strtoul
(
p
,
NULL
,
0
)
&
spec
->
gpio_mask
;
if
(
get_int_hint
(
codec
,
"gpio_dir"
,
&
spec
->
gpio_dir
))
spec
->
gpio_mask
&=
spec
->
gpio_mask
;
if
(
get_int_hint
(
codec
,
"gpio_data"
,
&
spec
->
gpio_data
))
spec
->
gpio_dir
&=
spec
->
gpio_mask
;
if
(
get_int_hint
(
codec
,
"eapd_mask"
,
&
spec
->
eapd_mask
))
spec
->
eapd_mask
&=
spec
->
gpio_mask
;
if
(
get_int_hint
(
codec
,
"gpio_mute"
,
&
spec
->
gpio_mute
))
spec
->
gpio_mute
&=
spec
->
gpio_mask
;
val
=
snd_hda_get_bool_hint
(
codec
,
"eapd_switch"
);
if
(
val
>=
0
)
spec
->
eapd_switch
=
val
;
get_int_hint
(
codec
,
"gpio_led_polarity"
,
&
spec
->
gpio_led_polarity
);
if
(
get_int_hint
(
codec
,
"gpio_led"
,
&
spec
->
gpio_led
))
{
spec
->
gpio_mask
|=
spec
->
gpio_led
;
spec
->
gpio_dir
|=
spec
->
gpio_led
;
if
(
spec
->
gpio_led_polarity
)
spec
->
gpio_data
|=
spec
->
gpio_led
;
}
}
static
int
stac92xx_init
(
struct
hda_codec
*
codec
)
...
...
@@ -4371,18 +4389,8 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
static
void
stac92xx_shutup
(
struct
hda_codec
*
codec
)
{
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
int
i
;
hda_nid_t
nid
;
/* reset each pin before powering down DAC/ADC to avoid click noise */
nid
=
codec
->
start_nid
;
for
(
i
=
0
;
i
<
codec
->
num_nodes
;
i
++
,
nid
++
)
{
unsigned
int
wcaps
=
get_wcaps
(
codec
,
nid
);
unsigned
int
wid_type
=
get_wcaps_type
(
wcaps
);
if
(
wid_type
==
AC_WID_PIN
)
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
);
}
snd_hda_shutup_pins
(
codec
);
if
(
spec
->
eapd_mask
)
stac_gpio_set
(
codec
,
spec
->
gpio_mask
,
...
...
@@ -5406,6 +5414,54 @@ static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
return
0
;
}
/* HP dv7 bass switch - GPIO5 */
#define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info
static
int
stac_hp_bass_gpio_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
!!
(
spec
->
gpio_data
&
0x20
);
return
0
;
}
static
int
stac_hp_bass_gpio_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
unsigned
int
gpio_data
;
gpio_data
=
(
spec
->
gpio_data
&
~
0x20
)
|
(
ucontrol
->
value
.
integer
.
value
[
0
]
?
0x20
:
0
);
if
(
gpio_data
==
spec
->
gpio_data
)
return
0
;
spec
->
gpio_data
=
gpio_data
;
stac_gpio_set
(
codec
,
spec
->
gpio_mask
,
spec
->
gpio_dir
,
spec
->
gpio_data
);
return
1
;
}
static
struct
snd_kcontrol_new
stac_hp_bass_sw_ctrl
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
info
=
stac_hp_bass_gpio_info
,
.
get
=
stac_hp_bass_gpio_get
,
.
put
=
stac_hp_bass_gpio_put
,
};
static
int
stac_add_hp_bass_switch
(
struct
hda_codec
*
codec
)
{
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
if
(
!
stac_control_new
(
spec
,
&
stac_hp_bass_sw_ctrl
,
"Bass Speaker Playback Switch"
,
0
))
return
-
ENOMEM
;
spec
->
gpio_mask
|=
0x20
;
spec
->
gpio_dir
|=
0x20
;
spec
->
gpio_data
|=
0x20
;
return
0
;
}
static
int
patch_stac92hd71bxx
(
struct
hda_codec
*
codec
)
{
struct
sigmatel_spec
*
spec
;
...
...
@@ -5646,6 +5702,15 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
return
err
;
}
/* enable bass on HP dv7 */
if
(
spec
->
board_config
==
STAC_HP_DV5
)
{
unsigned
int
cap
;
cap
=
snd_hda_param_read
(
codec
,
0x1
,
AC_PAR_GPIO_CAP
);
cap
&=
AC_GPIO_IO_COUNT
;
if
(
cap
>=
6
)
stac_add_hp_bass_switch
(
codec
);
}
codec
->
proc_widget_hook
=
stac92hd7x_proc_hook
;
return
0
;
...
...
sound/pci/hda/patch_via.c
浏览文件 @
47e91348
...
...
@@ -1907,8 +1907,7 @@ static int via_build_controls(struct hda_codec *codec)
/* assign Capture Source enums to NID */
kctl
=
snd_hda_find_mixer_ctl
(
codec
,
"Input Source"
);
for
(
i
=
0
;
kctl
&&
i
<
kctl
->
count
;
i
++
)
{
err
=
snd_hda_add_nids
(
codec
,
kctl
,
i
,
spec
->
mux_nids
,
spec
->
input_mux
->
num_items
);
err
=
snd_hda_add_nid
(
codec
,
kctl
,
i
,
spec
->
mux_nids
[
i
]);
if
(
err
<
0
)
return
err
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录