Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
09fd19da
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看板
提交
09fd19da
编写于
1月 21, 2014
作者:
L
Lee Jones
浏览文件
操作
浏览文件
下载
差异文件
Merge tag 'ib-asoc-3.14.2' into for-mfd-next
Immutable branch between MFD and ASoC due for the v3.14 merge window
上级
6eb37eb2
91460700
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
255 addition
and
30 deletion
+255
-30
drivers/mfd/twl-core.c
drivers/mfd/twl-core.c
+163
-27
drivers/mfd/twl6040.c
drivers/mfd/twl6040.c
+89
-3
include/linux/i2c/twl.h
include/linux/i2c/twl.h
+3
-0
未找到文件。
drivers/mfd/twl-core.c
浏览文件 @
09fd19da
...
...
@@ -47,6 +47,9 @@
#include <linux/i2c.h>
#include <linux/i2c/twl.h>
/* Register descriptions for audio */
#include <linux/mfd/twl4030-audio.h>
#include "twl-core.h"
/*
...
...
@@ -200,6 +203,105 @@ static struct twl_mapping twl4030_map[] = {
{
2
,
TWL5031_BASEADD_INTERRUPTS
},
};
static
struct
reg_default
twl4030_49_defaults
[]
=
{
/* Audio Registers */
{
0x01
,
0x00
},
/* CODEC_MODE */
{
0x02
,
0x00
},
/* OPTION */
/* 0x03 Unused */
{
0x04
,
0x00
},
/* MICBIAS_CTL */
{
0x05
,
0x00
},
/* ANAMICL */
{
0x06
,
0x00
},
/* ANAMICR */
{
0x07
,
0x00
},
/* AVADC_CTL */
{
0x08
,
0x00
},
/* ADCMICSEL */
{
0x09
,
0x00
},
/* DIGMIXING */
{
0x0a
,
0x0f
},
/* ATXL1PGA */
{
0x0b
,
0x0f
},
/* ATXR1PGA */
{
0x0c
,
0x0f
},
/* AVTXL2PGA */
{
0x0d
,
0x0f
},
/* AVTXR2PGA */
{
0x0e
,
0x00
},
/* AUDIO_IF */
{
0x0f
,
0x00
},
/* VOICE_IF */
{
0x10
,
0x3f
},
/* ARXR1PGA */
{
0x11
,
0x3f
},
/* ARXL1PGA */
{
0x12
,
0x3f
},
/* ARXR2PGA */
{
0x13
,
0x3f
},
/* ARXL2PGA */
{
0x14
,
0x25
},
/* VRXPGA */
{
0x15
,
0x00
},
/* VSTPGA */
{
0x16
,
0x00
},
/* VRX2ARXPGA */
{
0x17
,
0x00
},
/* AVDAC_CTL */
{
0x18
,
0x00
},
/* ARX2VTXPGA */
{
0x19
,
0x32
},
/* ARXL1_APGA_CTL*/
{
0x1a
,
0x32
},
/* ARXR1_APGA_CTL*/
{
0x1b
,
0x32
},
/* ARXL2_APGA_CTL*/
{
0x1c
,
0x32
},
/* ARXR2_APGA_CTL*/
{
0x1d
,
0x00
},
/* ATX2ARXPGA */
{
0x1e
,
0x00
},
/* BT_IF */
{
0x1f
,
0x55
},
/* BTPGA */
{
0x20
,
0x00
},
/* BTSTPGA */
{
0x21
,
0x00
},
/* EAR_CTL */
{
0x22
,
0x00
},
/* HS_SEL */
{
0x23
,
0x00
},
/* HS_GAIN_SET */
{
0x24
,
0x00
},
/* HS_POPN_SET */
{
0x25
,
0x00
},
/* PREDL_CTL */
{
0x26
,
0x00
},
/* PREDR_CTL */
{
0x27
,
0x00
},
/* PRECKL_CTL */
{
0x28
,
0x00
},
/* PRECKR_CTL */
{
0x29
,
0x00
},
/* HFL_CTL */
{
0x2a
,
0x00
},
/* HFR_CTL */
{
0x2b
,
0x05
},
/* ALC_CTL */
{
0x2c
,
0x00
},
/* ALC_SET1 */
{
0x2d
,
0x00
},
/* ALC_SET2 */
{
0x2e
,
0x00
},
/* BOOST_CTL */
{
0x2f
,
0x00
},
/* SOFTVOL_CTL */
{
0x30
,
0x13
},
/* DTMF_FREQSEL */
{
0x31
,
0x00
},
/* DTMF_TONEXT1H */
{
0x32
,
0x00
},
/* DTMF_TONEXT1L */
{
0x33
,
0x00
},
/* DTMF_TONEXT2H */
{
0x34
,
0x00
},
/* DTMF_TONEXT2L */
{
0x35
,
0x79
},
/* DTMF_TONOFF */
{
0x36
,
0x11
},
/* DTMF_WANONOFF */
{
0x37
,
0x00
},
/* I2S_RX_SCRAMBLE_H */
{
0x38
,
0x00
},
/* I2S_RX_SCRAMBLE_M */
{
0x39
,
0x00
},
/* I2S_RX_SCRAMBLE_L */
{
0x3a
,
0x06
},
/* APLL_CTL */
{
0x3b
,
0x00
},
/* DTMF_CTL */
{
0x3c
,
0x44
},
/* DTMF_PGA_CTL2 (0x3C) */
{
0x3d
,
0x69
},
/* DTMF_PGA_CTL1 (0x3D) */
{
0x3e
,
0x00
},
/* MISC_SET_1 */
{
0x3f
,
0x00
},
/* PCMBTMUX */
/* 0x40 - 0x42 Unused */
{
0x43
,
0x00
},
/* RX_PATH_SEL */
{
0x44
,
0x32
},
/* VDL_APGA_CTL */
{
0x45
,
0x00
},
/* VIBRA_CTL */
{
0x46
,
0x00
},
/* VIBRA_SET */
{
0x47
,
0x00
},
/* VIBRA_PWM_SET */
{
0x48
,
0x00
},
/* ANAMIC_GAIN */
{
0x49
,
0x00
},
/* MISC_SET_2 */
/* End of Audio Registers */
};
static
bool
twl4030_49_nop_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
0
:
case
3
:
case
40
:
case
41
:
case
42
:
return
false
;
default:
return
true
;
}
}
static
const
struct
regmap_range
twl4030_49_volatile_ranges
[]
=
{
regmap_reg_range
(
TWL4030_BASEADD_TEST
,
0xff
),
};
static
const
struct
regmap_access_table
twl4030_49_volatile_table
=
{
.
yes_ranges
=
twl4030_49_volatile_ranges
,
.
n_yes_ranges
=
ARRAY_SIZE
(
twl4030_49_volatile_ranges
),
};
static
struct
regmap_config
twl4030_regmap_config
[
4
]
=
{
{
/* Address 0x48 */
...
...
@@ -212,6 +314,15 @@ static struct regmap_config twl4030_regmap_config[4] = {
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
0xff
,
.
readable_reg
=
twl4030_49_nop_reg
,
.
writeable_reg
=
twl4030_49_nop_reg
,
.
volatile_table
=
&
twl4030_49_volatile_table
,
.
reg_defaults
=
twl4030_49_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
twl4030_49_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
},
{
/* Address 0x4a */
...
...
@@ -302,35 +413,50 @@ unsigned int twl_rev(void)
EXPORT_SYMBOL
(
twl_rev
);
/**
* twl_
i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
* twl_
get_regmap - Get the regmap associated with the given module
* @mod_no: module number
* @value: an array of num_bytes+1 containing data to write
* @reg: register address (just offset will do)
* @num_bytes: number of bytes to transfer
*
* Returns the re
sult of operation - 0 is success
* Returns the re
gmap pointer or NULL in case of failure.
*/
int
twl_i2c_write
(
u8
mod_no
,
u8
*
value
,
u8
reg
,
unsigned
num_bytes
)
static
struct
regmap
*
twl_get_regmap
(
u8
mod_no
)
{
int
ret
;
int
sid
;
struct
twl_client
*
twl
;
if
(
unlikely
(
!
twl_priv
||
!
twl_priv
->
ready
))
{
pr_err
(
"%s: not initialized
\n
"
,
DRIVER_NAME
);
return
-
EPERM
;
return
NULL
;
}
if
(
unlikely
(
mod_no
>=
twl_get_last_module
()))
{
pr_err
(
"%s: invalid module number %d
\n
"
,
DRIVER_NAME
,
mod_no
);
return
-
EPERM
;
return
NULL
;
}
sid
=
twl_priv
->
twl_map
[
mod_no
].
sid
;
twl
=
&
twl_priv
->
twl_modules
[
sid
];
ret
=
regmap_bulk_write
(
twl
->
regmap
,
twl_priv
->
twl_map
[
mod_no
].
base
+
reg
,
value
,
num_bytes
);
return
twl
->
regmap
;
}
/**
* twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
* @mod_no: module number
* @value: an array of num_bytes+1 containing data to write
* @reg: register address (just offset will do)
* @num_bytes: number of bytes to transfer
*
* Returns the result of operation - 0 is success
*/
int
twl_i2c_write
(
u8
mod_no
,
u8
*
value
,
u8
reg
,
unsigned
num_bytes
)
{
struct
regmap
*
regmap
=
twl_get_regmap
(
mod_no
);
int
ret
;
if
(
!
regmap
)
return
-
EPERM
;
ret
=
regmap_bulk_write
(
regmap
,
twl_priv
->
twl_map
[
mod_no
].
base
+
reg
,
value
,
num_bytes
);
if
(
ret
)
pr_err
(
"%s: Write failed (mod %d, reg 0x%02x count %d)
\n
"
,
...
...
@@ -351,25 +477,14 @@ EXPORT_SYMBOL(twl_i2c_write);
*/
int
twl_i2c_read
(
u8
mod_no
,
u8
*
value
,
u8
reg
,
unsigned
num_bytes
)
{
struct
regmap
*
regmap
=
twl_get_regmap
(
mod_no
);
int
ret
;
int
sid
;
struct
twl_client
*
twl
;
if
(
unlikely
(
!
twl_priv
||
!
twl_priv
->
ready
))
{
pr_err
(
"%s: not initialized
\n
"
,
DRIVER_NAME
);
return
-
EPERM
;
}
if
(
unlikely
(
mod_no
>=
twl_get_last_module
()))
{
pr_err
(
"%s: invalid module number %d
\n
"
,
DRIVER_NAME
,
mod_no
);
if
(
!
regmap
)
return
-
EPERM
;
}
sid
=
twl_priv
->
twl_map
[
mod_no
].
sid
;
twl
=
&
twl_priv
->
twl_modules
[
sid
];
ret
=
regmap_bulk_read
(
twl
->
regmap
,
twl_priv
->
twl_map
[
mod_no
].
base
+
reg
,
value
,
num_bytes
);
ret
=
regmap_bulk_read
(
regmap
,
twl_priv
->
twl_map
[
mod_no
].
base
+
reg
,
value
,
num_bytes
);
if
(
ret
)
pr_err
(
"%s: Read failed (mod %d, reg 0x%02x count %d)
\n
"
,
...
...
@@ -379,6 +494,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
}
EXPORT_SYMBOL
(
twl_i2c_read
);
/**
* twl_regcache_bypass - Configure the regcache bypass for the regmap associated
* with the module
* @mod_no: module number
* @enable: Regcache bypass state
*
* Returns 0 else failure.
*/
int
twl_set_regcache_bypass
(
u8
mod_no
,
bool
enable
)
{
struct
regmap
*
regmap
=
twl_get_regmap
(
mod_no
);
if
(
!
regmap
)
return
-
EPERM
;
regcache_cache_bypass
(
regmap
,
enable
);
return
0
;
}
EXPORT_SYMBOL
(
twl_set_regcache_bypass
);
/*----------------------------------------------------------------------*/
/**
...
...
drivers/mfd/twl6040.c
浏览文件 @
09fd19da
...
...
@@ -44,6 +44,54 @@
#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
#define TWL6040_NUM_SUPPLIES (2)
static
struct
reg_default
twl6040_defaults
[]
=
{
{
0x01
,
0x4B
},
/* REG_ASICID (ro) */
{
0x02
,
0x00
},
/* REG_ASICREV (ro) */
{
0x03
,
0x00
},
/* REG_INTID */
{
0x04
,
0x00
},
/* REG_INTMR */
{
0x05
,
0x00
},
/* REG_NCPCTRL */
{
0x06
,
0x00
},
/* REG_LDOCTL */
{
0x07
,
0x60
},
/* REG_HPPLLCTL */
{
0x08
,
0x00
},
/* REG_LPPLLCTL */
{
0x09
,
0x4A
},
/* REG_LPPLLDIV */
{
0x0A
,
0x00
},
/* REG_AMICBCTL */
{
0x0B
,
0x00
},
/* REG_DMICBCTL */
{
0x0C
,
0x00
},
/* REG_MICLCTL */
{
0x0D
,
0x00
},
/* REG_MICRCTL */
{
0x0E
,
0x00
},
/* REG_MICGAIN */
{
0x0F
,
0x1B
},
/* REG_LINEGAIN */
{
0x10
,
0x00
},
/* REG_HSLCTL */
{
0x11
,
0x00
},
/* REG_HSRCTL */
{
0x12
,
0x00
},
/* REG_HSGAIN */
{
0x13
,
0x00
},
/* REG_EARCTL */
{
0x14
,
0x00
},
/* REG_HFLCTL */
{
0x15
,
0x00
},
/* REG_HFLGAIN */
{
0x16
,
0x00
},
/* REG_HFRCTL */
{
0x17
,
0x00
},
/* REG_HFRGAIN */
{
0x18
,
0x00
},
/* REG_VIBCTLL */
{
0x19
,
0x00
},
/* REG_VIBDATL */
{
0x1A
,
0x00
},
/* REG_VIBCTLR */
{
0x1B
,
0x00
},
/* REG_VIBDATR */
{
0x1C
,
0x00
},
/* REG_HKCTL1 */
{
0x1D
,
0x00
},
/* REG_HKCTL2 */
{
0x1E
,
0x00
},
/* REG_GPOCTL */
{
0x1F
,
0x00
},
/* REG_ALB */
{
0x20
,
0x00
},
/* REG_DLB */
/* 0x28, REG_TRIM1 */
/* 0x29, REG_TRIM2 */
/* 0x2A, REG_TRIM3 */
/* 0x2B, REG_HSOTRIM */
/* 0x2C, REG_HFOTRIM */
{
0x2D
,
0x08
},
/* REG_ACCCTL */
{
0x2E
,
0x00
},
/* REG_STATUS (ro) */
};
struct
reg_default
twl6040_patch
[]
=
{
/* Select I2C bus access to dual access registers */
{
TWL6040_REG_ACCCTL
,
0x09
},
};
static
bool
twl6040_has_vibra
(
struct
device_node
*
node
)
{
#ifdef CONFIG_OF
...
...
@@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on)
if
(
twl6040
->
power_count
++
)
goto
out
;
/* Allow writes to the chip */
regcache_cache_only
(
twl6040
->
regmap
,
false
);
if
(
gpio_is_valid
(
twl6040
->
audpwron
))
{
/* use automatic power-up sequence */
ret
=
twl6040_power_up_automatic
(
twl6040
);
...
...
@@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on)
goto
out
;
}
}
/* Sync with the HW */
regcache_sync
(
twl6040
->
regmap
);
/* Default PLL configuration after power up */
twl6040
->
pll
=
TWL6040_SYSCLK_SEL_LPPLL
;
twl6040
->
sysclk
=
19200000
;
...
...
@@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use manual power-down sequence */
twl6040_power_down_manual
(
twl6040
);
}
/* Set regmap to cache only and mark it as dirty */
regcache_cache_only
(
twl6040
->
regmap
,
true
);
regcache_mark_dirty
(
twl6040
->
regmap
);
twl6040
->
sysclk
=
0
;
twl6040
->
mclk
=
0
;
}
...
...
@@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
static
bool
twl6040_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
TWL6040_REG_VIBCTLL
:
case
TWL6040_REG_VIBCTLR
:
case
TWL6040_REG_INTMR
:
case
TWL6040_REG_ASICID
:
case
TWL6040_REG_ASICREV
:
case
TWL6040_REG_INTID
:
case
TWL6040_REG_LPPLLCTL
:
case
TWL6040_REG_HPPLLCTL
:
case
TWL6040_REG_STATUS
:
return
true
;
default:
return
false
;
}
}
static
bool
twl6040_writeable_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
TWL6040_REG_ASICID
:
case
TWL6040_REG_ASICREV
:
case
TWL6040_REG_STATUS
:
return
false
;
default:
return
true
;
...
...
@@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
static
struct
regmap_config
twl6040_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
reg_defaults
=
twl6040_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
twl6040_defaults
),
.
max_register
=
TWL6040_REG_STATUS
,
/* 0x2e */
.
readable_reg
=
twl6040_readable_reg
,
.
volatile_reg
=
twl6040_volatile_reg
,
.
writeable_reg
=
twl6040_writeable_reg
,
.
cache_type
=
REGCACHE_RBTREE
,
};
...
...
@@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client,
/* dual-access registers controlled by I2C only */
twl6040_set_bits
(
twl6040
,
TWL6040_REG_ACCCTL
,
TWL6040_I2CSEL
);
regmap_register_patch
(
twl6040
->
regmap
,
twl6040_patch
,
ARRAY_SIZE
(
twl6040_patch
));
/*
* The main functionality of twl6040 to provide audio on OMAP4+ systems.
...
...
@@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client,
cell
->
name
=
"twl6040-gpo"
;
children
++
;
/* The chip is powered down so mark regmap to cache only and dirty */
regcache_cache_only
(
twl6040
->
regmap
,
true
);
regcache_mark_dirty
(
twl6040
->
regmap
);
ret
=
mfd_add_devices
(
&
client
->
dev
,
-
1
,
twl6040
->
cells
,
children
,
NULL
,
0
,
NULL
);
if
(
ret
)
...
...
include/linux/i2c/twl.h
浏览文件 @
09fd19da
...
...
@@ -175,6 +175,9 @@ static inline int twl_class_is_ ##class(void) \
TWL_CLASS_IS
(
4030
,
TWL4030_CLASS_ID
)
TWL_CLASS_IS
(
6030
,
TWL6030_CLASS_ID
)
/* Set the regcache bypass for the regmap associated with the nodule */
int
twl_set_regcache_bypass
(
u8
mod_no
,
bool
enable
);
/*
* Read and write several 8-bit registers at once.
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录