Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
2aa5eac5
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
2aa5eac5
编写于
8月 20, 2015
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nouveau/i2c: transition pad/ports away from being based on nvkm_object
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
d36a99d2
变更
52
显示空白变更内容
内联
并排
Showing
52 changed file
with
2293 addition
and
2021 deletion
+2293
-2021
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
+5
-6
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv04/disp.c
+3
-1
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+10
-6
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
+73
-52
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.c
+0
-1
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.c
+13
-13
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_dp.c
+8
-9
drivers/gpu/drm/nouveau/nouveau_encoder.h
drivers/gpu/drm/nouveau/nouveau_encoder.h
+3
-1
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.c
+27
-5
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
+7
-7
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+1
-5
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+2
-2
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
+25
-29
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
+2
-0
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
+4
-16
drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c
+2
-2
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+37
-39
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
+21
-7
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c
+180
-196
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+106
-45
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
+30
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
+181
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c
+181
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
+233
-436
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c
+66
-83
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c
+245
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
+37
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c
+95
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c
+96
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c
+86
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c
+113
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c
+4
-217
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c
+4
-71
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c
+3
-4
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c
+4
-4
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
+4
-187
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c
+2
-89
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c
+2
-85
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c
+3
-104
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h
+0
-28
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c
+76
-43
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
+59
-50
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c
+39
-50
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
+51
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c
+39
-50
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c
+10
-8
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c
+36
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c
+36
-0
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h
+0
-14
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
+2
-35
drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
+8
-8
drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
+19
-13
未找到文件。
drivers/gpu/drm/nouveau/dispnv04/dfp.c
浏览文件 @
2aa5eac5
...
...
@@ -624,8 +624,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
struct
dcb_output
*
dcb
=
nouveau_encoder
(
encoder
)
->
dcb
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nvkm_i2c
*
i2c
=
nvxx_i2c
(
&
drm
->
device
);
struct
nvkm_i2c_
port
*
port
=
i2c
->
find
(
i2c
,
2
);
struct
nvkm_i2c_b
oard_info
info
[]
=
{
struct
nvkm_i2c_
bus
*
bus
=
nvkm_i2c_bus_find
(
i2c
,
NVKM_I2C_BUS_PRI
);
struct
nvkm_i2c_b
us_probe
info
[]
=
{
{
{
.
type
=
"sil164"
,
...
...
@@ -639,16 +639,15 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
};
int
type
;
if
(
!
nv_gf4_disp_arch
(
dev
)
||
!
port
||
get_tmds_slave
(
encoder
))
if
(
!
nv_gf4_disp_arch
(
dev
)
||
!
bus
||
get_tmds_slave
(
encoder
))
return
;
type
=
i2c
->
identify
(
i2c
,
2
,
"TMDS transmitter"
,
info
,
NULL
,
NULL
);
type
=
nvkm_i2c_bus_probe
(
bus
,
"TMDS transmitter"
,
info
,
NULL
,
NULL
);
if
(
type
<
0
)
return
;
drm_i2c_encoder_init
(
dev
,
to_encoder_slave
(
encoder
),
&
port
->
adapter
,
&
info
[
type
].
dev
);
&
bus
->
i2c
,
&
info
[
type
].
dev
);
}
static
const
struct
drm_encoder_helper_funcs
nv04_lvds_helper_funcs
=
{
...
...
drivers/gpu/drm/nouveau/dispnv04/disp.c
浏览文件 @
2aa5eac5
...
...
@@ -101,7 +101,9 @@ nv04_display_create(struct drm_device *dev)
list_for_each_entry
(
encoder
,
&
dev
->
mode_config
.
encoder_list
,
head
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
nv_encoder
->
i2c
=
i2c
->
find
(
i2c
,
nv_encoder
->
dcb
->
i2c_index
);
struct
nvkm_i2c_bus
*
bus
=
nvkm_i2c_bus_find
(
i2c
,
nv_encoder
->
dcb
->
i2c_index
);
nv_encoder
->
i2c
=
bus
?
&
bus
->
i2c
:
NULL
;
}
/* Save previous state */
...
...
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
浏览文件 @
2aa5eac5
...
...
@@ -35,7 +35,7 @@
#include <drm/i2c/ch7006.h>
static
struct
nvkm_i2c_b
oard_info
nv04_tv_encoder_info
[]
=
{
static
struct
nvkm_i2c_b
us_probe
nv04_tv_encoder_info
[]
=
{
{
{
I2C_BOARD_INFO
(
"ch7006"
,
0x75
),
...
...
@@ -55,9 +55,13 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nvkm_i2c
*
i2c
=
nvxx_i2c
(
&
drm
->
device
);
return
i2c
->
identify
(
i2c
,
i2c_index
,
"TV encoder"
,
nv04_tv_encoder_info
,
NULL
,
NULL
);
struct
nvkm_i2c_bus
*
bus
=
nvkm_i2c_bus_find
(
i2c
,
i2c_index
);
if
(
bus
)
{
return
nvkm_i2c_bus_probe
(
bus
,
"TV encoder"
,
nv04_tv_encoder_info
,
NULL
,
NULL
);
}
return
-
ENODEV
;
}
...
...
@@ -205,7 +209,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
struct
drm_device
*
dev
=
connector
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nvkm_i2c
*
i2c
=
nvxx_i2c
(
&
drm
->
device
);
struct
nvkm_i2c_
port
*
port
=
i2c
->
find
(
i2c
,
entry
->
i2c_index
);
struct
nvkm_i2c_
bus
*
bus
=
nvkm_i2c_bus_
find
(
i2c
,
entry
->
i2c_index
);
int
type
,
ret
;
/* Ensure that we can talk to this encoder */
...
...
@@ -231,7 +235,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
/* Run the slave-specific initialization */
ret
=
drm_i2c_encoder_init
(
dev
,
to_encoder_slave
(
encoder
),
&
port
->
adapter
,
&
bus
->
i2c
,
&
nv04_tv_encoder_info
[
type
].
dev
);
if
(
ret
<
0
)
goto
fail_cleanup
;
...
...
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
浏览文件 @
2aa5eac5
...
...
@@ -6,15 +6,6 @@
#include <subdev/bios.h>
#include <subdev/bios/i2c.h>
#define NV_I2C_PORT(n) (0x00 + (n))
#define NV_I2C_AUX(n) (0x10 + (n))
#define NV_I2C_EXT(n) (0x20 + (n))
#define NV_I2C_DEFAULT(n) (0x80 + (n))
#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n))
#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)
#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8)
struct
nvkm_i2c_ntfy_req
{
#define NVKM_I2C_PLUG 0x01
#define NVKM_I2C_UNPLUG 0x02
...
...
@@ -29,55 +20,66 @@ struct nvkm_i2c_ntfy_rep {
u8
mask
;
};
struct
nvkm_i2c_
port
{
struct
nvkm_object
base
;
struct
i2c_adapter
adapter
;
struct
mutex
mutex
;
struct
nvkm_i2c_
bus_probe
{
struct
i2c_board_info
dev
;
u8
udelay
;
/* set to 0 to use the standard delay */
}
;
struct
list_head
head
;
u8
index
;
int
aux
;
struct
nvkm_i2c_bus
{
const
struct
nvkm_i2c_bus_func
*
func
;
struct
nvkm_i2c_pad
*
pad
;
#define NVKM_I2C_BUS_CCB(n)
/* 'n' is ccb index */
(n)
#define NVKM_I2C_BUS_EXT(n)
/* 'n' is dcb external encoder type */
((n) + 0x100)
#define NVKM_I2C_BUS_PRI
/* ccb primary comm. port */
-1
#define NVKM_I2C_BUS_SEC
/* ccb secondary comm. port */
-2
int
id
;
const
struct
nvkm_i2c_func
*
func
;
struct
mutex
mutex
;
struct
list_head
head
;
struct
i2c_adapter
i2c
;
};
struct
nvkm_i2c_func
{
void
(
*
drive_scl
)(
struct
nvkm_i2c_port
*
,
int
);
void
(
*
drive_sda
)(
struct
nvkm_i2c_port
*
,
int
);
int
(
*
sense_scl
)(
struct
nvkm_i2c_port
*
);
int
(
*
sense_sda
)(
struct
nvkm_i2c_port
*
);
int
nvkm_i2c_bus_acquire
(
struct
nvkm_i2c_bus
*
);
void
nvkm_i2c_bus_release
(
struct
nvkm_i2c_bus
*
);
int
nvkm_i2c_bus_probe
(
struct
nvkm_i2c_bus
*
,
const
char
*
,
struct
nvkm_i2c_bus_probe
*
,
bool
(
*
)(
struct
nvkm_i2c_bus
*
,
struct
i2c_board_info
*
,
void
*
),
void
*
);
int
(
*
aux
)(
struct
nvkm_i2c_port
*
,
bool
,
u8
,
u32
,
u8
*
,
u8
);
int
(
*
pattern
)(
struct
nvkm_i2c_port
*
,
int
pattern
);
int
(
*
lnk_ctl
)(
struct
nvkm_i2c_port
*
,
int
nr
,
int
bw
,
bool
enh
);
int
(
*
drv_ctl
)(
struct
nvkm_i2c_port
*
,
int
lane
,
int
sw
,
int
pe
);
};
struct
nvkm_i2c_aux
{
const
struct
nvkm_i2c_aux_func
*
func
;
struct
nvkm_i2c_pad
*
pad
;
#define NVKM_I2C_AUX_CCB(n)
/* 'n' is ccb index */
(n)
#define NVKM_I2C_AUX_EXT(n)
/* 'n' is dcb external encoder type */
((n) + 0x100)
int
id
;
struct
nvkm_i2c_board_info
{
struct
i2c_board_info
dev
;
u8
udelay
;
/* set to 0 to use the standard delay */
struct
mutex
mutex
;
struct
list_head
head
;
struct
i2c_adapter
i2c
;
u32
intr
;
};
void
nvkm_i2c_aux_monitor
(
struct
nvkm_i2c_aux
*
,
bool
monitor
);
int
nvkm_i2c_aux_acquire
(
struct
nvkm_i2c_aux
*
);
void
nvkm_i2c_aux_release
(
struct
nvkm_i2c_aux
*
);
int
nvkm_i2c_aux_xfer
(
struct
nvkm_i2c_aux
*
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
);
int
nvkm_i2c_aux_lnk_ctl
(
struct
nvkm_i2c_aux
*
,
int
link_nr
,
int
link_bw
,
bool
enhanced_framing
);
struct
nvkm_i2c
{
struct
nvkm_subdev
subdev
;
struct
nvkm_event
event
;
struct
nvkm_i2c_port
*
(
*
find
)(
struct
nvkm_i2c
*
,
u8
index
);
struct
nvkm_i2c_port
*
(
*
find_type
)(
struct
nvkm_i2c
*
,
u16
type
);
int
(
*
acquire_pad
)(
struct
nvkm_i2c_port
*
,
unsigned
long
timeout
);
void
(
*
release_pad
)(
struct
nvkm_i2c_port
*
);
int
(
*
acquire
)(
struct
nvkm_i2c_port
*
,
unsigned
long
timeout
);
void
(
*
release
)(
struct
nvkm_i2c_port
*
);
int
(
*
identify
)(
struct
nvkm_i2c
*
,
int
index
,
const
char
*
what
,
struct
nvkm_i2c_board_info
*
,
bool
(
*
match
)(
struct
nvkm_i2c_port
*
,
struct
i2c_board_info
*
,
void
*
),
void
*
);
wait_queue_head_t
wait
;
struct
list_head
ports
;
struct
list_head
pad
;
struct
list_head
bus
;
struct
list_head
aux
;
};
struct
nvkm_i2c_bus
*
nvkm_i2c_bus_find
(
struct
nvkm_i2c
*
,
int
);
struct
nvkm_i2c_aux
*
nvkm_i2c_aux_find
(
struct
nvkm_i2c
*
,
int
);
static
inline
struct
nvkm_i2c
*
nvkm_i2c
(
void
*
obj
)
{
...
...
@@ -94,7 +96,7 @@ extern struct nvkm_oclass *gk104_i2c_oclass;
extern
struct
nvkm_oclass
*
gm204_i2c_oclass
;
static
inline
int
nv
_rdi2cr
(
struct
nvkm_i2c_port
*
port
,
u8
addr
,
u8
reg
)
nv
km_rdi2cr
(
struct
i2c_adapter
*
adap
,
u8
addr
,
u8
reg
)
{
u8
val
;
struct
i2c_msg
msgs
[]
=
{
...
...
@@ -102,7 +104,7 @@ nv_rdi2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg)
{
.
addr
=
addr
,
.
flags
=
I2C_M_RD
,
.
len
=
1
,
.
buf
=
&
val
},
};
int
ret
=
i2c_transfer
(
&
port
->
adapter
,
msgs
,
2
);
int
ret
=
i2c_transfer
(
adap
,
msgs
,
ARRAY_SIZE
(
msgs
)
);
if
(
ret
!=
2
)
return
-
EIO
;
...
...
@@ -110,14 +112,14 @@ nv_rdi2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg)
}
static
inline
int
nv
_wri2cr
(
struct
nvkm_i2c_port
*
port
,
u8
addr
,
u8
reg
,
u8
val
)
nv
km_wri2cr
(
struct
i2c_adapter
*
adap
,
u8
addr
,
u8
reg
,
u8
val
)
{
u8
buf
[
2
]
=
{
reg
,
val
};
struct
i2c_msg
msgs
[]
=
{
{
.
addr
=
addr
,
.
flags
=
0
,
.
len
=
2
,
.
buf
=
buf
},
};
int
ret
=
i2c_transfer
(
&
port
->
adapter
,
msgs
,
1
);
int
ret
=
i2c_transfer
(
adap
,
msgs
,
ARRAY_SIZE
(
msgs
)
);
if
(
ret
!=
1
)
return
-
EIO
;
...
...
@@ -125,11 +127,30 @@ nv_wri2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg, u8 val)
}
static
inline
bool
nv_probe_i2c
(
struct
nvkm_i2c_port
*
port
,
u8
addr
)
nvkm_probe_i2c
(
struct
i2c_adapter
*
adap
,
u8
addr
)
{
return
nvkm_rdi2cr
(
adap
,
addr
,
0
)
>=
0
;
}
static
inline
int
nvkm_rdaux
(
struct
nvkm_i2c_aux
*
aux
,
u32
addr
,
u8
*
data
,
u8
size
)
{
return
nv_rdi2cr
(
port
,
addr
,
0
)
>=
0
;
int
ret
=
nvkm_i2c_aux_acquire
(
aux
);
if
(
ret
==
0
)
{
ret
=
nvkm_i2c_aux_xfer
(
aux
,
true
,
9
,
addr
,
data
,
size
);
nvkm_i2c_aux_release
(
aux
);
}
return
ret
;
}
int
nv_rdaux
(
struct
nvkm_i2c_port
*
,
u32
addr
,
u8
*
data
,
u8
size
);
int
nv_wraux
(
struct
nvkm_i2c_port
*
,
u32
addr
,
u8
*
data
,
u8
size
);
static
inline
int
nvkm_wraux
(
struct
nvkm_i2c_aux
*
aux
,
u32
addr
,
u8
*
data
,
u8
size
)
{
int
ret
=
nvkm_i2c_aux_acquire
(
aux
);
if
(
ret
==
0
)
{
ret
=
nvkm_i2c_aux_xfer
(
aux
,
true
,
8
,
addr
,
data
,
size
);
nvkm_i2c_aux_release
(
aux
);
}
return
ret
;
}
#endif
drivers/gpu/drm/nouveau/nouveau_bios.c
浏览文件 @
2aa5eac5
...
...
@@ -1495,7 +1495,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
break
;
}
link
=
entry
->
dpconf
.
sor
.
link
;
entry
->
i2c_index
+=
NV_I2C_AUX
(
0
);
break
;
case
DCB_OUTPUT_TMDS
:
if
(
dcb
->
version
>=
0x40
)
{
...
...
drivers/gpu/drm/nouveau/nouveau_connector.c
浏览文件 @
2aa5eac5
...
...
@@ -148,7 +148,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
break
;
}
else
if
(
nv_encoder
->
i2c
)
{
if
(
nv_probe_i2c
(
nv_encoder
->
i2c
,
0x50
))
if
(
nv
km
_probe_i2c
(
nv_encoder
->
i2c
,
0x50
))
break
;
}
}
...
...
@@ -241,7 +241,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
struct
nouveau_connector
*
nv_connector
=
nouveau_connector
(
connector
);
struct
nouveau_encoder
*
nv_encoder
=
NULL
;
struct
nouveau_encoder
*
nv_partner
;
struct
nvkm_i2c_port
*
i2c
;
struct
i2c_adapter
*
i2c
;
int
type
;
int
ret
;
enum
drm_connector_status
conn_status
=
connector_status_disconnected
;
...
...
@@ -259,7 +259,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
nv_encoder
=
nouveau_connector_ddc_detect
(
connector
);
if
(
nv_encoder
&&
(
i2c
=
nv_encoder
->
i2c
)
!=
NULL
)
{
nv_connector
->
edid
=
drm_get_edid
(
connector
,
&
i2c
->
adapter
);
nv_connector
->
edid
=
drm_get_edid
(
connector
,
i2c
);
drm_mode_connector_update_edid_property
(
connector
,
nv_connector
->
edid
);
if
(
!
nv_connector
->
edid
)
{
...
...
@@ -930,11 +930,11 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
nv_encoder
->
dcb
->
type
==
DCB_OUTPUT_DP
)
{
if
(
mode
==
DRM_MODE_DPMS_ON
)
{
u8
data
=
DP_SET_POWER_D0
;
nv
_wraux
(
nv_encoder
->
i2c
,
DP_SET_POWER
,
&
data
,
1
);
nv
km_wraux
(
nv_encoder
->
aux
,
DP_SET_POWER
,
&
data
,
1
);
usleep_range
(
1000
,
2000
);
}
else
{
u8
data
=
DP_SET_POWER_D3
;
nv
_wraux
(
nv_encoder
->
i2c
,
DP_SET_POWER
,
&
data
,
1
);
nv
km_wraux
(
nv_encoder
->
aux
,
DP_SET_POWER
,
&
data
,
1
);
}
}
...
...
@@ -980,29 +980,29 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
}
static
ssize_t
nouveau_connector_aux_xfer
(
struct
drm_dp_aux
*
aux
,
struct
drm_dp_aux_msg
*
msg
)
nouveau_connector_aux_xfer
(
struct
drm_dp_aux
*
obj
,
struct
drm_dp_aux_msg
*
msg
)
{
struct
nouveau_connector
*
nv_connector
=
container_of
(
aux
,
typeof
(
*
nv_connector
),
aux
);
container_of
(
obj
,
typeof
(
*
nv_connector
),
aux
);
struct
nouveau_encoder
*
nv_encoder
;
struct
nvkm_i2c_
port
*
port
;
struct
nvkm_i2c_
aux
*
aux
;
int
ret
;
nv_encoder
=
find_encoder
(
&
nv_connector
->
base
,
DCB_OUTPUT_DP
);
if
(
!
nv_encoder
||
!
(
port
=
nv_encoder
->
i2c
))
if
(
!
nv_encoder
||
!
(
aux
=
nv_encoder
->
aux
))
return
-
ENODEV
;
if
(
WARN_ON
(
msg
->
size
>
16
))
return
-
E2BIG
;
if
(
msg
->
size
==
0
)
return
msg
->
size
;
ret
=
nvkm_i2c
(
port
)
->
acquire
(
port
,
0
);
ret
=
nvkm_i2c
_aux_acquire
(
aux
);
if
(
ret
)
return
ret
;
ret
=
port
->
func
->
aux
(
port
,
false
,
msg
->
request
,
msg
->
address
,
ret
=
nvkm_i2c_aux_xfer
(
aux
,
false
,
msg
->
request
,
msg
->
address
,
msg
->
buffer
,
msg
->
size
);
nvkm_i2c
(
port
)
->
release
(
port
);
nvkm_i2c
_aux_release
(
aux
);
if
(
ret
>=
0
)
{
msg
->
reply
=
ret
;
return
msg
->
size
;
...
...
drivers/gpu/drm/nouveau/nouveau_dp.c
浏览文件 @
2aa5eac5
...
...
@@ -31,8 +31,7 @@
#include "nouveau_crtc.h"
static
void
nouveau_dp_probe_oui
(
struct
drm_device
*
dev
,
struct
nvkm_i2c_port
*
auxch
,
u8
*
dpcd
)
nouveau_dp_probe_oui
(
struct
drm_device
*
dev
,
struct
nvkm_i2c_aux
*
aux
,
u8
*
dpcd
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
u8
buf
[
3
];
...
...
@@ -40,11 +39,11 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_port *auxch,
if
(
!
(
dpcd
[
DP_DOWN_STREAM_PORT_COUNT
]
&
DP_OUI_SUPPORT
))
return
;
if
(
!
nv
_rdaux
(
auxch
,
DP_SINK_OUI
,
buf
,
3
))
if
(
!
nv
km_rdaux
(
aux
,
DP_SINK_OUI
,
buf
,
3
))
NV_DEBUG
(
drm
,
"Sink OUI: %02hx%02hx%02hx
\n
"
,
buf
[
0
],
buf
[
1
],
buf
[
2
]);
if
(
!
nv
_rdaux
(
auxch
,
DP_BRANCH_OUI
,
buf
,
3
))
if
(
!
nv
km_rdaux
(
aux
,
DP_BRANCH_OUI
,
buf
,
3
))
NV_DEBUG
(
drm
,
"Branch OUI: %02hx%02hx%02hx
\n
"
,
buf
[
0
],
buf
[
1
],
buf
[
2
]);
...
...
@@ -55,15 +54,15 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
{
struct
drm_device
*
dev
=
nv_encoder
->
base
.
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nvkm_i2c_
port
*
auxch
;
struct
nvkm_i2c_
aux
*
aux
;
u8
*
dpcd
=
nv_encoder
->
dp
.
dpcd
;
int
ret
;
aux
ch
=
nv_encoder
->
i2c
;
if
(
!
aux
ch
)
aux
=
nv_encoder
->
aux
;
if
(
!
aux
)
return
-
ENODEV
;
ret
=
nv
_rdaux
(
auxch
,
DP_DPCD_REV
,
dpcd
,
8
);
ret
=
nv
km_rdaux
(
aux
,
DP_DPCD_REV
,
dpcd
,
8
);
if
(
ret
)
return
ret
;
...
...
@@ -84,6 +83,6 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
NV_DEBUG
(
drm
,
"maximum: %dx%d
\n
"
,
nv_encoder
->
dp
.
link_nr
,
nv_encoder
->
dp
.
link_bw
);
nouveau_dp_probe_oui
(
dev
,
aux
ch
,
dpcd
);
nouveau_dp_probe_oui
(
dev
,
aux
,
dpcd
);
return
0
;
}
drivers/gpu/drm/nouveau/nouveau_encoder.h
浏览文件 @
2aa5eac5
...
...
@@ -41,7 +41,9 @@ struct nouveau_encoder {
struct
dcb_output
*
dcb
;
int
or
;
struct
nvkm_i2c_port
*
i2c
;
struct
i2c_adapter
*
i2c
;
struct
nvkm_i2c_aux
*
aux
;
/* different to drm_encoder.crtc, this reflects what's
* actually programmed on the hw, not the proposed crtc */
...
...
drivers/gpu/drm/nouveau/nv50_display.c
浏览文件 @
2aa5eac5
...
...
@@ -1688,6 +1688,7 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
connector
->
dev
);
struct
nvkm_i2c
*
i2c
=
nvxx_i2c
(
&
drm
->
device
);
struct
nvkm_i2c_bus
*
bus
;
struct
nouveau_encoder
*
nv_encoder
;
struct
drm_encoder
*
encoder
;
int
type
=
DRM_MODE_ENCODER_DAC
;
...
...
@@ -1697,7 +1698,10 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
return
-
ENOMEM
;
nv_encoder
->
dcb
=
dcbe
;
nv_encoder
->
or
=
ffs
(
dcbe
->
or
)
-
1
;
nv_encoder
->
i2c
=
i2c
->
find
(
i2c
,
dcbe
->
i2c_index
);
bus
=
nvkm_i2c_bus_find
(
i2c
,
dcbe
->
i2c_index
);
if
(
bus
)
nv_encoder
->
i2c
=
&
bus
->
i2c
;
encoder
=
to_drm_encoder
(
nv_encoder
);
encoder
->
possible_crtcs
=
dcbe
->
heads
;
...
...
@@ -2091,9 +2095,22 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
return
-
ENOMEM
;
nv_encoder
->
dcb
=
dcbe
;
nv_encoder
->
or
=
ffs
(
dcbe
->
or
)
-
1
;
nv_encoder
->
i2c
=
i2c
->
find
(
i2c
,
dcbe
->
i2c_index
);
nv_encoder
->
last_dpms
=
DRM_MODE_DPMS_OFF
;
if
(
dcbe
->
type
==
DCB_OUTPUT_DP
)
{
struct
nvkm_i2c_aux
*
aux
=
nvkm_i2c_aux_find
(
i2c
,
dcbe
->
i2c_index
);
if
(
aux
)
{
nv_encoder
->
i2c
=
&
aux
->
i2c
;
nv_encoder
->
aux
=
aux
;
}
}
else
{
struct
nvkm_i2c_bus
*
bus
=
nvkm_i2c_bus_find
(
i2c
,
dcbe
->
i2c_index
);
if
(
bus
)
nv_encoder
->
i2c
=
&
bus
->
i2c
;
}
encoder
=
to_drm_encoder
(
nv_encoder
);
encoder
->
possible_crtcs
=
dcbe
->
heads
;
encoder
->
possible_clones
=
0
;
...
...
@@ -2244,18 +2261,22 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
connector
->
dev
);
struct
nvkm_i2c
*
i2c
=
nvxx_i2c
(
&
drm
->
device
);
struct
nvkm_i2c_port
*
ddc
=
NULL
;
struct
nvkm_i2c_bus
*
bus
=
NULL
;
struct
nvkm_i2c_aux
*
aux
=
NULL
;
struct
i2c_adapter
*
ddc
;
struct
nouveau_encoder
*
nv_encoder
;
struct
drm_encoder
*
encoder
;
int
type
;
switch
(
dcbe
->
type
)
{
case
DCB_OUTPUT_TMDS
:
ddc
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTDDC
(
dcbe
->
extdev
));
bus
=
nvkm_i2c_bus_find
(
i2c
,
NVKM_I2C_BUS_EXT
(
dcbe
->
extdev
));
ddc
=
bus
?
&
bus
->
i2c
:
NULL
;
type
=
DRM_MODE_ENCODER_TMDS
;
break
;
case
DCB_OUTPUT_DP
:
ddc
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTAUX
(
dcbe
->
extdev
));
aux
=
nvkm_i2c_aux_find
(
i2c
,
NVKM_I2C_AUX_EXT
(
dcbe
->
extdev
));
ddc
=
aux
?
&
aux
->
i2c
:
NULL
;
type
=
DRM_MODE_ENCODER_TMDS
;
break
;
default:
...
...
@@ -2268,6 +2289,7 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
nv_encoder
->
dcb
=
dcbe
;
nv_encoder
->
or
=
ffs
(
dcbe
->
or
)
-
1
;
nv_encoder
->
i2c
=
ddc
;
nv_encoder
->
aux
=
aux
;
encoder
=
to_drm_encoder
(
nv_encoder
);
encoder
->
possible_crtcs
=
dcbe
->
heads
;
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
浏览文件 @
2aa5eac5
...
...
@@ -98,7 +98,7 @@ dp_set_link_config(struct dp_state *dp)
if
(
outp
->
dpcd
[
DPCD_RC02
]
&
DPCD_RC02_ENHANCED_FRAME_CAP
)
sink
[
1
]
|=
DPCD_LC01_ENHANCED_FRAME_EN
;
return
nv
_wraux
(
outp
->
base
.
edid
,
DPCD_LC00_LINK_BW_SET
,
sink
,
2
);
return
nv
km_wraux
(
outp
->
aux
,
DPCD_LC00_LINK_BW_SET
,
sink
,
2
);
}
static
void
...
...
@@ -111,10 +111,10 @@ dp_set_training_pattern(struct dp_state *dp, u8 pattern)
DBG
(
"training pattern %d
\n
"
,
pattern
);
impl
->
pattern
(
outp
,
pattern
);
nv
_rdaux
(
outp
->
base
.
edid
,
DPCD_LC02
,
&
sink_tp
,
1
);
nv
km_rdaux
(
outp
->
aux
,
DPCD_LC02
,
&
sink_tp
,
1
);
sink_tp
&=
~
DPCD_LC02_TRAINING_PATTERN_SET
;
sink_tp
|=
pattern
;
nv
_wraux
(
outp
->
base
.
edid
,
DPCD_LC02
,
&
sink_tp
,
1
);
nv
km_wraux
(
outp
->
aux
,
DPCD_LC02
,
&
sink_tp
,
1
);
}
static
int
...
...
@@ -150,12 +150,12 @@ dp_link_train_commit(struct dp_state *dp, bool pc)
impl
->
drv_ctl
(
outp
,
i
,
lvsw
&
3
,
lpre
&
3
,
lpc2
&
3
);
}
ret
=
nv
_wraux
(
outp
->
base
.
edid
,
DPCD_LC03
(
0
),
dp
->
conf
,
4
);
ret
=
nv
km_wraux
(
outp
->
aux
,
DPCD_LC03
(
0
),
dp
->
conf
,
4
);
if
(
ret
)
return
ret
;
if
(
pc
)
{
ret
=
nv
_wraux
(
outp
->
base
.
edid
,
DPCD_LC0F
,
dp
->
pc2conf
,
2
);
ret
=
nv
km_wraux
(
outp
->
aux
,
DPCD_LC0F
,
dp
->
pc2conf
,
2
);
if
(
ret
)
return
ret
;
}
...
...
@@ -174,12 +174,12 @@ dp_link_train_update(struct dp_state *dp, bool pc, u32 delay)
else
udelay
(
delay
);
ret
=
nv
_rdaux
(
outp
->
base
.
edid
,
DPCD_LS02
,
dp
->
stat
,
6
);
ret
=
nv
km_rdaux
(
outp
->
aux
,
DPCD_LS02
,
dp
->
stat
,
6
);
if
(
ret
)
return
ret
;
if
(
pc
)
{
ret
=
nv
_rdaux
(
outp
->
base
.
edid
,
DPCD_LS0C
,
&
dp
->
pc2stat
,
1
);
ret
=
nv
km_rdaux
(
outp
->
aux
,
DPCD_LS0C
,
&
dp
->
pc2stat
,
1
);
if
(
ret
)
dp
->
pc2stat
=
0x00
;
DBG
(
"status %6ph pc2 %02x
\n
"
,
dp
->
stat
,
dp
->
pc2stat
);
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
浏览文件 @
2aa5eac5
...
...
@@ -86,11 +86,7 @@ nvkm_output_create_(struct nvkm_object *parent,
dcbE
->
sorconf
.
link
:
0
,
dcbE
->
connector
,
dcbE
->
i2c_index
,
dcbE
->
bus
,
dcbE
->
heads
);
if
(
outp
->
info
.
type
!=
DCB_OUTPUT_DP
)
outp
->
port
=
i2c
->
find
(
i2c
,
NV_I2C_PORT
(
outp
->
info
.
i2c_index
));
else
outp
->
port
=
i2c
->
find
(
i2c
,
NV_I2C_AUX
(
outp
->
info
.
i2c_index
));
outp
->
edid
=
outp
->
port
;
outp
->
i2c
=
nvkm_i2c_bus_find
(
i2c
,
outp
->
info
.
i2c_index
);
data
=
nvbios_connEp
(
bios
,
outp
->
info
.
connector
,
&
ver
,
&
hdr
,
&
connE
);
if
(
!
data
)
{
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
浏览文件 @
2aa5eac5
...
...
@@ -13,8 +13,8 @@ struct nvkm_output {
int
index
;
int
or
;
struct
nvkm_i2c_port
*
port
;
struct
nvkm_i2c_
port
*
edid
;
// whatever (if anything) is pointed at by the dcb device entry
struct
nvkm_i2c_
bus
*
i2c
;
struct
nvkm_connector
*
conn
;
};
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
浏览文件 @
2aa5eac5
...
...
@@ -40,7 +40,7 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
int
ret
,
i
;
/* check that the link is trained at a high enough rate */
ret
=
nv
_rdaux
(
outp
->
base
.
edid
,
DPCD_LC00_LINK_BW_SET
,
link
,
2
);
ret
=
nv
km_rdaux
(
outp
->
aux
,
DPCD_LC00_LINK_BW_SET
,
link
,
2
);
if
(
ret
)
{
DBG
(
"failed to read link config, assuming no sink
\n
"
);
goto
done
;
...
...
@@ -55,7 +55,7 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
}
/* check that link is still trained */
ret
=
nv
_rdaux
(
outp
->
base
.
edid
,
DPCD_LS02
,
stat
,
3
);
ret
=
nv
km_rdaux
(
outp
->
aux
,
DPCD_LS02
,
stat
,
3
);
if
(
ret
)
{
DBG
(
"failed to read link status, assuming no sink
\n
"
);
goto
done
;
...
...
@@ -102,37 +102,31 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
}
static
void
nvkm_output_dp_enable
(
struct
nvkm_output_dp
*
outp
,
bool
present
)
nvkm_output_dp_enable
(
struct
nvkm_output_dp
*
outp
,
bool
enable
)
{
struct
nvkm_i2c_port
*
port
=
outp
->
base
.
edid
;
if
(
present
)
{
struct
nvkm_i2c_aux
*
aux
=
outp
->
aux
;
if
(
enable
)
{
if
(
!
outp
->
present
)
{
nvkm_i2c
(
port
)
->
acquire_pad
(
port
,
0
);
DBG
(
"aux power -> always
\n
"
);
nvkm_i2c_aux_monitor
(
aux
,
true
);
outp
->
present
=
true
;
}
if
(
!
nvkm_rdaux
(
aux
,
DPCD_RC00_DPCD_REV
,
outp
->
dpcd
,
sizeof
(
outp
->
dpcd
)))
{
nvkm_output_dp_train
(
&
outp
->
base
,
0
,
true
);
}
else
{
return
;
}
}
if
(
outp
->
present
)
{
nvkm_i2c
(
port
)
->
release_pad
(
port
);
DBG
(
"aux power -> demand
\n
"
);
nvkm_i2c_aux_monitor
(
aux
,
false
);
outp
->
present
=
false
;
}
atomic_set
(
&
outp
->
lt
.
done
,
0
);
}
}
static
void
nvkm_output_dp_detect
(
struct
nvkm_output_dp
*
outp
)
{
struct
nvkm_i2c_port
*
port
=
outp
->
base
.
edid
;
int
ret
=
nvkm_i2c
(
port
)
->
acquire_pad
(
port
,
0
);
if
(
ret
==
0
)
{
ret
=
nv_rdaux
(
outp
->
base
.
edid
,
DPCD_RC00_DPCD_REV
,
outp
->
dpcd
,
sizeof
(
outp
->
dpcd
));
nvkm_output_dp_enable
(
outp
,
ret
==
0
);
nvkm_i2c
(
port
)
->
release_pad
(
port
);
}
atomic_set
(
&
outp
->
lt
.
done
,
0
);
}
static
int
...
...
@@ -148,7 +142,7 @@ nvkm_output_dp_hpd(struct nvkm_notify *notify)
if
(
outp
->
base
.
conn
==
conn
&&
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
{
DBG
(
"HPD: %d
\n
"
,
line
->
mask
);
nvkm_output_dp_
detect
(
outp
);
nvkm_output_dp_
enable
(
outp
,
true
);
if
(
line
->
mask
&
NVKM_I2C_UNPLUG
)
rep
.
mask
|=
NVIF_NOTIFY_CONN_V0_UNPLUG
;
...
...
@@ -196,7 +190,7 @@ int
_nvkm_output_dp_init
(
struct
nvkm_object
*
object
)
{
struct
nvkm_output_dp
*
outp
=
(
void
*
)
object
;
nvkm_output_dp_
detect
(
outp
);
nvkm_output_dp_
enable
(
outp
,
true
);
return
nvkm_output_init
(
&
outp
->
base
);
}
...
...
@@ -231,7 +225,9 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
nvkm_notify_fini
(
&
outp
->
base
.
conn
->
hpd
);
/* access to the aux channel is not optional... */
if
(
!
outp
->
base
.
edid
)
{
//XXX: breaks anx support
outp
->
aux
=
nvkm_i2c_aux_find
(
i2c
,
outp
->
base
.
info
.
i2c_index
);
if
(
!
outp
->
aux
)
{
ERR
(
"aux channel not found
\n
"
);
return
-
ENODEV
;
}
...
...
@@ -256,7 +252,7 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
ret
=
nvkm_notify_init
(
NULL
,
&
i2c
->
event
,
nvkm_output_dp_irq
,
true
,
&
(
struct
nvkm_i2c_ntfy_req
)
{
.
mask
=
NVKM_I2C_IRQ
,
.
port
=
outp
->
base
.
edid
->
index
,
.
port
=
outp
->
aux
->
id
,
},
sizeof
(
struct
nvkm_i2c_ntfy_req
),
sizeof
(
struct
nvkm_i2c_ntfy_rep
),
...
...
@@ -270,7 +266,7 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
ret
=
nvkm_notify_init
(
NULL
,
&
i2c
->
event
,
nvkm_output_dp_hpd
,
true
,
&
(
struct
nvkm_i2c_ntfy_req
)
{
.
mask
=
NVKM_I2C_PLUG
|
NVKM_I2C_UNPLUG
,
.
port
=
outp
->
base
.
edid
->
index
,
.
port
=
outp
->
aux
->
id
,
},
sizeof
(
struct
nvkm_i2c_ntfy_req
),
sizeof
(
struct
nvkm_i2c_ntfy_rep
),
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
浏览文件 @
2aa5eac5
...
...
@@ -12,6 +12,8 @@ struct nvkm_output_dp {
struct
nvbios_dpout
info
;
u8
version
;
struct
nvkm_i2c_aux
*
aux
;
struct
nvkm_notify
irq
;
bool
present
;
u8
dpcd
[
16
];
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
浏览文件 @
2aa5eac5
...
...
@@ -41,7 +41,6 @@ nv50_pior_tmds_ctor(struct nvkm_object *parent,
struct
nvkm_oclass
*
oclass
,
void
*
info
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
parent
);
struct
nvkm_output
*
outp
;
int
ret
;
...
...
@@ -50,7 +49,6 @@ nv50_pior_tmds_ctor(struct nvkm_object *parent,
if
(
ret
)
return
ret
;
outp
->
edid
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTDDC
(
outp
->
info
.
extdev
));
return
0
;
}
...
...
@@ -72,10 +70,7 @@ nv50_pior_tmds_impl = {
static
int
nv50_pior_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
{
struct
nvkm_i2c_port
*
port
=
outp
->
base
.
edid
;
if
(
port
&&
port
->
func
->
pattern
)
return
port
->
func
->
pattern
(
port
,
pattern
);
return
port
?
0
:
-
ENODEV
;
return
-
ENODEV
;
}
static
int
...
...
@@ -87,19 +82,13 @@ nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
static
int
nv50_pior_dp_lnk_ctl
(
struct
nvkm_output_dp
*
outp
,
int
nr
,
int
bw
,
bool
ef
)
{
struct
nvkm_i2c_port
*
port
=
outp
->
base
.
edid
;
if
(
port
&&
port
->
func
->
lnk_ctl
)
return
port
->
func
->
lnk_ctl
(
port
,
nr
,
bw
,
ef
);
return
port
?
0
:
-
ENODEV
;
return
nvkm_i2c_aux_lnk_ctl
(
outp
->
aux
,
nr
,
bw
,
ef
);
}
static
int
nv50_pior_dp_drv_ctl
(
struct
nvkm_output_dp
*
outp
,
int
ln
,
int
vs
,
int
pe
,
int
pc
)
{
struct
nvkm_i2c_port
*
port
=
outp
->
base
.
edid
;
if
(
port
&&
port
->
func
->
drv_ctl
)
return
port
->
func
->
drv_ctl
(
port
,
ln
,
vs
,
pe
);
return
port
?
0
:
-
ENODEV
;
return
-
ENODEV
;
}
static
int
...
...
@@ -117,8 +106,7 @@ nv50_pior_dp_ctor(struct nvkm_object *parent,
if
(
ret
)
return
ret
;
outp
->
base
.
edid
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTAUX
(
outp
->
base
.
info
.
extdev
));
outp
->
aux
=
nvkm_i2c_aux_find
(
i2c
,
NVKM_I2C_AUX_EXT
(
outp
->
base
.
info
.
extdev
));
return
0
;
}
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c
浏览文件 @
2aa5eac5
...
...
@@ -76,8 +76,8 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info)
if
(
ent
)
{
if
(
ver
>=
0x41
)
{
u32
ent_value
=
nvbios_rd32
(
bios
,
ent
);
u8
i2c_port
=
(
ent_value
>>
27
)
&
0x1f
;
u8
dpaux_port
=
(
ent_value
>>
22
)
&
0x1f
;
u8
i2c_port
=
(
ent_value
>>
0
)
&
0x1f
;
u8
dpaux_port
=
(
ent_value
>>
5
)
&
0x1f
;
/* value 0x1f means unused according to DCB 4.x spec */
if
(
i2c_port
==
0x1f
&&
dpaux_port
==
0x1f
)
info
->
type
=
DCB_I2C_UNUSED
;
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
浏览文件 @
2aa5eac5
...
...
@@ -259,62 +259,60 @@ init_wrvgai(struct nvbios_init *init, u16 port, u8 index, u8 value)
}
}
static
struct
nvkm_i2c_port
*
static
struct
i2c_adapter
*
init_i2c
(
struct
nvbios_init
*
init
,
int
index
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
init
->
bios
);
struct
nvkm_i2c
*
i2c
=
init
->
bios
->
subdev
.
device
->
i2c
;
struct
nvkm_i2c_bus
*
bus
;
if
(
index
==
0xff
)
{
index
=
NV
_I2C_DEFAULT
(
0
)
;
index
=
NV
KM_I2C_BUS_PRI
;
if
(
init
->
outp
&&
init
->
outp
->
i2c_upper_default
)
index
=
NV_I2C_DEFAULT
(
1
);
}
else
if
(
index
<
0
)
{
if
(
!
init
->
outp
)
{
if
(
init_exec
(
init
))
error
(
"script needs output for i2c
\n
"
);
return
NULL
;
}
if
(
index
==
-
2
&&
init
->
outp
->
location
)
{
index
=
NV_I2C_TYPE_EXTAUX
(
init
->
outp
->
extdev
);
return
i2c
->
find_type
(
i2c
,
index
);
}
index
=
init
->
outp
->
i2c_index
;
if
(
init
->
outp
->
type
==
DCB_OUTPUT_DP
)
index
+=
NV_I2C_AUX
(
0
);
index
=
NVKM_I2C_BUS_SEC
;
}
return
i2c
->
find
(
i2c
,
index
);
bus
=
nvkm_i2c_bus_find
(
i2c
,
index
);
return
bus
?
&
bus
->
i2c
:
NULL
;
}
static
int
init_rdi2cr
(
struct
nvbios_init
*
init
,
u8
index
,
u8
addr
,
u8
reg
)
{
struct
nvkm_i2c_port
*
port
=
init_i2c
(
init
,
index
);
if
(
port
&&
init_exec
(
init
))
return
nv
_rdi2cr
(
port
,
addr
,
reg
);
struct
i2c_adapter
*
adap
=
init_i2c
(
init
,
index
);
if
(
adap
&&
init_exec
(
init
))
return
nv
km_rdi2cr
(
adap
,
addr
,
reg
);
return
-
ENODEV
;
}
static
int
init_wri2cr
(
struct
nvbios_init
*
init
,
u8
index
,
u8
addr
,
u8
reg
,
u8
val
)
{
struct
nvkm_i2c_port
*
port
=
init_i2c
(
init
,
index
);
if
(
port
&&
init_exec
(
init
))
return
nv
_wri2cr
(
port
,
addr
,
reg
,
val
);
struct
i2c_adapter
*
adap
=
init_i2c
(
init
,
index
);
if
(
adap
&&
init_exec
(
init
))
return
nv
km_wri2cr
(
adap
,
addr
,
reg
,
val
);
return
-
ENODEV
;
}
static
struct
nvkm_i2c_aux
*
init_aux
(
struct
nvbios_init
*
init
)
{
struct
nvkm_i2c
*
i2c
=
init
->
bios
->
subdev
.
device
->
i2c
;
if
(
!
init
->
outp
)
{
if
(
init_exec
(
init
))
error
(
"script needs output for aux
\n
"
);
return
NULL
;
}
return
nvkm_i2c_aux_find
(
i2c
,
init
->
outp
->
i2c_index
);
}
static
u8
init_rdauxr
(
struct
nvbios_init
*
init
,
u32
addr
)
{
struct
nvkm_i2c_
port
*
port
=
init_i2c
(
init
,
-
2
);
struct
nvkm_i2c_
aux
*
aux
=
init_aux
(
init
);
u8
data
;
if
(
port
&&
init_exec
(
init
))
{
int
ret
=
nv
_rdaux
(
port
,
addr
,
&
data
,
1
);
if
(
aux
&&
init_exec
(
init
))
{
int
ret
=
nv
km_rdaux
(
aux
,
addr
,
&
data
,
1
);
if
(
ret
==
0
)
return
data
;
trace
(
"auxch read failed with %d
\n
"
,
ret
);
...
...
@@ -326,9 +324,9 @@ init_rdauxr(struct nvbios_init *init, u32 addr)
static
int
init_wrauxr
(
struct
nvbios_init
*
init
,
u32
addr
,
u8
data
)
{
struct
nvkm_i2c_
port
*
port
=
init_i2c
(
init
,
-
2
);
if
(
port
&&
init_exec
(
init
))
{
int
ret
=
nv
_wraux
(
port
,
addr
,
&
data
,
1
);
struct
nvkm_i2c_
aux
*
aux
=
init_aux
(
init
);
if
(
aux
&&
init_exec
(
init
))
{
int
ret
=
nv
km_wraux
(
aux
,
addr
,
&
data
,
1
);
if
(
ret
)
trace
(
"auxch write failed with %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -1065,13 +1063,13 @@ init_zm_i2c(struct nvbios_init *init)
}
if
(
init_exec
(
init
))
{
struct
nvkm_i2c_port
*
port
=
init_i2c
(
init
,
index
);
struct
i2c_adapter
*
adap
=
init_i2c
(
init
,
index
);
struct
i2c_msg
msg
=
{
.
addr
=
addr
,
.
flags
=
0
,
.
len
=
count
,
.
buf
=
data
,
};
int
ret
;
if
(
port
&&
(
ret
=
i2c_transfer
(
&
port
->
adapter
,
&
msg
,
1
))
!=
1
)
if
(
adap
&&
(
ret
=
i2c_transfer
(
adap
,
&
msg
,
1
))
!=
1
)
warn
(
"i2c wr failed, %d
\n
"
,
ret
);
}
}
...
...
@@ -2127,15 +2125,15 @@ init_i2c_long_if(struct nvbios_init *init)
u8
reghi
=
nvbios_rd08
(
bios
,
init
->
offset
+
4
);
u8
mask
=
nvbios_rd08
(
bios
,
init
->
offset
+
5
);
u8
data
=
nvbios_rd08
(
bios
,
init
->
offset
+
6
);
struct
nvkm_i2c_port
*
port
;
struct
i2c_adapter
*
adap
;
trace
(
"I2C_LONG_IF
\t
"
"I2C[0x%02x][0x%02x][0x%02x%02x] & 0x%02x == 0x%02x
\n
"
,
index
,
addr
,
reglo
,
reghi
,
mask
,
data
);
init
->
offset
+=
7
;
port
=
init_i2c
(
init
,
index
);
if
(
port
)
{
adap
=
init_i2c
(
init
,
index
);
if
(
adap
)
{
u8
i
[
2
]
=
{
reghi
,
reglo
};
u8
o
[
1
]
=
{};
struct
i2c_msg
msg
[]
=
{
...
...
@@ -2144,7 +2142,7 @@ init_i2c_long_if(struct nvbios_init *init)
};
int
ret
;
ret
=
i2c_transfer
(
&
port
->
adapter
,
msg
,
2
);
ret
=
i2c_transfer
(
adap
,
msg
,
2
);
if
(
ret
==
2
&&
((
o
[
0
]
&
mask
)
==
data
))
return
;
}
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
浏览文件 @
2aa5eac5
nvkm-y += nvkm/subdev/i2c/base.o
nvkm-y += nvkm/subdev/i2c/anx9805.o
nvkm-y += nvkm/subdev/i2c/aux.o
nvkm-y += nvkm/subdev/i2c/bit.o
nvkm-y += nvkm/subdev/i2c/pad.o
nvkm-y += nvkm/subdev/i2c/padnv04.o
nvkm-y += nvkm/subdev/i2c/padg94.o
nvkm-y += nvkm/subdev/i2c/padgm204.o
nvkm-y += nvkm/subdev/i2c/nv04.o
nvkm-y += nvkm/subdev/i2c/nv4e.o
nvkm-y += nvkm/subdev/i2c/nv50.o
...
...
@@ -14,3 +7,24 @@ nvkm-y += nvkm/subdev/i2c/gf110.o
nvkm-y += nvkm/subdev/i2c/gf117.o
nvkm-y += nvkm/subdev/i2c/gk104.o
nvkm-y += nvkm/subdev/i2c/gm204.o
nvkm-y += nvkm/subdev/i2c/pad.o
nvkm-y += nvkm/subdev/i2c/padnv04.o
nvkm-y += nvkm/subdev/i2c/padnv4e.o
nvkm-y += nvkm/subdev/i2c/padnv50.o
nvkm-y += nvkm/subdev/i2c/padg94.o
nvkm-y += nvkm/subdev/i2c/padgf119.o
nvkm-y += nvkm/subdev/i2c/padgm204.o
nvkm-y += nvkm/subdev/i2c/bus.o
nvkm-y += nvkm/subdev/i2c/busnv04.o
nvkm-y += nvkm/subdev/i2c/busnv4e.o
nvkm-y += nvkm/subdev/i2c/busnv50.o
nvkm-y += nvkm/subdev/i2c/busgf119.o
nvkm-y += nvkm/subdev/i2c/bit.o
nvkm-y += nvkm/subdev/i2c/aux.o
nvkm-y += nvkm/subdev/i2c/auxg94.o
nvkm-y += nvkm/subdev/i2c/auxgm204.o
nvkm-y += nvkm/subdev/i2c/anx9805.o
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c
浏览文件 @
2aa5eac5
...
...
@@ -21,274 +21,258 @@
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "port.h"
#define anx9805_pad(p) container_of((p), struct anx9805_pad, base)
#define anx9805_bus(p) container_of((p), struct anx9805_bus, base)
#define anx9805_aux(p) container_of((p), struct anx9805_aux, base)
#include "aux.h"
#include "bus.h"
struct
anx9805_pad
{
struct
nvkm_i2c_pad
base
;
struct
nvkm_i2c_bus
*
bus
;
u8
addr
;
};
struct
anx9805_
i2c_port
{
struct
nvkm_i2c_
port
base
;
u32
addr
;
u
32
ctrl
;
struct
anx9805_
bus
{
struct
nvkm_i2c_
bus
base
;
struct
anx9805_pad
*
pad
;
u
8
addr
;
};
static
int
anx9805_
train
(
struct
nvkm_i2c_port
*
port
,
int
link_nr
,
int
link_bw
,
bool
enh
)
anx9805_
bus_xfer
(
struct
nvkm_i2c_bus
*
base
,
struct
i2c_msg
*
msgs
,
int
num
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
struct
nvkm_subdev
*
subdev
=
&
i2c
->
subdev
;
struct
anx9805_i2c_port
*
chan
=
(
void
*
)
port
;
struct
nvkm_i2c_port
*
mast
=
(
void
*
)
nv_object
(
chan
)
->
parent
;
u8
tmp
,
i
;
DBG
(
"ANX9805 train %d %02x %d
\n
"
,
link_nr
,
link_bw
,
enh
)
;
struct
anx9805_bus
*
bus
=
anx9805_bus
(
base
);
struct
anx9805_pad
*
pad
=
bus
->
pad
;
struct
i2c_adapter
*
adap
=
&
pad
->
bus
->
i2c
;
struct
i2c_msg
*
msg
=
msgs
;
int
ret
=
-
ETIMEDOUT
;
int
i
,
j
,
cnt
=
num
;
u8
seg
=
0x00
,
off
=
0x00
,
tmp
;
nv_wri2cr
(
mast
,
chan
->
addr
,
0xa0
,
link_bw
);
nv_wri2cr
(
mast
,
chan
->
addr
,
0xa1
,
link_nr
|
(
enh
?
0x80
:
0x00
));
nv_wri2cr
(
mast
,
chan
->
addr
,
0xa2
,
0x01
);
nv_wri2cr
(
mast
,
chan
->
addr
,
0xa8
,
0x01
);
tmp
=
nvkm_rdi2cr
(
adap
,
pad
->
addr
,
0x07
)
&
~
0x10
;
nvkm_wri2cr
(
adap
,
pad
->
addr
,
0x07
,
tmp
|
0x10
);
nvkm_wri2cr
(
adap
,
pad
->
addr
,
0x07
,
tmp
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x43
,
0x05
);
mdelay
(
5
);
i
=
0
;
while
((
tmp
=
nv_rdi2cr
(
mast
,
chan
->
addr
,
0xa8
))
&
0x01
)
{
while
(
cnt
--
)
{
if
(
(
msg
->
flags
&
I2C_M_RD
)
&&
msg
->
addr
==
0x50
)
{
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x40
,
msg
->
addr
<<
1
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x41
,
seg
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x42
,
off
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x44
,
msg
->
len
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x45
,
0x00
);
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x43
,
0x01
);
for
(
i
=
0
;
i
<
msg
->
len
;
i
++
)
{
j
=
0
;
while
(
nvkm_rdi2cr
(
adap
,
bus
->
addr
,
0x46
)
&
0x10
)
{
mdelay
(
5
);
if
(
i
++
==
100
)
{
nvkm_error
(
subdev
,
"link training timed out
\n
"
);
return
-
ETIMEDOUT
;
if
(
j
++
==
32
)
goto
done
;
}
msg
->
buf
[
i
]
=
nvkm_rdi2cr
(
adap
,
bus
->
addr
,
0x47
);
}
}
else
if
(
!
(
msg
->
flags
&
I2C_M_RD
))
{
if
(
msg
->
addr
==
0x50
&&
msg
->
len
==
0x01
)
{
off
=
msg
->
buf
[
0
];
}
else
if
(
msg
->
addr
==
0x30
&&
msg
->
len
==
0x01
)
{
seg
=
msg
->
buf
[
0
];
}
else
goto
done
;
}
else
{
goto
done
;
}
msg
++
;
}
if
(
tmp
&
0x70
)
{
nvkm_error
(
subdev
,
"link training failed: %02x
\n
"
,
tmp
);
return
-
EIO
;
ret
=
num
;
done:
nvkm_wri2cr
(
adap
,
bus
->
addr
,
0x43
,
0x00
);
return
ret
;
}
static
const
struct
nvkm_i2c_bus_func
anx9805_bus_func
=
{
.
xfer
=
anx9805_bus_xfer
,
};
static
int
anx9805_bus_new
(
struct
nvkm_i2c_pad
*
base
,
int
id
,
u8
drive
,
struct
nvkm_i2c_bus
**
pbus
)
{
struct
anx9805_pad
*
pad
=
anx9805_pad
(
base
);
struct
anx9805_bus
*
bus
;
int
ret
;
if
(
!
(
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
bus
->
base
;
bus
->
pad
=
pad
;
ret
=
nvkm_i2c_bus_ctor
(
&
anx9805_bus_func
,
&
pad
->
base
,
id
,
&
bus
->
base
);
if
(
ret
)
return
ret
;
switch
(
pad
->
addr
)
{
case
0x39
:
bus
->
addr
=
0x3d
;
break
;
case
0x3b
:
bus
->
addr
=
0x3f
;
break
;
default:
return
-
ENOSYS
;
}
return
1
;
return
0
;
}
struct
anx9805_aux
{
struct
nvkm_i2c_aux
base
;
struct
anx9805_pad
*
pad
;
u8
addr
;
};
static
int
anx9805_aux
(
struct
nvkm_i2c_port
*
port
,
bool
retry
,
anx9805_aux
_xfer
(
struct
nvkm_i2c_aux
*
base
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
anx9805_i2c_port
*
chan
=
(
void
*
)
port
;
struct
nvkm_i2c_port
*
mast
=
(
void
*
)
nv_object
(
chan
)
->
parent
;
struct
anx9805_aux
*
aux
=
anx9805_aux
(
base
);
struct
anx9805_pad
*
pad
=
aux
->
pad
;
struct
i2c_adapter
*
adap
=
&
pad
->
bus
->
i2c
;
int
i
,
ret
=
-
ETIMEDOUT
;
u8
buf
[
16
]
=
{};
u8
tmp
;
DBG
(
"%02x %05x %d
\n
"
,
type
,
addr
,
size
);
AUX_DBG
(
&
aux
->
base
,
"%02x %05x %d
"
,
type
,
addr
,
size
);
tmp
=
nv
_rdi2cr
(
mast
,
chan
->
ctrl
,
0x07
)
&
~
0x04
;
nv
_wri2cr
(
mast
,
chan
->
ctrl
,
0x07
,
tmp
|
0x04
);
nv
_wri2cr
(
mast
,
chan
->
ctrl
,
0x07
,
tmp
);
nv
_wri2cr
(
mast
,
chan
->
ctrl
,
0xf7
,
0x01
);
tmp
=
nv
km_rdi2cr
(
adap
,
pad
->
addr
,
0x07
)
&
~
0x04
;
nv
km_wri2cr
(
adap
,
pad
->
addr
,
0x07
,
tmp
|
0x04
);
nv
km_wri2cr
(
adap
,
pad
->
addr
,
0x07
,
tmp
);
nv
km_wri2cr
(
adap
,
pad
->
addr
,
0xf7
,
0x01
);
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe4
,
0x80
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe4
,
0x80
);
if
(
!
(
type
&
1
))
{
memcpy
(
buf
,
data
,
size
);
DBG
(
"%16ph"
,
buf
);
AUX_DBG
(
&
aux
->
base
,
"%16ph"
,
buf
);
for
(
i
=
0
;
i
<
size
;
i
++
)
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xf0
+
i
,
buf
[
i
]);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xf0
+
i
,
buf
[
i
]);
}
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe5
,
((
size
-
1
)
<<
4
)
|
type
);
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe6
,
(
addr
&
0x000ff
)
>>
0
);
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe7
,
(
addr
&
0x0ff00
)
>>
8
);
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe8
,
(
addr
&
0xf0000
)
>>
16
);
nv
_wri2cr
(
mast
,
chan
->
addr
,
0xe9
,
0x01
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe5
,
((
size
-
1
)
<<
4
)
|
type
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe6
,
(
addr
&
0x000ff
)
>>
0
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe7
,
(
addr
&
0x0ff00
)
>>
8
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe8
,
(
addr
&
0xf0000
)
>>
16
);
nv
km_wri2cr
(
adap
,
aux
->
addr
,
0xe9
,
0x01
);
i
=
0
;
while
((
tmp
=
nv
_rdi2cr
(
mast
,
chan
->
addr
,
0xe9
))
&
0x01
)
{
while
((
tmp
=
nv
km_rdi2cr
(
adap
,
aux
->
addr
,
0xe9
))
&
0x01
)
{
mdelay
(
5
);
if
(
i
++
==
32
)
goto
done
;
}
if
((
tmp
=
nv
_rdi2cr
(
mast
,
chan
->
ctrl
,
0xf7
))
&
0x01
)
{
if
((
tmp
=
nv
km_rdi2cr
(
adap
,
pad
->
addr
,
0xf7
))
&
0x01
)
{
ret
=
-
EIO
;
goto
done
;
}
if
(
type
&
1
)
{
for
(
i
=
0
;
i
<
size
;
i
++
)
buf
[
i
]
=
nv
_rdi2cr
(
mast
,
chan
->
addr
,
0xf0
+
i
);
DBG
(
"%16ph"
,
buf
);
buf
[
i
]
=
nv
km_rdi2cr
(
adap
,
aux
->
addr
,
0xf0
+
i
);
AUX_DBG
(
&
aux
->
base
,
"%16ph"
,
buf
);
memcpy
(
data
,
buf
,
size
);
}
ret
=
0
;
done:
nv
_wri2cr
(
mast
,
chan
->
ctrl
,
0xf7
,
0x01
);
nv
km_wri2cr
(
adap
,
pad
->
addr
,
0xf7
,
0x01
);
return
ret
;
}
static
const
struct
nvkm_i2c_func
anx9805_aux_func
=
{
.
aux
=
anx9805_aux
,
.
lnk_ctl
=
anx9805_train
,
};
static
int
anx9805_aux_chan_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
anx9805_aux_lnk_ctl
(
struct
nvkm_i2c_aux
*
base
,
int
link_nr
,
int
link_bw
,
bool
enh
)
{
struct
nvkm_i2c_port
*
mast
=
(
void
*
)
parent
;
struct
anx9805_i2c_port
*
chan
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_aux_algo
,
&
anx9805_aux_func
,
&
chan
);
*
pobject
=
nv_object
(
chan
);
if
(
ret
)
return
ret
;
switch
((
oclass
->
handle
&
0xff00
)
>>
8
)
{
case
0x0d
:
chan
->
addr
=
0x38
;
chan
->
ctrl
=
0x39
;
break
;
case
0x0e
:
chan
->
addr
=
0x3c
;
chan
->
ctrl
=
0x3b
;
break
;
default:
BUG_ON
(
1
);
}
if
(
mast
->
adapter
.
algo
==
&
i2c_bit_algo
)
{
struct
i2c_algo_bit_data
*
algo
=
mast
->
adapter
.
algo_data
;
algo
->
udelay
=
max
(
algo
->
udelay
,
40
);
}
return
0
;
}
static
struct
nvkm_ofuncs
anx9805_aux_ofuncs
=
{
.
ctor
=
anx9805_aux_chan_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
};
struct
anx9805_aux
*
aux
=
anx9805_aux
(
base
);
struct
anx9805_pad
*
pad
=
aux
->
pad
;
struct
i2c_adapter
*
adap
=
&
pad
->
bus
->
i2c
;
u8
tmp
,
i
;
static
int
anx9805_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
{
struct
anx9805_i2c_port
*
port
=
adap
->
algo_data
;
struct
nvkm_i2c_port
*
mast
=
(
void
*
)
nv_object
(
port
)
->
parent
;
struct
i2c_msg
*
msg
=
msgs
;
int
ret
=
-
ETIMEDOUT
;
int
i
,
j
,
cnt
=
num
;
u8
seg
=
0x00
,
off
=
0x00
,
tmp
;
AUX_DBG
(
&
aux
->
base
,
"ANX9805 train %d %02x %d"
,
link_nr
,
link_bw
,
enh
);
tmp
=
nv_rdi2cr
(
mast
,
port
->
ctrl
,
0x07
)
&
~
0x10
;
nv_wri2cr
(
mast
,
port
->
ctrl
,
0x07
,
tmp
|
0x10
);
nv_wri2cr
(
mast
,
port
->
ctrl
,
0x07
,
tmp
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x43
,
0x05
);
mdelay
(
5
);
nvkm_wri2cr
(
adap
,
aux
->
addr
,
0xa0
,
link_bw
);
nvkm_wri2cr
(
adap
,
aux
->
addr
,
0xa1
,
link_nr
|
(
enh
?
0x80
:
0x00
));
nvkm_wri2cr
(
adap
,
aux
->
addr
,
0xa2
,
0x01
);
nvkm_wri2cr
(
adap
,
aux
->
addr
,
0xa8
,
0x01
);
while
(
cnt
--
)
{
if
(
(
msg
->
flags
&
I2C_M_RD
)
&&
msg
->
addr
==
0x50
)
{
nv_wri2cr
(
mast
,
port
->
addr
,
0x40
,
msg
->
addr
<<
1
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x41
,
seg
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x42
,
off
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x44
,
msg
->
len
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x45
,
0x00
);
nv_wri2cr
(
mast
,
port
->
addr
,
0x43
,
0x01
);
for
(
i
=
0
;
i
<
msg
->
len
;
i
++
)
{
j
=
0
;
while
(
nv_rdi2cr
(
mast
,
port
->
addr
,
0x46
)
&
0x10
)
{
i
=
0
;
while
((
tmp
=
nvkm_rdi2cr
(
adap
,
aux
->
addr
,
0xa8
))
&
0x01
)
{
mdelay
(
5
);
if
(
j
++
==
32
)
goto
done
;
}
msg
->
buf
[
i
]
=
nv_rdi2cr
(
mast
,
port
->
addr
,
0x47
);
}
}
else
if
(
!
(
msg
->
flags
&
I2C_M_RD
))
{
if
(
msg
->
addr
==
0x50
&&
msg
->
len
==
0x01
)
{
off
=
msg
->
buf
[
0
];
}
else
if
(
msg
->
addr
==
0x30
&&
msg
->
len
==
0x01
)
{
seg
=
msg
->
buf
[
0
];
}
else
goto
done
;
}
else
{
goto
done
;
if
(
i
++
==
100
)
{
AUX_ERR
(
&
aux
->
base
,
"link training timeout"
);
return
-
ETIMEDOUT
;
}
msg
++
;
}
ret
=
num
;
done:
nv_wri2cr
(
mast
,
port
->
addr
,
0x43
,
0x00
);
return
ret
;
}
if
(
tmp
&
0x70
)
{
AUX_ERR
(
&
aux
->
base
,
"link training failed"
);
return
-
EIO
;
}
static
u32
anx9805_func
(
struct
i2c_adapter
*
adap
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
return
0
;
}
static
const
struct
i2c_algorithm
anx9805_i2c_algo
=
{
.
master_xfer
=
anx9805_xfer
,
.
functionality
=
anx9805_func
};
static
const
struct
nvkm_i2c_func
anx9805_i2c_func
=
{
static
const
struct
nvkm_i2c_aux_func
anx9805_aux_func
=
{
.
xfer
=
anx9805_aux_xfer
,
.
lnk_ctl
=
anx9805_aux_lnk_ctl
,
};
static
int
anx9805_ddc_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
anx9805_aux_new
(
struct
nvkm_i2c_pad
*
base
,
int
id
,
u8
drive
,
struct
nvkm_i2c_aux
**
pbus
)
{
struct
nvkm_i2c_port
*
mast
=
(
void
*
)
parent
;
struct
anx9805_
i2c_port
*
port
;
struct
anx9805_pad
*
pad
=
anx9805_pad
(
base
)
;
struct
anx9805_
aux
*
aux
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
anx9805_i2c_algo
,
&
anx9805_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
!
(
aux
=
kzalloc
(
sizeof
(
*
aux
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
aux
->
base
;
aux
->
pad
=
pad
;
ret
=
nvkm_i2c_aux_ctor
(
&
anx9805_aux_func
,
&
pad
->
base
,
id
,
&
aux
->
base
);
if
(
ret
)
return
ret
;
switch
((
oclass
->
handle
&
0xff00
)
>>
8
)
{
case
0x0d
:
port
->
addr
=
0x3d
;
port
->
ctrl
=
0x39
;
break
;
case
0x0e
:
port
->
addr
=
0x3f
;
port
->
ctrl
=
0x3b
;
break
;
switch
(
pad
->
addr
)
{
case
0x39
:
aux
->
addr
=
0x38
;
break
;
case
0x3b
:
aux
->
addr
=
0x3c
;
break
;
default:
BUG_ON
(
1
);
}
if
(
mast
->
adapter
.
algo
==
&
i2c_bit_algo
)
{
struct
i2c_algo_bit_data
*
algo
=
mast
->
adapter
.
algo_data
;
algo
->
udelay
=
max
(
algo
->
udelay
,
40
);
return
-
ENOSYS
;
}
return
0
;
}
static
struct
nvkm_ofuncs
anx9805_ddc_ofuncs
=
{
.
ctor
=
anx9805_ddc_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
static
const
struct
nvkm_i2c_pad_func
anx9805_pad_func
=
{
.
bus_new_4
=
anx9805_bus_new
,
.
aux_new_6
=
anx9805_aux_new
,
};
struct
nvkm_oclass
nvkm_anx9805_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_EXTDDC
(
0x0d
),
.
ofuncs
=
&
anx9805_ddc_ofuncs
},
{
.
handle
=
NV_I2C_TYPE_EXTAUX
(
0x0d
),
.
ofuncs
=
&
anx9805_aux_ofuncs
},
{
.
handle
=
NV_I2C_TYPE_EXTDDC
(
0x0e
),
.
ofuncs
=
&
anx9805_ddc_ofuncs
},
{
.
handle
=
NV_I2C_TYPE_EXTAUX
(
0x0e
),
.
ofuncs
=
&
anx9805_aux_ofuncs
},
{}
};
int
anx9805_pad_new
(
struct
nvkm_i2c_bus
*
bus
,
int
id
,
u8
addr
,
struct
nvkm_i2c_pad
**
ppad
)
{
struct
anx9805_pad
*
pad
;
if
(
!
(
pad
=
kzalloc
(
sizeof
(
*
pad
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
ppad
=
&
pad
->
base
;
nvkm_i2c_pad_ctor
(
&
anx9805_pad_func
,
bus
->
pad
->
i2c
,
id
,
&
pad
->
base
);
pad
->
bus
=
bus
;
pad
->
addr
=
addr
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
浏览文件 @
2aa5eac5
...
...
@@ -21,50 +21,17 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
int
nv_rdaux
(
struct
nvkm_i2c_port
*
port
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
if
(
port
->
func
->
aux
)
{
int
ret
=
i2c
->
acquire
(
port
,
0
);
if
(
ret
==
0
)
{
ret
=
port
->
func
->
aux
(
port
,
true
,
9
,
addr
,
data
,
size
);
i2c
->
release
(
port
);
}
return
ret
;
}
return
-
ENODEV
;
}
int
nv_wraux
(
struct
nvkm_i2c_port
*
port
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
if
(
port
->
func
->
aux
)
{
int
ret
=
i2c
->
acquire
(
port
,
0
);
if
(
ret
==
0
)
{
ret
=
port
->
func
->
aux
(
port
,
true
,
8
,
addr
,
data
,
size
);
i2c
->
release
(
port
);
}
return
ret
;
}
return
-
ENODEV
;
}
#include "aux.h"
#include "pad.h"
static
int
aux
_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
nvkm_i2c_aux_i2c
_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
{
struct
nvkm_i2c_port
*
port
=
adap
->
algo_data
;
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
struct
nvkm_i2c_aux
*
aux
=
container_of
(
adap
,
typeof
(
*
aux
),
i2c
);
struct
i2c_msg
*
msg
=
msgs
;
int
ret
,
mcnt
=
num
;
if
(
!
port
->
func
->
aux
)
return
-
ENODEV
;
ret
=
i2c
->
acquire
(
port
,
0
);
ret
=
nvkm_i2c_aux_acquire
(
aux
);
if
(
ret
)
return
ret
;
...
...
@@ -84,9 +51,9 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if
(
mcnt
||
remaining
>
16
)
cmd
|=
4
;
/* MOT */
ret
=
port
->
func
->
aux
(
port
,
true
,
cmd
,
msg
->
addr
,
ptr
,
cnt
);
ret
=
aux
->
func
->
xfer
(
aux
,
true
,
cmd
,
msg
->
addr
,
ptr
,
cnt
);
if
(
ret
<
0
)
{
i2c
->
release
(
port
);
nvkm_i2c_aux_release
(
aux
);
return
ret
;
}
...
...
@@ -97,17 +64,111 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
msg
++
;
}
i2c
->
release
(
port
);
nvkm_i2c_aux_release
(
aux
);
return
num
;
}
static
u32
aux
_func
(
struct
i2c_adapter
*
adap
)
nvkm_i2c_aux_i2c
_func
(
struct
i2c_adapter
*
adap
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
}
const
struct
i2c_algorithm
nvkm_i2c_aux_algo
=
{
.
master_xfer
=
aux_xfer
,
.
functionality
=
aux_func
const
struct
i2c_algorithm
nvkm_i2c_aux_i2c_algo
=
{
.
master_xfer
=
nvkm_i2c_aux_i2c_xfer
,
.
functionality
=
nvkm_i2c_aux_i2c_func
};
void
nvkm_i2c_aux_monitor
(
struct
nvkm_i2c_aux
*
aux
,
bool
monitor
)
{
struct
nvkm_i2c_pad
*
pad
=
aux
->
pad
;
AUX_TRACE
(
aux
,
"monitor: %s"
,
monitor
?
"yes"
:
"no"
);
if
(
monitor
)
nvkm_i2c_pad_mode
(
pad
,
NVKM_I2C_PAD_AUX
);
else
nvkm_i2c_pad_mode
(
pad
,
NVKM_I2C_PAD_OFF
);
}
void
nvkm_i2c_aux_release
(
struct
nvkm_i2c_aux
*
aux
)
{
struct
nvkm_i2c_pad
*
pad
=
aux
->
pad
;
AUX_TRACE
(
aux
,
"release"
);
nvkm_i2c_pad_release
(
pad
);
mutex_unlock
(
&
aux
->
mutex
);
}
int
nvkm_i2c_aux_acquire
(
struct
nvkm_i2c_aux
*
aux
)
{
struct
nvkm_i2c_pad
*
pad
=
aux
->
pad
;
int
ret
;
AUX_TRACE
(
aux
,
"acquire"
);
mutex_lock
(
&
aux
->
mutex
);
ret
=
nvkm_i2c_pad_acquire
(
pad
,
NVKM_I2C_PAD_AUX
);
if
(
ret
)
mutex_unlock
(
&
aux
->
mutex
);
return
ret
;
}
int
nvkm_i2c_aux_xfer
(
struct
nvkm_i2c_aux
*
aux
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
return
aux
->
func
->
xfer
(
aux
,
retry
,
type
,
addr
,
data
,
size
);
}
int
nvkm_i2c_aux_lnk_ctl
(
struct
nvkm_i2c_aux
*
aux
,
int
nr
,
int
bw
,
bool
ef
)
{
if
(
aux
->
func
->
lnk_ctl
)
return
aux
->
func
->
lnk_ctl
(
aux
,
nr
,
bw
,
ef
);
return
-
ENODEV
;
}
void
nvkm_i2c_aux_del
(
struct
nvkm_i2c_aux
**
paux
)
{
struct
nvkm_i2c_aux
*
aux
=
*
paux
;
if
(
aux
&&
!
WARN_ON
(
!
aux
->
func
))
{
AUX_TRACE
(
aux
,
"dtor"
);
list_del
(
&
aux
->
head
);
i2c_del_adapter
(
&
aux
->
i2c
);
kfree
(
*
paux
);
*
paux
=
NULL
;
}
}
int
nvkm_i2c_aux_ctor
(
const
struct
nvkm_i2c_aux_func
*
func
,
struct
nvkm_i2c_pad
*
pad
,
int
id
,
struct
nvkm_i2c_aux
*
aux
)
{
struct
nvkm_device
*
device
=
pad
->
i2c
->
subdev
.
device
;
aux
->
func
=
func
;
aux
->
pad
=
pad
;
aux
->
id
=
id
;
mutex_init
(
&
aux
->
mutex
);
list_add_tail
(
&
aux
->
head
,
&
pad
->
i2c
->
aux
);
AUX_TRACE
(
aux
,
"ctor"
);
snprintf
(
aux
->
i2c
.
name
,
sizeof
(
aux
->
i2c
.
name
),
"nvkm-%s-aux-%04x"
,
dev_name
(
device
->
dev
),
id
);
aux
->
i2c
.
owner
=
THIS_MODULE
;
aux
->
i2c
.
dev
.
parent
=
device
->
dev
;
aux
->
i2c
.
algo
=
&
nvkm_i2c_aux_i2c_algo
;
return
i2c_add_adapter
(
&
aux
->
i2c
);
}
int
nvkm_i2c_aux_new_
(
const
struct
nvkm_i2c_aux_func
*
func
,
struct
nvkm_i2c_pad
*
pad
,
int
id
,
struct
nvkm_i2c_aux
**
paux
)
{
if
(
!
(
*
paux
=
kzalloc
(
sizeof
(
**
paux
),
GFP_KERNEL
)))
return
-
ENOMEM
;
return
nvkm_i2c_aux_ctor
(
func
,
pad
,
id
,
*
paux
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
0 → 100644
浏览文件 @
2aa5eac5
#ifndef __NVKM_I2C_AUX_H__
#define __NVKM_I2C_AUX_H__
#include "pad.h"
struct
nvkm_i2c_aux_func
{
int
(
*
xfer
)(
struct
nvkm_i2c_aux
*
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
);
int
(
*
lnk_ctl
)(
struct
nvkm_i2c_aux
*
,
int
link_nr
,
int
link_bw
,
bool
enhanced_framing
);
};
int
nvkm_i2c_aux_ctor
(
const
struct
nvkm_i2c_aux_func
*
,
struct
nvkm_i2c_pad
*
,
int
id
,
struct
nvkm_i2c_aux
*
);
int
nvkm_i2c_aux_new_
(
const
struct
nvkm_i2c_aux_func
*
,
struct
nvkm_i2c_pad
*
,
int
id
,
struct
nvkm_i2c_aux
**
);
void
nvkm_i2c_aux_del
(
struct
nvkm_i2c_aux
**
);
int
nvkm_i2c_aux_xfer
(
struct
nvkm_i2c_aux
*
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
);
int
g94_i2c_aux_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
struct
nvkm_i2c_aux
**
);
int
gm204_i2c_aux_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
struct
nvkm_i2c_aux
**
);
#define AUX_MSG(b,l,f,a...) do { \
struct nvkm_i2c_aux *_aux = (b); \
nvkm_##l(&_aux->pad->i2c->subdev, "aux %04x: "f"\n", _aux->id, ##a); \
} while(0)
#define AUX_ERR(b,f,a...) AUX_MSG((b), error, f, ##a)
#define AUX_DBG(b,f,a...) AUX_MSG((b), debug, f, ##a)
#define AUX_TRACE(b,f,a...) AUX_MSG((b), trace, f, ##a)
#endif
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define g94_i2c_aux(p) container_of((p), struct g94_i2c_aux, base)
#include "aux.h"
struct
g94_i2c_aux
{
struct
nvkm_i2c_aux
base
;
int
ch
;
};
static
void
g94_i2c_aux_fini
(
struct
g94_i2c_aux
*
aux
)
{
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
0x00e4e4
+
(
aux
->
ch
*
0x50
),
0x00310000
,
0x00000000
);
}
static
int
g94_i2c_aux_init
(
struct
g94_i2c_aux
*
aux
)
{
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
const
u32
unksel
=
1
;
/* nfi which to use, or if it matters.. */
const
u32
ureq
=
unksel
?
0x00100000
:
0x00200000
;
const
u32
urep
=
unksel
?
0x01000000
:
0x02000000
;
u32
ctrl
,
timeout
;
/* wait up to 1ms for any previous transaction to be done... */
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
aux
->
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"begin idle timeout %08x"
,
ctrl
);
return
-
EBUSY
;
}
}
while
(
ctrl
&
0x03010000
);
/* set some magic, and wait up to 1ms for it to appear */
nvkm_mask
(
device
,
0x00e4e4
+
(
aux
->
ch
*
0x50
),
0x00300000
,
ureq
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
aux
->
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"magic wait %08x"
,
ctrl
);
g94_i2c_aux_fini
(
aux
);
return
-
EBUSY
;
}
}
while
((
ctrl
&
0x03000000
)
!=
urep
);
return
0
;
}
static
int
g94_i2c_aux_xfer
(
struct
nvkm_i2c_aux
*
obj
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
g94_i2c_aux
*
aux
=
g94_i2c_aux
(
obj
);
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
const
u32
base
=
aux
->
ch
*
0x50
;
u32
ctrl
,
stat
,
timeout
,
retries
;
u32
xbuf
[
4
]
=
{};
int
ret
,
i
;
AUX_TRACE
(
&
aux
->
base
,
"%d: %08x %d"
,
type
,
addr
,
size
);
ret
=
g94_i2c_aux_init
(
aux
);
if
(
ret
<
0
)
goto
out
;
stat
=
nvkm_rd32
(
device
,
0x00e4e8
+
base
);
if
(
!
(
stat
&
0x10000000
))
{
AUX_TRACE
(
&
aux
->
base
,
"sink not detected"
);
ret
=
-
ENXIO
;
goto
out
;
}
if
(
!
(
type
&
1
))
{
memcpy
(
xbuf
,
data
,
size
);
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
AUX_TRACE
(
&
aux
->
base
,
"wr %08x"
,
xbuf
[
i
/
4
]);
nvkm_wr32
(
device
,
0x00e4c0
+
base
+
i
,
xbuf
[
i
/
4
]);
}
}
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
base
);
ctrl
&=
~
0x0001f0ff
;
ctrl
|=
type
<<
12
;
ctrl
|=
size
-
1
;
nvkm_wr32
(
device
,
0x00e4e0
+
base
,
addr
);
/* (maybe) retry transaction a number of times on failure... */
for
(
retries
=
0
;
!
ret
&&
retries
<
32
;
retries
++
)
{
/* reset, and delay a while if this is a retry */
nvkm_wr32
(
device
,
0x00e4e4
+
base
,
0x80000000
|
ctrl
);
nvkm_wr32
(
device
,
0x00e4e4
+
base
,
0x00000000
|
ctrl
);
if
(
retries
)
udelay
(
400
);
/* transaction request, wait up to 1ms for it to complete */
nvkm_wr32
(
device
,
0x00e4e4
+
base
,
0x00010000
|
ctrl
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
base
);
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"timeout %08x"
,
ctrl
);
ret
=
-
EIO
;
goto
out
;
}
}
while
(
ctrl
&
0x00010000
);
ret
=
1
;
/* read status, and check if transaction completed ok */
stat
=
nvkm_mask
(
device
,
0x00e4e8
+
base
,
0
,
0
);
if
((
stat
&
0x000f0000
)
==
0x00080000
||
(
stat
&
0x000f0000
)
==
0x00020000
)
ret
=
retry
?
0
:
1
;
if
((
stat
&
0x00000100
))
ret
=
-
ETIMEDOUT
;
if
((
stat
&
0x00000e00
))
ret
=
-
EIO
;
AUX_TRACE
(
&
aux
->
base
,
"%02d %08x %08x"
,
retries
,
ctrl
,
stat
);
}
if
(
type
&
1
)
{
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
xbuf
[
i
/
4
]
=
nvkm_rd32
(
device
,
0x00e4d0
+
base
+
i
);
AUX_TRACE
(
&
aux
->
base
,
"rd %08x"
,
xbuf
[
i
/
4
]);
}
memcpy
(
data
,
xbuf
,
size
);
}
out:
g94_i2c_aux_fini
(
aux
);
return
ret
<
0
?
ret
:
(
stat
&
0x000f0000
)
>>
16
;
}
static
const
struct
nvkm_i2c_aux_func
g94_i2c_aux_func
=
{
.
xfer
=
g94_i2c_aux_xfer
,
};
int
g94_i2c_aux_new
(
struct
nvkm_i2c_pad
*
pad
,
int
index
,
u8
drive
,
struct
nvkm_i2c_aux
**
paux
)
{
struct
g94_i2c_aux
*
aux
;
if
(
!
(
aux
=
kzalloc
(
sizeof
(
*
aux
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
paux
=
&
aux
->
base
;
nvkm_i2c_aux_ctor
(
&
g94_i2c_aux_func
,
pad
,
index
,
&
aux
->
base
);
aux
->
ch
=
drive
;
aux
->
base
.
intr
=
1
<<
aux
->
ch
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define gm204_i2c_aux(p) container_of((p), struct gm204_i2c_aux, base)
#include "aux.h"
struct
gm204_i2c_aux
{
struct
nvkm_i2c_aux
base
;
int
ch
;
};
static
void
gm204_i2c_aux_fini
(
struct
gm204_i2c_aux
*
aux
)
{
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
0x00d954
+
(
aux
->
ch
*
0x50
),
0x00310000
,
0x00000000
);
}
static
int
gm204_i2c_aux_init
(
struct
gm204_i2c_aux
*
aux
)
{
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
const
u32
unksel
=
1
;
/* nfi which to use, or if it matters.. */
const
u32
ureq
=
unksel
?
0x00100000
:
0x00200000
;
const
u32
urep
=
unksel
?
0x01000000
:
0x02000000
;
u32
ctrl
,
timeout
;
/* wait up to 1ms for any previous transaction to be done... */
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
aux
->
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"begin idle timeout %08x"
,
ctrl
);
return
-
EBUSY
;
}
}
while
(
ctrl
&
0x03010000
);
/* set some magic, and wait up to 1ms for it to appear */
nvkm_mask
(
device
,
0x00d954
+
(
aux
->
ch
*
0x50
),
0x00300000
,
ureq
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
aux
->
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"magic wait %08x"
,
ctrl
);
gm204_i2c_aux_fini
(
aux
);
return
-
EBUSY
;
}
}
while
((
ctrl
&
0x03000000
)
!=
urep
);
return
0
;
}
static
int
gm204_i2c_aux_xfer
(
struct
nvkm_i2c_aux
*
obj
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
gm204_i2c_aux
*
aux
=
gm204_i2c_aux
(
obj
);
struct
nvkm_device
*
device
=
aux
->
base
.
pad
->
i2c
->
subdev
.
device
;
const
u32
base
=
aux
->
ch
*
0x50
;
u32
ctrl
,
stat
,
timeout
,
retries
;
u32
xbuf
[
4
]
=
{};
int
ret
,
i
;
AUX_TRACE
(
&
aux
->
base
,
"%d: %08x %d"
,
type
,
addr
,
size
);
ret
=
gm204_i2c_aux_init
(
aux
);
if
(
ret
<
0
)
goto
out
;
stat
=
nvkm_rd32
(
device
,
0x00d958
+
base
);
if
(
!
(
stat
&
0x10000000
))
{
AUX_TRACE
(
&
aux
->
base
,
"sink not detected"
);
ret
=
-
ENXIO
;
goto
out
;
}
if
(
!
(
type
&
1
))
{
memcpy
(
xbuf
,
data
,
size
);
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
AUX_TRACE
(
&
aux
->
base
,
"wr %08x"
,
xbuf
[
i
/
4
]);
nvkm_wr32
(
device
,
0x00d930
+
base
+
i
,
xbuf
[
i
/
4
]);
}
}
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
base
);
ctrl
&=
~
0x0001f0ff
;
ctrl
|=
type
<<
12
;
ctrl
|=
size
-
1
;
nvkm_wr32
(
device
,
0x00d950
+
base
,
addr
);
/* (maybe) retry transaction a number of times on failure... */
for
(
retries
=
0
;
!
ret
&&
retries
<
32
;
retries
++
)
{
/* reset, and delay a while if this is a retry */
nvkm_wr32
(
device
,
0x00d954
+
base
,
0x80000000
|
ctrl
);
nvkm_wr32
(
device
,
0x00d954
+
base
,
0x00000000
|
ctrl
);
if
(
retries
)
udelay
(
400
);
/* transaction request, wait up to 1ms for it to complete */
nvkm_wr32
(
device
,
0x00d954
+
base
,
0x00010000
|
ctrl
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
base
);
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
&
aux
->
base
,
"timeout %08x"
,
ctrl
);
ret
=
-
EIO
;
goto
out
;
}
}
while
(
ctrl
&
0x00010000
);
ret
=
1
;
/* read status, and check if transaction completed ok */
stat
=
nvkm_mask
(
device
,
0x00d958
+
base
,
0
,
0
);
if
((
stat
&
0x000f0000
)
==
0x00080000
||
(
stat
&
0x000f0000
)
==
0x00020000
)
ret
=
retry
?
0
:
1
;
if
((
stat
&
0x00000100
))
ret
=
-
ETIMEDOUT
;
if
((
stat
&
0x00000e00
))
ret
=
-
EIO
;
AUX_TRACE
(
&
aux
->
base
,
"%02d %08x %08x"
,
retries
,
ctrl
,
stat
);
}
if
(
type
&
1
)
{
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
xbuf
[
i
/
4
]
=
nvkm_rd32
(
device
,
0x00d940
+
base
+
i
);
AUX_TRACE
(
&
aux
->
base
,
"rd %08x"
,
xbuf
[
i
/
4
]);
}
memcpy
(
data
,
xbuf
,
size
);
}
out:
gm204_i2c_aux_fini
(
aux
);
return
ret
<
0
?
ret
:
(
stat
&
0x000f0000
)
>>
16
;
}
static
const
struct
nvkm_i2c_aux_func
gm204_i2c_aux_func
=
{
.
xfer
=
gm204_i2c_aux_xfer
,
};
int
gm204_i2c_aux_new
(
struct
nvkm_i2c_pad
*
pad
,
int
index
,
u8
drive
,
struct
nvkm_i2c_aux
**
paux
)
{
struct
gm204_i2c_aux
*
aux
;
if
(
!
(
aux
=
kzalloc
(
sizeof
(
*
aux
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
paux
=
&
aux
->
base
;
nvkm_i2c_aux_ctor
(
&
gm204_i2c_aux_func
,
pad
,
index
,
&
aux
->
base
);
aux
->
ch
=
drive
;
aux
->
base
.
intr
=
1
<<
aux
->
ch
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
浏览文件 @
2aa5eac5
...
...
@@ -22,325 +22,88 @@
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "aux.h"
#include "bus.h"
#include "pad.h"
#include <core/notify.h>
#include <core/option.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/i2c.h>
/******************************************************************************
* interface to linux i2c bit-banging algorithm
*****************************************************************************/
#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
#define CSTMSEL true
#else
#define CSTMSEL false
#endif
static
int
nvkm_i2c_pre_xfer
(
struct
i2c_adapter
*
adap
)
{
struct
i2c_algo_bit_data
*
bit
=
adap
->
algo_data
;
struct
nvkm_i2c_port
*
port
=
bit
->
data
;
return
nvkm_i2c
(
port
)
->
acquire
(
port
,
bit
->
timeout
);
}
static
void
nvkm_i2c_post_xfer
(
struct
i2c_adapter
*
adap
)
{
struct
i2c_algo_bit_data
*
bit
=
adap
->
algo_data
;
struct
nvkm_i2c_port
*
port
=
bit
->
data
;
return
nvkm_i2c
(
port
)
->
release
(
port
);
}
static
void
nvkm_i2c_setscl
(
void
*
data
,
int
state
)
{
struct
nvkm_i2c_port
*
port
=
data
;
port
->
func
->
drive_scl
(
port
,
state
);
}
static
void
nvkm_i2c_setsda
(
void
*
data
,
int
state
)
{
struct
nvkm_i2c_port
*
port
=
data
;
port
->
func
->
drive_sda
(
port
,
state
);
}
static
int
nvkm_i2c_getscl
(
void
*
data
)
{
struct
nvkm_i2c_port
*
port
=
data
;
return
port
->
func
->
sense_scl
(
port
);
}
static
int
nvkm_i2c_getsda
(
void
*
data
)
{
struct
nvkm_i2c_port
*
port
=
data
;
return
port
->
func
->
sense_sda
(
port
);
}
/******************************************************************************
* base i2c "port" class implementation
*****************************************************************************/
int
_nvkm_i2c_port_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
{
struct
nvkm_i2c_port
*
port
=
(
void
*
)
object
;
struct
nvkm_i2c_pad
*
pad
=
nvkm_i2c_pad
(
port
);
nv_ofuncs
(
pad
)
->
fini
(
nv_object
(
pad
),
suspend
);
return
nvkm_object_fini
(
&
port
->
base
,
suspend
);
}
void
_nvkm_i2c_port_dtor
(
struct
nvkm_object
*
object
)
{
struct
nvkm_i2c_port
*
port
=
(
void
*
)
object
;
i2c_del_adapter
(
&
port
->
adapter
);
nvkm_object_destroy
(
&
port
->
base
);
}
int
nvkm_i2c_port_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
u8
index
,
const
struct
i2c_algorithm
*
algo
,
const
struct
nvkm_i2c_func
*
func
,
int
size
,
void
**
pobject
)
static
struct
nvkm_i2c_pad
*
nvkm_i2c_pad_find
(
struct
nvkm_i2c
*
i2c
,
int
id
)
{
struct
nvkm_device
*
device
=
nv_device
(
parent
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
parent
);
struct
nvkm_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_object_create_
(
parent
,
engine
,
oclass
,
0
,
size
,
pobject
);
port
=
*
pobject
;
if
(
ret
)
return
ret
;
struct
nvkm_i2c_pad
*
pad
;
snprintf
(
port
->
adapter
.
name
,
sizeof
(
port
->
adapter
.
name
),
"nvkm-%s-%d"
,
device
->
name
,
index
);
port
->
adapter
.
owner
=
THIS_MODULE
;
port
->
adapter
.
dev
.
parent
=
nv_device_base
(
device
);
port
->
index
=
index
;
port
->
aux
=
-
1
;
port
->
func
=
func
;
mutex_init
(
&
port
->
mutex
);
if
(
algo
==
&
nvkm_i2c_bit_algo
&&
!
nvkm_boolopt
(
device
->
cfgopt
,
"NvI2C"
,
CSTMSEL
))
{
struct
i2c_algo_bit_data
*
bit
;
bit
=
kzalloc
(
sizeof
(
*
bit
),
GFP_KERNEL
);
if
(
!
bit
)
return
-
ENOMEM
;
bit
->
udelay
=
10
;
bit
->
timeout
=
usecs_to_jiffies
(
2200
);
bit
->
data
=
port
;
bit
->
pre_xfer
=
nvkm_i2c_pre_xfer
;
bit
->
post_xfer
=
nvkm_i2c_post_xfer
;
bit
->
setsda
=
nvkm_i2c_setsda
;
bit
->
setscl
=
nvkm_i2c_setscl
;
bit
->
getsda
=
nvkm_i2c_getsda
;
bit
->
getscl
=
nvkm_i2c_getscl
;
port
->
adapter
.
algo_data
=
bit
;
ret
=
i2c_bit_add_bus
(
&
port
->
adapter
);
}
else
{
port
->
adapter
.
algo_data
=
port
;
port
->
adapter
.
algo
=
algo
;
ret
=
i2c_add_adapter
(
&
port
->
adapter
);
list_for_each_entry
(
pad
,
&
i2c
->
pad
,
head
)
{
if
(
pad
->
id
==
id
)
return
pad
;
}
if
(
ret
==
0
)
list_add_tail
(
&
port
->
head
,
&
i2c
->
ports
);
return
ret
;
return
NULL
;
}
/******************************************************************************
* base i2c subdev class implementation
*****************************************************************************/
static
struct
nvkm_i2c_port
*
nvkm_i2c_find
(
struct
nvkm_i2c
*
i2c
,
u8
index
)
struct
nvkm_i2c_bus
*
nvkm_i2c_bus_find
(
struct
nvkm_i2c
*
i2c
,
int
id
)
{
struct
nvkm_bios
*
bios
=
nvkm_bios
(
i2c
)
;
struct
nvkm_i2c_
port
*
port
;
struct
nvkm_bios
*
bios
=
i2c
->
subdev
.
device
->
bios
;
struct
nvkm_i2c_
bus
*
bus
;
if
(
index
==
NV_I2C_DEFAULT
(
0
)
||
index
==
NV_I2C_DEFAULT
(
1
))
{
if
(
id
==
NVKM_I2C_BUS_PRI
||
id
==
NVKM_I2C_BUS_SEC
)
{
u8
ver
,
hdr
,
cnt
,
len
;
u16
i2c
=
dcb_i2c_table
(
bios
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
);
if
(
i2c
&&
ver
>=
0x30
)
{
u8
auxidx
=
nvbios_rd08
(
bios
,
i2c
+
4
);
if
(
i
ndex
==
NV_I2C_DEFAULT
(
0
)
)
i
ndex
=
(
auxidx
&
0x0f
)
>>
0
;
if
(
i
d
==
NVKM_I2C_BUS_PRI
)
i
d
=
NVKM_I2C_BUS_CCB
((
auxidx
&
0x0f
)
>>
0
)
;
else
i
ndex
=
(
auxidx
&
0xf0
)
>>
4
;
i
d
=
NVKM_I2C_BUS_CCB
((
auxidx
&
0xf0
)
>>
4
)
;
}
else
{
i
ndex
=
2
;
i
d
=
NVKM_I2C_BUS_CCB
(
2
)
;
}
}
list_for_each_entry
(
port
,
&
i2c
->
port
s
,
head
)
{
if
(
port
->
index
==
index
)
return
port
;
list_for_each_entry
(
bus
,
&
i2c
->
bu
s
,
head
)
{
if
(
bus
->
id
==
id
)
return
bus
;
}
return
NULL
;
}
st
atic
struct
nvkm_i2c_port
*
nvkm_i2c_
find_type
(
struct
nvkm_i2c
*
i2c
,
u16
type
)
st
ruct
nvkm_i2c_aux
*
nvkm_i2c_
aux_find
(
struct
nvkm_i2c
*
i2c
,
int
id
)
{
struct
nvkm_i2c_
port
*
port
;
struct
nvkm_i2c_
aux
*
aux
;
list_for_each_entry
(
port
,
&
i2c
->
ports
,
head
)
{
if
(
nv_hclass
(
port
)
==
type
)
return
port
;
list_for_each_entry
(
aux
,
&
i2c
->
aux
,
head
)
{
if
(
aux
->
id
==
id
)
return
aux
;
}
return
NULL
;
}
static
void
nvkm_i2c_release_pad
(
struct
nvkm_i2c_port
*
port
)
{
struct
nvkm_i2c_pad
*
pad
=
nvkm_i2c_pad
(
port
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
if
(
atomic_dec_and_test
(
&
nv_object
(
pad
)
->
usecount
))
{
nv_ofuncs
(
pad
)
->
fini
(
nv_object
(
pad
),
false
);
wake_up_all
(
&
i2c
->
wait
);
}
}
static
int
nvkm_i2c_try_acquire_pad
(
struct
nvkm_i2c_port
*
port
)
{
struct
nvkm_i2c_pad
*
pad
=
nvkm_i2c_pad
(
port
);
if
(
atomic_add_return
(
1
,
&
nv_object
(
pad
)
->
usecount
)
!=
1
)
{
struct
nvkm_object
*
owner
=
(
void
*
)
pad
->
port
;
do
{
if
(
owner
==
(
void
*
)
port
)
return
0
;
owner
=
owner
->
parent
;
}
while
(
owner
);
nvkm_i2c_release_pad
(
port
);
return
-
EBUSY
;
}
pad
->
next
=
port
;
nv_ofuncs
(
pad
)
->
init
(
nv_object
(
pad
));
return
0
;
}
static
int
nvkm_i2c_acquire_pad
(
struct
nvkm_i2c_port
*
port
,
unsigned
long
timeout
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
port
);
if
(
timeout
)
{
if
(
wait_event_timeout
(
i2c
->
wait
,
nvkm_i2c_try_acquire_pad
(
port
)
==
0
,
timeout
)
==
0
)
return
-
EBUSY
;
}
else
{
wait_event
(
i2c
->
wait
,
nvkm_i2c_try_acquire_pad
(
port
)
==
0
);
}
return
0
;
}
static
void
nvkm_i2c_release
(
struct
nvkm_i2c_port
*
port
)
__releases
(
pad
->
mutex
)
{
nvkm_i2c
(
port
)
->
release_pad
(
port
);
mutex_unlock
(
&
port
->
mutex
);
}
static
int
nvkm_i2c_acquire
(
struct
nvkm_i2c_port
*
port
,
unsigned
long
timeout
)
__acquires
(
pad
->
mutex
)
{
int
ret
;
mutex_lock
(
&
port
->
mutex
);
if
((
ret
=
nvkm_i2c
(
port
)
->
acquire_pad
(
port
,
timeout
)))
mutex_unlock
(
&
port
->
mutex
);
return
ret
;
}
static
int
nvkm_i2c_identify
(
struct
nvkm_i2c
*
i2c
,
int
index
,
const
char
*
what
,
struct
nvkm_i2c_board_info
*
info
,
bool
(
*
match
)(
struct
nvkm_i2c_port
*
,
struct
i2c_board_info
*
,
void
*
),
void
*
data
)
{
struct
nvkm_subdev
*
subdev
=
&
i2c
->
subdev
;
struct
nvkm_i2c_port
*
port
=
nvkm_i2c_find
(
i2c
,
index
);
int
i
;
if
(
!
port
)
{
nvkm_debug
(
subdev
,
"no bus when probing %s on %d
\n
"
,
what
,
index
);
return
-
ENODEV
;
}
nvkm_debug
(
subdev
,
"probing %ss on bus: %d
\n
"
,
what
,
port
->
index
);
for
(
i
=
0
;
info
[
i
].
dev
.
addr
;
i
++
)
{
u8
orig_udelay
=
0
;
if
((
port
->
adapter
.
algo
==
&
i2c_bit_algo
)
&&
(
info
[
i
].
udelay
!=
0
))
{
struct
i2c_algo_bit_data
*
algo
=
port
->
adapter
.
algo_data
;
nvkm_debug
(
subdev
,
"using custom udelay %d instead of %d
\n
"
,
info
[
i
].
udelay
,
algo
->
udelay
);
orig_udelay
=
algo
->
udelay
;
algo
->
udelay
=
info
[
i
].
udelay
;
}
if
(
nv_probe_i2c
(
port
,
info
[
i
].
dev
.
addr
)
&&
(
!
match
||
match
(
port
,
&
info
[
i
].
dev
,
data
)))
{
nvkm_info
(
subdev
,
"detected %s: %s
\n
"
,
what
,
info
[
i
].
dev
.
type
);
return
i
;
}
if
(
orig_udelay
)
{
struct
i2c_algo_bit_data
*
algo
=
port
->
adapter
.
algo_data
;
algo
->
udelay
=
orig_udelay
;
}
}
nvkm_debug
(
subdev
,
"no devices found.
\n
"
);
return
-
ENODEV
;
}
static
void
nvkm_i2c_intr_fini
(
struct
nvkm_event
*
event
,
int
type
,
int
index
)
nvkm_i2c_intr_fini
(
struct
nvkm_event
*
event
,
int
type
,
int
id
)
{
struct
nvkm_i2c
*
i2c
=
container_of
(
event
,
typeof
(
*
i2c
),
event
);
struct
nvkm_i2c_
port
*
port
=
i2c
->
find
(
i2c
,
index
);
struct
nvkm_i2c_
aux
*
aux
=
nvkm_i2c_aux_find
(
i2c
,
id
);
const
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
nv_object
(
i2c
)
->
oclass
;
if
(
port
&&
port
->
aux
>=
0
)
impl
->
aux_mask
(
i2c
,
type
,
1
<<
port
->
aux
,
0
);
if
(
aux
)
impl
->
aux_mask
(
i2c
,
type
,
aux
->
intr
,
0
);
}
static
void
nvkm_i2c_intr_init
(
struct
nvkm_event
*
event
,
int
type
,
int
i
ndex
)
nvkm_i2c_intr_init
(
struct
nvkm_event
*
event
,
int
type
,
int
i
d
)
{
struct
nvkm_i2c
*
i2c
=
container_of
(
event
,
typeof
(
*
i2c
),
event
);
struct
nvkm_i2c_
port
*
port
=
i2c
->
find
(
i2c
,
index
);
struct
nvkm_i2c_
aux
*
aux
=
nvkm_i2c_aux_find
(
i2c
,
id
);
const
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
nv_object
(
i2c
)
->
oclass
;
if
(
port
&&
port
->
aux
>=
0
)
impl
->
aux_mask
(
i2c
,
type
,
1
<<
port
->
aux
,
1
<<
port
->
aux
);
if
(
aux
)
impl
->
aux_mask
(
i2c
,
type
,
aux
->
intr
,
aux
->
intr
);
}
static
int
...
...
@@ -358,33 +121,32 @@ nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size,
}
static
void
nvkm_i2c_intr
(
struct
nvkm_subdev
*
subdev
)
nvkm_i2c_intr
(
struct
nvkm_subdev
*
obj
)
{
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
nv_oclass
(
subdev
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
subdev
);
struct
nvkm_i2c_port
*
port
;
u32
hi
,
lo
,
rq
,
tx
,
e
;
struct
nvkm_i2c
*
i2c
=
container_of
(
obj
,
typeof
(
*
i2c
),
subdev
);
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
i2c
->
subdev
.
object
.
oclass
;
struct
nvkm_i2c_aux
*
aux
;
u32
hi
,
lo
,
rq
,
tx
;
if
(
!
impl
->
aux_stat
)
return
;
if
(
impl
->
aux_stat
)
{
impl
->
aux_stat
(
i2c
,
&
hi
,
&
lo
,
&
rq
,
&
tx
);
if
(
hi
||
lo
||
rq
||
tx
)
{
list_for_each_entry
(
port
,
&
i2c
->
ports
,
head
)
{
if
(
e
=
0
,
port
->
aux
<
0
)
continue
;
if
(
!
hi
&&
!
lo
&&
!
rq
&&
!
tx
)
return
;
if
(
hi
&
(
1
<<
port
->
aux
))
e
|=
NVKM_I2C_PLUG
;
if
(
lo
&
(
1
<<
port
->
aux
))
e
|=
NVKM_I2C_UNPLUG
;
if
(
rq
&
(
1
<<
port
->
aux
))
e
|=
NVKM_I2C_IRQ
;
if
(
tx
&
(
1
<<
port
->
aux
))
e
|=
NVKM_I2C_DONE
;
if
(
e
)
{
list_for_each_entry
(
aux
,
&
i2c
->
aux
,
head
)
{
u32
mask
=
0
;
if
(
hi
&
aux
->
intr
)
mask
|=
NVKM_I2C_PLUG
;
if
(
lo
&
aux
->
intr
)
mask
|=
NVKM_I2C_UNPLUG
;
if
(
rq
&
aux
->
intr
)
mask
|=
NVKM_I2C_IRQ
;
if
(
tx
&
aux
->
intr
)
mask
|=
NVKM_I2C_DONE
;
if
(
mask
)
{
struct
nvkm_i2c_ntfy_rep
rep
=
{
.
mask
=
e
,
.
mask
=
mask
,
};
nvkm_event_send
(
&
i2c
->
event
,
rep
.
mask
,
port
->
index
,
&
rep
,
sizeof
(
rep
));
}
}
nvkm_event_send
(
&
i2c
->
event
,
rep
.
mask
,
aux
->
id
,
&
rep
,
sizeof
(
rep
));
}
}
}
...
...
@@ -401,206 +163,241 @@ _nvkm_i2c_fini(struct nvkm_object *object, bool suspend)
{
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
nv_oclass
(
object
);
struct
nvkm_i2c
*
i2c
=
(
void
*
)
object
;
struct
nvkm_i2c_p
ort
*
port
;
struct
nvkm_i2c_p
ad
*
pad
;
u32
mask
;
int
ret
;
list_for_each_entry
(
port
,
&
i2c
->
ports
,
head
)
{
ret
=
nv_ofuncs
(
port
)
->
fini
(
nv_object
(
port
),
suspend
);
if
(
ret
&&
suspend
)
goto
fail
;
}
if
((
mask
=
(
1
<<
impl
->
aux
)
-
1
),
impl
->
aux_stat
)
{
impl
->
aux_mask
(
i2c
,
NVKM_I2C_ANY
,
mask
,
0
);
impl
->
aux_stat
(
i2c
,
&
mask
,
&
mask
,
&
mask
,
&
mask
);
}
return
nvkm_subdev_fini
(
&
i2c
->
subdev
,
suspend
);
fail:
list_for_each_entry_continue_reverse
(
port
,
&
i2c
->
ports
,
head
)
{
nv_ofuncs
(
port
)
->
init
(
nv_object
(
port
));
list_for_each_entry
(
pad
,
&
i2c
->
pad
,
head
)
{
nvkm_i2c_pad_fini
(
pad
);
}
return
ret
;
return
nvkm_subdev_fini
(
&
i2c
->
subdev
,
suspend
)
;
}
int
_nvkm_i2c_init
(
struct
nvkm_object
*
object
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
object
;
struct
nvkm_i2c_port
*
port
;
struct
nvkm_i2c_bus
*
bus
;
struct
nvkm_i2c_pad
*
pad
;
int
ret
;
ret
=
nvkm_subdev_init
(
&
i2c
->
subdev
);
if
(
ret
==
0
)
{
list_for_each_entry
(
port
,
&
i2c
->
ports
,
head
)
{
ret
=
nv_ofuncs
(
port
)
->
init
(
nv_object
(
port
));
if
(
ret
)
goto
fail
;
}
return
ret
;
list_for_each_entry
(
pad
,
&
i2c
->
pad
,
head
)
{
nvkm_i2c_pad_init
(
pad
);
}
return
ret
;
fail:
list_for_each_entry_continue_reverse
(
port
,
&
i2c
->
ports
,
head
)
{
nv_ofuncs
(
port
)
->
fini
(
nv_object
(
port
),
false
);
list_for_each_entry
(
bus
,
&
i2c
->
bus
,
head
)
{
nvkm_i2c_bus_init
(
bus
);
}
return
ret
;
return
0
;
}
void
_nvkm_i2c_dtor
(
struct
nvkm_object
*
object
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
object
;
struct
nvkm_i2c_port
*
port
,
*
temp
;
nvkm_event_fini
(
&
i2c
->
event
);
list_for_each_entry_safe
(
port
,
temp
,
&
i2c
->
ports
,
head
)
{
nvkm_object_ref
(
NULL
,
(
struct
nvkm_object
**
)
&
port
);
while
(
!
list_empty
(
&
i2c
->
aux
))
{
struct
nvkm_i2c_aux
*
aux
=
list_first_entry
(
&
i2c
->
aux
,
typeof
(
*
aux
),
head
);
nvkm_i2c_aux_del
(
&
aux
);
}
nvkm_subdev_destroy
(
&
i2c
->
subdev
);
}
static
struct
nvkm_oclass
*
nvkm_i2c_extdev_sclass
[]
=
{
nvkm_anx9805_sclass
,
};
static
void
nvkm_i2c_create_port
(
struct
nvkm_i2c
*
i2c
,
int
index
,
u8
type
,
struct
dcb_i2c_entry
*
info
)
{
const
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
nv_oclass
(
i2c
);
struct
nvkm_oclass
*
oclass
;
struct
nvkm_object
*
parent
;
struct
nvkm_object
*
object
;
int
ret
,
pad
;
if
(
info
->
share
!=
DCB_I2C_UNUSED
)
{
pad
=
info
->
share
;
oclass
=
impl
->
pad_s
;
}
else
{
if
(
type
!=
DCB_I2C_NVIO_AUX
)
pad
=
0x100
+
info
->
drive
;
else
pad
=
0x100
+
info
->
auxch
;
oclass
=
impl
->
pad_x
;
while
(
!
list_empty
(
&
i2c
->
bus
))
{
struct
nvkm_i2c_bus
*
bus
=
list_first_entry
(
&
i2c
->
bus
,
typeof
(
*
bus
),
head
);
nvkm_i2c_bus_del
(
&
bus
);
}
ret
=
nvkm_object_ctor
(
nv_object
(
i2c
),
NULL
,
oclass
,
NULL
,
pad
,
&
parent
);
if
(
ret
<
0
)
return
;
oclass
=
impl
->
sclass
;
do
{
ret
=
-
EINVAL
;
if
(
oclass
->
handle
==
type
)
{
ret
=
nvkm_object_ctor
(
parent
,
NULL
,
oclass
,
info
,
index
,
&
object
);
while
(
!
list_empty
(
&
i2c
->
pad
))
{
struct
nvkm_i2c_pad
*
pad
=
list_first_entry
(
&
i2c
->
pad
,
typeof
(
*
pad
),
head
);
nvkm_i2c_pad_del
(
&
pad
);
}
}
while
(
ret
&&
(
++
oclass
)
->
handle
);
nvkm_object_ref
(
NULL
,
&
parent
);
nvkm_subdev_destroy
(
&
i2c
->
subdev
);
}
static
const
struct
nvkm_i2c_drv
{
u8
bios
;
u8
addr
;
int
(
*
pad_new
)(
struct
nvkm_i2c_bus
*
,
int
id
,
u8
addr
,
struct
nvkm_i2c_pad
**
);
}
nvkm_i2c_drv
[]
=
{
{
0x0d
,
0x39
,
anx9805_pad_new
},
{
0x0e
,
0x3b
,
anx9805_pad_new
},
{}
};
int
nvkm_i2c_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
int
length
,
void
**
pobject
)
{
struct
nvkm_bios
*
bios
=
nvkm_bios
(
parent
);
struct
nvkm_i2c_impl
*
impl
=
(
void
*
)
oclass
;
struct
nvkm_device
*
device
=
(
void
*
)
parent
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
struct
nvkm_i2c
*
i2c
;
struct
nvkm_object
*
object
;
struct
dcb_i2c_entry
info
;
int
ret
,
i
,
j
,
index
=
-
1
;
struct
dcb_output
outp
;
struct
dcb_i2c_entry
ccbE
;
struct
dcb_output
dcbE
;
u8
ver
,
hdr
;
u32
data
;
int
ret
,
i
;
ret
=
nvkm_subdev_create
(
parent
,
engine
,
oclass
,
0
,
"I2C"
,
"i2c"
,
&
i2c
);
*
pobject
=
nv_object
(
i2c
);
if
(
ret
)
return
ret
;
INIT_LIST_HEAD
(
&
i2c
->
pad
);
INIT_LIST_HEAD
(
&
i2c
->
bus
);
INIT_LIST_HEAD
(
&
i2c
->
aux
);
nv_subdev
(
i2c
)
->
intr
=
nvkm_i2c_intr
;
i2c
->
find
=
nvkm_i2c_find
;
i2c
->
find_type
=
nvkm_i2c_find_type
;
i2c
->
acquire_pad
=
nvkm_i2c_acquire_pad
;
i2c
->
release_pad
=
nvkm_i2c_release_pad
;
i2c
->
acquire
=
nvkm_i2c_acquire
;
i2c
->
release
=
nvkm_i2c_release
;
i2c
->
identify
=
nvkm_i2c_identify
;
init_waitqueue_head
(
&
i2c
->
wait
);
INIT_LIST_HEAD
(
&
i2c
->
ports
);
while
(
!
dcb_i2c_parse
(
bios
,
++
index
,
&
info
))
{
switch
(
info
.
type
)
{
case
DCB_I2C_NV04_BIT
:
case
DCB_I2C_NV4E_BIT
:
case
DCB_I2C_NVIO_BIT
:
nvkm_i2c_create_port
(
i2c
,
NV_I2C_PORT
(
index
),
info
.
type
,
&
info
);
break
;
case
DCB_I2C_NVIO_AUX
:
nvkm_i2c_create_port
(
i2c
,
NV_I2C_AUX
(
index
),
info
.
type
,
&
info
);
break
;
case
DCB_I2C_PMGR
:
if
(
info
.
drive
!=
DCB_I2C_UNUSED
)
{
nvkm_i2c_create_port
(
i2c
,
NV_I2C_PORT
(
index
),
DCB_I2C_NVIO_BIT
,
&
info
);
i
=
-
1
;
while
(
!
dcb_i2c_parse
(
bios
,
++
i
,
&
ccbE
))
{
struct
nvkm_i2c_pad
*
pad
=
NULL
;
struct
nvkm_i2c_bus
*
bus
=
NULL
;
struct
nvkm_i2c_aux
*
aux
=
NULL
;
nvkm_debug
(
&
i2c
->
subdev
,
"ccb %02x: type %02x drive %02x "
"sense %02x share %02x auxch %02x
\n
"
,
i
,
ccbE
.
type
,
ccbE
.
drive
,
ccbE
.
sense
,
ccbE
.
share
,
ccbE
.
auxch
);
if
(
ccbE
.
share
!=
DCB_I2C_UNUSED
)
{
const
int
id
=
NVKM_I2C_PAD_HYBRID
(
ccbE
.
share
);
if
(
!
(
pad
=
nvkm_i2c_pad_find
(
i2c
,
id
)))
ret
=
impl
->
pad_s_new
(
i2c
,
id
,
&
pad
);
else
ret
=
0
;
}
else
{
ret
=
impl
->
pad_x_new
(
i2c
,
NVKM_I2C_PAD_CCB
(
i
),
&
pad
);
}
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"ccb %02x pad, %d
\n
"
,
i
,
ret
);
nvkm_i2c_pad_del
(
&
pad
);
continue
;
}
if
(
info
.
auxch
!=
DCB_I2C_UNUSED
)
{
nvkm_i2c_create_port
(
i2c
,
NV_I2C_AUX
(
index
),
DCB_I2C_NVIO_AUX
,
&
info
);
if
(
pad
->
func
->
bus_new_0
&&
ccbE
.
type
==
DCB_I2C_NV04_BIT
)
{
ret
=
pad
->
func
->
bus_new_0
(
pad
,
NVKM_I2C_BUS_CCB
(
i
),
ccbE
.
drive
,
ccbE
.
sense
,
&
bus
);
}
else
if
(
pad
->
func
->
bus_new_4
&&
(
ccbE
.
type
==
DCB_I2C_NV4E_BIT
||
ccbE
.
type
==
DCB_I2C_NVIO_BIT
||
(
ccbE
.
type
==
DCB_I2C_PMGR
&&
ccbE
.
drive
!=
DCB_I2C_UNUSED
)))
{
ret
=
pad
->
func
->
bus_new_4
(
pad
,
NVKM_I2C_BUS_CCB
(
i
),
ccbE
.
drive
,
&
bus
);
}
break
;
case
DCB_I2C_UNUSED
:
default:
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"ccb %02x bus, %d
\n
"
,
i
,
ret
);
nvkm_i2c_bus_del
(
&
bus
);
}
if
(
pad
->
func
->
aux_new_6
&&
(
ccbE
.
type
==
DCB_I2C_NVIO_AUX
||
(
ccbE
.
type
==
DCB_I2C_PMGR
&&
ccbE
.
auxch
!=
DCB_I2C_UNUSED
)))
{
ret
=
pad
->
func
->
aux_new_6
(
pad
,
NVKM_I2C_BUS_CCB
(
i
),
ccbE
.
auxch
,
&
aux
);
}
else
{
ret
=
0
;
}
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"ccb %02x aux, %d
\n
"
,
i
,
ret
);
nvkm_i2c_aux_del
(
&
aux
);
}
if
(
ccbE
.
type
!=
DCB_I2C_UNUSED
&&
!
bus
&&
!
aux
)
{
nvkm_warn
(
&
i2c
->
subdev
,
"ccb %02x was ignored
\n
"
,
i
);
continue
;
}
}
/* in addition to the busses specified in the i2c table, there
* may be ddc/aux channels hiding behind external tmds/dp/etc
* transmitters.
*/
index
=
NV_I2C_EXT
(
0
);
i
=
-
1
;
while
((
data
=
dcb_outp_parse
(
bios
,
++
i
,
&
ver
,
&
hdr
,
&
outp
)))
{
if
(
!
outp
.
location
||
!
outp
.
extdev
)
while
(
dcb_outp_parse
(
bios
,
++
i
,
&
ver
,
&
hdr
,
&
dcbE
))
{
const
struct
nvkm_i2c_drv
*
drv
=
nvkm_i2c_drv
;
struct
nvkm_i2c_bus
*
bus
;
struct
nvkm_i2c_pad
*
pad
;
/* internal outputs handled by native i2c busses (above) */
if
(
!
dcbE
.
location
)
continue
;
switch
(
outp
.
type
)
{
case
DCB_OUTPUT_TMDS
:
info
.
type
=
NV_I2C_TYPE_EXTDDC
(
outp
.
extdev
);
break
;
case
DCB_OUTPUT_DP
:
info
.
type
=
NV_I2C_TYPE_EXTAUX
(
outp
.
extdev
);
/* we need an i2c bus to talk to the external encoder */
bus
=
nvkm_i2c_bus_find
(
i2c
,
dcbE
.
i2c_index
);
if
(
!
bus
)
{
nvkm_debug
(
&
i2c
->
subdev
,
"dcb %02x no bus
\n
"
,
i
);
continue
;
}
/* ... and a driver for it */
while
(
drv
->
pad_new
)
{
if
(
drv
->
bios
==
dcbE
.
extdev
)
break
;
default:
drv
++
;
}
if
(
!
drv
->
pad_new
)
{
nvkm_debug
(
&
i2c
->
subdev
,
"dcb %02x drv %02x unknown
\n
"
,
i
,
dcbE
.
extdev
);
continue
;
}
ret
=
-
ENODEV
;
j
=
-
1
;
while
(
ret
&&
++
j
<
ARRAY_SIZE
(
nvkm_i2c_extdev_sclass
))
{
parent
=
nv_object
(
i2c
->
find
(
i2c
,
outp
.
i2c_index
));
oclass
=
nvkm_i2c_extdev_sclass
[
j
];
do
{
if
(
oclass
->
handle
!=
info
.
type
)
/* find/create an instance of the driver */
pad
=
nvkm_i2c_pad_find
(
i2c
,
NVKM_I2C_PAD_EXT
(
dcbE
.
extdev
));
if
(
!
pad
)
{
const
int
id
=
NVKM_I2C_PAD_EXT
(
dcbE
.
extdev
);
ret
=
drv
->
pad_new
(
bus
,
id
,
drv
->
addr
,
&
pad
);
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"dcb %02x pad, %d
\n
"
,
i
,
ret
);
nvkm_i2c_pad_del
(
&
pad
);
continue
;
ret
=
nvkm_object_ctor
(
parent
,
NULL
,
oclass
,
NULL
,
index
++
,
&
object
);
}
while
(
ret
&&
(
++
oclass
)
->
handle
);
}
}
ret
=
nvkm_event_init
(
&
nvkm_i2c_intr_func
,
4
,
index
,
&
i2c
->
event
);
/* create any i2c bus / aux channel required by the output */
if
(
pad
->
func
->
aux_new_6
&&
dcbE
.
type
==
DCB_OUTPUT_DP
)
{
const
int
id
=
NVKM_I2C_AUX_EXT
(
dcbE
.
extdev
);
struct
nvkm_i2c_aux
*
aux
=
NULL
;
ret
=
pad
->
func
->
aux_new_6
(
pad
,
id
,
0
,
&
aux
);
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"dcb %02x aux, %d
\n
"
,
i
,
ret
);
nvkm_i2c_aux_del
(
&
aux
);
}
}
else
if
(
pad
->
func
->
bus_new_4
)
{
const
int
id
=
NVKM_I2C_BUS_EXT
(
dcbE
.
extdev
);
struct
nvkm_i2c_bus
*
bus
=
NULL
;
ret
=
pad
->
func
->
bus_new_4
(
pad
,
id
,
0
,
&
bus
);
if
(
ret
)
{
nvkm_error
(
&
i2c
->
subdev
,
"dcb %02x bus, %d
\n
"
,
i
,
ret
);
nvkm_i2c_bus_del
(
&
bus
);
}
}
}
ret
=
nvkm_event_init
(
&
nvkm_i2c_intr_func
,
4
,
i
,
&
i2c
->
event
);
if
(
ret
)
return
ret
;
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c
浏览文件 @
2aa5eac5
...
...
@@ -9,7 +9,7 @@
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial
port
ions of the Software.
* all copies or substantial
bus
ions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
...
...
@@ -21,7 +21,7 @@
*
* Authors: Ben Skeggs
*/
#include "
priv
.h"
#include "
bus
.h"
#ifdef CONFIG_NOUVEAU_I2C_INTERNAL
#define T_TIMEOUT 2200000
...
...
@@ -29,205 +29,188 @@
#define T_HOLD 5000
static
inline
void
i2c_drive_scl
(
struct
nvkm_i2c_port
*
port
,
int
state
)
nvkm_i2c_drive_scl
(
struct
nvkm_i2c_bus
*
bus
,
int
state
)
{
port
->
func
->
drive_scl
(
port
,
state
);
bus
->
func
->
drive_scl
(
bus
,
state
);
}
static
inline
void
i2c_drive_sda
(
struct
nvkm_i2c_port
*
port
,
int
state
)
nvkm_i2c_drive_sda
(
struct
nvkm_i2c_bus
*
bus
,
int
state
)
{
port
->
func
->
drive_sda
(
port
,
state
);
bus
->
func
->
drive_sda
(
bus
,
state
);
}
static
inline
int
i2c_sense_scl
(
struct
nvkm_i2c_port
*
port
)
nvkm_i2c_sense_scl
(
struct
nvkm_i2c_bus
*
bus
)
{
return
port
->
func
->
sense_scl
(
port
);
return
bus
->
func
->
sense_scl
(
bus
);
}
static
inline
int
i2c_sense_sda
(
struct
nvkm_i2c_port
*
port
)
nvkm_i2c_sense_sda
(
struct
nvkm_i2c_bus
*
bus
)
{
return
port
->
func
->
sense_sda
(
port
);
return
bus
->
func
->
sense_sda
(
bus
);
}
static
void
i2c_delay
(
struct
nvkm_i2c_port
*
port
,
u32
nsec
)
nvkm_i2c_delay
(
struct
nvkm_i2c_bus
*
bus
,
u32
nsec
)
{
udelay
((
nsec
+
500
)
/
1000
);
}
static
bool
i2c_raise_scl
(
struct
nvkm_i2c_port
*
port
)
nvkm_i2c_raise_scl
(
struct
nvkm_i2c_bus
*
bus
)
{
u32
timeout
=
T_TIMEOUT
/
T_RISEFALL
;
i2c_drive_scl
(
port
,
1
);
nvkm_i2c_drive_scl
(
bus
,
1
);
do
{
i2c_delay
(
port
,
T_RISEFALL
);
}
while
(
!
i2c_sense_scl
(
port
)
&&
--
timeout
);
nvkm_i2c_delay
(
bus
,
T_RISEFALL
);
}
while
(
!
nvkm_i2c_sense_scl
(
bus
)
&&
--
timeout
);
return
timeout
!=
0
;
}
static
int
i2c_start
(
struct
nvkm_i2c_
port
*
port
)
i2c_start
(
struct
nvkm_i2c_
bus
*
bus
)
{
int
ret
=
0
;
if
(
!
i2c_sense_scl
(
port
)
||
!
i2c_sense_sda
(
port
))
{
i2c_drive_scl
(
port
,
0
);
i2c_drive_sda
(
port
,
1
);
if
(
!
i2c_raise_scl
(
port
))
if
(
!
nvkm_i2c_sense_scl
(
bus
)
||
!
nvkm_i2c_sense_sda
(
bus
))
{
nvkm_i2c_drive_scl
(
bus
,
0
);
nvkm_i2c_drive_sda
(
bus
,
1
);
if
(
!
nvkm_i2c_raise_scl
(
bus
))
ret
=
-
EBUSY
;
}
i2c_drive_sda
(
port
,
0
);
i2c_delay
(
port
,
T_HOLD
);
i2c_drive_scl
(
port
,
0
);
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_drive_sda
(
bus
,
0
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
nvkm_i2c_drive_scl
(
bus
,
0
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
return
ret
;
}
static
void
i2c_stop
(
struct
nvkm_i2c_
port
*
port
)
i2c_stop
(
struct
nvkm_i2c_
bus
*
bus
)
{
i2c_drive_scl
(
port
,
0
);
i2c_drive_sda
(
port
,
0
);
i2c_delay
(
port
,
T_RISEFALL
);
i2c_drive_scl
(
port
,
1
);
i2c_delay
(
port
,
T_HOLD
);
i2c_drive_sda
(
port
,
1
);
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_drive_scl
(
bus
,
0
);
nvkm_i2c_drive_sda
(
bus
,
0
);
nvkm_i2c_delay
(
bus
,
T_RISEFALL
);
nvkm_i2c_drive_scl
(
bus
,
1
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
nvkm_i2c_drive_sda
(
bus
,
1
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
}
static
int
i2c_bitw
(
struct
nvkm_i2c_
port
*
port
,
int
sda
)
i2c_bitw
(
struct
nvkm_i2c_
bus
*
bus
,
int
sda
)
{
i2c_drive_sda
(
port
,
sda
);
i2c_delay
(
port
,
T_RISEFALL
);
nvkm_i2c_drive_sda
(
bus
,
sda
);
nvkm_i2c_delay
(
bus
,
T_RISEFALL
);
if
(
!
i2c_raise_scl
(
port
))
if
(
!
nvkm_i2c_raise_scl
(
bus
))
return
-
ETIMEDOUT
;
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
i2c_drive_scl
(
port
,
0
);
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_drive_scl
(
bus
,
0
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
return
0
;
}
static
int
i2c_bitr
(
struct
nvkm_i2c_
port
*
port
)
i2c_bitr
(
struct
nvkm_i2c_
bus
*
bus
)
{
int
sda
;
i2c_drive_sda
(
port
,
1
);
i2c_delay
(
port
,
T_RISEFALL
);
nvkm_i2c_drive_sda
(
bus
,
1
);
nvkm_i2c_delay
(
bus
,
T_RISEFALL
);
if
(
!
i2c_raise_scl
(
port
))
if
(
!
nvkm_i2c_raise_scl
(
bus
))
return
-
ETIMEDOUT
;
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
sda
=
i2c_sense_sda
(
port
);
sda
=
nvkm_i2c_sense_sda
(
bus
);
i2c_drive_scl
(
port
,
0
);
i2c_delay
(
port
,
T_HOLD
);
nvkm_i2c_drive_scl
(
bus
,
0
);
nvkm_i2c_delay
(
bus
,
T_HOLD
);
return
sda
;
}
static
int
i2c_get_byte
(
struct
nvkm_i2c_port
*
port
,
u8
*
byte
,
bool
last
)
nvkm_i2c_get_byte
(
struct
nvkm_i2c_bus
*
bus
,
u8
*
byte
,
bool
last
)
{
int
i
,
bit
;
*
byte
=
0
;
for
(
i
=
7
;
i
>=
0
;
i
--
)
{
bit
=
i2c_bitr
(
port
);
bit
=
i2c_bitr
(
bus
);
if
(
bit
<
0
)
return
bit
;
*
byte
|=
bit
<<
i
;
}
return
i2c_bitw
(
port
,
last
?
1
:
0
);
return
i2c_bitw
(
bus
,
last
?
1
:
0
);
}
static
int
i2c_put_byte
(
struct
nvkm_i2c_port
*
port
,
u8
byte
)
nvkm_i2c_put_byte
(
struct
nvkm_i2c_bus
*
bus
,
u8
byte
)
{
int
i
,
ret
;
for
(
i
=
7
;
i
>=
0
;
i
--
)
{
ret
=
i2c_bitw
(
port
,
!!
(
byte
&
(
1
<<
i
)));
ret
=
i2c_bitw
(
bus
,
!!
(
byte
&
(
1
<<
i
)));
if
(
ret
<
0
)
return
ret
;
}
ret
=
i2c_bitr
(
port
);
ret
=
i2c_bitr
(
bus
);
if
(
ret
==
1
)
/* nack */
ret
=
-
EIO
;
return
ret
;
}
static
int
i2c_addr
(
struct
nvkm_i2c_
port
*
port
,
struct
i2c_msg
*
msg
)
i2c_addr
(
struct
nvkm_i2c_
bus
*
bus
,
struct
i2c_msg
*
msg
)
{
u32
addr
=
msg
->
addr
<<
1
;
if
(
msg
->
flags
&
I2C_M_RD
)
addr
|=
1
;
return
i2c_put_byte
(
port
,
addr
);
return
nvkm_i2c_put_byte
(
bus
,
addr
);
}
static
int
i2c_bit_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
int
nvkm_i2c_bit_xfer
(
struct
nvkm_i2c_bus
*
bus
,
struct
i2c_msg
*
msgs
,
int
num
)
{
struct
nvkm_i2c_port
*
port
=
adap
->
algo_data
;
struct
i2c_msg
*
msg
=
msgs
;
int
ret
=
0
,
mcnt
=
num
;
ret
=
nvkm_i2c
(
port
)
->
acquire
(
port
,
nsecs_to_jiffies
(
T_TIMEOUT
));
if
(
ret
)
return
ret
;
while
(
!
ret
&&
mcnt
--
)
{
u8
remaining
=
msg
->
len
;
u8
*
ptr
=
msg
->
buf
;
ret
=
i2c_start
(
port
);
ret
=
i2c_start
(
bus
);
if
(
ret
==
0
)
ret
=
i2c_addr
(
port
,
msg
);
ret
=
i2c_addr
(
bus
,
msg
);
if
(
msg
->
flags
&
I2C_M_RD
)
{
while
(
!
ret
&&
remaining
--
)
ret
=
i2c_get_byte
(
port
,
ptr
++
,
!
remaining
);
ret
=
nvkm_i2c_get_byte
(
bus
,
ptr
++
,
!
remaining
);
}
else
{
while
(
!
ret
&&
remaining
--
)
ret
=
i2c_put_byte
(
port
,
*
ptr
++
);
ret
=
nvkm_i2c_put_byte
(
bus
,
*
ptr
++
);
}
msg
++
;
}
i2c_stop
(
port
);
nvkm_i2c
(
port
)
->
release
(
port
);
i2c_stop
(
bus
);
return
(
ret
<
0
)
?
ret
:
num
;
}
#else
static
int
i2c_bit_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
int
nvkm_i2c_bit_xfer
(
struct
nvkm_i2c_bus
*
bus
,
struct
i2c_msg
*
msgs
,
int
num
)
{
return
-
ENODEV
;
}
#endif
static
u32
i2c_bit_func
(
struct
i2c_adapter
*
adap
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
}
const
struct
i2c_algorithm
nvkm_i2c_bit_algo
=
{
.
master_xfer
=
i2c_bit_xfer
,
.
functionality
=
i2c_bit_func
};
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "bus.h"
#include "pad.h"
#include <core/option.h>
/*******************************************************************************
* i2c-algo-bit
******************************************************************************/
static
int
nvkm_i2c_bus_pre_xfer
(
struct
i2c_adapter
*
adap
)
{
struct
nvkm_i2c_bus
*
bus
=
container_of
(
adap
,
typeof
(
*
bus
),
i2c
);
return
nvkm_i2c_bus_acquire
(
bus
);
}
static
void
nvkm_i2c_bus_post_xfer
(
struct
i2c_adapter
*
adap
)
{
struct
nvkm_i2c_bus
*
bus
=
container_of
(
adap
,
typeof
(
*
bus
),
i2c
);
return
nvkm_i2c_bus_release
(
bus
);
}
static
void
nvkm_i2c_bus_setscl
(
void
*
data
,
int
state
)
{
struct
nvkm_i2c_bus
*
bus
=
data
;
bus
->
func
->
drive_scl
(
bus
,
state
);
}
static
void
nvkm_i2c_bus_setsda
(
void
*
data
,
int
state
)
{
struct
nvkm_i2c_bus
*
bus
=
data
;
bus
->
func
->
drive_sda
(
bus
,
state
);
}
static
int
nvkm_i2c_bus_getscl
(
void
*
data
)
{
struct
nvkm_i2c_bus
*
bus
=
data
;
return
bus
->
func
->
sense_scl
(
bus
);
}
static
int
nvkm_i2c_bus_getsda
(
void
*
data
)
{
struct
nvkm_i2c_bus
*
bus
=
data
;
return
bus
->
func
->
sense_sda
(
bus
);
}
/*******************************************************************************
* !i2c-algo-bit (off-chip i2c bus / hw i2c / internal bit-banging algo)
******************************************************************************/
static
int
nvkm_i2c_bus_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
{
struct
nvkm_i2c_bus
*
bus
=
container_of
(
adap
,
typeof
(
*
bus
),
i2c
);
int
ret
;
ret
=
nvkm_i2c_bus_acquire
(
bus
);
if
(
ret
)
return
ret
;
ret
=
bus
->
func
->
xfer
(
bus
,
msgs
,
num
);
nvkm_i2c_bus_release
(
bus
);
return
ret
;
}
static
u32
nvkm_i2c_bus_func
(
struct
i2c_adapter
*
adap
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
}
static
const
struct
i2c_algorithm
nvkm_i2c_bus_algo
=
{
.
master_xfer
=
nvkm_i2c_bus_xfer
,
.
functionality
=
nvkm_i2c_bus_func
,
};
/*******************************************************************************
* nvkm_i2c_bus base
******************************************************************************/
void
nvkm_i2c_bus_init
(
struct
nvkm_i2c_bus
*
bus
)
{
BUS_TRACE
(
bus
,
"init"
);
if
(
bus
->
func
->
init
)
bus
->
func
->
init
(
bus
);
}
void
nvkm_i2c_bus_release
(
struct
nvkm_i2c_bus
*
bus
)
{
struct
nvkm_i2c_pad
*
pad
=
bus
->
pad
;
BUS_TRACE
(
bus
,
"release"
);
nvkm_i2c_pad_release
(
pad
);
mutex_unlock
(
&
bus
->
mutex
);
}
int
nvkm_i2c_bus_acquire
(
struct
nvkm_i2c_bus
*
bus
)
{
struct
nvkm_i2c_pad
*
pad
=
bus
->
pad
;
int
ret
;
BUS_TRACE
(
bus
,
"acquire"
);
mutex_lock
(
&
bus
->
mutex
);
ret
=
nvkm_i2c_pad_acquire
(
pad
,
NVKM_I2C_PAD_I2C
);
if
(
ret
)
mutex_unlock
(
&
bus
->
mutex
);
return
ret
;
}
int
nvkm_i2c_bus_probe
(
struct
nvkm_i2c_bus
*
bus
,
const
char
*
what
,
struct
nvkm_i2c_bus_probe
*
info
,
bool
(
*
match
)(
struct
nvkm_i2c_bus
*
,
struct
i2c_board_info
*
,
void
*
),
void
*
data
)
{
int
i
;
BUS_DBG
(
bus
,
"probing %ss"
,
what
);
for
(
i
=
0
;
info
[
i
].
dev
.
addr
;
i
++
)
{
u8
orig_udelay
=
0
;
if
((
bus
->
i2c
.
algo
==
&
i2c_bit_algo
)
&&
(
info
[
i
].
udelay
!=
0
))
{
struct
i2c_algo_bit_data
*
algo
=
bus
->
i2c
.
algo_data
;
BUS_DBG
(
bus
,
"%dms delay instead of %dms"
,
info
[
i
].
udelay
,
algo
->
udelay
);
orig_udelay
=
algo
->
udelay
;
algo
->
udelay
=
info
[
i
].
udelay
;
}
if
(
nvkm_probe_i2c
(
&
bus
->
i2c
,
info
[
i
].
dev
.
addr
)
&&
(
!
match
||
match
(
bus
,
&
info
[
i
].
dev
,
data
)))
{
BUS_DBG
(
bus
,
"detected %s: %s"
,
what
,
info
[
i
].
dev
.
type
);
return
i
;
}
if
(
orig_udelay
)
{
struct
i2c_algo_bit_data
*
algo
=
bus
->
i2c
.
algo_data
;
algo
->
udelay
=
orig_udelay
;
}
}
BUS_DBG
(
bus
,
"no devices found."
);
return
-
ENODEV
;
}
void
nvkm_i2c_bus_del
(
struct
nvkm_i2c_bus
**
pbus
)
{
struct
nvkm_i2c_bus
*
bus
=
*
pbus
;
if
(
bus
&&
!
WARN_ON
(
!
bus
->
func
))
{
BUS_TRACE
(
bus
,
"dtor"
);
list_del
(
&
bus
->
head
);
i2c_del_adapter
(
&
bus
->
i2c
);
kfree
(
bus
->
i2c
.
algo_data
);
kfree
(
*
pbus
);
*
pbus
=
NULL
;
}
}
int
nvkm_i2c_bus_ctor
(
const
struct
nvkm_i2c_bus_func
*
func
,
struct
nvkm_i2c_pad
*
pad
,
int
id
,
struct
nvkm_i2c_bus
*
bus
)
{
struct
nvkm_device
*
device
=
pad
->
i2c
->
subdev
.
device
;
struct
i2c_algo_bit_data
*
bit
;
#ifndef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
const
bool
internal
=
false
;
#else
const
bool
internal
=
true
;
#endif
int
ret
;
bus
->
func
=
func
;
bus
->
pad
=
pad
;
bus
->
id
=
id
;
mutex_init
(
&
bus
->
mutex
);
list_add_tail
(
&
bus
->
head
,
&
pad
->
i2c
->
bus
);
BUS_TRACE
(
bus
,
"ctor"
);
snprintf
(
bus
->
i2c
.
name
,
sizeof
(
bus
->
i2c
.
name
),
"nvkm-%s-bus-%04x"
,
dev_name
(
device
->
dev
),
id
);
bus
->
i2c
.
owner
=
THIS_MODULE
;
bus
->
i2c
.
dev
.
parent
=
device
->
dev
;
if
(
bus
->
func
->
drive_scl
&&
!
nvkm_boolopt
(
device
->
cfgopt
,
"NvI2C"
,
internal
))
{
if
(
!
(
bit
=
kzalloc
(
sizeof
(
*
bit
),
GFP_KERNEL
)))
return
-
ENOMEM
;
bit
->
udelay
=
10
;
bit
->
timeout
=
usecs_to_jiffies
(
2200
);
bit
->
data
=
bus
;
bit
->
pre_xfer
=
nvkm_i2c_bus_pre_xfer
;
bit
->
post_xfer
=
nvkm_i2c_bus_post_xfer
;
bit
->
setscl
=
nvkm_i2c_bus_setscl
;
bit
->
setsda
=
nvkm_i2c_bus_setsda
;
bit
->
getscl
=
nvkm_i2c_bus_getscl
;
bit
->
getsda
=
nvkm_i2c_bus_getsda
;
bus
->
i2c
.
algo_data
=
bit
;
ret
=
i2c_bit_add_bus
(
&
bus
->
i2c
);
}
else
{
bus
->
i2c
.
algo
=
&
nvkm_i2c_bus_algo
;
ret
=
i2c_add_adapter
(
&
bus
->
i2c
);
}
return
ret
;
}
int
nvkm_i2c_bus_new_
(
const
struct
nvkm_i2c_bus_func
*
func
,
struct
nvkm_i2c_pad
*
pad
,
int
id
,
struct
nvkm_i2c_bus
**
pbus
)
{
if
(
!
(
*
pbus
=
kzalloc
(
sizeof
(
**
pbus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
return
nvkm_i2c_bus_ctor
(
func
,
pad
,
id
,
*
pbus
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
0 → 100644
浏览文件 @
2aa5eac5
#ifndef __NVKM_I2C_BUS_H__
#define __NVKM_I2C_BUS_H__
#include "pad.h"
struct
nvkm_i2c_bus_func
{
void
(
*
init
)(
struct
nvkm_i2c_bus
*
);
void
(
*
drive_scl
)(
struct
nvkm_i2c_bus
*
,
int
state
);
void
(
*
drive_sda
)(
struct
nvkm_i2c_bus
*
,
int
state
);
int
(
*
sense_scl
)(
struct
nvkm_i2c_bus
*
);
int
(
*
sense_sda
)(
struct
nvkm_i2c_bus
*
);
int
(
*
xfer
)(
struct
nvkm_i2c_bus
*
,
struct
i2c_msg
*
,
int
num
);
};
int
nvkm_i2c_bus_ctor
(
const
struct
nvkm_i2c_bus_func
*
,
struct
nvkm_i2c_pad
*
,
int
id
,
struct
nvkm_i2c_bus
*
);
int
nvkm_i2c_bus_new_
(
const
struct
nvkm_i2c_bus_func
*
,
struct
nvkm_i2c_pad
*
,
int
id
,
struct
nvkm_i2c_bus
**
);
void
nvkm_i2c_bus_del
(
struct
nvkm_i2c_bus
**
);
void
nvkm_i2c_bus_init
(
struct
nvkm_i2c_bus
*
);
int
nvkm_i2c_bit_xfer
(
struct
nvkm_i2c_bus
*
,
struct
i2c_msg
*
,
int
);
int
nv04_i2c_bus_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
u8
,
struct
nvkm_i2c_bus
**
);
int
nv4e_i2c_bus_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
struct
nvkm_i2c_bus
**
);
int
nv50_i2c_bus_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
struct
nvkm_i2c_bus
**
);
int
gf119_i2c_bus_new
(
struct
nvkm_i2c_pad
*
,
int
,
u8
,
struct
nvkm_i2c_bus
**
);
#define BUS_MSG(b,l,f,a...) do { \
struct nvkm_i2c_bus *_bus = (b); \
nvkm_##l(&_bus->pad->i2c->subdev, "bus %04x: "f"\n", _bus->id, ##a); \
} while(0)
#define BUS_ERR(b,f,a...) BUS_MSG((b), error, f, ##a)
#define BUS_DBG(b,f,a...) BUS_MSG((b), debug, f, ##a)
#define BUS_TRACE(b,f,a...) BUS_MSG((b), trace, f, ##a)
#endif
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define gf119_i2c_bus(p) container_of((p), struct gf119_i2c_bus, base)
#include "bus.h"
struct
gf119_i2c_bus
{
struct
nvkm_i2c_bus
base
;
u32
addr
;
};
static
void
gf119_i2c_bus_drive_scl
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
gf119_i2c_bus
*
bus
=
gf119_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
bus
->
addr
,
0x00000001
,
state
?
0x00000001
:
0
);
}
static
void
gf119_i2c_bus_drive_sda
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
gf119_i2c_bus
*
bus
=
gf119_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
bus
->
addr
,
0x00000002
,
state
?
0x00000002
:
0
);
}
static
int
gf119_i2c_bus_sense_scl
(
struct
nvkm_i2c_bus
*
base
)
{
struct
gf119_i2c_bus
*
bus
=
gf119_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00000010
);
}
static
int
gf119_i2c_bus_sense_sda
(
struct
nvkm_i2c_bus
*
base
)
{
struct
gf119_i2c_bus
*
bus
=
gf119_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00000020
);
}
static
void
gf119_i2c_bus_init
(
struct
nvkm_i2c_bus
*
base
)
{
struct
gf119_i2c_bus
*
bus
=
gf119_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_wr32
(
device
,
bus
->
addr
,
0x00000007
);
}
static
const
struct
nvkm_i2c_bus_func
gf119_i2c_bus_func
=
{
.
init
=
gf119_i2c_bus_init
,
.
drive_scl
=
gf119_i2c_bus_drive_scl
,
.
drive_sda
=
gf119_i2c_bus_drive_sda
,
.
sense_scl
=
gf119_i2c_bus_sense_scl
,
.
sense_sda
=
gf119_i2c_bus_sense_sda
,
.
xfer
=
nvkm_i2c_bit_xfer
,
};
int
gf119_i2c_bus_new
(
struct
nvkm_i2c_pad
*
pad
,
int
id
,
u8
drive
,
struct
nvkm_i2c_bus
**
pbus
)
{
struct
gf119_i2c_bus
*
bus
;
if
(
!
(
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
bus
->
base
;
nvkm_i2c_bus_ctor
(
&
gf119_i2c_bus_func
,
pad
,
id
,
&
bus
->
base
);
bus
->
addr
=
0x00d014
+
(
drive
*
0x20
);
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define nv04_i2c_bus(p) container_of((p), struct nv04_i2c_bus, base)
#include "bus.h"
#include <subdev/vga.h>
struct
nv04_i2c_bus
{
struct
nvkm_i2c_bus
base
;
u8
drive
;
u8
sense
;
};
static
void
nv04_i2c_bus_drive_scl
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv04_i2c_bus
*
bus
=
nv04_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
u8
val
=
nvkm_rdvgac
(
device
,
0
,
bus
->
drive
);
if
(
state
)
val
|=
0x20
;
else
val
&=
0xdf
;
nvkm_wrvgac
(
device
,
0
,
bus
->
drive
,
val
|
0x01
);
}
static
void
nv04_i2c_bus_drive_sda
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv04_i2c_bus
*
bus
=
nv04_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
u8
val
=
nvkm_rdvgac
(
device
,
0
,
bus
->
drive
);
if
(
state
)
val
|=
0x10
;
else
val
&=
0xef
;
nvkm_wrvgac
(
device
,
0
,
bus
->
drive
,
val
|
0x01
);
}
static
int
nv04_i2c_bus_sense_scl
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv04_i2c_bus
*
bus
=
nv04_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rdvgac
(
device
,
0
,
bus
->
sense
)
&
0x04
);
}
static
int
nv04_i2c_bus_sense_sda
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv04_i2c_bus
*
bus
=
nv04_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rdvgac
(
device
,
0
,
bus
->
sense
)
&
0x08
);
}
static
const
struct
nvkm_i2c_bus_func
nv04_i2c_bus_func
=
{
.
drive_scl
=
nv04_i2c_bus_drive_scl
,
.
drive_sda
=
nv04_i2c_bus_drive_sda
,
.
sense_scl
=
nv04_i2c_bus_sense_scl
,
.
sense_sda
=
nv04_i2c_bus_sense_sda
,
.
xfer
=
nvkm_i2c_bit_xfer
,
};
int
nv04_i2c_bus_new
(
struct
nvkm_i2c_pad
*
pad
,
int
id
,
u8
drive
,
u8
sense
,
struct
nvkm_i2c_bus
**
pbus
)
{
struct
nv04_i2c_bus
*
bus
;
if
(
!
(
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
bus
->
base
;
nvkm_i2c_bus_ctor
(
&
nv04_i2c_bus_func
,
pad
,
id
,
&
bus
->
base
);
bus
->
drive
=
drive
;
bus
->
sense
=
sense
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define nv4e_i2c_bus(p) container_of((p), struct nv4e_i2c_bus, base)
#include "bus.h"
struct
nv4e_i2c_bus
{
struct
nvkm_i2c_bus
base
;
u32
addr
;
};
static
void
nv4e_i2c_bus_drive_scl
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv4e_i2c_bus
*
bus
=
nv4e_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
bus
->
addr
,
0x2f
,
state
?
0x21
:
0x01
);
}
static
void
nv4e_i2c_bus_drive_sda
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv4e_i2c_bus
*
bus
=
nv4e_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
bus
->
addr
,
0x1f
,
state
?
0x11
:
0x01
);
}
static
int
nv4e_i2c_bus_sense_scl
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv4e_i2c_bus
*
bus
=
nv4e_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00040000
);
}
static
int
nv4e_i2c_bus_sense_sda
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv4e_i2c_bus
*
bus
=
nv4e_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00080000
);
}
static
const
struct
nvkm_i2c_bus_func
nv4e_i2c_bus_func
=
{
.
drive_scl
=
nv4e_i2c_bus_drive_scl
,
.
drive_sda
=
nv4e_i2c_bus_drive_sda
,
.
sense_scl
=
nv4e_i2c_bus_sense_scl
,
.
sense_sda
=
nv4e_i2c_bus_sense_sda
,
.
xfer
=
nvkm_i2c_bit_xfer
,
};
int
nv4e_i2c_bus_new
(
struct
nvkm_i2c_pad
*
pad
,
int
id
,
u8
drive
,
struct
nvkm_i2c_bus
**
pbus
)
{
struct
nv4e_i2c_bus
*
bus
;
if
(
!
(
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
bus
->
base
;
nvkm_i2c_bus_ctor
(
&
nv4e_i2c_bus_func
,
pad
,
id
,
&
bus
->
base
);
bus
->
addr
=
0x600800
+
drive
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2015 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial busions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#define nv50_i2c_bus(p) container_of((p), struct nv50_i2c_bus, base)
#include "bus.h"
#include <subdev/vga.h>
struct
nv50_i2c_bus
{
struct
nvkm_i2c_bus
base
;
u32
addr
;
u32
data
;
};
static
void
nv50_i2c_bus_drive_scl
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv50_i2c_bus
*
bus
=
nv50_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
if
(
state
)
bus
->
data
|=
0x01
;
else
bus
->
data
&=
0xfe
;
nvkm_wr32
(
device
,
bus
->
addr
,
bus
->
data
);
}
static
void
nv50_i2c_bus_drive_sda
(
struct
nvkm_i2c_bus
*
base
,
int
state
)
{
struct
nv50_i2c_bus
*
bus
=
nv50_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
if
(
state
)
bus
->
data
|=
0x02
;
else
bus
->
data
&=
0xfd
;
nvkm_wr32
(
device
,
bus
->
addr
,
bus
->
data
);
}
static
int
nv50_i2c_bus_sense_scl
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv50_i2c_bus
*
bus
=
nv50_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00000001
);
}
static
int
nv50_i2c_bus_sense_sda
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv50_i2c_bus
*
bus
=
nv50_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
return
!!
(
nvkm_rd32
(
device
,
bus
->
addr
)
&
0x00000002
);
}
static
void
nv50_i2c_bus_init
(
struct
nvkm_i2c_bus
*
base
)
{
struct
nv50_i2c_bus
*
bus
=
nv50_i2c_bus
(
base
);
struct
nvkm_device
*
device
=
bus
->
base
.
pad
->
i2c
->
subdev
.
device
;
nvkm_wr32
(
device
,
bus
->
addr
,
(
bus
->
data
=
0x00000007
));
}
static
const
struct
nvkm_i2c_bus_func
nv50_i2c_bus_func
=
{
.
init
=
nv50_i2c_bus_init
,
.
drive_scl
=
nv50_i2c_bus_drive_scl
,
.
drive_sda
=
nv50_i2c_bus_drive_sda
,
.
sense_scl
=
nv50_i2c_bus_sense_scl
,
.
sense_sda
=
nv50_i2c_bus_sense_sda
,
.
xfer
=
nvkm_i2c_bit_xfer
,
};
int
nv50_i2c_bus_new
(
struct
nvkm_i2c_pad
*
pad
,
int
id
,
u8
drive
,
struct
nvkm_i2c_bus
**
pbus
)
{
static
const
u32
addr
[]
=
{
0x00e138
,
0x00e150
,
0x00e168
,
0x00e180
,
0x00e254
,
0x00e274
,
0x00e764
,
0x00e780
,
0x00e79c
,
0x00e7b8
};
struct
nv50_i2c_bus
*
bus
;
if
(
drive
>=
ARRAY_SIZE
(
addr
))
{
nvkm_warn
(
&
pad
->
i2c
->
subdev
,
"bus %d unknown
\n
"
,
drive
);
return
-
ENODEV
;
}
if
(
!
(
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
pbus
=
&
bus
->
base
;
nvkm_i2c_bus_ctor
(
&
nv50_i2c_bus_func
,
pad
,
id
,
&
bus
->
base
);
bus
->
addr
=
addr
[
drive
];
bus
->
data
=
0x00000007
;
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c
浏览文件 @
2aa5eac5
...
...
@@ -21,7 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#include "priv.h"
#include "pad.h"
void
g94_aux_stat
(
struct
nvkm_i2c
*
i2c
,
u32
*
hi
,
u32
*
lo
,
u32
*
rq
,
u32
*
tx
)
...
...
@@ -55,219 +56,6 @@ g94_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data)
nvkm_wr32
(
device
,
0x00e068
,
temp
);
}
#define AUX_DBG(fmt, args...) \
nvkm_debug(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
#define AUX_ERR(fmt, args...) \
nvkm_error(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
static
void
auxch_fini
(
struct
nvkm_i2c
*
i2c
,
int
ch
)
{
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
0x00e4e4
+
(
ch
*
0x50
),
0x00310000
,
0x00000000
);
}
static
int
auxch_init
(
struct
nvkm_i2c
*
i2c
,
int
ch
)
{
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
const
u32
unksel
=
1
;
/* nfi which to use, or if it matters.. */
const
u32
ureq
=
unksel
?
0x00100000
:
0x00200000
;
const
u32
urep
=
unksel
?
0x01000000
:
0x02000000
;
u32
ctrl
,
timeout
;
/* wait up to 1ms for any previous transaction to be done... */
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"begin idle timeout %08x
\n
"
,
ctrl
);
return
-
EBUSY
;
}
}
while
(
ctrl
&
0x03010000
);
/* set some magic, and wait up to 1ms for it to appear */
nvkm_mask
(
device
,
0x00e4e4
+
(
ch
*
0x50
),
0x00300000
,
ureq
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"magic wait %08x
\n
"
,
ctrl
);
auxch_fini
(
i2c
,
ch
);
return
-
EBUSY
;
}
}
while
((
ctrl
&
0x03000000
)
!=
urep
);
return
0
;
}
int
g94_aux
(
struct
nvkm_i2c_port
*
base
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
u32
ctrl
,
stat
,
timeout
,
retries
;
u32
xbuf
[
4
]
=
{};
int
ch
=
port
->
addr
;
int
ret
,
i
;
AUX_DBG
(
"%d: %08x %d
\n
"
,
type
,
addr
,
size
);
ret
=
auxch_init
(
i2c
,
ch
);
if
(
ret
<
0
)
goto
out
;
stat
=
nvkm_rd32
(
device
,
0x00e4e8
+
(
ch
*
0x50
));
if
(
!
(
stat
&
0x10000000
))
{
AUX_DBG
(
"sink not detected
\n
"
);
ret
=
-
ENXIO
;
goto
out
;
}
if
(
!
(
type
&
1
))
{
memcpy
(
xbuf
,
data
,
size
);
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
AUX_DBG
(
"wr %08x
\n
"
,
xbuf
[
i
/
4
]);
nvkm_wr32
(
device
,
0x00e4c0
+
(
ch
*
0x50
)
+
i
,
xbuf
[
i
/
4
]);
}
}
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
ch
*
0x50
));
ctrl
&=
~
0x0001f0ff
;
ctrl
|=
type
<<
12
;
ctrl
|=
size
-
1
;
nvkm_wr32
(
device
,
0x00e4e0
+
(
ch
*
0x50
),
addr
);
/* (maybe) retry transaction a number of times on failure... */
for
(
retries
=
0
;
!
ret
&&
retries
<
32
;
retries
++
)
{
/* reset, and delay a while if this is a retry */
nvkm_wr32
(
device
,
0x00e4e4
+
(
ch
*
0x50
),
0x80000000
|
ctrl
);
nvkm_wr32
(
device
,
0x00e4e4
+
(
ch
*
0x50
),
0x00000000
|
ctrl
);
if
(
retries
)
udelay
(
400
);
/* transaction request, wait up to 1ms for it to complete */
nvkm_wr32
(
device
,
0x00e4e4
+
(
ch
*
0x50
),
0x00010000
|
ctrl
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00e4e4
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"tx req timeout %08x
\n
"
,
ctrl
);
ret
=
-
EIO
;
goto
out
;
}
}
while
(
ctrl
&
0x00010000
);
ret
=
1
;
/* read status, and check if transaction completed ok */
stat
=
nvkm_mask
(
device
,
0x00e4e8
+
(
ch
*
0x50
),
0
,
0
);
if
((
stat
&
0x000f0000
)
==
0x00080000
||
(
stat
&
0x000f0000
)
==
0x00020000
)
ret
=
retry
?
0
:
1
;
if
((
stat
&
0x00000100
))
ret
=
-
ETIMEDOUT
;
if
((
stat
&
0x00000e00
))
ret
=
-
EIO
;
AUX_DBG
(
"%02d %08x %08x
\n
"
,
retries
,
ctrl
,
stat
);
}
if
(
type
&
1
)
{
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
xbuf
[
i
/
4
]
=
nvkm_rd32
(
device
,
0x00e4d0
+
(
ch
*
0x50
)
+
i
);
AUX_DBG
(
"rd %08x
\n
"
,
xbuf
[
i
/
4
]);
}
memcpy
(
data
,
xbuf
,
size
);
}
out:
auxch_fini
(
i2c
,
ch
);
return
ret
<
0
?
ret
:
(
stat
&
0x000f0000
)
>>
16
;
}
static
const
struct
nvkm_i2c_func
g94_i2c_func
=
{
.
drive_scl
=
nv50_i2c_drive_scl
,
.
drive_sda
=
nv50_i2c_drive_sda
,
.
sense_scl
=
nv50_i2c_sense_scl
,
.
sense_sda
=
nv50_i2c_sense_sda
,
};
static
int
g94_i2c_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv50_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_bit_algo
,
&
g94_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
if
(
info
->
drive
>=
nv50_i2c_addr_nr
)
return
-
EINVAL
;
port
->
state
=
7
;
port
->
addr
=
nv50_i2c_addr
[
info
->
drive
];
return
0
;
}
static
const
struct
nvkm_i2c_func
g94_aux_func
=
{
.
aux
=
g94_aux
,
};
int
g94_aux_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv50_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_aux_algo
,
&
g94_aux_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
port
->
base
.
aux
=
info
->
auxch
;
port
->
addr
=
info
->
auxch
;
return
0
;
}
static
struct
nvkm_oclass
g94_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
g94_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
nv50_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_AUX
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
g94_aux_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
struct
nvkm_oclass
*
g94_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
.
base
.
handle
=
NV_SUBDEV
(
I2C
,
0x94
),
...
...
@@ -277,9 +65,8 @@ g94_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
g94_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_s
=
&
g94_i2c_pad_oclass
,
.
pad_x_new
=
g94_i2c_pad_x_new
,
.
pad_s_new
=
g94_i2c_pad_s_new
,
.
aux
=
4
,
.
aux_stat
=
g94_aux_stat
,
.
aux_mask
=
g94_aux_mask
,
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c
浏览文件 @
2aa5eac5
...
...
@@ -21,74 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
static
int
gf110_i2c_sense_scl
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00000010
);
}
static
int
gf110_i2c_sense_sda
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00000020
);
}
static
const
struct
nvkm_i2c_func
gf110_i2c_func
=
{
.
drive_scl
=
nv50_i2c_drive_scl
,
.
drive_sda
=
nv50_i2c_drive_sda
,
.
sense_scl
=
gf110_i2c_sense_scl
,
.
sense_sda
=
gf110_i2c_sense_sda
,
};
int
gf110_i2c_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv50_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_bit_algo
,
&
gf110_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
port
->
state
=
0x00000007
;
port
->
addr
=
0x00d014
+
(
info
->
drive
*
0x20
);
return
0
;
}
struct
nvkm_oclass
gf110_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
gf110_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
nv50_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_AUX
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
g94_aux_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
#include "priv.h"
#include "pad.h"
struct
nvkm_oclass
*
gf110_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -99,9 +33,8 @@ gf110_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
gf110_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_s
=
&
g94_i2c_pad_oclass
,
.
pad_x_new
=
gf119_i2c_pad_x_new
,
.
pad_s_new
=
gf119_i2c_pad_s_new
,
.
aux
=
4
,
.
aux_stat
=
g94_aux_stat
,
.
aux_mask
=
g94_aux_mask
,
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c
浏览文件 @
2aa5eac5
...
...
@@ -21,7 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#include "priv.h"
#include "pad.h"
struct
nvkm_oclass
*
gf117_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -32,7 +33,5 @@ gf117_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
gf110_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_s
=
&
nv04_i2c_pad_oclass
,
.
pad_x_new
=
gf119_i2c_pad_x_new
,
}.
base
;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c
浏览文件 @
2aa5eac5
...
...
@@ -21,7 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#include "priv.h"
#include "pad.h"
void
gk104_aux_stat
(
struct
nvkm_i2c
*
i2c
,
u32
*
hi
,
u32
*
lo
,
u32
*
rq
,
u32
*
tx
)
...
...
@@ -64,9 +65,8 @@ gk104_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
gf110_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_s
=
&
g94_i2c_pad_oclass
,
.
pad_x_new
=
gf119_i2c_pad_x_new
,
.
pad_s_new
=
gf119_i2c_pad_s_new
,
.
aux
=
4
,
.
aux_stat
=
gk104_aux_stat
,
.
aux_mask
=
gk104_aux_mask
,
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
浏览文件 @
2aa5eac5
...
...
@@ -21,190 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#define AUX_DBG(fmt, args...) \
nvkm_debug(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
#define AUX_ERR(fmt, args...) \
nvkm_error(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
static
void
auxch_fini
(
struct
nvkm_i2c
*
i2c
,
int
ch
)
{
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
nvkm_mask
(
device
,
0x00d954
+
(
ch
*
0x50
),
0x00310000
,
0x00000000
);
}
static
int
auxch_init
(
struct
nvkm_i2c
*
i2c
,
int
ch
)
{
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
const
u32
unksel
=
1
;
/* nfi which to use, or if it matters.. */
const
u32
ureq
=
unksel
?
0x00100000
:
0x00200000
;
const
u32
urep
=
unksel
?
0x01000000
:
0x02000000
;
u32
ctrl
,
timeout
;
/* wait up to 1ms for any previous transaction to be done... */
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"begin idle timeout %08x
\n
"
,
ctrl
);
return
-
EBUSY
;
}
}
while
(
ctrl
&
0x03010000
);
/* set some magic, and wait up to 1ms for it to appear */
nvkm_mask
(
device
,
0x00d954
+
(
ch
*
0x50
),
0x00300000
,
ureq
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"magic wait %08x
\n
"
,
ctrl
);
auxch_fini
(
i2c
,
ch
);
return
-
EBUSY
;
}
}
while
((
ctrl
&
0x03000000
)
!=
urep
);
return
0
;
}
int
gm204_aux
(
struct
nvkm_i2c_port
*
base
,
bool
retry
,
u8
type
,
u32
addr
,
u8
*
data
,
u8
size
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
u32
ctrl
,
stat
,
timeout
,
retries
;
u32
xbuf
[
4
]
=
{};
int
ch
=
port
->
addr
;
int
ret
,
i
;
AUX_DBG
(
"%d: %08x %d
\n
"
,
type
,
addr
,
size
);
ret
=
auxch_init
(
i2c
,
ch
);
if
(
ret
<
0
)
goto
out
;
stat
=
nvkm_rd32
(
device
,
0x00d958
+
(
ch
*
0x50
));
if
(
!
(
stat
&
0x10000000
))
{
AUX_DBG
(
"sink not detected
\n
"
);
ret
=
-
ENXIO
;
goto
out
;
}
if
(
!
(
type
&
1
))
{
memcpy
(
xbuf
,
data
,
size
);
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
AUX_DBG
(
"wr %08x
\n
"
,
xbuf
[
i
/
4
]);
nvkm_wr32
(
device
,
0x00d930
+
(
ch
*
0x50
)
+
i
,
xbuf
[
i
/
4
]);
}
}
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
ch
*
0x50
));
ctrl
&=
~
0x0001f0ff
;
ctrl
|=
type
<<
12
;
ctrl
|=
size
-
1
;
nvkm_wr32
(
device
,
0x00d950
+
(
ch
*
0x50
),
addr
);
/* (maybe) retry transaction a number of times on failure... */
for
(
retries
=
0
;
!
ret
&&
retries
<
32
;
retries
++
)
{
/* reset, and delay a while if this is a retry */
nvkm_wr32
(
device
,
0x00d954
+
(
ch
*
0x50
),
0x80000000
|
ctrl
);
nvkm_wr32
(
device
,
0x00d954
+
(
ch
*
0x50
),
0x00000000
|
ctrl
);
if
(
retries
)
udelay
(
400
);
/* transaction request, wait up to 1ms for it to complete */
nvkm_wr32
(
device
,
0x00d954
+
(
ch
*
0x50
),
0x00010000
|
ctrl
);
timeout
=
1000
;
do
{
ctrl
=
nvkm_rd32
(
device
,
0x00d954
+
(
ch
*
0x50
));
udelay
(
1
);
if
(
!
timeout
--
)
{
AUX_ERR
(
"tx req timeout %08x
\n
"
,
ctrl
);
ret
=
-
EIO
;
goto
out
;
}
}
while
(
ctrl
&
0x00010000
);
ret
=
1
;
/* read status, and check if transaction completed ok */
stat
=
nvkm_mask
(
device
,
0x00d958
+
(
ch
*
0x50
),
0
,
0
);
if
((
stat
&
0x000f0000
)
==
0x00080000
||
(
stat
&
0x000f0000
)
==
0x00020000
)
ret
=
retry
?
0
:
1
;
if
((
stat
&
0x00000100
))
ret
=
-
ETIMEDOUT
;
if
((
stat
&
0x00000e00
))
ret
=
-
EIO
;
AUX_DBG
(
"%02d %08x %08x
\n
"
,
retries
,
ctrl
,
stat
);
}
if
(
type
&
1
)
{
for
(
i
=
0
;
i
<
16
;
i
+=
4
)
{
xbuf
[
i
/
4
]
=
nvkm_rd32
(
device
,
0x00d940
+
(
ch
*
0x50
)
+
i
);
AUX_DBG
(
"rd %08x
\n
"
,
xbuf
[
i
/
4
]);
}
memcpy
(
data
,
xbuf
,
size
);
}
out:
auxch_fini
(
i2c
,
ch
);
return
ret
<
0
?
ret
:
(
stat
&
0x000f0000
)
>>
16
;
}
static
const
struct
nvkm_i2c_func
gm204_aux_func
=
{
.
aux
=
gm204_aux
,
};
int
gm204_aux_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv50_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_aux_algo
,
&
gm204_aux_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
port
->
base
.
aux
=
info
->
auxch
;
port
->
addr
=
info
->
auxch
;
return
0
;
}
struct
nvkm_oclass
gm204_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
gf110_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
nv50_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_AUX
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
gm204_aux_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
#include "priv.h"
#include "pad.h"
struct
nvkm_oclass
*
gm204_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -215,9 +33,8 @@ gm204_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
gm204_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_s
=
&
gm204_i2c_pad_oclass
,
.
pad_x_new
=
gf119_i2c_pad_x_new
,
.
pad_s_new
=
gm204_i2c_pad_s_new
,
.
aux
=
8
,
.
aux_stat
=
gk104_aux_stat
,
.
aux_mask
=
gk104_aux_mask
,
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c
浏览文件 @
2aa5eac5
...
...
@@ -22,93 +22,7 @@
* Authors: Ben Skeggs
*/
#include "priv.h"
#include <subdev/vga.h>
struct
nv04_i2c_port
{
struct
nvkm_i2c_port
base
;
u8
drive
;
u8
sense
;
};
static
void
nv04_i2c_drive_scl
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_device
*
device
=
nvkm_i2c
(
base
)
->
subdev
.
device
;
struct
nv04_i2c_port
*
port
=
(
void
*
)
base
;
u8
val
=
nvkm_rdvgac
(
device
,
0
,
port
->
drive
);
if
(
state
)
val
|=
0x20
;
else
val
&=
0xdf
;
nvkm_wrvgac
(
device
,
0
,
port
->
drive
,
val
|
0x01
);
}
static
void
nv04_i2c_drive_sda
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_device
*
device
=
nvkm_i2c
(
base
)
->
subdev
.
device
;
struct
nv04_i2c_port
*
port
=
(
void
*
)
base
;
u8
val
=
nvkm_rdvgac
(
device
,
0
,
port
->
drive
);
if
(
state
)
val
|=
0x10
;
else
val
&=
0xef
;
nvkm_wrvgac
(
device
,
0
,
port
->
drive
,
val
|
0x01
);
}
static
int
nv04_i2c_sense_scl
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_device
*
device
=
nvkm_i2c
(
base
)
->
subdev
.
device
;
struct
nv04_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rdvgac
(
device
,
0
,
port
->
sense
)
&
0x04
);
}
static
int
nv04_i2c_sense_sda
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_device
*
device
=
nvkm_i2c
(
base
)
->
subdev
.
device
;
struct
nv04_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rdvgac
(
device
,
0
,
port
->
sense
)
&
0x08
);
}
static
const
struct
nvkm_i2c_func
nv04_i2c_func
=
{
.
drive_scl
=
nv04_i2c_drive_scl
,
.
drive_sda
=
nv04_i2c_drive_sda
,
.
sense_scl
=
nv04_i2c_sense_scl
,
.
sense_sda
=
nv04_i2c_sense_sda
,
};
static
int
nv04_i2c_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv04_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_bit_algo
,
&
nv04_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
port
->
drive
=
info
->
drive
;
port
->
sense
=
info
->
sense
;
return
0
;
}
static
struct
nvkm_oclass
nv04_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NV04_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
nv04_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
#include "pad.h"
struct
nvkm_oclass
*
nv04_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -119,6 +33,5 @@ nv04_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
nv04_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_x_new
=
nv04_i2c_pad_new
,
}.
base
;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c
浏览文件 @
2aa5eac5
...
...
@@ -22,89 +22,7 @@
* Authors: Ben Skeggs
*/
#include "priv.h"
#include <subdev/vga.h>
struct
nv4e_i2c_port
{
struct
nvkm_i2c_port
base
;
u32
addr
;
};
static
void
nv4e_i2c_drive_scl
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv4e_i2c_port
*
port
=
(
void
*
)
base
;
nvkm_mask
(
device
,
port
->
addr
,
0x2f
,
state
?
0x21
:
0x01
);
}
static
void
nv4e_i2c_drive_sda
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv4e_i2c_port
*
port
=
(
void
*
)
base
;
nvkm_mask
(
device
,
port
->
addr
,
0x1f
,
state
?
0x11
:
0x01
);
}
static
int
nv4e_i2c_sense_scl
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv4e_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00040000
);
}
static
int
nv4e_i2c_sense_sda
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv4e_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00080000
);
}
static
const
struct
nvkm_i2c_func
nv4e_i2c_func
=
{
.
drive_scl
=
nv4e_i2c_drive_scl
,
.
drive_sda
=
nv4e_i2c_drive_sda
,
.
sense_scl
=
nv4e_i2c_sense_scl
,
.
sense_sda
=
nv4e_i2c_sense_sda
,
};
static
int
nv4e_i2c_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv4e_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_bit_algo
,
&
nv4e_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
port
->
addr
=
0x600800
+
info
->
drive
;
return
0
;
}
static
struct
nvkm_oclass
nv4e_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NV4E_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
nv4e_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
_nvkm_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
#include "pad.h"
struct
nvkm_oclass
*
nv4e_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -115,6 +33,5 @@ nv4e_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
nv4e_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_x_new
=
nv4e_i2c_pad_new
,
}.
base
;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c
浏览文件 @
2aa5eac5
...
...
@@ -21,108 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
void
nv50_i2c_drive_scl
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
if
(
state
)
port
->
state
|=
0x01
;
else
port
->
state
&=
0xfe
;
nvkm_wr32
(
device
,
port
->
addr
,
port
->
state
);
}
void
nv50_i2c_drive_sda
(
struct
nvkm_i2c_port
*
base
,
int
state
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
if
(
state
)
port
->
state
|=
0x02
;
else
port
->
state
&=
0xfd
;
nvkm_wr32
(
device
,
port
->
addr
,
port
->
state
);
}
int
nv50_i2c_sense_scl
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00000001
);
}
int
nv50_i2c_sense_sda
(
struct
nvkm_i2c_port
*
base
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
base
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
base
;
return
!!
(
nvkm_rd32
(
device
,
port
->
addr
)
&
0x00000002
);
}
static
const
struct
nvkm_i2c_func
nv50_i2c_func
=
{
.
drive_scl
=
nv50_i2c_drive_scl
,
.
drive_sda
=
nv50_i2c_drive_sda
,
.
sense_scl
=
nv50_i2c_sense_scl
,
.
sense_sda
=
nv50_i2c_sense_sda
,
};
const
u32
nv50_i2c_addr
[]
=
{
0x00e138
,
0x00e150
,
0x00e168
,
0x00e180
,
0x00e254
,
0x00e274
,
0x00e764
,
0x00e780
,
0x00e79c
,
0x00e7b8
};
const
int
nv50_i2c_addr_nr
=
ARRAY_SIZE
(
nv50_i2c_addr
);
static
int
nv50_i2c_port_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
dcb_i2c_entry
*
info
=
data
;
struct
nv50_i2c_port
*
port
;
int
ret
;
ret
=
nvkm_i2c_port_create
(
parent
,
engine
,
oclass
,
index
,
&
nvkm_i2c_bit_algo
,
&
nv50_i2c_func
,
&
port
);
*
pobject
=
nv_object
(
port
);
if
(
ret
)
return
ret
;
if
(
info
->
drive
>=
nv50_i2c_addr_nr
)
return
-
EINVAL
;
port
->
state
=
0x00000007
;
port
->
addr
=
nv50_i2c_addr
[
info
->
drive
];
return
0
;
}
int
nv50_i2c_port_init
(
struct
nvkm_object
*
object
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
object
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
nv50_i2c_port
*
port
=
(
void
*
)
object
;
nvkm_wr32
(
device
,
port
->
addr
,
port
->
state
);
return
nvkm_i2c_port_init
(
&
port
->
base
);
}
static
struct
nvkm_oclass
nv50_i2c_sclass
[]
=
{
{
.
handle
=
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
),
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
nv50_i2c_port_ctor
,
.
dtor
=
_nvkm_i2c_port_dtor
,
.
init
=
nv50_i2c_port_init
,
.
fini
=
_nvkm_i2c_port_fini
,
},
},
{}
};
#include "priv.h"
#include "pad.h"
struct
nvkm_oclass
*
nv50_i2c_oclass
=
&
(
struct
nvkm_i2c_impl
)
{
...
...
@@ -133,6 +33,5 @@ nv50_i2c_oclass = &(struct nvkm_i2c_impl) {
.
init
=
_nvkm_i2c_init
,
.
fini
=
_nvkm_i2c_fini
,
},
.
sclass
=
nv50_i2c_sclass
,
.
pad_x
=
&
nv04_i2c_pad_oclass
,
.
pad_x_new
=
nv50_i2c_pad_new
,
}.
base
;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h
已删除
100644 → 0
浏览文件 @
d36a99d2
#ifndef __NV50_I2C_H__
#define __NV50_I2C_H__
#include "priv.h"
struct
nv50_i2c_port
{
struct
nvkm_i2c_port
base
;
u32
addr
;
u32
state
;
};
extern
const
u32
nv50_i2c_addr
[];
extern
const
int
nv50_i2c_addr_nr
;
int
nv50_i2c_port_init
(
struct
nvkm_object
*
);
int
nv50_i2c_sense_scl
(
struct
nvkm_i2c_port
*
);
int
nv50_i2c_sense_sda
(
struct
nvkm_i2c_port
*
);
void
nv50_i2c_drive_scl
(
struct
nvkm_i2c_port
*
,
int
state
);
void
nv50_i2c_drive_sda
(
struct
nvkm_i2c_port
*
,
int
state
);
int
g94_aux_port_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
void
g94_i2c_acquire
(
struct
nvkm_i2c_port
*
);
void
g94_i2c_release
(
struct
nvkm_i2c_port
*
);
int
gf110_i2c_port_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
#endif
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c
浏览文件 @
2aa5eac5
/*
* Copyright 201
4
Red Hat Inc.
* Copyright 201
5
Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
...
...
@@ -19,65 +19,98 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
* Authors: Ben Skeggs
<bskeggs@redhat.com>
*/
#include "pad.h"
int
_nvkm_i2c_pad_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
static
void
nvkm_i2c_pad_mode_locked
(
struct
nvkm_i2c_pad
*
pad
,
enum
nvkm_i2c_pad_mode
mode
)
{
struct
nvkm_i2c_pad
*
pad
=
(
void
*
)
object
;
DBG
(
"-> NULL
\n
"
);
pad
->
port
=
NULL
;
return
nvkm_object_fini
(
&
pad
->
base
,
suspend
);
PAD_TRACE
(
pad
,
"-> %s"
,
(
mode
==
NVKM_I2C_PAD_AUX
)
?
"aux"
:
(
mode
==
NVKM_I2C_PAD_I2C
)
?
"i2c"
:
"off
"
);
if
(
pad
->
func
->
mode
)
pad
->
func
->
mode
(
pad
,
mode
);
}
int
_nvkm_i2c_pad_init
(
struct
nvkm_object
*
object
)
void
nvkm_i2c_pad_mode
(
struct
nvkm_i2c_pad
*
pad
,
enum
nvkm_i2c_pad_mode
mode
)
{
struct
nvkm_i2c_pad
*
pad
=
(
void
*
)
object
;
DBG
(
"-> PORT:%02x
\n
"
,
pad
->
next
->
index
);
pad
->
port
=
pad
->
next
;
return
nvkm_object_init
(
&
pad
->
base
);
PAD_TRACE
(
pad
,
"mode %d"
,
mode
);
mutex_lock
(
&
pad
->
mutex
);
nvkm_i2c_pad_mode_locked
(
pad
,
mode
);
pad
->
mode
=
mode
;
mutex_unlock
(
&
pad
->
mutex
);
}
int
nvkm_i2c_pad_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
int
index
,
int
size
,
void
**
pobject
)
void
nvkm_i2c_pad_release
(
struct
nvkm_i2c_pad
*
pad
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
parent
);
struct
nvkm_i2c_port
*
port
;
struct
nvkm_i2c_pad
*
pad
;
int
ret
;
PAD_TRACE
(
pad
,
"release"
);
if
(
pad
->
mode
==
NVKM_I2C_PAD_OFF
)
nvkm_i2c_pad_mode_locked
(
pad
,
pad
->
mode
);
mutex_unlock
(
&
pad
->
mutex
);
}
list_for_each_entry
(
port
,
&
i2c
->
ports
,
head
)
{
pad
=
nvkm_i2c_pad
(
port
);
if
(
pad
->
index
==
index
)
{
atomic_inc
(
&
nv_object
(
pad
)
->
refcount
);
*
pobject
=
pad
;
return
1
;
int
nvkm_i2c_pad_acquire
(
struct
nvkm_i2c_pad
*
pad
,
enum
nvkm_i2c_pad_mode
mode
)
{
PAD_TRACE
(
pad
,
"acquire"
);
mutex_lock
(
&
pad
->
mutex
);
if
(
pad
->
mode
!=
mode
)
{
if
(
pad
->
mode
!=
NVKM_I2C_PAD_OFF
)
{
mutex_unlock
(
&
pad
->
mutex
);
return
-
EBUSY
;
}
nvkm_i2c_pad_mode_locked
(
pad
,
mode
);
}
return
0
;
}
void
nvkm_i2c_pad_fini
(
struct
nvkm_i2c_pad
*
pad
)
{
PAD_TRACE
(
pad
,
"fini"
);
nvkm_i2c_pad_mode_locked
(
pad
,
NVKM_I2C_PAD_OFF
);
}
ret
=
nvkm_object_create_
(
parent
,
engine
,
oclass
,
0
,
size
,
pobject
);
pad
=
*
pobject
;
if
(
ret
)
return
ret
;
void
nvkm_i2c_pad_init
(
struct
nvkm_i2c_pad
*
pad
)
{
PAD_TRACE
(
pad
,
"init"
);
nvkm_i2c_pad_mode_locked
(
pad
,
pad
->
mode
);
}
pad
->
index
=
index
;
return
0
;
void
nvkm_i2c_pad_del
(
struct
nvkm_i2c_pad
**
ppad
)
{
struct
nvkm_i2c_pad
*
pad
=
*
ppad
;
if
(
pad
)
{
PAD_TRACE
(
pad
,
"dtor"
);
list_del
(
&
pad
->
head
);
kfree
(
pad
);
pad
=
NULL
;
}
}
void
nvkm_i2c_pad_ctor
(
const
struct
nvkm_i2c_pad_func
*
func
,
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
*
pad
)
{
pad
->
func
=
func
;
pad
->
i2c
=
i2c
;
pad
->
id
=
id
;
pad
->
mode
=
NVKM_I2C_PAD_OFF
;
mutex_init
(
&
pad
->
mutex
);
list_add_tail
(
&
pad
->
head
,
&
i2c
->
pad
);
PAD_TRACE
(
pad
,
"ctor"
);
}
int
_nvkm_i2c_pad_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
nvkm_i2c_pad_new_
(
const
struct
nvkm_i2c_pad_func
*
func
,
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
struct
nvkm_i2c_pad
*
pad
;
int
ret
;
ret
=
nvkm_i2c_pad_create
(
parent
,
engine
,
oclass
,
index
,
&
pad
);
*
pobject
=
nv_object
(
pad
);
return
ret
;
if
(
!
(
*
ppad
=
kzalloc
(
sizeof
(
**
ppad
),
GFP_KERNEL
)))
return
-
ENOMEM
;
nvkm_i2c_pad_ctor
(
func
,
i2c
,
id
,
*
ppad
);
return
0
;
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
浏览文件 @
2aa5eac5
#ifndef __NVKM_I2C_PAD_H__
#define __NVKM_I2C_PAD_H__
#include
"priv.h"
#include
<subdev/i2c.h>
struct
nvkm_i2c_pad
{
struct
nvkm_object
base
;
int
index
;
struct
nvkm_i2c_port
*
port
;
struct
nvkm_i2c_port
*
next
;
const
struct
nvkm_i2c_pad_func
*
func
;
struct
nvkm_i2c
*
i2c
;
#define NVKM_I2C_PAD_HYBRID(n)
/* 'n' is hw pad index */
(n)
#define NVKM_I2C_PAD_CCB(n)
/* 'n' is ccb index */
((n) + 0x100)
#define NVKM_I2C_PAD_EXT(n)
/* 'n' is dcb external encoder type */
((n) + 0x200)
int
id
;
enum
nvkm_i2c_pad_mode
{
NVKM_I2C_PAD_OFF
,
NVKM_I2C_PAD_I2C
,
NVKM_I2C_PAD_AUX
,
}
mode
;
struct
mutex
mutex
;
struct
list_head
head
;
};
struct
nvkm_i2c_pad_func
{
int
(
*
bus_new_0
)(
struct
nvkm_i2c_pad
*
,
int
id
,
u8
drive
,
u8
sense
,
struct
nvkm_i2c_bus
**
);
int
(
*
bus_new_4
)(
struct
nvkm_i2c_pad
*
,
int
id
,
u8
drive
,
struct
nvkm_i2c_bus
**
);
int
(
*
aux_new_6
)(
struct
nvkm_i2c_pad
*
,
int
id
,
u8
drive
,
struct
nvkm_i2c_aux
**
);
void
(
*
mode
)(
struct
nvkm_i2c_pad
*
,
enum
nvkm_i2c_pad_mode
);
};
static
inline
struct
nvkm_i2c_pad
*
nvkm_i2c_pad
(
struct
nvkm_i2c_port
*
port
)
{
struct
nvkm_object
*
pad
=
nv_object
(
port
);
while
(
!
nv_iclass
(
pad
->
parent
,
NV_SUBDEV_CLASS
))
pad
=
pad
->
parent
;
return
(
void
*
)
pad
;
}
#define nvkm_i2c_pad_create(p,e,o,i,d) \
nvkm_i2c_pad_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
#define nvkm_i2c_pad_destroy(p) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_dtor(nv_object(_p)); \
})
#define nvkm_i2c_pad_init(p) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_init(nv_object(_p)); \
})
#define nvkm_i2c_pad_fini(p,s) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_fini(nv_object(_p), (s)); \
})
int
nvkm_i2c_pad_create_
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
int
index
,
int
,
void
**
);
int
_nvkm_i2c_pad_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
#define _nvkm_i2c_pad_dtor nvkm_object_destroy
int
_nvkm_i2c_pad_init
(
struct
nvkm_object
*
);
int
_nvkm_i2c_pad_fini
(
struct
nvkm_object
*
,
bool
);
#ifndef MSG
#define MSG(l,f,a...) do { \
struct nvkm_i2c_pad *_pad = (void *)pad; \
struct nvkm_i2c *_i2c = nvkm_i2c(_pad); \
nvkm_##l(&_i2c->subdev, "PAD:%c:%02x: "f, \
_pad->index >= 0x100 ? 'X' : 'S', \
_pad->index >= 0x100 ? \
_pad->index - 0x100 : _pad->index, ##a); \
void
nvkm_i2c_pad_ctor
(
const
struct
nvkm_i2c_pad_func
*
,
struct
nvkm_i2c
*
,
int
id
,
struct
nvkm_i2c_pad
*
);
int
nvkm_i2c_pad_new_
(
const
struct
nvkm_i2c_pad_func
*
,
struct
nvkm_i2c
*
,
int
id
,
struct
nvkm_i2c_pad
**
);
void
nvkm_i2c_pad_del
(
struct
nvkm_i2c_pad
**
);
void
nvkm_i2c_pad_init
(
struct
nvkm_i2c_pad
*
);
void
nvkm_i2c_pad_fini
(
struct
nvkm_i2c_pad
*
);
void
nvkm_i2c_pad_mode
(
struct
nvkm_i2c_pad
*
,
enum
nvkm_i2c_pad_mode
);
int
nvkm_i2c_pad_acquire
(
struct
nvkm_i2c_pad
*
,
enum
nvkm_i2c_pad_mode
);
void
nvkm_i2c_pad_release
(
struct
nvkm_i2c_pad
*
);
void
g94_i2c_pad_mode
(
struct
nvkm_i2c_pad
*
,
enum
nvkm_i2c_pad_mode
);
int
nv04_i2c_pad_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
nv4e_i2c_pad_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
nv50_i2c_pad_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
g94_i2c_pad_x_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
gf119_i2c_pad_x_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
gm204_i2c_pad_x_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
g94_i2c_pad_s_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
gf119_i2c_pad_s_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
gm204_i2c_pad_s_new
(
struct
nvkm_i2c
*
,
int
,
struct
nvkm_i2c_pad
**
);
int
anx9805_pad_new
(
struct
nvkm_i2c_bus
*
,
int
,
u8
,
struct
nvkm_i2c_pad
**
);
#define PAD_MSG(p,l,f,a...) do { \
struct nvkm_i2c_pad *_pad = (p); \
nvkm_##l(&_pad->i2c->subdev, "pad %04x: "f"\n", _pad->id, ##a); \
} while(0)
#define
DBG(f,a...) MSG(debug
, f, ##a)
#define
ERR(f,a...) MSG(error
, f, ##a)
#
endif
#define
PAD_ERR(p,f,a...) PAD_MSG((p), error
, f, ##a)
#define
PAD_DBG(p,f,a...) PAD_MSG((p), debug
, f, ##a)
#
define PAD_TRACE(p,f,a...) PAD_MSG((p), trace, f, ##a)
#endif
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c
浏览文件 @
2aa5eac5
...
...
@@ -22,66 +22,55 @@
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "aux.h"
#include "bus.h"
struct
g94_i2c_pad
{
struct
nvkm_i2c_pad
base
;
int
addr
;
};
static
int
g94_i2c_pad_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
object
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
g94_i2c_pad
*
pad
=
(
void
*
)
object
;
nvkm_mask
(
device
,
0x00e50c
+
pad
->
addr
,
0x00000001
,
0x00000001
);
return
nvkm_i2c_pad_fini
(
&
pad
->
base
,
suspend
);
}
static
int
g94_i2c_pad_init
(
struct
nvkm_object
*
object
)
void
g94_i2c_pad_mode
(
struct
nvkm_i2c_pad
*
pad
,
enum
nvkm_i2c_pad_mode
mode
)
{
struct
nvkm_
i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
object
)
;
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
g94_i2c_pad
*
pad
=
(
void
*
)
object
;
struct
nvkm_
subdev
*
subdev
=
&
pad
->
i2c
->
subdev
;
struct
nvkm_device
*
device
=
subdev
->
device
;
const
u32
base
=
(
pad
->
id
-
NVKM_I2C_PAD_HYBRID
(
0
))
*
0x50
;
switch
(
nv_oclass
(
pad
->
base
.
next
)
->
handle
)
{
case
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_AUX
):
nvkm_mask
(
device
,
0x00e500
+
pad
->
addr
,
0x0000c003
,
0x00000002
);
switch
(
mode
)
{
case
NVKM_I2C_PAD_OFF
:
nvkm_mask
(
device
,
0x00e50c
+
base
,
0x00000001
,
0x00000001
);
break
;
case
NVKM_I2C_PAD_I2C
:
nvkm_mask
(
device
,
0x00e500
+
base
,
0x0000c003
,
0x0000c001
);
nvkm_mask
(
device
,
0x00e50c
+
base
,
0x00000001
,
0x00000000
);
break
;
case
NVKM_I2C_PAD_AUX
:
nvkm_mask
(
device
,
0x00e500
+
base
,
0x0000c003
,
0x00000002
);
nvkm_mask
(
device
,
0x00e50c
+
base
,
0x00000001
,
0x00000000
);
break
;
case
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
):
default:
nvkm_mask
(
device
,
0x00e500
+
pad
->
addr
,
0x0000c003
,
0x0000c00
1
);
WARN_ON
(
1
);
break
;
}
nvkm_mask
(
device
,
0x00e50c
+
pad
->
addr
,
0x00000001
,
0x00000000
);
return
nvkm_i2c_pad_init
(
&
pad
->
base
);
}
static
int
g94_i2c_pad_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
g94_i2c_pad
*
pad
;
int
ret
;
ret
=
nvkm_i2c_pad_create
(
parent
,
engine
,
oclass
,
index
,
&
pad
);
*
pobject
=
nv_object
(
pad
);
if
(
ret
)
return
ret
;
static
const
struct
nvkm_i2c_pad_func
g94_i2c_pad_s_func
=
{
.
bus_new_4
=
nv50_i2c_bus_new
,
.
aux_new_6
=
g94_i2c_aux_new
,
.
mode
=
g94_i2c_pad_mode
,
};
pad
->
addr
=
index
*
0x50
;;
return
0
;
int
g94_i2c_pad_s_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
g94_i2c_pad_s_func
,
i2c
,
id
,
ppad
);
}
struct
nvkm_oclass
g94_i2c_pad_oclass
=
{
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
g94_i2c_pad_ctor
,
.
dtor
=
_nvkm_i2c_pad_dtor
,
.
init
=
g94_i2c_pad_init
,
.
fini
=
g94_i2c_pad_fini
,
},
static
const
struct
nvkm_i2c_pad_func
g94_i2c_pad_x_func
=
{
.
bus_new_4
=
nv50_i2c_bus_new
,
.
aux_new_6
=
g94_i2c_aux_new
,
};
int
g94_i2c_pad_x_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
g94_i2c_pad_x_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "aux.h"
#include "bus.h"
static
const
struct
nvkm_i2c_pad_func
gf119_i2c_pad_s_func
=
{
.
bus_new_4
=
gf119_i2c_bus_new
,
.
aux_new_6
=
g94_i2c_aux_new
,
.
mode
=
g94_i2c_pad_mode
,
};
int
gf119_i2c_pad_s_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
gf119_i2c_pad_s_func
,
i2c
,
id
,
ppad
);
}
static
const
struct
nvkm_i2c_pad_func
gf119_i2c_pad_x_func
=
{
.
bus_new_4
=
gf119_i2c_bus_new
,
.
aux_new_6
=
g94_i2c_aux_new
,
};
int
gf119_i2c_pad_x_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
gf119_i2c_pad_x_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c
浏览文件 @
2aa5eac5
...
...
@@ -22,66 +22,55 @@
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "aux.h"
#include "bus.h"
struct
gm204_i2c_pad
{
struct
nvkm_i2c_pad
base
;
int
addr
;
};
static
int
gm204_i2c_pad_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
{
struct
nvkm_i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
object
);
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
gm204_i2c_pad
*
pad
=
(
void
*
)
object
;
nvkm_mask
(
device
,
0x00d97c
+
pad
->
addr
,
0x00000001
,
0x00000001
);
return
nvkm_i2c_pad_fini
(
&
pad
->
base
,
suspend
);
}
static
int
gm204_i2c_pad_init
(
struct
nvkm_object
*
object
)
static
void
gm204_i2c_pad_mode
(
struct
nvkm_i2c_pad
*
pad
,
enum
nvkm_i2c_pad_mode
mode
)
{
struct
nvkm_
i2c
*
i2c
=
(
void
*
)
nvkm_i2c
(
object
)
;
struct
nvkm_device
*
device
=
i2c
->
subdev
.
device
;
struct
gm204_i2c_pad
*
pad
=
(
void
*
)
object
;
struct
nvkm_
subdev
*
subdev
=
&
pad
->
i2c
->
subdev
;
struct
nvkm_device
*
device
=
subdev
->
device
;
const
u32
base
=
(
pad
->
id
-
NVKM_I2C_PAD_HYBRID
(
0
))
*
0x50
;
switch
(
nv_oclass
(
pad
->
base
.
next
)
->
handle
)
{
case
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_AUX
):
nvkm_mask
(
device
,
0x00d970
+
pad
->
addr
,
0x0000c003
,
0x00000002
);
switch
(
mode
)
{
case
NVKM_I2C_PAD_OFF
:
nvkm_mask
(
device
,
0x00d97c
+
base
,
0x00000001
,
0x00000001
);
break
;
case
NVKM_I2C_PAD_I2C
:
nvkm_mask
(
device
,
0x00d970
+
base
,
0x0000c003
,
0x0000c001
);
nvkm_mask
(
device
,
0x00d97c
+
base
,
0x00000001
,
0x00000000
);
break
;
case
NVKM_I2C_PAD_AUX
:
nvkm_mask
(
device
,
0x00d970
+
base
,
0x0000c003
,
0x00000002
);
nvkm_mask
(
device
,
0x00d97c
+
base
,
0x00000001
,
0x00000000
);
break
;
case
NV_I2C_TYPE_DCBI2C
(
DCB_I2C_NVIO_BIT
):
default:
nvkm_mask
(
device
,
0x00d970
+
pad
->
addr
,
0x0000c003
,
0x0000c00
1
);
WARN_ON
(
1
);
break
;
}
nvkm_mask
(
device
,
0x00d97c
+
pad
->
addr
,
0x00000001
,
0x00000000
);
return
nvkm_i2c_pad_init
(
&
pad
->
base
);
}
static
int
gm204_i2c_pad_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
data
,
u32
index
,
struct
nvkm_object
**
pobject
)
{
struct
gm204_i2c_pad
*
pad
;
int
ret
;
ret
=
nvkm_i2c_pad_create
(
parent
,
engine
,
oclass
,
index
,
&
pad
);
*
pobject
=
nv_object
(
pad
);
if
(
ret
)
return
ret
;
static
const
struct
nvkm_i2c_pad_func
gm204_i2c_pad_s_func
=
{
.
bus_new_4
=
gf119_i2c_bus_new
,
.
aux_new_6
=
gm204_i2c_aux_new
,
.
mode
=
gm204_i2c_pad_mode
,
};
pad
->
addr
=
index
*
0x50
;;
return
0
;
int
gm204_i2c_pad_s_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
gm204_i2c_pad_s_func
,
i2c
,
id
,
ppad
);
}
struct
nvkm_oclass
gm204_i2c_pad_oclass
=
{
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
gm204_i2c_pad_ctor
,
.
dtor
=
_nvkm_i2c_pad_dtor
,
.
init
=
gm204_i2c_pad_init
,
.
fini
=
gm204_i2c_pad_fini
,
},
static
const
struct
nvkm_i2c_pad_func
gm204_i2c_pad_x_func
=
{
.
bus_new_4
=
gf119_i2c_bus_new
,
.
aux_new_6
=
gm204_i2c_aux_new
,
};
int
gm204_i2c_pad_x_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
gm204_i2c_pad_x_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c
浏览文件 @
2aa5eac5
...
...
@@ -22,13 +22,15 @@
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "bus.h"
struct
nvkm_oclass
nv04_i2c_pad_oclass
=
{
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_i2c_pad_ctor
,
.
dtor
=
_nvkm_i2c_pad_dtor
,
.
init
=
_nvkm_i2c_pad_init
,
.
fini
=
_nvkm_i2c_pad_fini
,
},
static
const
struct
nvkm_i2c_pad_func
nv04_i2c_pad_func
=
{
.
bus_new_0
=
nv04_i2c_bus_new
,
};
int
nv04_i2c_pad_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
nv04_i2c_pad_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "bus.h"
static
const
struct
nvkm_i2c_pad_func
nv4e_i2c_pad_func
=
{
.
bus_new_4
=
nv4e_i2c_bus_new
,
};
int
nv4e_i2c_pad_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
nv4e_i2c_pad_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c
0 → 100644
浏览文件 @
2aa5eac5
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
#include "bus.h"
static
const
struct
nvkm_i2c_pad_func
nv50_i2c_pad_func
=
{
.
bus_new_4
=
nv50_i2c_bus_new
,
};
int
nv50_i2c_pad_new
(
struct
nvkm_i2c
*
i2c
,
int
id
,
struct
nvkm_i2c_pad
**
ppad
)
{
return
nvkm_i2c_pad_new_
(
&
nv50_i2c_pad_func
,
i2c
,
id
,
ppad
);
}
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h
已删除
100644 → 0
浏览文件 @
d36a99d2
#ifndef __NVKM_I2C_PORT_H__
#define __NVKM_I2C_PORT_H__
#include "priv.h"
#ifndef MSG
#define MSG(l,f,a...) do { \
struct nvkm_i2c_port *_port = (void *)port; \
struct nvkm_i2c *_i2c = nvkm_i2c(_port); \
nvkm_##l(&_i2c->subdev, "PORT:%02x: "f, _port->index, ##a); \
} while(0)
#define DBG(f,a...) MSG(debug, f, ##a)
#define ERR(f,a...) MSG(error, f, ##a)
#endif
#endif
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
浏览文件 @
2aa5eac5
...
...
@@ -2,31 +2,6 @@
#define __NVKM_I2C_PRIV_H__
#include <subdev/i2c.h>
extern
struct
nvkm_oclass
nv04_i2c_pad_oclass
;
extern
struct
nvkm_oclass
g94_i2c_pad_oclass
;
extern
struct
nvkm_oclass
gm204_i2c_pad_oclass
;
#define nvkm_i2c_port_create(p,e,o,i,a,f,d) \
nvkm_i2c_port_create_((p), (e), (o), (i), (a), (f), \
sizeof(**d), (void **)d)
#define nvkm_i2c_port_destroy(p) ({ \
struct nvkm_i2c_port *port = (p); \
_nvkm_i2c_port_dtor(nv_object(i2c)); \
})
#define nvkm_i2c_port_init(p) \
nvkm_object_init(&(p)->base)
#define nvkm_i2c_port_fini(p,s) \
nvkm_object_fini(&(p)->base, (s))
int
nvkm_i2c_port_create_
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
u8
,
const
struct
i2c_algorithm
*
,
const
struct
nvkm_i2c_func
*
,
int
,
void
**
);
void
_nvkm_i2c_port_dtor
(
struct
nvkm_object
*
);
#define _nvkm_i2c_port_init nvkm_object_init
int
_nvkm_i2c_port_fini
(
struct
nvkm_object
*
,
bool
);
#define nvkm_i2c_create(p,e,o,d) \
nvkm_i2c_create_((p), (e), (o), sizeof(**d), (void **)d)
#define nvkm_i2c_destroy(p) ({ \
...
...
@@ -51,19 +26,11 @@ void _nvkm_i2c_dtor(struct nvkm_object *);
int
_nvkm_i2c_init
(
struct
nvkm_object
*
);
int
_nvkm_i2c_fini
(
struct
nvkm_object
*
,
bool
);
extern
struct
nvkm_oclass
nvkm_anx9805_sclass
[];
extern
struct
nvkm_oclass
gf110_i2c_sclass
[];
extern
const
struct
i2c_algorithm
nvkm_i2c_bit_algo
;
extern
const
struct
i2c_algorithm
nvkm_i2c_aux_algo
;
struct
nvkm_i2c_impl
{
struct
nvkm_oclass
base
;
/* supported i2c port classes */
struct
nvkm_oclass
*
sclass
;
struct
nvkm_oclass
*
pad_x
;
struct
nvkm_oclass
*
pad_s
;
int
(
*
pad_x_new
)(
struct
nvkm_i2c
*
,
int
id
,
struct
nvkm_i2c_pad
**
);
int
(
*
pad_s_new
)(
struct
nvkm_i2c
*
,
int
id
,
struct
nvkm_i2c_pad
**
);
/* number of native dp aux channels present */
int
aux
;
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
浏览文件 @
2aa5eac5
...
...
@@ -29,7 +29,7 @@
#include <subdev/i2c.h>
static
bool
mxm_shadow_rom_fetch
(
struct
nvkm_i2c_
port
*
i2c
,
u8
addr
,
mxm_shadow_rom_fetch
(
struct
nvkm_i2c_
bus
*
bus
,
u8
addr
,
u8
offset
,
u8
size
,
u8
*
data
)
{
struct
i2c_msg
msgs
[]
=
{
...
...
@@ -37,7 +37,7 @@ mxm_shadow_rom_fetch(struct nvkm_i2c_port *i2c, u8 addr,
{
.
addr
=
addr
,
.
flags
=
I2C_M_RD
,
.
len
=
size
,
.
buf
=
data
,
},
};
return
i2c_transfer
(
&
i2c
->
adapter
,
msgs
,
2
)
==
2
;
return
i2c_transfer
(
&
bus
->
i2c
,
msgs
,
2
)
==
2
;
}
static
bool
...
...
@@ -45,19 +45,19 @@ mxm_shadow_rom(struct nvkm_mxm *mxm, u8 version)
{
struct
nvkm_bios
*
bios
=
nvkm_bios
(
mxm
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
mxm
);
struct
nvkm_i2c_
port
*
port
=
NULL
;
struct
nvkm_i2c_
bus
*
bus
=
NULL
;
u8
i2cidx
,
mxms
[
6
],
addr
,
size
;
i2cidx
=
mxm_ddc_map
(
bios
,
1
/* LVDS_DDC */
)
&
0x0f
;
if
(
i2cidx
<
0x0f
)
port
=
i2c
->
find
(
i2c
,
i2cidx
);
if
(
!
port
)
bus
=
nvkm_i2c_bus_
find
(
i2c
,
i2cidx
);
if
(
!
bus
)
return
false
;
addr
=
0x54
;
if
(
!
mxm_shadow_rom_fetch
(
port
,
addr
,
0
,
6
,
mxms
))
{
if
(
!
mxm_shadow_rom_fetch
(
bus
,
addr
,
0
,
6
,
mxms
))
{
addr
=
0x56
;
if
(
!
mxm_shadow_rom_fetch
(
port
,
addr
,
0
,
6
,
mxms
))
if
(
!
mxm_shadow_rom_fetch
(
bus
,
addr
,
0
,
6
,
mxms
))
return
false
;
}
...
...
@@ -66,7 +66,7 @@ mxm_shadow_rom(struct nvkm_mxm *mxm, u8 version)
mxm
->
mxms
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
mxm
->
mxms
&&
mxm_shadow_rom_fetch
(
port
,
addr
,
0
,
size
,
mxm
->
mxms
))
mxm_shadow_rom_fetch
(
bus
,
addr
,
0
,
size
,
mxm
->
mxms
))
return
true
;
kfree
(
mxm
->
mxms
);
...
...
drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
浏览文件 @
2aa5eac5
...
...
@@ -27,7 +27,7 @@
#include <subdev/i2c.h>
static
bool
probe_monitoring_device
(
struct
nvkm_i2c_
port
*
i2c
,
probe_monitoring_device
(
struct
nvkm_i2c_
bus
*
bus
,
struct
i2c_board_info
*
info
,
void
*
data
)
{
struct
nvkm_therm_priv
*
therm
=
data
;
...
...
@@ -36,7 +36,7 @@ probe_monitoring_device(struct nvkm_i2c_port *i2c,
request_module
(
"%s%s"
,
I2C_MODULE_PREFIX
,
info
->
type
);
client
=
i2c_new_device
(
&
i2c
->
adapter
,
info
);
client
=
i2c_new_device
(
&
bus
->
i2c
,
info
);
if
(
!
client
)
return
false
;
...
...
@@ -54,7 +54,7 @@ probe_monitoring_device(struct nvkm_i2c_port *i2c,
return
true
;
}
static
struct
nvkm_i2c_b
oard_info
static
struct
nvkm_i2c_b
us_probe
nv_board_infos
[]
=
{
{
{
I2C_BOARD_INFO
(
"w83l785ts"
,
0x2d
)
},
0
},
{
{
I2C_BOARD_INFO
(
"w83781d"
,
0x2d
)
},
0
},
...
...
@@ -83,30 +83,36 @@ void
nvkm_therm_ic_ctor
(
struct
nvkm_therm
*
obj
)
{
struct
nvkm_therm_priv
*
therm
=
container_of
(
obj
,
typeof
(
*
therm
),
base
);
struct
nvkm_bios
*
bios
=
nvkm_bios
(
therm
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
therm
);
struct
nvkm_device
*
device
=
therm
->
base
.
subdev
.
device
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
struct
nvkm_i2c
*
i2c
=
device
->
i2c
;
struct
nvkm_i2c_bus
*
bus
;
struct
nvbios_extdev_func
extdev_entry
;
bus
=
nvkm_i2c_bus_find
(
i2c
,
NVKM_I2C_BUS_PRI
);
if
(
!
bus
)
return
;
if
(
!
nvbios_extdev_find
(
bios
,
NVBIOS_EXTDEV_LM89
,
&
extdev_entry
))
{
struct
nvkm_i2c_b
oard_info
board
[]
=
{
struct
nvkm_i2c_b
us_probe
board
[]
=
{
{
{
I2C_BOARD_INFO
(
"lm90"
,
extdev_entry
.
addr
>>
1
)
},
0
},
{
}
};
i2c
->
identify
(
i2c
,
NV_I2C_DEFAULT
(
0
),
"monitoring device"
,
board
,
probe_monitoring_device
,
therm
);
nvkm_i2c_bus_probe
(
bus
,
"monitoring device"
,
board
,
probe_monitoring_device
,
therm
);
if
(
therm
->
ic
)
return
;
}
if
(
!
nvbios_extdev_find
(
bios
,
NVBIOS_EXTDEV_ADT7473
,
&
extdev_entry
))
{
struct
nvkm_i2c_b
oard_info
board
[]
=
{
struct
nvkm_i2c_b
us_probe
board
[]
=
{
{
{
I2C_BOARD_INFO
(
"adt7473"
,
extdev_entry
.
addr
>>
1
)
},
20
},
{
}
};
i2c
->
identify
(
i2c
,
NV_I2C_DEFAULT
(
0
),
"monitoring device"
,
board
,
probe_monitoring_device
,
therm
);
nvkm_i2c_bus_probe
(
bus
,
"monitoring device"
,
board
,
probe_monitoring_device
,
therm
);
if
(
therm
->
ic
)
return
;
}
...
...
@@ -114,6 +120,6 @@ nvkm_therm_ic_ctor(struct nvkm_therm *obj)
/* The vbios doesn't provide the address of an exisiting monitoring
device. Let's try our static list.
*/
i2c
->
identify
(
i2c
,
NV_I2C_DEFAULT
(
0
),
"monitoring device"
,
nv_board_infos
,
probe_monitoring_device
,
therm
);
nvkm_i2c_bus_probe
(
bus
,
"monitoring device"
,
nv_board_infos
,
probe_monitoring_device
,
therm
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录