Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
3caa2827
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3caa2827
编写于
10月 24, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/tlv320aic3x' into asoc-next
上级
24a6703a
b3b70786
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
139 addition
and
121 deletion
+139
-121
Documentation/devicetree/bindings/sound/tlv320aic3x.txt
Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+26
-0
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.c
+113
-121
未找到文件。
Documentation/devicetree/bindings/sound/tlv320aic3x.txt
浏览文件 @
3caa2827
...
@@ -24,10 +24,36 @@ Optional properties:
...
@@ -24,10 +24,36 @@ Optional properties:
3 - MICBIAS output is connected to AVDD,
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
If this node is not mentioned or if the value is incorrect, then MicBias
is powered down.
is powered down.
- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
CODEC output pins:
* LLOUT
* RLOUT
* MONO_LOUT
* HPLOUT
* HPROUT
* HPLCOM
* HPRCOM
CODEC input pins:
* MIC3L
* MIC3R
* LINE1L
* LINE2L
* LINE1R
* LINE2R
The pins can be used in referring sound node's audio-routing property.
Example:
Example:
tlv320aic3x: tlv320aic3x@1b {
tlv320aic3x: tlv320aic3x@1b {
compatible = "ti,tlv320aic3x";
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
reg = <0x1b>;
AVDD-supply = <®ulator>;
IOVDD-supply = <®ulator>;
DRVDD-supply = <®ulator>;
DVDD-supply = <®ulator>;
};
};
sound/soc/codecs/tlv320aic3x.c
浏览文件 @
3caa2827
...
@@ -40,6 +40,7 @@
...
@@ -40,6 +40,7 @@
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/core.h>
...
@@ -72,9 +73,9 @@ struct aic3x_disable_nb {
...
@@ -72,9 +73,9 @@ struct aic3x_disable_nb {
/* codec private data */
/* codec private data */
struct
aic3x_priv
{
struct
aic3x_priv
{
struct
snd_soc_codec
*
codec
;
struct
snd_soc_codec
*
codec
;
struct
regmap
*
regmap
;
struct
regulator_bulk_data
supplies
[
AIC3X_NUM_SUPPLIES
];
struct
regulator_bulk_data
supplies
[
AIC3X_NUM_SUPPLIES
];
struct
aic3x_disable_nb
disable_nb
[
AIC3X_NUM_SUPPLIES
];
struct
aic3x_disable_nb
disable_nb
[
AIC3X_NUM_SUPPLIES
];
enum
snd_soc_control_type
control_type
;
struct
aic3x_setup_data
*
setup
;
struct
aic3x_setup_data
*
setup
;
unsigned
int
sysclk
;
unsigned
int
sysclk
;
struct
list_head
list
;
struct
list_head
list
;
...
@@ -90,41 +91,45 @@ struct aic3x_priv {
...
@@ -90,41 +91,45 @@ struct aic3x_priv {
enum
aic3x_micbias_voltage
micbias_vg
;
enum
aic3x_micbias_voltage
micbias_vg
;
};
};
/*
static
const
struct
reg_default
aic3x_reg
[]
=
{
* AIC3X register cache
{
0
,
0x00
},
{
1
,
0x00
},
{
2
,
0x00
},
{
3
,
0x10
},
* We can't read the AIC3X register space when we are
{
4
,
0x04
},
{
5
,
0x00
},
{
6
,
0x00
},
{
7
,
0x00
},
* using 2 wire for device control, so we cache them instead.
{
8
,
0x00
},
{
9
,
0x00
},
{
10
,
0x00
},
{
11
,
0x01
},
* There is no point in caching the reset register
{
12
,
0x00
},
{
13
,
0x00
},
{
14
,
0x00
},
{
15
,
0x80
},
*/
{
16
,
0x80
},
{
17
,
0xff
},
{
18
,
0xff
},
{
19
,
0x78
},
static
const
u8
aic3x_reg
[
AIC3X_CACHEREGNUM
]
=
{
{
20
,
0x78
},
{
21
,
0x78
},
{
22
,
0x78
},
{
23
,
0x78
},
0x00
,
0x00
,
0x00
,
0x10
,
/* 0 */
{
24
,
0x78
},
{
25
,
0x00
},
{
26
,
0x00
},
{
27
,
0xfe
},
0x04
,
0x00
,
0x00
,
0x00
,
/* 4 */
{
28
,
0x00
},
{
29
,
0x00
},
{
30
,
0xfe
},
{
31
,
0x00
},
0x00
,
0x00
,
0x00
,
0x01
,
/* 8 */
{
32
,
0x18
},
{
33
,
0x18
},
{
34
,
0x00
},
{
35
,
0x00
},
0x00
,
0x00
,
0x00
,
0x80
,
/* 12 */
{
36
,
0x00
},
{
37
,
0x00
},
{
38
,
0x00
},
{
39
,
0x00
},
0x80
,
0xff
,
0xff
,
0x78
,
/* 16 */
{
40
,
0x00
},
{
41
,
0x00
},
{
42
,
0x00
},
{
43
,
0x80
},
0x78
,
0x78
,
0x78
,
0x78
,
/* 20 */
{
44
,
0x80
},
{
45
,
0x00
},
{
46
,
0x00
},
{
47
,
0x00
},
0x78
,
0x00
,
0x00
,
0xfe
,
/* 24 */
{
48
,
0x00
},
{
49
,
0x00
},
{
50
,
0x00
},
{
51
,
0x04
},
0x00
,
0x00
,
0xfe
,
0x00
,
/* 28 */
{
52
,
0x00
},
{
53
,
0x00
},
{
54
,
0x00
},
{
55
,
0x00
},
0x18
,
0x18
,
0x00
,
0x00
,
/* 32 */
{
56
,
0x00
},
{
57
,
0x00
},
{
58
,
0x04
},
{
59
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 36 */
{
60
,
0x00
},
{
61
,
0x00
},
{
62
,
0x00
},
{
63
,
0x00
},
0x00
,
0x00
,
0x00
,
0x80
,
/* 40 */
{
64
,
0x00
},
{
65
,
0x04
},
{
66
,
0x00
},
{
67
,
0x00
},
0x80
,
0x00
,
0x00
,
0x00
,
/* 44 */
{
68
,
0x00
},
{
69
,
0x00
},
{
70
,
0x00
},
{
71
,
0x00
},
0x00
,
0x00
,
0x00
,
0x04
,
/* 48 */
{
72
,
0x04
},
{
73
,
0x00
},
{
74
,
0x00
},
{
75
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 52 */
{
76
,
0x00
},
{
77
,
0x00
},
{
78
,
0x00
},
{
79
,
0x00
},
0x00
,
0x00
,
0x04
,
0x00
,
/* 56 */
{
80
,
0x00
},
{
81
,
0x00
},
{
82
,
0x00
},
{
83
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 60 */
{
84
,
0x00
},
{
85
,
0x00
},
{
86
,
0x00
},
{
87
,
0x00
},
0x00
,
0x04
,
0x00
,
0x00
,
/* 64 */
{
88
,
0x00
},
{
89
,
0x00
},
{
90
,
0x00
},
{
91
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 68 */
{
92
,
0x00
},
{
93
,
0x00
},
{
94
,
0x00
},
{
95
,
0x00
},
0x04
,
0x00
,
0x00
,
0x00
,
/* 72 */
{
96
,
0x00
},
{
97
,
0x00
},
{
98
,
0x00
},
{
99
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 76 */
{
100
,
0x00
},
{
101
,
0x00
},
{
102
,
0x02
},
{
103
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 80 */
{
104
,
0x00
},
{
105
,
0x00
},
{
106
,
0x00
},
{
107
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 84 */
{
108
,
0x00
},
{
109
,
0x00
},
0x00
,
0x00
,
0x00
,
0x00
,
/* 88 */
};
0x00
,
0x00
,
0x00
,
0x00
,
/* 92 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 96 */
static
const
struct
regmap_config
aic3x_regmap
=
{
0x00
,
0x00
,
0x02
,
0x00
,
/* 100 */
.
reg_bits
=
8
,
0x00
,
0x00
,
0x00
,
0x00
,
/* 104 */
.
val_bits
=
8
,
0x00
,
0x00
,
/* 108 */
.
max_register
=
DAC_ICC_ADJ
,
.
reg_defaults
=
aic3x_reg
,
.
num_reg_defaults
=
ARRAY_SIZE
(
aic3x_reg
),
.
cache_type
=
REGCACHE_RBTREE
,
};
};
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
...
@@ -828,12 +833,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
...
@@ -828,12 +833,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
struct
aic3x_priv
*
aic3x
=
snd_soc_codec_get_drvdata
(
codec
);
struct
aic3x_priv
*
aic3x
=
snd_soc_codec_get_drvdata
(
codec
);
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
dapm
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
dapm
;
snd_soc_dapm_new_controls
(
dapm
,
aic3x_dapm_widgets
,
ARRAY_SIZE
(
aic3x_dapm_widgets
));
/* set up audio path interconnects */
snd_soc_dapm_add_routes
(
dapm
,
intercon
,
ARRAY_SIZE
(
intercon
));
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
snd_soc_dapm_new_controls
(
dapm
,
aic3007_dapm_widgets
,
snd_soc_dapm_new_controls
(
dapm
,
aic3007_dapm_widgets
,
ARRAY_SIZE
(
aic3007_dapm_widgets
));
ARRAY_SIZE
(
aic3007_dapm_widgets
));
...
@@ -1082,29 +1081,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
...
@@ -1082,29 +1081,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
0
;
return
0
;
}
}
static
int
aic3x_init_3007
(
struct
snd_soc_codec
*
codec
)
{
u8
tmp1
,
tmp2
,
*
cache
=
codec
->
reg_cache
;
/*
* There is no need to cache writes to undocumented page 0xD but
* respective page 0 register cache entries must be preserved
*/
tmp1
=
cache
[
0xD
];
tmp2
=
cache
[
0x8
];
/* Class-D speaker driver init; datasheet p. 46 */
snd_soc_write
(
codec
,
AIC3X_PAGE_SELECT
,
0x0D
);
snd_soc_write
(
codec
,
0xD
,
0x0D
);
snd_soc_write
(
codec
,
0x8
,
0x5C
);
snd_soc_write
(
codec
,
0x8
,
0x5D
);
snd_soc_write
(
codec
,
0x8
,
0x5C
);
snd_soc_write
(
codec
,
AIC3X_PAGE_SELECT
,
0x00
);
cache
[
0xD
]
=
tmp1
;
cache
[
0x8
]
=
tmp2
;
return
0
;
}
static
int
aic3x_regulator_event
(
struct
notifier_block
*
nb
,
static
int
aic3x_regulator_event
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
data
)
unsigned
long
event
,
void
*
data
)
{
{
...
@@ -1119,7 +1095,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
...
@@ -1119,7 +1095,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
*/
*/
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
))
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
))
gpio_set_value
(
aic3x
->
gpio_reset
,
0
);
gpio_set_value
(
aic3x
->
gpio_reset
,
0
);
aic3x
->
codec
->
cache_sync
=
1
;
regcache_mark_dirty
(
aic3x
->
regmap
)
;
}
}
return
0
;
return
0
;
...
@@ -1128,8 +1104,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
...
@@ -1128,8 +1104,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
static
int
aic3x_set_power
(
struct
snd_soc_codec
*
codec
,
int
power
)
static
int
aic3x_set_power
(
struct
snd_soc_codec
*
codec
,
int
power
)
{
{
struct
aic3x_priv
*
aic3x
=
snd_soc_codec_get_drvdata
(
codec
);
struct
aic3x_priv
*
aic3x
=
snd_soc_codec_get_drvdata
(
codec
);
int
i
,
ret
;
int
ret
;
u8
*
cache
=
codec
->
reg_cache
;
if
(
power
)
{
if
(
power
)
{
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
aic3x
->
supplies
),
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
aic3x
->
supplies
),
...
@@ -1137,12 +1112,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
...
@@ -1137,12 +1112,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
if
(
ret
)
if
(
ret
)
goto
out
;
goto
out
;
aic3x
->
power
=
1
;
aic3x
->
power
=
1
;
/*
* Reset release and cache sync is necessary only if some
* supply was off or if there were cached writes
*/
if
(
!
codec
->
cache_sync
)
goto
out
;
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
))
{
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
))
{
udelay
(
1
);
udelay
(
1
);
...
@@ -1150,12 +1119,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
...
@@ -1150,12 +1119,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
}
}
/* Sync reg_cache with the hardware */
/* Sync reg_cache with the hardware */
codec
->
cache_only
=
0
;
regcache_cache_only
(
aic3x
->
regmap
,
false
);
for
(
i
=
AIC3X_SAMPLE_RATE_SEL_REG
;
i
<
ARRAY_SIZE
(
aic3x_reg
);
i
++
)
regcache_sync
(
aic3x
->
regmap
);
snd_soc_write
(
codec
,
i
,
cache
[
i
]);
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
aic3x_init_3007
(
codec
);
codec
->
cache_sync
=
0
;
}
else
{
}
else
{
/*
/*
* Do soft reset to this codec instance in order to clear
* Do soft reset to this codec instance in order to clear
...
@@ -1163,10 +1128,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
...
@@ -1163,10 +1128,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
* remain on
* remain on
*/
*/
snd_soc_write
(
codec
,
AIC3X_RESET
,
SOFT_RESET
);
snd_soc_write
(
codec
,
AIC3X_RESET
,
SOFT_RESET
);
codec
->
cache_sync
=
1
;
regcache_mark_dirty
(
aic3x
->
regmap
)
;
aic3x
->
power
=
0
;
aic3x
->
power
=
0
;
/* HW writes are needless when bias is off */
/* HW writes are needless when bias is off */
codec
->
cache_only
=
1
;
regcache_cache_only
(
aic3x
->
regmap
,
true
)
;
ret
=
regulator_bulk_disable
(
ARRAY_SIZE
(
aic3x
->
supplies
),
ret
=
regulator_bulk_disable
(
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
aic3x
->
supplies
);
}
}
...
@@ -1321,7 +1286,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
...
@@ -1321,7 +1286,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
snd_soc_write
(
codec
,
LINE2R_2_MONOLOPM_VOL
,
DEFAULT_VOL
);
snd_soc_write
(
codec
,
LINE2R_2_MONOLOPM_VOL
,
DEFAULT_VOL
);
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
aic3x_init_3007
(
codec
);
snd_soc_write
(
codec
,
CLASSD_CTRL
,
0
);
snd_soc_write
(
codec
,
CLASSD_CTRL
,
0
);
}
}
...
@@ -1349,29 +1313,12 @@ static int aic3x_probe(struct snd_soc_codec *codec)
...
@@ -1349,29 +1313,12 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD
(
&
aic3x
->
list
);
INIT_LIST_HEAD
(
&
aic3x
->
list
);
aic3x
->
codec
=
codec
;
aic3x
->
codec
=
codec
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
8
,
aic3x
->
control_type
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
8
,
SND_SOC_REGMAP
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
return
ret
;
}
}
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
{
ret
=
gpio_request
(
aic3x
->
gpio_reset
,
"tlv320aic3x reset"
);
if
(
ret
!=
0
)
goto
err_gpio
;
gpio_direction_output
(
aic3x
->
gpio_reset
,
0
);
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
aic3x
->
supplies
[
i
].
supply
=
aic3x_supply_names
[
i
];
ret
=
regulator_bulk_get
(
codec
->
dev
,
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to request supplies: %d
\n
"
,
ret
);
goto
err_get
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
{
aic3x
->
disable_nb
[
i
].
nb
.
notifier_call
=
aic3x_regulator_event
;
aic3x
->
disable_nb
[
i
].
nb
.
notifier_call
=
aic3x_regulator_event
;
aic3x
->
disable_nb
[
i
].
aic3x
=
aic3x
;
aic3x
->
disable_nb
[
i
].
aic3x
=
aic3x
;
...
@@ -1385,7 +1332,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
...
@@ -1385,7 +1332,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
}
}
}
}
codec
->
cache_only
=
1
;
regcache_mark_dirty
(
aic3x
->
regmap
)
;
aic3x_init
(
codec
);
aic3x_init
(
codec
);
if
(
aic3x
->
setup
)
{
if
(
aic3x
->
setup
)
{
...
@@ -1396,8 +1343,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
...
@@ -1396,8 +1343,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(
aic3x
->
setup
->
gpio_func
[
1
]
&
0xf
)
<<
4
);
(
aic3x
->
setup
->
gpio_func
[
1
]
&
0xf
)
<<
4
);
}
}
snd_soc_add_codec_controls
(
codec
,
aic3x_snd_controls
,
ARRAY_SIZE
(
aic3x_snd_controls
));
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
snd_soc_add_codec_controls
(
codec
,
&
aic3x_classd_amp_gain_ctrl
,
1
);
snd_soc_add_codec_controls
(
codec
,
&
aic3x_classd_amp_gain_ctrl
,
1
);
...
@@ -1428,12 +1373,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
...
@@ -1428,12 +1373,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
while
(
i
--
)
while
(
i
--
)
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
&
aic3x
->
disable_nb
[
i
].
nb
);
&
aic3x
->
disable_nb
[
i
].
nb
);
regulator_bulk_free
(
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
err_get:
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
gpio_free
(
aic3x
->
gpio_reset
);
err_gpio:
return
ret
;
return
ret
;
}
}
...
@@ -1444,15 +1383,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
...
@@ -1444,15 +1383,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
aic3x_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
aic3x_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
list_del
(
&
aic3x
->
list
);
list_del
(
&
aic3x
->
list
);
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
{
gpio_set_value
(
aic3x
->
gpio_reset
,
0
);
gpio_free
(
aic3x
->
gpio_reset
);
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
&
aic3x
->
disable_nb
[
i
].
nb
);
&
aic3x
->
disable_nb
[
i
].
nb
);
regulator_bulk_free
(
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
return
0
;
return
0
;
}
}
...
@@ -1460,13 +1393,16 @@ static int aic3x_remove(struct snd_soc_codec *codec)
...
@@ -1460,13 +1393,16 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static
struct
snd_soc_codec_driver
soc_codec_dev_aic3x
=
{
static
struct
snd_soc_codec_driver
soc_codec_dev_aic3x
=
{
.
set_bias_level
=
aic3x_set_bias_level
,
.
set_bias_level
=
aic3x_set_bias_level
,
.
idle_bias_off
=
true
,
.
idle_bias_off
=
true
,
.
reg_cache_size
=
ARRAY_SIZE
(
aic3x_reg
),
.
reg_word_size
=
sizeof
(
u8
),
.
reg_cache_default
=
aic3x_reg
,
.
probe
=
aic3x_probe
,
.
probe
=
aic3x_probe
,
.
remove
=
aic3x_remove
,
.
remove
=
aic3x_remove
,
.
suspend
=
aic3x_suspend
,
.
suspend
=
aic3x_suspend
,
.
resume
=
aic3x_resume
,
.
resume
=
aic3x_resume
,
.
controls
=
aic3x_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
aic3x_snd_controls
),
.
dapm_widgets
=
aic3x_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
aic3x_dapm_widgets
),
.
dapm_routes
=
intercon
,
.
num_dapm_routes
=
ARRAY_SIZE
(
intercon
),
};
};
/*
/*
...
@@ -1483,6 +1419,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
...
@@ -1483,6 +1419,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
};
};
MODULE_DEVICE_TABLE
(
i2c
,
aic3x_i2c_id
);
MODULE_DEVICE_TABLE
(
i2c
,
aic3x_i2c_id
);
static
const
struct
reg_default
aic3007_class_d
[]
=
{
/* Class-D speaker driver init; datasheet p. 46 */
{
AIC3X_PAGE_SELECT
,
0x0D
},
{
0xD
,
0x0D
},
{
0x8
,
0x5C
},
{
0x8
,
0x5D
},
{
0x8
,
0x5C
},
{
AIC3X_PAGE_SELECT
,
0x00
},
};
/*
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* If the i2c layer weren't so broken, we could pass this kind of data
* around
* around
...
@@ -1494,7 +1440,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
...
@@ -1494,7 +1440,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
struct
aic3x_priv
*
aic3x
;
struct
aic3x_priv
*
aic3x
;
struct
aic3x_setup_data
*
ai3x_setup
;
struct
aic3x_setup_data
*
ai3x_setup
;
struct
device_node
*
np
=
i2c
->
dev
.
of_node
;
struct
device_node
*
np
=
i2c
->
dev
.
of_node
;
int
ret
;
int
ret
,
i
;
u32
value
;
u32
value
;
aic3x
=
devm_kzalloc
(
&
i2c
->
dev
,
sizeof
(
struct
aic3x_priv
),
GFP_KERNEL
);
aic3x
=
devm_kzalloc
(
&
i2c
->
dev
,
sizeof
(
struct
aic3x_priv
),
GFP_KERNEL
);
...
@@ -1503,7 +1449,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
...
@@ -1503,7 +1449,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
aic3x
->
control_type
=
SND_SOC_I2C
;
aic3x
->
regmap
=
devm_regmap_init_i2c
(
i2c
,
&
aic3x_regmap
);
if
(
IS_ERR
(
aic3x
->
regmap
))
{
ret
=
PTR_ERR
(
aic3x
->
regmap
);
return
ret
;
}
regcache_cache_only
(
aic3x
->
regmap
,
true
);
i2c_set_clientdata
(
i2c
,
aic3x
);
i2c_set_clientdata
(
i2c
,
aic3x
);
if
(
pdata
)
{
if
(
pdata
)
{
...
@@ -1555,14 +1507,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
...
@@ -1555,14 +1507,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
aic3x
->
model
=
id
->
driver_data
;
aic3x
->
model
=
id
->
driver_data
;
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
{
ret
=
gpio_request
(
aic3x
->
gpio_reset
,
"tlv320aic3x reset"
);
if
(
ret
!=
0
)
goto
err
;
gpio_direction_output
(
aic3x
->
gpio_reset
,
0
);
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
aic3x
->
supplies
);
i
++
)
aic3x
->
supplies
[
i
].
supply
=
aic3x_supply_names
[
i
];
ret
=
devm_regulator_bulk_get
(
&
i2c
->
dev
,
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
&
i2c
->
dev
,
"Failed to request supplies: %d
\n
"
,
ret
);
goto
err_gpio
;
}
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
ret
=
regmap_register_patch
(
aic3x
->
regmap
,
aic3007_class_d
,
ARRAY_SIZE
(
aic3007_class_d
));
if
(
ret
!=
0
)
dev_err
(
&
i2c
->
dev
,
"Failed to init class D: %d
\n
"
,
ret
);
}
ret
=
snd_soc_register_codec
(
&
i2c
->
dev
,
ret
=
snd_soc_register_codec
(
&
i2c
->
dev
,
&
soc_codec_dev_aic3x
,
&
aic3x_dai
,
1
);
&
soc_codec_dev_aic3x
,
&
aic3x_dai
,
1
);
return
ret
;
return
ret
;
err_gpio:
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
gpio_free
(
aic3x
->
gpio_reset
);
err:
return
ret
;
}
}
static
int
aic3x_i2c_remove
(
struct
i2c_client
*
client
)
static
int
aic3x_i2c_remove
(
struct
i2c_client
*
client
)
{
{
struct
aic3x_priv
*
aic3x
=
i2c_get_clientdata
(
client
);
snd_soc_unregister_codec
(
&
client
->
dev
);
snd_soc_unregister_codec
(
&
client
->
dev
);
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
)
&&
!
aic3x_is_shared_reset
(
aic3x
))
{
gpio_set_value
(
aic3x
->
gpio_reset
,
0
);
gpio_free
(
aic3x
->
gpio_reset
);
}
return
0
;
return
0
;
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录