Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
214c3eee
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
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看板
提交
214c3eee
编写于
6月 28, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/twl6040' into asoc-next
上级
da51f83f
98c5fb1f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
114 addition
and
2 deletion
+114
-2
include/linux/mfd/twl6040.h
include/linux/mfd/twl6040.h
+7
-0
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.c
+107
-2
未找到文件。
include/linux/mfd/twl6040.h
浏览文件 @
214c3eee
...
...
@@ -125,8 +125,15 @@
#define TWL6040_HSDACENA (1 << 0)
#define TWL6040_HSDACMODE (1 << 1)
#define TWL6040_HSDRVENA (1 << 2)
#define TWL6040_HSDRVMODE (1 << 3)
/* HFLCTL/R (0x14/0x16) fields */
#define TWL6040_HFDACENA (1 << 0)
#define TWL6040_HFPGAENA (1 << 1)
#define TWL6040_HFDRVENA (1 << 4)
/* VIBCTLL/R (0x18/0x1A) fields */
#define TWL6040_VIBENA (1 << 0)
...
...
sound/soc/codecs/twl6040.c
浏览文件 @
214c3eee
...
...
@@ -38,6 +38,14 @@
#include "twl6040.h"
enum
twl6040_dai_id
{
TWL6040_DAI_LEGACY
=
0
,
TWL6040_DAI_UL
,
TWL6040_DAI_DL1
,
TWL6040_DAI_DL2
,
TWL6040_DAI_VIB
,
};
#define TWL6040_RATES SNDRV_PCM_RATE_8000_96000
#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
...
...
@@ -67,6 +75,8 @@ struct twl6040_data {
int
pll_power_mode
;
int
hs_power_mode
;
int
hs_power_mode_locked
;
bool
dl1_unmuted
;
bool
dl2_unmuted
;
unsigned
int
clk_in
;
unsigned
int
sysclk
;
struct
twl6040_jack_data
hs_jack
;
...
...
@@ -220,6 +230,25 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
return
value
;
}
static
bool
twl6040_is_path_unmuted
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
struct
twl6040_data
*
priv
=
snd_soc_codec_get_drvdata
(
codec
);
switch
(
reg
)
{
case
TWL6040_REG_HSLCTL
:
case
TWL6040_REG_HSRCTL
:
case
TWL6040_REG_EARCTL
:
/* DL1 path */
return
priv
->
dl1_unmuted
;
case
TWL6040_REG_HFLCTL
:
case
TWL6040_REG_HFRCTL
:
return
priv
->
dl2_unmuted
;
default:
return
1
;
};
}
/*
* write to the twl6040 register space
*/
...
...
@@ -232,7 +261,8 @@ static int twl6040_write(struct snd_soc_codec *codec,
return
-
EIO
;
twl6040_write_reg_cache
(
codec
,
reg
,
value
);
if
(
likely
(
reg
<
TWL6040_REG_SW_SHADOW
))
if
(
likely
(
reg
<
TWL6040_REG_SW_SHADOW
)
&&
twl6040_is_path_unmuted
(
codec
,
reg
))
return
twl6040_reg_write
(
twl6040
,
reg
,
value
);
else
return
0
;
...
...
@@ -1026,16 +1056,84 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return
0
;
}
static
void
twl6040_mute_path
(
struct
snd_soc_codec
*
codec
,
enum
twl6040_dai_id
id
,
int
mute
)
{
struct
twl6040
*
twl6040
=
codec
->
control_data
;
struct
twl6040_data
*
priv
=
snd_soc_codec_get_drvdata
(
codec
);
int
hslctl
,
hsrctl
,
earctl
;
int
hflctl
,
hfrctl
;
switch
(
id
)
{
case
TWL6040_DAI_DL1
:
hslctl
=
twl6040_read_reg_cache
(
codec
,
TWL6040_REG_HSLCTL
);
hsrctl
=
twl6040_read_reg_cache
(
codec
,
TWL6040_REG_HSRCTL
);
earctl
=
twl6040_read_reg_cache
(
codec
,
TWL6040_REG_EARCTL
);
if
(
mute
)
{
/* Power down drivers and DACs */
earctl
&=
~
0x01
;
hslctl
&=
~
(
TWL6040_HSDRVENA
|
TWL6040_HSDACENA
);
hsrctl
&=
~
(
TWL6040_HSDRVENA
|
TWL6040_HSDACENA
);
}
twl6040_reg_write
(
twl6040
,
TWL6040_REG_EARCTL
,
earctl
);
twl6040_reg_write
(
twl6040
,
TWL6040_REG_HSLCTL
,
hslctl
);
twl6040_reg_write
(
twl6040
,
TWL6040_REG_HSRCTL
,
hsrctl
);
priv
->
dl1_unmuted
=
!
mute
;
break
;
case
TWL6040_DAI_DL2
:
hflctl
=
twl6040_read_reg_cache
(
codec
,
TWL6040_REG_HFLCTL
);
hfrctl
=
twl6040_read_reg_cache
(
codec
,
TWL6040_REG_HFRCTL
);
if
(
mute
)
{
/* Power down drivers and DACs */
hflctl
&=
~
(
TWL6040_HFDACENA
|
TWL6040_HFPGAENA
|
TWL6040_HFDRVENA
);
hfrctl
&=
~
(
TWL6040_HFDACENA
|
TWL6040_HFPGAENA
|
TWL6040_HFDRVENA
);
}
twl6040_reg_write
(
twl6040
,
TWL6040_REG_HFLCTL
,
hflctl
);
twl6040_reg_write
(
twl6040
,
TWL6040_REG_HFRCTL
,
hfrctl
);
priv
->
dl2_unmuted
=
!
mute
;
break
;
default:
break
;
};
}
static
int
twl6040_digital_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
switch
(
dai
->
id
)
{
case
TWL6040_DAI_LEGACY
:
twl6040_mute_path
(
dai
->
codec
,
TWL6040_DAI_DL1
,
mute
);
twl6040_mute_path
(
dai
->
codec
,
TWL6040_DAI_DL2
,
mute
);
break
;
case
TWL6040_DAI_DL1
:
case
TWL6040_DAI_DL2
:
twl6040_mute_path
(
dai
->
codec
,
dai
->
id
,
mute
);
break
;
default:
break
;
}
return
0
;
}
static
const
struct
snd_soc_dai_ops
twl6040_dai_ops
=
{
.
startup
=
twl6040_startup
,
.
hw_params
=
twl6040_hw_params
,
.
prepare
=
twl6040_prepare
,
.
set_sysclk
=
twl6040_set_dai_sysclk
,
.
digital_mute
=
twl6040_digital_mute
,
};
static
struct
snd_soc_dai_driver
twl6040_dai
[]
=
{
{
.
name
=
"twl6040-legacy"
,
.
id
=
TWL6040_DAI_LEGACY
,
.
playback
=
{
.
stream_name
=
"Legacy Playback"
,
.
channels_min
=
1
,
...
...
@@ -1054,6 +1152,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
},
{
.
name
=
"twl6040-ul"
,
.
id
=
TWL6040_DAI_UL
,
.
capture
=
{
.
stream_name
=
"Capture"
,
.
channels_min
=
1
,
...
...
@@ -1065,6 +1164,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
},
{
.
name
=
"twl6040-dl1"
,
.
id
=
TWL6040_DAI_DL1
,
.
playback
=
{
.
stream_name
=
"Headset Playback"
,
.
channels_min
=
1
,
...
...
@@ -1076,6 +1176,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
},
{
.
name
=
"twl6040-dl2"
,
.
id
=
TWL6040_DAI_DL2
,
.
playback
=
{
.
stream_name
=
"Handsfree Playback"
,
.
channels_min
=
1
,
...
...
@@ -1087,6 +1188,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
},
{
.
name
=
"twl6040-vib"
,
.
id
=
TWL6040_DAI_VIB
,
.
playback
=
{
.
stream_name
=
"Vibra Playback"
,
.
channels_min
=
1
,
...
...
@@ -1143,7 +1245,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
mutex_init
(
&
priv
->
mutex
);
ret
=
devm_request_threaded_irq
(
codec
->
dev
,
priv
->
plug_irq
,
NULL
,
ret
=
request_threaded_irq
(
priv
->
plug_irq
,
NULL
,
twl6040_audio_handler
,
IRQF_NO_SUSPEND
,
"twl6040_irq_plug"
,
codec
);
if
(
ret
)
{
...
...
@@ -1159,6 +1261,9 @@ static int twl6040_probe(struct snd_soc_codec *codec)
static
int
twl6040_remove
(
struct
snd_soc_codec
*
codec
)
{
struct
twl6040_data
*
priv
=
snd_soc_codec_get_drvdata
(
codec
);
free_irq
(
priv
->
plug_irq
,
codec
);
twl6040_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
return
0
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录