Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
bug2833
cloud-kernel
提交
b24a63d5
cloud-kernel
项目概览
bug2833
/
cloud-kernel
与 Fork 源项目一致
Fork自
openanolis / cloud-kernel
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b24a63d5
编写于
11月 08, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/tlv320aic3x' into asoc-next
上级
32b7fdfe
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
浏览文件 @
b24a63d5
...
...
@@ -24,10 +24,36 @@ Optional properties:
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
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:
tlv320aic3x: tlv320aic3x@1b {
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
AVDD-supply = <®ulator>;
IOVDD-supply = <®ulator>;
DRVDD-supply = <®ulator>;
DVDD-supply = <®ulator>;
};
sound/soc/codecs/tlv320aic3x.c
浏览文件 @
b24a63d5
...
...
@@ -40,6 +40,7 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <sound/core.h>
...
...
@@ -72,9 +73,9 @@ struct aic3x_disable_nb {
/* codec private data */
struct
aic3x_priv
{
struct
snd_soc_codec
*
codec
;
struct
regmap
*
regmap
;
struct
regulator_bulk_data
supplies
[
AIC3X_NUM_SUPPLIES
];
struct
aic3x_disable_nb
disable_nb
[
AIC3X_NUM_SUPPLIES
];
enum
snd_soc_control_type
control_type
;
struct
aic3x_setup_data
*
setup
;
unsigned
int
sysclk
;
struct
list_head
list
;
...
...
@@ -90,41 +91,45 @@ struct aic3x_priv {
enum
aic3x_micbias_voltage
micbias_vg
;
};
/*
* AIC3X register cache
* We can't read the AIC3X register space when we are
* using 2 wire for device control, so we cache them instead.
* There is no point in caching the reset register
*/
static
const
u8
aic3x_reg
[
AIC3X_CACHEREGNUM
]
=
{
0x00
,
0x00
,
0x00
,
0x10
,
/* 0 */
0x04
,
0x00
,
0x00
,
0x00
,
/* 4 */
0x00
,
0x00
,
0x00
,
0x01
,
/* 8 */
0x00
,
0x00
,
0x00
,
0x80
,
/* 12 */
0x80
,
0xff
,
0xff
,
0x78
,
/* 16 */
0x78
,
0x78
,
0x78
,
0x78
,
/* 20 */
0x78
,
0x00
,
0x00
,
0xfe
,
/* 24 */
0x00
,
0x00
,
0xfe
,
0x00
,
/* 28 */
0x18
,
0x18
,
0x00
,
0x00
,
/* 32 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 36 */
0x00
,
0x00
,
0x00
,
0x80
,
/* 40 */
0x80
,
0x00
,
0x00
,
0x00
,
/* 44 */
0x00
,
0x00
,
0x00
,
0x04
,
/* 48 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 52 */
0x00
,
0x00
,
0x04
,
0x00
,
/* 56 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 60 */
0x00
,
0x04
,
0x00
,
0x00
,
/* 64 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 68 */
0x04
,
0x00
,
0x00
,
0x00
,
/* 72 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 76 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 80 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 84 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 88 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 92 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 96 */
0x00
,
0x00
,
0x02
,
0x00
,
/* 100 */
0x00
,
0x00
,
0x00
,
0x00
,
/* 104 */
0x00
,
0x00
,
/* 108 */
static
const
struct
reg_default
aic3x_reg
[]
=
{
{
0
,
0x00
},
{
1
,
0x00
},
{
2
,
0x00
},
{
3
,
0x10
},
{
4
,
0x04
},
{
5
,
0x00
},
{
6
,
0x00
},
{
7
,
0x00
},
{
8
,
0x00
},
{
9
,
0x00
},
{
10
,
0x00
},
{
11
,
0x01
},
{
12
,
0x00
},
{
13
,
0x00
},
{
14
,
0x00
},
{
15
,
0x80
},
{
16
,
0x80
},
{
17
,
0xff
},
{
18
,
0xff
},
{
19
,
0x78
},
{
20
,
0x78
},
{
21
,
0x78
},
{
22
,
0x78
},
{
23
,
0x78
},
{
24
,
0x78
},
{
25
,
0x00
},
{
26
,
0x00
},
{
27
,
0xfe
},
{
28
,
0x00
},
{
29
,
0x00
},
{
30
,
0xfe
},
{
31
,
0x00
},
{
32
,
0x18
},
{
33
,
0x18
},
{
34
,
0x00
},
{
35
,
0x00
},
{
36
,
0x00
},
{
37
,
0x00
},
{
38
,
0x00
},
{
39
,
0x00
},
{
40
,
0x00
},
{
41
,
0x00
},
{
42
,
0x00
},
{
43
,
0x80
},
{
44
,
0x80
},
{
45
,
0x00
},
{
46
,
0x00
},
{
47
,
0x00
},
{
48
,
0x00
},
{
49
,
0x00
},
{
50
,
0x00
},
{
51
,
0x04
},
{
52
,
0x00
},
{
53
,
0x00
},
{
54
,
0x00
},
{
55
,
0x00
},
{
56
,
0x00
},
{
57
,
0x00
},
{
58
,
0x04
},
{
59
,
0x00
},
{
60
,
0x00
},
{
61
,
0x00
},
{
62
,
0x00
},
{
63
,
0x00
},
{
64
,
0x00
},
{
65
,
0x04
},
{
66
,
0x00
},
{
67
,
0x00
},
{
68
,
0x00
},
{
69
,
0x00
},
{
70
,
0x00
},
{
71
,
0x00
},
{
72
,
0x04
},
{
73
,
0x00
},
{
74
,
0x00
},
{
75
,
0x00
},
{
76
,
0x00
},
{
77
,
0x00
},
{
78
,
0x00
},
{
79
,
0x00
},
{
80
,
0x00
},
{
81
,
0x00
},
{
82
,
0x00
},
{
83
,
0x00
},
{
84
,
0x00
},
{
85
,
0x00
},
{
86
,
0x00
},
{
87
,
0x00
},
{
88
,
0x00
},
{
89
,
0x00
},
{
90
,
0x00
},
{
91
,
0x00
},
{
92
,
0x00
},
{
93
,
0x00
},
{
94
,
0x00
},
{
95
,
0x00
},
{
96
,
0x00
},
{
97
,
0x00
},
{
98
,
0x00
},
{
99
,
0x00
},
{
100
,
0x00
},
{
101
,
0x00
},
{
102
,
0x02
},
{
103
,
0x00
},
{
104
,
0x00
},
{
105
,
0x00
},
{
106
,
0x00
},
{
107
,
0x00
},
{
108
,
0x00
},
{
109
,
0x00
},
};
static
const
struct
regmap_config
aic3x_regmap
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
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) \
...
...
@@ -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
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
)
{
snd_soc_dapm_new_controls
(
dapm
,
aic3007_dapm_widgets
,
ARRAY_SIZE
(
aic3007_dapm_widgets
));
...
...
@@ -1082,29 +1081,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
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
,
unsigned
long
event
,
void
*
data
)
{
...
...
@@ -1119,7 +1095,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
*/
if
(
gpio_is_valid
(
aic3x
->
gpio_reset
))
gpio_set_value
(
aic3x
->
gpio_reset
,
0
);
aic3x
->
codec
->
cache_sync
=
1
;
regcache_mark_dirty
(
aic3x
->
regmap
)
;
}
return
0
;
...
...
@@ -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
)
{
struct
aic3x_priv
*
aic3x
=
snd_soc_codec_get_drvdata
(
codec
);
int
i
,
ret
;
u8
*
cache
=
codec
->
reg_cache
;
int
ret
;
if
(
power
)
{
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
aic3x
->
supplies
),
...
...
@@ -1137,12 +1112,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
if
(
ret
)
goto
out
;
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
))
{
udelay
(
1
);
...
...
@@ -1150,12 +1119,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
}
/* Sync reg_cache with the hardware */
codec
->
cache_only
=
0
;
for
(
i
=
AIC3X_SAMPLE_RATE_SEL_REG
;
i
<
ARRAY_SIZE
(
aic3x_reg
);
i
++
)
snd_soc_write
(
codec
,
i
,
cache
[
i
]);
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
aic3x_init_3007
(
codec
);
codec
->
cache_sync
=
0
;
regcache_cache_only
(
aic3x
->
regmap
,
false
);
regcache_sync
(
aic3x
->
regmap
);
}
else
{
/*
* 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)
* remain on
*/
snd_soc_write
(
codec
,
AIC3X_RESET
,
SOFT_RESET
);
codec
->
cache_sync
=
1
;
regcache_mark_dirty
(
aic3x
->
regmap
)
;
aic3x
->
power
=
0
;
/* 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
),
aic3x
->
supplies
);
}
...
...
@@ -1321,7 +1286,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
snd_soc_write
(
codec
,
LINE2R_2_MONOLOPM_VOL
,
DEFAULT_VOL
);
if
(
aic3x
->
model
==
AIC3X_MODEL_3007
)
{
aic3x_init_3007
(
codec
);
snd_soc_write
(
codec
,
CLASSD_CTRL
,
0
);
}
...
...
@@ -1349,29 +1313,12 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD
(
&
aic3x
->
list
);
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
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
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
++
)
{
aic3x
->
disable_nb
[
i
].
nb
.
notifier_call
=
aic3x_regulator_event
;
aic3x
->
disable_nb
[
i
].
aic3x
=
aic3x
;
...
...
@@ -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
);
if
(
aic3x
->
setup
)
{
...
...
@@ -1396,8 +1343,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(
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
)
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)
while
(
i
--
)
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
&
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
;
}
...
...
@@ -1444,15 +1383,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
aic3x_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
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
++
)
regulator_unregister_notifier
(
aic3x
->
supplies
[
i
].
consumer
,
&
aic3x
->
disable_nb
[
i
].
nb
);
regulator_bulk_free
(
ARRAY_SIZE
(
aic3x
->
supplies
),
aic3x
->
supplies
);
return
0
;
}
...
...
@@ -1460,13 +1393,16 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static
struct
snd_soc_codec_driver
soc_codec_dev_aic3x
=
{
.
set_bias_level
=
aic3x_set_bias_level
,
.
idle_bias_off
=
true
,
.
reg_cache_size
=
ARRAY_SIZE
(
aic3x_reg
),
.
reg_word_size
=
sizeof
(
u8
),
.
reg_cache_default
=
aic3x_reg
,
.
probe
=
aic3x_probe
,
.
remove
=
aic3x_remove
,
.
suspend
=
aic3x_suspend
,
.
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[] = {
};
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
* around
...
...
@@ -1494,7 +1440,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
struct
aic3x_priv
*
aic3x
;
struct
aic3x_setup_data
*
ai3x_setup
;
struct
device_node
*
np
=
i2c
->
dev
.
of_node
;
int
ret
;
int
ret
,
i
;
u32
value
;
aic3x
=
devm_kzalloc
(
&
i2c
->
dev
,
sizeof
(
struct
aic3x_priv
),
GFP_KERNEL
);
...
...
@@ -1503,7 +1449,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
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
);
if
(
pdata
)
{
...
...
@@ -1555,14 +1507,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
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
,
&
soc_codec_dev_aic3x
,
&
aic3x_dai
,
1
);
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
)
{
struct
aic3x_priv
*
aic3x
=
i2c_get_clientdata
(
client
);
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
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录