Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
f2c906fc
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
f2c906fc
编写于
8月 20, 2015
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nouveau/disp: transition outp/conn away from being based on nvkm_object
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
2aa5eac5
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
629 addition
and
635 deletion
+629
-635
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+1
-0
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+13
-8
drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+130
-36
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
+36
-78
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
+18
-43
drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
+12
-0
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
+30
-30
drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
+5
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
+6
-8
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
+6
-9
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
+4
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
+4
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+4
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c
+4
-7
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
+5
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
+6
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+9
-12
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+1
-1
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+36
-87
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+32
-42
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
+75
-81
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
+31
-28
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
+63
-97
drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
+19
-2
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
+38
-24
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c
+13
-16
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c
+16
-20
drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
+12
-0
未找到文件。
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
浏览文件 @
f2c906fc
...
...
@@ -7,6 +7,7 @@ struct nvkm_disp {
struct
nvkm_engine
engine
;
struct
list_head
outp
;
struct
list_head
conn
;
struct
nvkm_event
hpd
;
struct
nvkm_event
vblank
;
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
浏览文件 @
f2c906fc
nvkm-y += nvkm/engine/disp/base.o
nvkm-y += nvkm/engine/disp/conn.o
nvkm-y += nvkm/engine/disp/outp.o
nvkm-y += nvkm/engine/disp/outpdp.o
nvkm-y += nvkm/engine/disp/nv04.o
nvkm-y += nvkm/engine/disp/nv50.o
nvkm-y += nvkm/engine/disp/g84.o
...
...
@@ -13,17 +10,25 @@ nvkm-y += nvkm/engine/disp/gk104.o
nvkm-y += nvkm/engine/disp/gk110.o
nvkm-y += nvkm/engine/disp/gm107.o
nvkm-y += nvkm/engine/disp/gm204.o
nvkm-y += nvkm/engine/disp/outp.o
nvkm-y += nvkm/engine/disp/outpdp.o
nvkm-y += nvkm/engine/disp/dacnv50.o
nvkm-y += nvkm/engine/disp/piornv50.o
nvkm-y += nvkm/engine/disp/sornv50.o
nvkm-y += nvkm/engine/disp/sorg94.o
nvkm-y += nvkm/engine/disp/sorgf110.o
nvkm-y += nvkm/engine/disp/sorgm204.o
nvkm-y += nvkm/engine/disp/dport.o
nvkm-y += nvkm/engine/disp/conn.o
nvkm-y += nvkm/engine/disp/hdagt215.o
nvkm-y += nvkm/engine/disp/hdagf110.o
nvkm-y += nvkm/engine/disp/hdmig84.o
nvkm-y += nvkm/engine/disp/hdmigt215.o
nvkm-y += nvkm/engine/disp/hdmigf110.o
nvkm-y += nvkm/engine/disp/hdmigk104.o
nvkm-y += nvkm/engine/disp/piornv50.o
nvkm-y += nvkm/engine/disp/sornv50.o
nvkm-y += nvkm/engine/disp/sorg94.o
nvkm-y += nvkm/engine/disp/sorgf110.o
nvkm-y += nvkm/engine/disp/sorgm204.o
nvkm-y += nvkm/engine/disp/vga.o
drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
浏览文件 @
f2c906fc
...
...
@@ -118,29 +118,25 @@ int
_nvkm_disp_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
{
struct
nvkm_disp
*
disp
=
(
void
*
)
object
;
struct
nvkm_connector
*
conn
;
struct
nvkm_output
*
outp
;
int
ret
;
list_for_each_entry
(
outp
,
&
disp
->
outp
,
head
)
{
ret
=
nv_ofuncs
(
outp
)
->
fini
(
nv_object
(
outp
),
suspend
);
if
(
ret
&&
suspend
)
goto
fail_outp
;
nvkm_output_fini
(
outp
);
}
return
nvkm_engine_fini
(
&
disp
->
engine
,
suspend
);
fail_outp:
list_for_each_entry_continue_reverse
(
outp
,
&
disp
->
outp
,
head
)
{
nv_ofuncs
(
outp
)
->
init
(
nv_object
(
outp
));
list_for_each_entry
(
conn
,
&
disp
->
conn
,
head
)
{
nvkm_connector_fini
(
conn
);
}
return
ret
;
return
nvkm_engine_fini
(
&
disp
->
engine
,
suspend
)
;
}
int
_nvkm_disp_init
(
struct
nvkm_object
*
object
)
{
struct
nvkm_disp
*
disp
=
(
void
*
)
object
;
struct
nvkm_connector
*
conn
;
struct
nvkm_output
*
outp
;
int
ret
;
...
...
@@ -148,17 +144,12 @@ _nvkm_disp_init(struct nvkm_object *object)
if
(
ret
)
return
ret
;
list_for_each_entry
(
outp
,
&
disp
->
outp
,
head
)
{
ret
=
nv_ofuncs
(
outp
)
->
init
(
nv_object
(
outp
));
if
(
ret
)
goto
fail_outp
;
list_for_each_entry
(
conn
,
&
disp
->
conn
,
head
)
{
nvkm_connector_init
(
conn
);
}
return
ret
;
fail_outp:
list_for_each_entry_continue_reverse
(
outp
,
&
disp
->
outp
,
head
)
{
nv_ofuncs
(
outp
)
->
fini
(
nv_object
(
outp
),
false
);
list_for_each_entry
(
outp
,
&
disp
->
outp
,
head
)
{
nvkm_output_init
(
outp
);
}
return
ret
;
...
...
@@ -168,15 +159,22 @@ void
_nvkm_disp_dtor
(
struct
nvkm_object
*
object
)
{
struct
nvkm_disp
*
disp
=
(
void
*
)
object
;
struct
nvkm_output
*
outp
,
*
outt
;
struct
nvkm_connector
*
conn
;
struct
nvkm_output
*
outp
;
nvkm_event_fini
(
&
disp
->
vblank
);
nvkm_event_fini
(
&
disp
->
hpd
);
if
(
disp
->
outp
.
next
)
{
list_for_each_entry_safe
(
outp
,
outt
,
&
disp
->
outp
,
head
)
{
nvkm_object_ref
(
NULL
,
(
struct
nvkm_object
**
)
&
outp
);
}
while
(
!
list_empty
(
&
disp
->
outp
))
{
outp
=
list_first_entry
(
&
disp
->
outp
,
typeof
(
*
outp
),
head
);
list_del
(
&
outp
->
head
);
nvkm_output_del
(
&
outp
);
}
while
(
!
list_empty
(
&
disp
->
conn
))
{
conn
=
list_first_entry
(
&
disp
->
conn
,
typeof
(
*
conn
),
head
);
list_del
(
&
conn
->
head
);
nvkm_connector_del
(
&
conn
);
}
nvkm_engine_destroy
(
&
disp
->
engine
);
...
...
@@ -188,10 +186,12 @@ nvkm_disp_create_(struct nvkm_object *parent, struct nvkm_object *engine,
const
char
*
extname
,
int
length
,
void
**
pobject
)
{
struct
nvkm_disp_impl
*
impl
=
(
void
*
)
oclass
;
struct
nvkm_bios
*
bios
=
nvkm_bios
(
parent
);
struct
nvkm_device
*
device
=
(
void
*
)
parent
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
struct
nvkm_disp
*
disp
;
struct
nvkm_oclass
**
sclass
;
struct
nvkm_object
*
object
;
struct
nvkm_connector
*
conn
;
struct
nvkm_output
*
outp
,
*
outt
,
*
pair
;
struct
nvbios_connE
connE
;
struct
dcb_output
dcbE
;
u8
hpd
=
0
,
ver
,
hdr
;
u32
data
;
...
...
@@ -204,30 +204,124 @@ nvkm_disp_create_(struct nvkm_object *parent, struct nvkm_object *engine,
return
ret
;
INIT_LIST_HEAD
(
&
disp
->
outp
);
INIT_LIST_HEAD
(
&
disp
->
conn
);
/* create output objects for each display path in the vbios */
i
=
-
1
;
while
((
data
=
dcb_outp_parse
(
bios
,
++
i
,
&
ver
,
&
hdr
,
&
dcbE
)))
{
const
struct
nvkm_disp_func_outp
*
outps
;
int
(
*
ctor
)(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
if
(
dcbE
.
type
==
DCB_OUTPUT_UNUSED
)
continue
;
if
(
dcbE
.
type
==
DCB_OUTPUT_EOL
)
break
;
data
=
dcbE
.
location
<<
4
|
dcbE
.
type
;
outp
=
NULL
;
switch
(
dcbE
.
location
)
{
case
0
:
outps
=
&
impl
->
outp
.
internal
;
break
;
case
1
:
outps
=
&
impl
->
outp
.
external
;
break
;
default:
nvkm_warn
(
&
disp
->
engine
.
subdev
,
"dcb %d locn %d unknown
\n
"
,
i
,
dcbE
.
location
);
continue
;
}
oclass
=
nvkm_output_oclass
;
sclass
=
impl
->
outp
;
while
(
sclass
&&
sclass
[
0
])
{
if
(
sclass
[
0
]
->
handle
==
data
)
{
oclass
=
sclass
[
0
];
break
;
switch
(
dcbE
.
type
)
{
case
DCB_OUTPUT_ANALOG
:
ctor
=
outps
->
crt
;
break
;
case
DCB_OUTPUT_TV
:
ctor
=
outps
->
tv
;
break
;
case
DCB_OUTPUT_TMDS
:
ctor
=
outps
->
tmds
;
break
;
case
DCB_OUTPUT_LVDS
:
ctor
=
outps
->
lvds
;
break
;
case
DCB_OUTPUT_DP
:
ctor
=
outps
->
dp
;
break
;
default:
nvkm_warn
(
&
disp
->
engine
.
subdev
,
"dcb %d type %d unknown
\n
"
,
i
,
dcbE
.
type
);
continue
;
}
if
(
ctor
)
ret
=
ctor
(
disp
,
i
,
&
dcbE
,
&
outp
);
else
ret
=
-
ENODEV
;
if
(
ret
)
{
if
(
ret
==
-
ENODEV
)
{
nvkm_debug
(
&
disp
->
engine
.
subdev
,
"dcb %d %d/%d not supported
\n
"
,
i
,
dcbE
.
location
,
dcbE
.
type
);
continue
;
}
sclass
++
;
nvkm_error
(
&
disp
->
engine
.
subdev
,
"failed to create output %d
\n
"
,
i
);
nvkm_output_del
(
&
outp
);
continue
;
}
nvkm_object_ctor
(
*
pobject
,
NULL
,
oclass
,
&
dcbE
,
i
,
&
object
);
list_add_tail
(
&
outp
->
head
,
&
disp
->
outp
);
hpd
=
max
(
hpd
,
(
u8
)(
dcbE
.
connector
+
1
));
}
/* create connector objects based on the outputs we support */
list_for_each_entry_safe
(
outp
,
outt
,
&
disp
->
outp
,
head
)
{
/* bios data *should* give us the most useful information */
data
=
nvbios_connEp
(
bios
,
outp
->
info
.
connector
,
&
ver
,
&
hdr
,
&
connE
);
/* no bios connector data... */
if
(
!
data
)
{
/* heuristic: anything with the same ccb index is
* considered to be on the same connector, any
* output path without an associated ccb entry will
* be put on its own connector
*/
int
ccb_index
=
outp
->
info
.
i2c_index
;
if
(
ccb_index
!=
0xf
)
{
list_for_each_entry
(
pair
,
&
disp
->
outp
,
head
)
{
if
(
pair
->
info
.
i2c_index
==
ccb_index
)
{
outp
->
conn
=
pair
->
conn
;
break
;
}
}
}
/* connector shared with another output path */
if
(
outp
->
conn
)
continue
;
memset
(
&
connE
,
0x00
,
sizeof
(
connE
));
connE
.
type
=
DCB_CONNECTOR_NONE
;
i
=
-
1
;
}
else
{
i
=
outp
->
info
.
connector
;
}
/* check that we haven't already created this connector */
list_for_each_entry
(
conn
,
&
disp
->
conn
,
head
)
{
if
(
conn
->
index
==
outp
->
info
.
connector
)
{
outp
->
conn
=
conn
;
break
;
}
}
if
(
outp
->
conn
)
continue
;
/* apparently we need to create a new one! */
ret
=
nvkm_connector_new
(
disp
,
i
,
&
connE
,
&
outp
->
conn
);
if
(
ret
)
{
nvkm_error
(
&
disp
->
engine
.
subdev
,
"failed to create output %d conn: %d
\n
"
,
outp
->
index
,
ret
);
nvkm_connector_del
(
&
outp
->
conn
);
list_del
(
&
outp
->
head
);
nvkm_output_del
(
&
outp
);
continue
;
}
list_add_tail
(
&
outp
->
conn
->
head
,
&
disp
->
conn
);
}
ret
=
nvkm_event_init
(
&
nvkm_disp_hpd_func
,
3
,
hpd
,
&
disp
->
hpd
);
if
(
ret
)
return
ret
;
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
浏览文件 @
f2c906fc
...
...
@@ -33,13 +33,13 @@ static int
nvkm_connector_hpd
(
struct
nvkm_notify
*
notify
)
{
struct
nvkm_connector
*
conn
=
container_of
(
notify
,
typeof
(
*
conn
),
hpd
);
struct
nvkm_disp
*
disp
=
nvkm_disp
(
conn
)
;
struct
nvkm_gpio
*
gpio
=
nvkm_gpio
(
conn
)
;
struct
nvkm_disp
*
disp
=
conn
->
disp
;
struct
nvkm_gpio
*
gpio
=
disp
->
engine
.
subdev
.
device
->
gpio
;
const
struct
nvkm_gpio_ntfy_rep
*
line
=
notify
->
data
;
struct
nvif_notify_conn_rep_v0
rep
;
int
index
=
conn
->
index
;
DBG
(
"HPD: %d
\n
"
,
line
->
mask
);
CONN_DBG
(
conn
,
"HPD: %d
"
,
line
->
mask
);
if
(
!
gpio
->
get
(
gpio
,
0
,
DCB_GPIO_UNUSED
,
conn
->
hpd
.
index
))
rep
.
mask
=
NVIF_NOTIFY_CONN_V0_UNPLUG
;
...
...
@@ -51,78 +51,58 @@ nvkm_connector_hpd(struct nvkm_notify *notify)
return
NVKM_NOTIFY_KEEP
;
}
int
_nvkm_connector_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
void
nvkm_connector_fini
(
struct
nvkm_connector
*
conn
)
{
struct
nvkm_connector
*
conn
=
(
void
*
)
object
;
nvkm_notify_put
(
&
conn
->
hpd
);
return
nvkm_object_fini
(
&
conn
->
base
,
suspend
);
}
int
_nvkm_connector_init
(
struct
nvkm_object
*
object
)
void
nvkm_connector_init
(
struct
nvkm_connector
*
conn
)
{
struct
nvkm_connector
*
conn
=
(
void
*
)
object
;
int
ret
=
nvkm_object_init
(
&
conn
->
base
);
if
(
ret
==
0
)
nvkm_notify_get
(
&
conn
->
hpd
);
return
ret
;
nvkm_notify_get
(
&
conn
->
hpd
);
}
void
_nvkm_connector_dtor
(
struct
nvkm_object
*
object
)
nvkm_connector_del
(
struct
nvkm_connector
**
pconn
)
{
struct
nvkm_connector
*
conn
=
(
void
*
)
object
;
nvkm_notify_fini
(
&
conn
->
hpd
);
nvkm_object_destroy
(
&
conn
->
base
);
struct
nvkm_connector
*
conn
=
*
pconn
;
if
(
conn
)
{
nvkm_notify_fini
(
&
conn
->
hpd
);
kfree
(
*
pconn
);
*
pconn
=
NULL
;
}
}
int
nvkm_connector_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
struct
nvbios_connE
*
info
,
int
index
,
int
length
,
void
**
pobject
)
static
void
nvkm_connector_ctor
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
nvbios_connE
*
info
,
struct
nvkm_connector
*
conn
)
{
static
const
u8
hpd
[]
=
{
0x07
,
0x08
,
0x51
,
0x52
,
0x5e
,
0x5f
,
0x60
};
struct
nvkm_disp
*
disp
=
nvkm_disp
(
parent
);
struct
nvkm_gpio
*
gpio
=
nvkm_gpio
(
parent
);
struct
nvkm_connector
*
conn
;
struct
nvkm_output
*
outp
;
struct
nvkm_gpio
*
gpio
=
disp
->
engine
.
subdev
.
device
->
gpio
;
struct
dcb_gpio_func
func
;
int
ret
;
list_for_each_entry
(
outp
,
&
disp
->
outp
,
head
)
{
if
(
outp
->
conn
&&
outp
->
conn
->
index
==
index
)
{
atomic_inc
(
&
nv_object
(
outp
->
conn
)
->
refcount
);
*
pobject
=
outp
->
conn
;
return
1
;
}
}
ret
=
nvkm_object_create_
(
parent
,
engine
,
oclass
,
0
,
length
,
pobject
);
conn
=
*
pobject
;
if
(
ret
)
return
ret
;
conn
->
info
=
*
info
;
conn
->
disp
=
disp
;
conn
->
index
=
index
;
conn
->
info
=
*
info
;
DBG
(
"type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x
\n
"
,
info
->
type
,
info
->
location
,
info
->
hpd
,
info
->
dp
,
info
->
di
,
info
->
sr
,
info
->
lcdid
);
CONN_DBG
(
conn
,
"type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x
"
,
info
->
type
,
info
->
location
,
info
->
hpd
,
info
->
dp
,
info
->
di
,
info
->
sr
,
info
->
lcdid
);
if
((
info
->
hpd
=
ffs
(
info
->
hpd
)))
{
if
(
--
info
->
hpd
>=
ARRAY_SIZE
(
hpd
))
{
ERR
(
"hpd %02x unknown
\
n
"
,
info
->
hpd
);
return
0
;
CONN_ERR
(
conn
,
"hpd %02x unknow
n"
,
info
->
hpd
);
return
;
}
info
->
hpd
=
hpd
[
info
->
hpd
];
ret
=
gpio
->
find
(
gpio
,
0
,
info
->
hpd
,
DCB_GPIO_UNUSED
,
&
func
);
if
(
ret
)
{
ERR
(
"func %02x lookup failed, %d
\n
"
,
info
->
hpd
,
ret
);
return
0
;
CONN_ERR
(
conn
,
"func %02x lookup failed, %d"
,
info
->
hpd
,
ret
);
return
;
}
ret
=
nvkm_notify_init
(
NULL
,
&
gpio
->
event
,
nvkm_connector_hpd
,
...
...
@@ -134,41 +114,19 @@ nvkm_connector_create_(struct nvkm_object *parent,
sizeof
(
struct
nvkm_gpio_ntfy_rep
),
&
conn
->
hpd
);
if
(
ret
)
{
ERR
(
"func %02x failed, %d
\n
"
,
info
->
hpd
,
ret
);
CONN_ERR
(
conn
,
"func %02x failed, %d
"
,
info
->
hpd
,
ret
);
}
else
{
DBG
(
"func %02x (HPD)
\n
"
,
info
->
hpd
);
CONN_DBG
(
conn
,
"func %02x (HPD)
"
,
info
->
hpd
);
}
}
return
0
;
}
int
_nvkm_connector_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
info
,
u32
index
,
struct
nvkm_object
**
pobject
)
nvkm_connector_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
nvbios_connE
*
info
,
struct
nvkm_connector
**
pconn
)
{
struct
nvkm_connector
*
conn
;
int
ret
;
ret
=
nvkm_connector_create
(
parent
,
engine
,
oclass
,
info
,
index
,
&
conn
);
*
pobject
=
nv_object
(
conn
);
if
(
ret
)
return
ret
;
if
(
!
(
*
pconn
=
kzalloc
(
sizeof
(
**
pconn
),
GFP_KERNEL
)))
return
-
ENOMEM
;
nvkm_connector_ctor
(
disp
,
index
,
info
,
*
pconn
);
return
0
;
}
struct
nvkm_oclass
*
nvkm_connector_oclass
=
&
(
struct
nvkm_connector_impl
)
{
.
base
=
{
.
handle
=
0
,
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_connector_ctor
,
.
dtor
=
_nvkm_connector_dtor
,
.
init
=
_nvkm_connector_init
,
.
fini
=
_nvkm_connector_fini
,
},
},
}.
base
;
drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
浏览文件 @
f2c906fc
#ifndef __NVKM_DISP_CONN_H__
#define __NVKM_DISP_CONN_H__
#include <core/object.h>
#include <core/notify.h>
#include <engine/disp.h>
#include <core/notify.h>
#include <subdev/bios.h>
#include <subdev/bios/conn.h>
struct
nvkm_connector
{
struct
nvkm_object
base
;
struct
list_head
head
;
struct
nvbios_connE
info
;
struct
nvkm_disp
*
disp
;
int
index
;
struct
nvbios_connE
info
;
struct
nvkm_notify
hpd
;
};
#define nvkm_connector_create(p,e,c,b,i,d) \
nvkm_connector_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d)
#define nvkm_connector_destroy(d) ({ \
struct nvkm_connector *disp = (d); \
_nvkm_connector_dtor(nv_object(disp)); \
})
#define nvkm_connector_init(d) ({ \
struct nvkm_connector *disp = (d); \
_nvkm_connector_init(nv_object(disp)); \
})
#define nvkm_connector_fini(d,s) ({ \
struct nvkm_connector *disp = (d); \
_nvkm_connector_fini(nv_object(disp), (s)); \
})
int
nvkm_connector_create_
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
struct
nvbios_connE
*
,
int
,
int
,
void
**
);
int
_nvkm_connector_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
void
_nvkm_connector_dtor
(
struct
nvkm_object
*
);
int
_nvkm_connector_init
(
struct
nvkm_object
*
);
int
_nvkm_connector_fini
(
struct
nvkm_object
*
,
bool
);
struct
nvkm_connector_impl
{
struct
nvkm_oclass
base
;
struct
list_head
head
;
};
#ifndef MSG
#define MSG(l,f,a...) do { \
struct nvkm_connector *_conn = (void *)conn; \
nvkm_##l(&nvkm_disp(_conn)->engine.subdev, "%02x:%02x%02x: "f, _conn->index, \
_conn->info.location, _conn->info.type, ##a); \
int
nvkm_connector_new
(
struct
nvkm_disp
*
,
int
index
,
struct
nvbios_connE
*
,
struct
nvkm_connector
**
);
void
nvkm_connector_del
(
struct
nvkm_connector
**
);
void
nvkm_connector_init
(
struct
nvkm_connector
*
);
void
nvkm_connector_fini
(
struct
nvkm_connector
*
);
#define CONN_MSG(c,l,f,a...) do { \
struct nvkm_connector *_conn = (c); \
nvkm_##l(&_conn->disp->engine.subdev, "conn %02x:%02x%02x: "f"\n", \
_conn->index, _conn->info.location, _conn->info.type, ##a); \
} while(0)
#define
DBG(f,a...) MSG(debug
, f, ##a)
#define
ERR(f,a...) MSG(error
, f, ##a)
#
endif
#define
CONN_ERR(c,f,a...) CONN_MSG((c), error
, f, ##a)
#define
CONN_DBG(c,f,a...) CONN_MSG((c), debug
, f, ##a)
#
define CONN_TRACE(c,f,a...) CONN_MSG((c), trace, f, ##a)
#endif
drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
浏览文件 @
f2c906fc
...
...
@@ -112,3 +112,15 @@ nv50_dac_sense(NV50_DISP_MTHD_V1)
args
->
v0
.
load
=
(
loadval
&
0x38000000
)
>>
27
;
return
0
;
}
static
const
struct
nvkm_output_func
nv50_dac_output_func
=
{
};
int
nv50_dac_output_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_new_
(
&
nv50_dac_output_func
,
disp
,
index
,
dcbE
,
poutp
);
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
浏览文件 @
f2c906fc
...
...
@@ -48,12 +48,12 @@ struct dp_state {
static
int
dp_set_link_config
(
struct
dp_state
*
dp
)
{
struct
nvkm_output_dp_impl
*
impl
=
(
void
*
)
nv_oclass
(
dp
->
outp
);
struct
nvkm_output_dp
*
outp
=
dp
->
outp
;
struct
nvkm_disp
*
disp
=
nvkm_disp
(
outp
);
struct
nvkm_bios
*
bios
=
nvkm_bios
(
disp
);
struct
nvkm_disp
*
disp
=
outp
->
base
.
disp
;
struct
nvkm_subdev
*
subdev
=
&
disp
->
engine
.
subdev
;
struct
nvkm_bios
*
bios
=
subdev
->
device
->
bios
;
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
disp
)
,
.
subdev
=
subdev
,
.
bios
=
bios
,
.
offset
=
0x0000
,
.
outp
=
&
outp
->
base
.
info
,
...
...
@@ -64,7 +64,7 @@ dp_set_link_config(struct dp_state *dp)
u8
sink
[
2
];
int
ret
;
DBG
(
"%d lanes at %d KB/s
\n
"
,
dp
->
link_nr
,
dp
->
link_bw
);
OUTP_DBG
(
&
outp
->
base
,
"%d lanes at %d KB/s
"
,
dp
->
link_nr
,
dp
->
link_bw
);
/* set desired link configuration on the source */
if
((
lnkcmp
=
dp
->
outp
->
info
.
lnkcmp
))
{
...
...
@@ -81,16 +81,16 @@ dp_set_link_config(struct dp_state *dp)
nvbios_exec
(
&
init
);
}
ret
=
impl
->
lnk_ctl
(
outp
,
dp
->
link_nr
,
dp
->
link_bw
/
27000
,
outp
->
dpcd
[
DPCD_RC02
]
&
DPCD_RC02_ENHANCED_FRAME_CAP
);
ret
=
outp
->
func
->
lnk_ctl
(
outp
,
dp
->
link_nr
,
dp
->
link_bw
/
27000
,
outp
->
dpcd
[
DPCD_RC02
]
&
DPCD_RC02_ENHANCED_FRAME_CAP
);
if
(
ret
)
{
if
(
ret
<
0
)
ERR
(
"lnk_ctl failed with %d
\n
"
,
ret
);
OUTP_ERR
(
&
outp
->
base
,
"lnk_ctl failed with %d
"
,
ret
);
return
ret
;
}
impl
->
lnk_pwr
(
outp
,
dp
->
link_nr
);
outp
->
func
->
lnk_pwr
(
outp
,
dp
->
link_nr
);
/* set desired link configuration on the sink */
sink
[
0
]
=
dp
->
link_bw
/
27000
;
...
...
@@ -104,12 +104,11 @@ dp_set_link_config(struct dp_state *dp)
static
void
dp_set_training_pattern
(
struct
dp_state
*
dp
,
u8
pattern
)
{
struct
nvkm_output_dp_impl
*
impl
=
(
void
*
)
nv_oclass
(
dp
->
outp
);
struct
nvkm_output_dp
*
outp
=
dp
->
outp
;
u8
sink_tp
;
DBG
(
"training pattern %d
\n
"
,
pattern
);
impl
->
pattern
(
outp
,
pattern
);
OUTP_DBG
(
&
outp
->
base
,
"training pattern %d
"
,
pattern
);
outp
->
func
->
pattern
(
outp
,
pattern
);
nvkm_rdaux
(
outp
->
aux
,
DPCD_LC02
,
&
sink_tp
,
1
);
sink_tp
&=
~
DPCD_LC02_TRAINING_PATTERN_SET
;
...
...
@@ -120,7 +119,6 @@ dp_set_training_pattern(struct dp_state *dp, u8 pattern)
static
int
dp_link_train_commit
(
struct
dp_state
*
dp
,
bool
pc
)
{
struct
nvkm_output_dp_impl
*
impl
=
(
void
*
)
nv_oclass
(
dp
->
outp
);
struct
nvkm_output_dp
*
outp
=
dp
->
outp
;
int
ret
,
i
;
...
...
@@ -146,8 +144,9 @@ dp_link_train_commit(struct dp_state *dp, bool pc)
dp
->
conf
[
i
]
=
(
lpre
<<
3
)
|
lvsw
;
dp
->
pc2conf
[
i
>>
1
]
|=
lpc2
<<
((
i
&
1
)
*
4
);
DBG
(
"config lane %d %02x %02x
\n
"
,
i
,
dp
->
conf
[
i
],
lpc2
);
impl
->
drv_ctl
(
outp
,
i
,
lvsw
&
3
,
lpre
&
3
,
lpc2
&
3
);
OUTP_DBG
(
&
outp
->
base
,
"config lane %d %02x %02x"
,
i
,
dp
->
conf
[
i
],
lpc2
);
outp
->
func
->
drv_ctl
(
outp
,
i
,
lvsw
&
3
,
lpre
&
3
,
lpc2
&
3
);
}
ret
=
nvkm_wraux
(
outp
->
aux
,
DPCD_LC03
(
0
),
dp
->
conf
,
4
);
...
...
@@ -182,9 +181,10 @@ dp_link_train_update(struct dp_state *dp, bool pc, u32 delay)
ret
=
nvkm_rdaux
(
outp
->
aux
,
DPCD_LS0C
,
&
dp
->
pc2stat
,
1
);
if
(
ret
)
dp
->
pc2stat
=
0x00
;
DBG
(
"status %6ph pc2 %02x
\n
"
,
dp
->
stat
,
dp
->
pc2stat
);
OUTP_DBG
(
&
outp
->
base
,
"status %6ph pc2 %02x"
,
dp
->
stat
,
dp
->
pc2stat
);
}
else
{
DBG
(
"status %6ph
\n
"
,
dp
->
stat
);
OUTP_DBG
(
&
outp
->
base
,
"status %6ph
"
,
dp
->
stat
);
}
return
0
;
...
...
@@ -260,11 +260,11 @@ static void
dp_link_train_init
(
struct
dp_state
*
dp
,
bool
spread
)
{
struct
nvkm_output_dp
*
outp
=
dp
->
outp
;
struct
nvkm_disp
*
disp
=
nvkm_disp
(
outp
)
;
struct
nvkm_
bios
*
bios
=
nvkm_bios
(
disp
)
;
struct
nvkm_disp
*
disp
=
outp
->
base
.
disp
;
struct
nvkm_
subdev
*
subdev
=
&
disp
->
engine
.
subdev
;
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
disp
)
,
.
bios
=
bios
,
.
subdev
=
subdev
,
.
bios
=
subdev
->
device
->
bios
,
.
outp
=
&
outp
->
base
.
info
,
.
crtc
=
-
1
,
.
execute
=
1
,
...
...
@@ -286,11 +286,11 @@ static void
dp_link_train_fini
(
struct
dp_state
*
dp
)
{
struct
nvkm_output_dp
*
outp
=
dp
->
outp
;
struct
nvkm_disp
*
disp
=
nvkm_disp
(
outp
)
;
struct
nvkm_
bios
*
bios
=
nvkm_bios
(
disp
)
;
struct
nvkm_disp
*
disp
=
outp
->
base
.
disp
;
struct
nvkm_
subdev
*
subdev
=
&
disp
->
engine
.
subdev
;
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
disp
)
,
.
bios
=
bios
,
.
subdev
=
subdev
,
.
bios
=
subdev
->
device
->
bios
,
.
outp
=
&
outp
->
base
.
info
,
.
crtc
=
-
1
,
.
execute
=
1
,
...
...
@@ -322,7 +322,7 @@ void
nvkm_dp_train
(
struct
work_struct
*
w
)
{
struct
nvkm_output_dp
*
outp
=
container_of
(
w
,
typeof
(
*
outp
),
lt
.
work
);
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
)
;
struct
nv50_disp
*
disp
=
(
void
*
)
outp
->
base
.
disp
;
const
struct
dp_rates
*
cfg
=
nvkm_dp_rates
;
struct
dp_state
_dp
=
{
.
outp
=
outp
,
...
...
@@ -334,7 +334,7 @@ nvkm_dp_train(struct work_struct *w)
disp
->
sor
.
magic
(
&
outp
->
base
);
/* bring capabilities within encoder limits */
if
(
nv_mclass
(
disp
)
<
GF110_DISP
)
if
(
disp
->
base
.
engine
.
subdev
.
device
->
chipset
<
0xd0
)
outp
->
dpcd
[
2
]
&=
~
DPCD_RC02_TPS3_SUPPORTED
;
if
((
outp
->
dpcd
[
2
]
&
0x1f
)
>
outp
->
base
.
info
.
dpconf
.
link_nr
)
{
outp
->
dpcd
[
2
]
&=
~
DPCD_RC02_MAX_LANE_COUNT
;
...
...
@@ -386,12 +386,12 @@ nvkm_dp_train(struct work_struct *w)
/* finish link training and execute post-train script from vbios */
dp_set_training_pattern
(
dp
,
0
);
if
(
ret
<
0
)
ERR
(
"link training failed
\n
"
);
OUTP_ERR
(
&
outp
->
base
,
"link training failed
"
);
dp_link_train_fini
(
dp
);
/* signal completion and enable link interrupt handling */
DBG
(
"training complete
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"training complete
"
);
atomic_set
(
&
outp
->
lt
.
done
,
1
);
wake_up
(
&
outp
->
lt
.
wait
);
nvkm_notify_get
(
&
outp
->
irq
);
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
浏览文件 @
f2c906fc
...
...
@@ -262,8 +262,12 @@ g84_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
external
.
tmds
=
nv50_pior_output_new
,
.
base
.
outp
.
external
.
dp
=
nv50_pior_dp_new
,
.
base
.
vblank
=
&
nv50_disp_vblank_func
,
.
base
.
outp
=
nv50_disp_outp_sclass
,
.
mthd
.
core
=
&
g84_disp_core_mthd_chan
,
.
mthd
.
base
=
&
g84_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
g84_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
浏览文件 @
f2c906fc
...
...
@@ -113,13 +113,6 @@ g94_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return
0
;
}
struct
nvkm_oclass
*
g94_disp_outp_sclass
[]
=
{
&
nv50_pior_dp_impl
.
base
.
base
,
&
g94_sor_dp_impl
.
base
.
base
,
NULL
};
struct
nvkm_oclass
*
g94_disp_oclass
=
&
(
struct
nv50_disp_impl
)
{
.
base
.
base
.
handle
=
NV_ENGINE
(
DISP
,
0x88
),
...
...
@@ -129,8 +122,13 @@ g94_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
g94_sor_dp_new
,
.
base
.
outp
.
external
.
lvds
=
nv50_pior_output_new
,
.
base
.
outp
.
external
.
dp
=
nv50_pior_dp_new
,
.
base
.
vblank
=
&
nv50_disp_vblank_func
,
.
base
.
outp
=
g94_disp_outp_sclass
,
.
mthd
.
core
=
&
g94_disp_core_mthd_chan
,
.
mthd
.
base
=
&
g84_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
g84_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
浏览文件 @
f2c906fc
...
...
@@ -988,7 +988,7 @@ gf110_disp_intr_unk2_0(struct nv50_disp *disp, int head)
/* see note in nv50_disp_intr_unk20_0() */
if
(
outp
&&
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
{
struct
nvkm_output_dp
*
outpdp
=
(
void
*
)
outp
;
struct
nvkm_output_dp
*
outpdp
=
nvkm_output_dp
(
outp
)
;
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
disp
),
.
bios
=
nvkm_bios
(
disp
),
...
...
@@ -1101,7 +1101,7 @@ gf110_disp_intr_unk2_2(struct nv50_disp *disp, int head)
}
if
(
nvkm_output_dp_train
(
outp
,
pclk
,
true
))
ERR
(
"link not trained before attach
\n
"
);
OUTP_ERR
(
outp
,
"link not trained before attach
"
);
}
else
{
if
(
disp
->
sor
.
magic
)
disp
->
sor
.
magic
(
outp
);
...
...
@@ -1339,12 +1339,6 @@ gf110_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return
0
;
}
struct
nvkm_oclass
*
gf110_disp_outp_sclass
[]
=
{
&
gf110_sor_dp_impl
.
base
.
base
,
NULL
};
struct
nvkm_oclass
*
gf110_disp_oclass
=
&
(
struct
nv50_disp_impl
)
{
.
base
.
base
.
handle
=
NV_ENGINE
(
DISP
,
0x90
),
...
...
@@ -1354,8 +1348,11 @@ gf110_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
gf110_sor_dp_new
,
.
base
.
vblank
=
&
gf110_disp_vblank_func
,
.
base
.
outp
=
gf110_disp_outp_sclass
,
.
mthd
.
core
=
&
gf110_disp_core_mthd_chan
,
.
mthd
.
base
=
&
gf110_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gf110_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
浏览文件 @
f2c906fc
...
...
@@ -259,8 +259,11 @@ gk104_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
gf110_sor_dp_new
,
.
base
.
vblank
=
&
gf110_disp_vblank_func
,
.
base
.
outp
=
gf110_disp_outp_sclass
,
.
mthd
.
core
=
&
gk104_disp_core_mthd_chan
,
.
mthd
.
base
=
&
gf110_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gk104_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
浏览文件 @
f2c906fc
...
...
@@ -94,8 +94,11 @@ gk110_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
gf110_sor_dp_new
,
.
base
.
vblank
=
&
gf110_disp_vblank_func
,
.
base
.
outp
=
gf110_disp_outp_sclass
,
.
mthd
.
core
=
&
gk104_disp_core_mthd_chan
,
.
mthd
.
base
=
&
gf110_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gk104_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
浏览文件 @
f2c906fc
...
...
@@ -94,8 +94,11 @@ gm107_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
gf110_sor_dp_new
,
.
base
.
vblank
=
&
gf110_disp_vblank_func
,
.
base
.
outp
=
gf110_disp_outp_sclass
,
.
mthd
.
core
=
&
gk104_disp_core_mthd_chan
,
.
mthd
.
base
=
&
gf110_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gk104_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c
浏览文件 @
f2c906fc
...
...
@@ -87,12 +87,6 @@ gm204_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return
0
;
}
struct
nvkm_oclass
*
gm204_disp_outp_sclass
[]
=
{
&
gm204_sor_dp_impl
.
base
.
base
,
NULL
};
struct
nvkm_oclass
*
gm204_disp_oclass
=
&
(
struct
nv50_disp_impl
)
{
.
base
.
base
.
handle
=
NV_ENGINE
(
DISP
,
0x07
),
...
...
@@ -102,8 +96,11 @@ gm204_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
gm204_sor_dp_new
,
.
base
.
vblank
=
&
gf110_disp_vblank_func
,
.
base
.
outp
=
gm204_disp_outp_sclass
,
.
mthd
.
core
=
&
gk104_disp_core_mthd_chan
,
.
mthd
.
base
=
&
gf110_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gk104_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
浏览文件 @
f2c906fc
...
...
@@ -138,8 +138,12 @@ gt200_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
external
.
tmds
=
nv50_pior_output_new
,
.
base
.
outp
.
external
.
dp
=
nv50_pior_dp_new
,
.
base
.
vblank
=
&
nv50_disp_vblank_func
,
.
base
.
outp
=
nv50_disp_outp_sclass
,
.
mthd
.
core
=
&
g84_disp_core_mthd_chan
,
.
mthd
.
base
=
&
g84_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
gt200_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
浏览文件 @
f2c906fc
...
...
@@ -94,8 +94,13 @@ gt215_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
dp
=
g94_sor_dp_new
,
.
base
.
outp
.
external
.
lvds
=
nv50_pior_output_new
,
.
base
.
outp
.
external
.
dp
=
nv50_pior_dp_new
,
.
base
.
vblank
=
&
nv50_disp_vblank_func
,
.
base
.
outp
=
g94_disp_outp_sclass
,
.
mthd
.
core
=
&
g94_disp_core_mthd_chan
,
.
mthd
.
base
=
&
g84_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
g84_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
浏览文件 @
f2c906fc
...
...
@@ -1109,7 +1109,7 @@ nv50_disp_main_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
}
break
;
case
NV50_DISP_MTHD_V1_SOR_DP_PWR
:
{
struct
nvkm_output_dp
*
outpdp
=
(
void
*
)
outp
;
struct
nvkm_output_dp
*
outpdp
=
nvkm_output_dp
(
outp
)
;
union
{
struct
nv50_disp_sor_dp_pwr_v0
v0
;
}
*
args
=
data
;
...
...
@@ -1119,8 +1119,7 @@ nv50_disp_main_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
args
->
v0
.
version
,
args
->
v0
.
state
);
if
(
args
->
v0
.
state
==
0
)
{
nvkm_notify_put
(
&
outpdp
->
irq
);
((
struct
nvkm_output_dp_impl
*
)
nv_oclass
(
outp
))
->
lnk_pwr
(
outpdp
,
0
);
outpdp
->
func
->
lnk_pwr
(
outpdp
,
0
);
atomic_set
(
&
outpdp
->
lt
.
done
,
0
);
return
0
;
}
else
...
...
@@ -1655,7 +1654,7 @@ nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
* in a blank screen (SOR_PWR off/on can restore it)
*/
if
(
outp
&&
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
{
struct
nvkm_output_dp
*
outpdp
=
(
void
*
)
outp
;
struct
nvkm_output_dp
*
outpdp
=
nvkm_output_dp
(
outp
)
;
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
disp
),
.
bios
=
nvkm_bios
(
disp
),
...
...
@@ -1855,7 +1854,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
}
if
(
nvkm_output_dp_train
(
outp
,
datarate
/
soff
,
true
))
ERR
(
"link not trained before attach
\n
"
);
OUTP_ERR
(
outp
,
"link not trained before attach
"
);
}
exec_clkcmp
(
disp
,
head
,
0
,
pclk
,
&
conf
);
...
...
@@ -2047,12 +2046,6 @@ nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return
0
;
}
struct
nvkm_oclass
*
nv50_disp_outp_sclass
[]
=
{
&
nv50_pior_dp_impl
.
base
.
base
,
NULL
};
struct
nvkm_oclass
*
nv50_disp_oclass
=
&
(
struct
nv50_disp_impl
)
{
.
base
.
base
.
handle
=
NV_ENGINE
(
DISP
,
0x50
),
...
...
@@ -2062,8 +2055,12 @@ nv50_disp_oclass = &(struct nv50_disp_impl) {
.
init
=
_nvkm_disp_init
,
.
fini
=
_nvkm_disp_fini
,
},
.
base
.
outp
.
internal
.
crt
=
nv50_dac_output_new
,
.
base
.
outp
.
internal
.
tmds
=
nv50_sor_output_new
,
.
base
.
outp
.
internal
.
lvds
=
nv50_sor_output_new
,
.
base
.
outp
.
external
.
tmds
=
nv50_pior_output_new
,
.
base
.
outp
.
external
.
dp
=
nv50_pior_dp_new
,
.
base
.
vblank
=
&
nv50_disp_vblank_func
,
.
base
.
outp
=
nv50_disp_outp_sclass
,
.
mthd
.
core
=
&
nv50_disp_core_mthd_chan
,
.
mthd
.
base
=
&
nv50_disp_base_mthd_chan
,
.
mthd
.
ovly
=
&
nv50_disp_ovly_mthd_chan
,
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
浏览文件 @
f2c906fc
...
...
@@ -214,7 +214,7 @@ extern struct nvkm_output_dp_impl nv50_pior_dp_impl;
extern
struct
nvkm_oclass
*
nv50_disp_outp_sclass
[];
extern
struct
nvkm_output_dp_impl
g94_sor_dp_impl
;
u32
g94_sor_dp_lane_map
(
struct
nv
50_disp
*
,
u8
lane
);
u32
g94_sor_dp_lane_map
(
struct
nv
km_device
*
,
u8
lane
);
int
g94_sor_dp_lnk_pwr
(
struct
nvkm_output_dp
*
,
int
);
extern
struct
nvkm_oclass
*
g94_disp_outp_sclass
[];
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
浏览文件 @
f2c906fc
...
...
@@ -22,117 +22,66 @@
* Authors: Ben Skeggs
*/
#include "outp.h"
#include "priv.h"
#include <subdev/bios.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/dcb.h>
#include <subdev/i2c.h>
int
_nvkm_output_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
void
nvkm_output_fini
(
struct
nvkm_output
*
outp
)
{
struct
nvkm_output
*
outp
=
(
void
*
)
object
;
nv_ofuncs
(
outp
->
conn
)
->
fini
(
nv_object
(
outp
->
conn
),
suspend
);
return
nvkm_object_fini
(
&
outp
->
base
,
suspend
);
if
(
outp
->
func
->
fini
)
outp
->
func
->
fini
(
outp
);
}
int
_nvkm_output_init
(
struct
nvkm_object
*
object
)
void
nvkm_output_init
(
struct
nvkm_output
*
outp
)
{
struct
nvkm_output
*
outp
=
(
void
*
)
object
;
int
ret
=
nvkm_object_init
(
&
outp
->
base
);
if
(
ret
==
0
)
nv_ofuncs
(
outp
->
conn
)
->
init
(
nv_object
(
outp
->
conn
));
return
0
;
if
(
outp
->
func
->
init
)
outp
->
func
->
init
(
outp
);
}
void
_nvkm_output_dtor
(
struct
nvkm_object
*
object
)
nvkm_output_del
(
struct
nvkm_output
**
poutp
)
{
struct
nvkm_output
*
outp
=
(
void
*
)
object
;
list_del
(
&
outp
->
head
);
nvkm_object_ref
(
NULL
,
(
void
*
)
&
outp
->
conn
);
nvkm_object_destroy
(
&
outp
->
base
);
struct
nvkm_output
*
outp
=
*
poutp
;
if
(
outp
&&
!
WARN_ON
(
!
outp
->
func
))
{
if
(
outp
->
func
->
dtor
)
*
poutp
=
outp
->
func
->
dtor
(
outp
);
kfree
(
*
poutp
);
*
poutp
=
NULL
;
}
}
int
nvkm_output_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
struct
dcb_output
*
dcbE
,
int
index
,
int
length
,
void
**
pobject
)
void
nvkm_output_ctor
(
const
struct
nvkm_output_func
*
func
,
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
*
outp
)
{
struct
nvkm_disp
*
disp
=
nvkm_disp
(
parent
);
struct
nvkm_bios
*
bios
=
nvkm_bios
(
parent
);
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
parent
);
struct
nvbios_connE
connE
;
struct
nvkm_output
*
outp
;
u8
ver
,
hdr
;
u32
data
;
int
ret
;
struct
nvkm_i2c
*
i2c
=
disp
->
engine
.
subdev
.
device
->
i2c
;
ret
=
nvkm_object_create_
(
parent
,
engine
,
oclass
,
0
,
length
,
pobject
);
outp
=
*
pobject
;
if
(
ret
)
return
ret
;
outp
->
info
=
*
dcbE
;
outp
->
func
=
func
;
outp
->
disp
=
disp
;
outp
->
index
=
index
;
outp
->
info
=
*
dcbE
;
outp
->
i2c
=
nvkm_i2c_bus_find
(
i2c
,
dcbE
->
i2c_index
);
outp
->
or
=
ffs
(
outp
->
info
.
or
)
-
1
;
DBG
(
"type %02x loc %d or %d link %d con %x edid %x bus %d head %x
\n
"
,
dcbE
->
type
,
dcbE
->
location
,
dcbE
->
or
,
dcbE
->
type
>=
2
?
dcbE
->
sorconf
.
link
:
0
,
dcbE
->
connector
,
dcbE
->
i2c_index
,
dcbE
->
bus
,
dcbE
->
heads
);
outp
->
i2c
=
nvkm_i2c_bus_find
(
i2c
,
outp
->
info
.
i2c_index
);
data
=
nvbios_connEp
(
bios
,
outp
->
info
.
connector
,
&
ver
,
&
hdr
,
&
connE
);
if
(
!
data
)
{
DBG
(
"vbios connector data not found
\n
"
);
memset
(
&
connE
,
0x00
,
sizeof
(
connE
));
connE
.
type
=
DCB_CONNECTOR_NONE
;
}
ret
=
nvkm_object_ctor
(
parent
,
NULL
,
nvkm_connector_oclass
,
&
connE
,
outp
->
info
.
connector
,
(
struct
nvkm_object
**
)
&
outp
->
conn
);
if
(
ret
<
0
)
{
ERR
(
"error %d creating connector, disabling
\n
"
,
ret
);
return
ret
;
}
list_add_tail
(
&
outp
->
head
,
&
disp
->
outp
);
return
0
;
OUTP_DBG
(
outp
,
"type %02x loc %d or %d link %d con %x "
"edid %x bus %d head %x"
,
outp
->
info
.
type
,
outp
->
info
.
location
,
outp
->
info
.
or
,
outp
->
info
.
type
>=
2
?
outp
->
info
.
sorconf
.
link
:
0
,
outp
->
info
.
connector
,
outp
->
info
.
i2c_index
,
outp
->
info
.
bus
,
outp
->
info
.
heads
);
}
int
_nvkm_output_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
dcbE
,
u32
index
,
struct
nvkm_object
**
pobject
)
nvkm_output_new_
(
const
struct
nvkm_output_func
*
func
,
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
struct
nvkm_output
*
outp
;
int
ret
;
ret
=
nvkm_output_create
(
parent
,
engine
,
oclass
,
dcbE
,
index
,
&
outp
);
*
pobject
=
nv_object
(
outp
);
if
(
ret
)
return
ret
;
if
(
!
(
*
poutp
=
kzalloc
(
sizeof
(
**
poutp
),
GFP_KERNEL
)))
return
-
ENOMEM
;
nvkm_output_ctor
(
func
,
disp
,
index
,
dcbE
,
*
poutp
);
return
0
;
}
struct
nvkm_oclass
*
nvkm_output_oclass
=
&
(
struct
nvkm_output_impl
)
{
.
base
=
{
.
handle
=
0
,
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_output_ctor
,
.
dtor
=
_nvkm_output_dtor
,
.
init
=
_nvkm_output_init
,
.
fini
=
_nvkm_output_fini
,
},
},
}.
base
;
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
浏览文件 @
f2c906fc
#ifndef __NVKM_DISP_OUTP_H__
#define __NVKM_DISP_OUTP_H__
#include <
core/object
.h>
#include <
engine/disp
.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
struct
nvkm_output
{
struct
nvkm_object
base
;
struct
list_head
head
;
struct
dcb_output
info
;
const
struct
nvkm_output_func
*
func
;
struct
nvkm_disp
*
disp
;
int
index
;
int
or
;
struct
dcb_output
info
;
// whatever (if anything) is pointed at by the dcb device entry
struct
nvkm_i2c_bus
*
i2c
;
int
or
;
struct
list_head
head
;
struct
nvkm_connector
*
conn
;
};
#define nvkm_output_create(p,e,c,b,i,d) \
nvkm_output_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d)
#define nvkm_output_destroy(d) ({ \
struct nvkm_output *_outp = (d); \
_nvkm_output_dtor(nv_object(_outp)); \
})
#define nvkm_output_init(d) ({ \
struct nvkm_output *_outp = (d); \
_nvkm_output_init(nv_object(_outp)); \
})
#define nvkm_output_fini(d,s) ({ \
struct nvkm_output *_outp = (d); \
_nvkm_output_fini(nv_object(_outp), (s)); \
})
int
nvkm_output_create_
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
struct
dcb_output
*
,
int
,
int
,
void
**
);
int
_nvkm_output_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
void
_nvkm_output_dtor
(
struct
nvkm_object
*
);
int
_nvkm_output_init
(
struct
nvkm_object
*
);
int
_nvkm_output_fini
(
struct
nvkm_object
*
,
bool
);
struct
nvkm_output_impl
{
struct
nvkm_oclass
base
;
struct
nvkm_output_func
{
void
*
(
*
dtor
)(
struct
nvkm_output
*
);
void
(
*
init
)(
struct
nvkm_output
*
);
void
(
*
fini
)(
struct
nvkm_output
*
);
};
#ifndef MSG
#define MSG(l,f,a...) do { \
struct nvkm_output *_outp = (void *)outp; \
nvkm_##l(&nvkm_disp(_outp)->engine.subdev, "%02x:%04x:%04x: "f, _outp->index, \
_outp->info.hasht, _outp->info.hashm, ##a); \
void
nvkm_output_ctor
(
const
struct
nvkm_output_func
*
,
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
*
);
int
nvkm_output_new_
(
const
struct
nvkm_output_func
*
,
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
void
nvkm_output_del
(
struct
nvkm_output
**
);
void
nvkm_output_init
(
struct
nvkm_output
*
);
void
nvkm_output_fini
(
struct
nvkm_output
*
);
int
nv50_dac_output_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
nv50_sor_output_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
nv50_pior_output_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
#define OUTP_MSG(o,l,f,a...) do { \
struct nvkm_output *_outp = (o); \
nvkm_##l(&_outp->disp->engine.subdev, "outp %02x:%04x:%04x: "f"\n", \
_outp->index, _outp->info.hasht, _outp->info.hashm, ##a); \
} while(0)
#define
DBG(f,a...) MSG(debug
, f, ##a)
#define
ERR(f,a...) MSG(error
, f, ##a)
#
endif
#define
OUTP_ERR(o,f,a...) OUTP_MSG((o), error
, f, ##a)
#define
OUTP_DBG(o,f,a...) OUTP_MSG((o), debug
, f, ##a)
#
define OUTP_TRACE(o,f,a...) OUTP_MSG((o), trace, f, ##a)
#endif
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
浏览文件 @
f2c906fc
...
...
@@ -33,7 +33,7 @@
int
nvkm_output_dp_train
(
struct
nvkm_output
*
base
,
u32
datarate
,
bool
wait
)
{
struct
nvkm_output_dp
*
outp
=
(
void
*
)
base
;
struct
nvkm_output_dp
*
outp
=
nvkm_output_dp
(
base
)
;
bool
retrain
=
true
;
u8
link
[
2
],
stat
[
3
];
u32
linkrate
;
...
...
@@ -42,7 +42,8 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
/* check that the link is trained at a high enough rate */
ret
=
nvkm_rdaux
(
outp
->
aux
,
DPCD_LC00_LINK_BW_SET
,
link
,
2
);
if
(
ret
)
{
DBG
(
"failed to read link config, assuming no sink
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"failed to read link config, assuming no sink"
);
goto
done
;
}
...
...
@@ -50,14 +51,15 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
linkrate
=
(
linkrate
*
8
)
/
10
;
/* 8B/10B coding overhead */
datarate
=
(
datarate
+
9
)
/
10
;
/* -> decakilobits */
if
(
linkrate
<
datarate
)
{
DBG
(
"link not trained at sufficient rate
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"link not trained at sufficient rate
"
);
goto
done
;
}
/* check that link is still trained */
ret
=
nvkm_rdaux
(
outp
->
aux
,
DPCD_LS02
,
stat
,
3
);
if
(
ret
)
{
DBG
(
"failed to read link status, assuming no sink
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"failed to read link status, assuming no sink"
);
goto
done
;
}
...
...
@@ -67,13 +69,14 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
if
(
!
(
lane
&
DPCD_LS02_LANE0_CR_DONE
)
||
!
(
lane
&
DPCD_LS02_LANE0_CHANNEL_EQ_DONE
)
||
!
(
lane
&
DPCD_LS02_LANE0_SYMBOL_LOCKED
))
{
DBG
(
"lane %d not equalised
\n
"
,
lane
);
OUTP_DBG
(
&
outp
->
base
,
"lane %d not equalised"
,
lane
);
goto
done
;
}
}
retrain
=
false
;
}
else
{
DBG
(
"no inter-lane alignment
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"no inter-lane alignment
"
);
}
done:
...
...
@@ -108,7 +111,7 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
if
(
enable
)
{
if
(
!
outp
->
present
)
{
DBG
(
"aux power -> always
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"aux power -> always
"
);
nvkm_i2c_aux_monitor
(
aux
,
true
);
outp
->
present
=
true
;
}
...
...
@@ -121,7 +124,7 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
}
if
(
outp
->
present
)
{
DBG
(
"aux power -> demand
\n
"
);
OUTP_DBG
(
&
outp
->
base
,
"aux power -> demand
"
);
nvkm_i2c_aux_monitor
(
aux
,
false
);
outp
->
present
=
false
;
}
...
...
@@ -132,116 +135,108 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
static
int
nvkm_output_dp_hpd
(
struct
nvkm_notify
*
notify
)
{
struct
nvkm_connector
*
conn
=
container_of
(
notify
,
typeof
(
*
conn
),
hpd
);
struct
nvkm_output_dp
*
outp
;
struct
nvkm_disp
*
disp
=
nvkm_disp
(
conn
);
const
struct
nvkm_i2c_ntfy_rep
*
line
=
notify
->
data
;
struct
nvkm_output_dp
*
outp
=
container_of
(
notify
,
typeof
(
*
outp
),
hpd
);
struct
nvkm_connector
*
conn
=
outp
->
base
.
conn
;
struct
nvkm_disp
*
disp
=
outp
->
base
.
disp
;
struct
nvif_notify_conn_rep_v0
rep
=
{};
list_for_each_entry
(
outp
,
&
disp
->
outp
,
base
.
head
)
{
if
(
outp
->
base
.
conn
==
conn
&&
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
{
DBG
(
"HPD: %d
\n
"
,
line
->
mask
);
nvkm_output_dp_enable
(
outp
,
true
);
if
(
line
->
mask
&
NVKM_I2C_UNPLUG
)
rep
.
mask
|=
NVIF_NOTIFY_CONN_V0_UNPLUG
;
if
(
line
->
mask
&
NVKM_I2C_PLUG
)
rep
.
mask
|=
NVIF_NOTIFY_CONN_V0_PLUG
;
OUTP_DBG
(
&
outp
->
base
,
"HPD: %d"
,
line
->
mask
);
nvkm_output_dp_enable
(
outp
,
true
);
nvkm_event_send
(
&
disp
->
hpd
,
rep
.
mask
,
conn
->
index
,
&
rep
,
sizeof
(
rep
));
return
NVKM_NOTIFY_KEEP
;
}
}
if
(
line
->
mask
&
NVKM_I2C_UNPLUG
)
rep
.
mask
|=
NVIF_NOTIFY_CONN_V0_UNPLUG
;
if
(
line
->
mask
&
NVKM_I2C_PLUG
)
rep
.
mask
|=
NVIF_NOTIFY_CONN_V0_PLUG
;
WARN_ON
(
1
);
return
NVKM_NOTIFY_
DRO
P
;
nvkm_event_send
(
&
disp
->
hpd
,
rep
.
mask
,
conn
->
index
,
&
rep
,
sizeof
(
rep
)
);
return
NVKM_NOTIFY_
KEE
P
;
}
static
int
nvkm_output_dp_irq
(
struct
nvkm_notify
*
notify
)
{
struct
nvkm_output_dp
*
outp
=
container_of
(
notify
,
typeof
(
*
outp
),
irq
);
struct
nvkm_disp
*
disp
=
nvkm_disp
(
outp
);
const
struct
nvkm_i2c_ntfy_rep
*
line
=
notify
->
data
;
struct
nvkm_output_dp
*
outp
=
container_of
(
notify
,
typeof
(
*
outp
),
irq
);
struct
nvkm_connector
*
conn
=
outp
->
base
.
conn
;
struct
nvkm_disp
*
disp
=
outp
->
base
.
disp
;
struct
nvif_notify_conn_rep_v0
rep
=
{
.
mask
=
NVIF_NOTIFY_CONN_V0_IRQ
,
};
int
index
=
outp
->
base
.
info
.
connector
;
DBG
(
"IRQ: %d
\n
"
,
line
->
mask
);
OUTP_DBG
(
&
outp
->
base
,
"IRQ: %d
"
,
line
->
mask
);
nvkm_output_dp_train
(
&
outp
->
base
,
0
,
true
);
nvkm_event_send
(
&
disp
->
hpd
,
rep
.
mask
,
index
,
&
rep
,
sizeof
(
rep
));
nvkm_event_send
(
&
disp
->
hpd
,
rep
.
mask
,
conn
->
index
,
&
rep
,
sizeof
(
rep
));
return
NVKM_NOTIFY_DROP
;
}
int
_nvkm_output_dp_fini
(
struct
nvkm_object
*
object
,
bool
suspend
)
static
void
nvkm_output_dp_fini
(
struct
nvkm_output
*
base
)
{
struct
nvkm_output_dp
*
outp
=
(
void
*
)
object
;
struct
nvkm_output_dp
*
outp
=
nvkm_output_dp
(
base
);
nvkm_notify_put
(
&
outp
->
hpd
);
nvkm_notify_put
(
&
outp
->
irq
);
flush_work
(
&
outp
->
lt
.
work
);
nvkm_output_dp_enable
(
outp
,
false
);
return
nvkm_output_fini
(
&
outp
->
base
,
suspend
);
}
int
_nvkm_output_dp_init
(
struct
nvkm_object
*
object
)
static
void
nvkm_output_dp_init
(
struct
nvkm_output
*
base
)
{
struct
nvkm_output_dp
*
outp
=
(
void
*
)
object
;
struct
nvkm_output_dp
*
outp
=
nvkm_output_dp
(
base
);
nvkm_notify_put
(
&
outp
->
base
.
conn
->
hpd
);
nvkm_output_dp_enable
(
outp
,
true
);
return
nvkm_output_init
(
&
outp
->
base
);
nvkm_notify_get
(
&
outp
->
hpd
);
}
void
_nvkm_output_dp_dtor
(
struct
nvkm_object
*
object
)
static
void
*
nvkm_output_dp_dtor
(
struct
nvkm_output
*
base
)
{
struct
nvkm_output_dp
*
outp
=
(
void
*
)
object
;
struct
nvkm_output_dp
*
outp
=
nvkm_output_dp
(
base
);
nvkm_notify_fini
(
&
outp
->
hpd
);
nvkm_notify_fini
(
&
outp
->
irq
);
nvkm_output_destroy
(
&
outp
->
base
)
;
return
outp
;
}
static
const
struct
nvkm_output_func
nvkm_output_dp_func
=
{
.
dtor
=
nvkm_output_dp_dtor
,
.
init
=
nvkm_output_dp_init
,
.
fini
=
nvkm_output_dp_fini
,
};
int
nvkm_output_dp_create_
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
struct
dcb_output
*
info
,
int
index
,
int
length
,
void
**
pobject
)
nvkm_output_dp_ctor
(
const
struct
nvkm_output_dp_func
*
func
,
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_i2c_aux
*
aux
,
struct
nvkm_output_dp
*
outp
)
{
struct
nvkm_
bios
*
bios
=
nvkm_bios
(
parent
)
;
struct
nvkm_
i2c
*
i2c
=
nvkm_i2c
(
parent
)
;
struct
nvkm_
output_dp
*
outp
;
struct
nvkm_
device
*
device
=
disp
->
engine
.
subdev
.
device
;
struct
nvkm_
bios
*
bios
=
device
->
bios
;
struct
nvkm_
i2c
*
i2c
=
device
->
i2c
;
u8
hdr
,
cnt
,
len
;
u32
data
;
int
ret
;
ret
=
nvkm_output_create_
(
parent
,
engine
,
oclass
,
info
,
index
,
length
,
pobject
);
outp
=
*
pobject
;
if
(
ret
)
return
ret
;
nvkm_notify_fini
(
&
outp
->
base
.
conn
->
hpd
);
/* access to the aux channel is not optional... */
//XXX: breaks anx support
outp
->
aux
=
nvkm_i2c_aux_find
(
i2c
,
outp
->
base
.
info
.
i2c_index
);
nvkm_output_ctor
(
&
nvkm_output_dp_func
,
disp
,
index
,
dcbE
,
&
outp
->
base
);
outp
->
func
=
func
;
outp
->
aux
=
aux
;
if
(
!
outp
->
aux
)
{
ERR
(
"aux channel not found
\n
"
);
OUTP_ERR
(
&
outp
->
base
,
"no aux
"
);
return
-
ENODEV
;
}
/*
nor is the bios data for this output...
*/
/*
bios data is not optional
*/
data
=
nvbios_dpout_match
(
bios
,
outp
->
base
.
info
.
hasht
,
outp
->
base
.
info
.
hashm
,
&
outp
->
version
,
&
hdr
,
&
cnt
,
&
len
,
&
outp
->
info
);
if
(
!
data
)
{
ERR
(
"no bios dp data
\n
"
);
OUTP_ERR
(
&
outp
->
base
,
"no bios dp data
"
);
return
-
ENODEV
;
}
DBG
(
"bios dp %02x %02x %02x %02x
\n
"
,
outp
->
version
,
hdr
,
cnt
,
len
);
OUTP_DBG
(
&
outp
->
base
,
"bios dp %02x %02x %02x %02x"
,
outp
->
version
,
hdr
,
cnt
,
len
);
/* link training */
INIT_WORK
(
&
outp
->
lt
.
work
,
nvkm_dp_train
);
...
...
@@ -258,7 +253,7 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
sizeof
(
struct
nvkm_i2c_ntfy_rep
),
&
outp
->
irq
);
if
(
ret
)
{
ERR
(
"error monitoring aux irq event: %d
\n
"
,
ret
);
OUTP_ERR
(
&
outp
->
base
,
"error monitoring aux irq: %d
"
,
ret
);
return
ret
;
}
...
...
@@ -270,9 +265,9 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
},
sizeof
(
struct
nvkm_i2c_ntfy_req
),
sizeof
(
struct
nvkm_i2c_ntfy_rep
),
&
outp
->
base
.
conn
->
hpd
);
&
outp
->
hpd
);
if
(
ret
)
{
ERR
(
"error monitoring aux hpd events: %d
\n
"
,
ret
);
OUTP_ERR
(
&
outp
->
base
,
"error monitoring aux hpd: %d
"
,
ret
);
return
ret
;
}
...
...
@@ -280,18 +275,17 @@ nvkm_output_dp_create_(struct nvkm_object *parent,
}
int
_nvkm_output_dp_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
info
,
u32
index
,
struct
nvkm_object
**
pobject
)
nvkm_output_dp_new_
(
const
struct
nvkm_output_dp_func
*
func
,
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
struct
nvkm_i2c
*
i2c
=
disp
->
engine
.
subdev
.
device
->
i2c
;
struct
nvkm_i2c_aux
*
aux
=
nvkm_i2c_aux_find
(
i2c
,
dcbE
->
i2c_index
);
struct
nvkm_output_dp
*
outp
;
int
ret
;
ret
=
nvkm_output_dp_create
(
parent
,
engine
,
oclass
,
info
,
index
,
&
outp
);
*
pobject
=
nv_object
(
outp
);
if
(
ret
)
return
ret
;
if
(
!
(
outp
=
kzalloc
(
sizeof
(
*
outp
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
poutp
=
&
outp
->
base
;
return
0
;
return
nvkm_output_dp_ctor
(
func
,
disp
,
index
,
dcbE
,
aux
,
outp
)
;
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
浏览文件 @
f2c906fc
#ifndef __NVKM_DISP_OUTP_DP_H__
#define __NVKM_DISP_OUTP_DP_H__
#define nvkm_output_dp(p) container_of((p), struct nvkm_output_dp, base)
#ifndef MSG
#define MSG(l,f,a...) \
nvkm_##l(&outp->base.disp->engine.subdev, "%02x:%04x:%04x: "f, \
outp->base.index, outp->base.info.hasht, \
outp->base.info.hashm, ##a)
#define DBG(f,a...) MSG(debug, f, ##a)
#define ERR(f,a...) MSG(error, f, ##a)
#endif
#include "outp.h"
#include <core/notify.h>
...
...
@@ -7,6 +16,7 @@
#include <subdev/bios/dp.h>
struct
nvkm_output_dp
{
const
struct
nvkm_output_dp_func
*
func
;
struct
nvkm_output
base
;
struct
nvbios_dpout
info
;
...
...
@@ -15,6 +25,7 @@ struct nvkm_output_dp {
struct
nvkm_i2c_aux
*
aux
;
struct
nvkm_notify
irq
;
struct
nvkm_notify
hpd
;
bool
present
;
u8
dpcd
[
16
];
...
...
@@ -25,34 +36,7 @@ struct nvkm_output_dp {
}
lt
;
};
#define nvkm_output_dp_create(p,e,c,b,i,d) \
nvkm_output_dp_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d)
#define nvkm_output_dp_destroy(d) ({ \
struct nvkm_output_dp *_outp = (d); \
_nvkm_output_dp_dtor(nv_object(_outp)); \
})
#define nvkm_output_dp_init(d) ({ \
struct nvkm_output_dp *_outp = (d); \
_nvkm_output_dp_init(nv_object(_outp)); \
})
#define nvkm_output_dp_fini(d,s) ({ \
struct nvkm_output_dp *_outp = (d); \
_nvkm_output_dp_fini(nv_object(_outp), (s)); \
})
int
nvkm_output_dp_create_
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
struct
dcb_output
*
,
int
,
int
,
void
**
);
int
_nvkm_output_dp_ctor
(
struct
nvkm_object
*
,
struct
nvkm_object
*
,
struct
nvkm_oclass
*
,
void
*
,
u32
,
struct
nvkm_object
**
);
void
_nvkm_output_dp_dtor
(
struct
nvkm_object
*
);
int
_nvkm_output_dp_init
(
struct
nvkm_object
*
);
int
_nvkm_output_dp_fini
(
struct
nvkm_object
*
,
bool
);
struct
nvkm_output_dp_impl
{
struct
nvkm_output_impl
base
;
struct
nvkm_output_dp_func
{
int
(
*
pattern
)(
struct
nvkm_output_dp
*
,
int
);
int
(
*
lnk_pwr
)(
struct
nvkm_output_dp
*
,
int
nr
);
int
(
*
lnk_ctl
)(
struct
nvkm_output_dp
*
,
int
nr
,
int
bw
,
bool
ef
);
...
...
@@ -60,4 +44,23 @@ struct nvkm_output_dp_impl {
};
int
nvkm_output_dp_train
(
struct
nvkm_output
*
,
u32
rate
,
bool
wait
);
int
nvkm_output_dp_ctor
(
const
struct
nvkm_output_dp_func
*
,
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_i2c_aux
*
,
struct
nvkm_output_dp
*
);
int
nvkm_output_dp_new_
(
const
struct
nvkm_output_dp_func
*
,
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
nv50_pior_dp_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
g94_sor_dp_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
gf110_sor_dp_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
gm204_sor_dp_new
(
struct
nvkm_disp
*
,
int
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
#endif
drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
浏览文件 @
f2c906fc
...
...
@@ -21,8 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#include "outpdp.h"
#include "nv50.h"
#include <core/client.h>
#include <subdev/i2c.h>
...
...
@@ -31,135 +31,101 @@
#include <nvif/class.h>
#include <nvif/unpack.h>
/******************************************************************************
* TMDS
*****************************************************************************/
static
int
nv50_pior_tmds_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
info
,
u32
index
,
struct
nvkm_object
**
pobject
)
int
nv50_pior_power
(
NV50_DISP_MTHD_V1
)
{
struct
nvkm_output
*
outp
;
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
const
u32
soff
=
outp
->
or
*
0x800
;
union
{
struct
nv50_disp_pior_pwr_v0
v0
;
}
*
args
=
data
;
u32
ctrl
,
type
;
int
ret
;
ret
=
nvkm_output_create
(
parent
,
engine
,
oclass
,
info
,
index
,
&
outp
);
*
pobject
=
nv_object
(
outp
);
if
(
ret
)
nvif_ioctl
(
object
,
"disp pior pwr size %d
\n
"
,
size
);
if
(
nvif_unpack
(
args
->
v0
,
0
,
0
,
false
))
{
nvif_ioctl
(
object
,
"disp pior pwr vers %d state %d type %x
\n
"
,
args
->
v0
.
version
,
args
->
v0
.
state
,
args
->
v0
.
type
);
if
(
args
->
v0
.
type
>
0x0f
)
return
-
EINVAL
;
ctrl
=
!!
args
->
v0
.
state
;
type
=
args
->
v0
.
type
;
}
else
return
ret
;
nvkm_msec
(
device
,
2000
,
if
(
!
(
nvkm_rd32
(
device
,
0x61e004
+
soff
)
&
0x80000000
))
break
;
);
nvkm_mask
(
device
,
0x61e004
+
soff
,
0x80000101
,
0x80000000
|
ctrl
);
nvkm_msec
(
device
,
2000
,
if
(
!
(
nvkm_rd32
(
device
,
0x61e004
+
soff
)
&
0x80000000
))
break
;
);
disp
->
pior
.
type
[
outp
->
or
]
=
type
;
return
0
;
}
struct
nvkm_output_impl
nv50_pior_tmds_impl
=
{
.
base
.
handle
=
DCB_OUTPUT_TMDS
|
0x0100
,
.
base
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
nv50_pior_tmds_ctor
,
.
dtor
=
_nvkm_output_dtor
,
.
init
=
_nvkm_output_init
,
.
fini
=
_nvkm_output_fini
,
},
};
/******************************************************************************
*
DisplayPort
*
TMDS
*****************************************************************************/
static
const
struct
nvkm_output_func
nv50_pior_output_func
=
{
};
static
int
nv50_pior_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
int
nv50_pior_output_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
-
ENODEV
;
return
nvkm_output_new_
(
&
nv50_pior_output_func
,
disp
,
index
,
dcbE
,
poutp
);
}
/******************************************************************************
* DisplayPort
*****************************************************************************/
static
int
nv50_pior_
dp_lnk_pwr
(
struct
nvkm_output_dp
*
outp
,
int
nr
)
nv50_pior_
output_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
{
return
0
;
}
static
int
nv50_pior_dp_lnk_ctl
(
struct
nvkm_output_dp
*
outp
,
int
nr
,
int
bw
,
bool
ef
)
{
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
)
nv50_pior_output_dp_lnk_pwr
(
struct
nvkm_output_dp
*
outp
,
int
nr
)
{
return
-
ENODEV
;
return
0
;
}
static
int
nv50_pior_dp_ctor
(
struct
nvkm_object
*
parent
,
struct
nvkm_object
*
engine
,
struct
nvkm_oclass
*
oclass
,
void
*
info
,
u32
index
,
struct
nvkm_object
**
pobject
)
nv50_pior_output_dp_lnk_ctl
(
struct
nvkm_output_dp
*
outp
,
int
nr
,
int
bw
,
bool
ef
)
{
struct
nvkm_i2c
*
i2c
=
nvkm_i2c
(
parent
);
struct
nvkm_output_dp
*
outp
;
int
ret
;
ret
=
nvkm_output_dp_create
(
parent
,
engine
,
oclass
,
info
,
index
,
&
outp
);
*
pobject
=
nv_object
(
outp
);
int
ret
=
nvkm_i2c_aux_lnk_ctl
(
outp
->
aux
,
nr
,
bw
,
ef
);
if
(
ret
)
return
ret
;
outp
->
aux
=
nvkm_i2c_aux_find
(
i2c
,
NVKM_I2C_AUX_EXT
(
outp
->
base
.
info
.
extdev
));
return
0
;
return
1
;
}
struct
nvkm_output_dp_impl
nv50_pior_dp_impl
=
{
.
base
.
base
.
handle
=
DCB_OUTPUT_DP
|
0x0010
,
.
base
.
base
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
nv50_pior_dp_ctor
,
.
dtor
=
_nvkm_output_dp_dtor
,
.
init
=
_nvkm_output_dp_init
,
.
fini
=
_nvkm_output_dp_fini
,
},
.
pattern
=
nv50_pior_dp_pattern
,
.
lnk_pwr
=
nv50_pior_dp_lnk_pwr
,
.
lnk_ctl
=
nv50_pior_dp_lnk_ctl
,
.
drv_ctl
=
nv50_pior_dp_drv_ctl
,
static
const
struct
nvkm_output_dp_func
nv50_pior_output_dp_func
=
{
.
pattern
=
nv50_pior_output_dp_pattern
,
.
lnk_pwr
=
nv50_pior_output_dp_lnk_pwr
,
.
lnk_ctl
=
nv50_pior_output_dp_lnk_ctl
,
};
/******************************************************************************
* General PIOR handling
*****************************************************************************/
int
nv50_pior_power
(
NV50_DISP_MTHD_V1
)
nv50_pior_dp_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
const
u32
soff
=
outp
->
or
*
0x800
;
union
{
struct
nv50_disp_pior_pwr_v0
v0
;
}
*
args
=
data
;
u32
ctrl
,
type
;
int
ret
;
struct
nvkm_i2c
*
i2c
=
disp
->
engine
.
subdev
.
device
->
i2c
;
struct
nvkm_i2c_aux
*
aux
=
nvkm_i2c_aux_find
(
i2c
,
NVKM_I2C_AUX_EXT
(
dcbE
->
extdev
));
struct
nvkm_output_dp
*
outp
;
nvif_ioctl
(
object
,
"disp pior pwr size %d
\n
"
,
size
);
if
(
nvif_unpack
(
args
->
v0
,
0
,
0
,
false
))
{
nvif_ioctl
(
object
,
"disp pior pwr vers %d state %d type %x
\n
"
,
args
->
v0
.
version
,
args
->
v0
.
state
,
args
->
v0
.
type
);
if
(
args
->
v0
.
type
>
0x0f
)
return
-
EINVAL
;
ctrl
=
!!
args
->
v0
.
state
;
type
=
args
->
v0
.
type
;
}
else
return
ret
;
if
(
!
(
outp
=
kzalloc
(
sizeof
(
*
outp
),
GFP_KERNEL
)))
return
-
ENOMEM
;
*
poutp
=
&
outp
->
base
;
nvkm_msec
(
device
,
2000
,
if
(
!
(
nvkm_rd32
(
device
,
0x61e004
+
soff
)
&
0x80000000
))
break
;
);
nvkm_mask
(
device
,
0x61e004
+
soff
,
0x80000101
,
0x80000000
|
ctrl
);
nvkm_msec
(
device
,
2000
,
if
(
!
(
nvkm_rd32
(
device
,
0x61e004
+
soff
)
&
0x80000000
))
break
;
);
disp
->
pior
.
type
[
outp
->
or
]
=
type
;
return
0
;
return
nvkm_output_dp_ctor
(
&
nv50_pior_output_dp_func
,
disp
,
index
,
dcbE
,
aux
,
outp
);
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
浏览文件 @
f2c906fc
#ifndef __NVKM_DISP_PRIV_H__
#define __NVKM_DISP_PRIV_H__
#include <engine/disp.h>
#include "outp.h"
#include "outpdp.h"
struct
nvkm_disp_func_outp
{
int
(
*
crt
)(
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
(
*
tv
)(
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
(
*
tmds
)(
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
(
*
lvds
)(
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
int
(
*
dp
)(
struct
nvkm_disp
*
,
int
index
,
struct
dcb_output
*
,
struct
nvkm_output
**
);
};
struct
nvkm_disp_impl
{
struct
nvkm_oclass
base
;
struct
nvkm_oclass
**
outp
;
struct
nvkm_oclass
**
conn
;
struct
{
const
struct
nvkm_disp_func_outp
internal
;
const
struct
nvkm_disp_func_outp
external
;
}
outp
;
const
struct
nvkm_event_func
*
vblank
;
};
...
...
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
浏览文件 @
f2c906fc
...
...
@@ -38,15 +38,33 @@ g94_sor_loff(struct nvkm_output_dp *outp)
return
g94_sor_soff
(
outp
)
+
!
(
outp
->
base
.
info
.
sorconf
.
link
&
1
)
*
0x80
;
}
/*******************************************************************************
* TMDS/LVDS
******************************************************************************/
static
const
struct
nvkm_output_func
g94_sor_output_func
=
{
};
int
g94_sor_output_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_new_
(
&
g94_sor_output_func
,
disp
,
index
,
dcbE
,
poutp
);
}
/*******************************************************************************
* DisplayPort
******************************************************************************/
u32
g94_sor_dp_lane_map
(
struct
nv
50_disp
*
disp
,
u8
lane
)
g94_sor_dp_lane_map
(
struct
nv
km_device
*
device
,
u8
lane
)
{
static
const
u8
gm100
[]
=
{
0
,
8
,
16
,
24
};
static
const
u8
mcp89
[]
=
{
24
,
16
,
8
,
0
};
/* thanks, apple.. */
static
const
u8
g94
[]
=
{
16
,
8
,
0
,
24
};
if
(
nv_device
(
disp
)
->
chipset
>=
0x110
)
if
(
device
->
chipset
>=
0x110
)
return
gm100
[
lane
];
if
(
nv_device
(
disp
)
->
chipset
==
0xaf
)
if
(
device
->
chipset
==
0xaf
)
return
mcp89
[
lane
];
return
g94
[
lane
];
}
...
...
@@ -54,8 +72,7 @@ g94_sor_dp_lane_map(struct nv50_disp *disp, u8 lane)
static
int
g94_sor_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
loff
=
g94_sor_loff
(
outp
);
nvkm_mask
(
device
,
0x61c10c
+
loff
,
0x0f000000
,
pattern
<<
24
);
return
0
;
...
...
@@ -64,14 +81,13 @@ g94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
int
g94_sor_dp_lnk_pwr
(
struct
nvkm_output_dp
*
outp
,
int
nr
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
g94_sor_soff
(
outp
);
const
u32
loff
=
g94_sor_loff
(
outp
);
u32
mask
=
0
,
i
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
mask
|=
1
<<
(
g94_sor_dp_lane_map
(
d
isp
,
i
)
>>
3
);
mask
|=
1
<<
(
g94_sor_dp_lane_map
(
d
evice
,
i
)
>>
3
);
nvkm_mask
(
device
,
0x61c130
+
loff
,
0x0000000f
,
mask
);
nvkm_mask
(
device
,
0x61c034
+
soff
,
0x80000000
,
0x80000000
);
...
...
@@ -85,8 +101,7 @@ g94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
static
int
g94_sor_dp_lnk_ctl
(
struct
nvkm_output_dp
*
outp
,
int
nr
,
int
bw
,
bool
ef
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
g94_sor_soff
(
outp
);
const
u32
loff
=
g94_sor_loff
(
outp
);
u32
dpctrl
=
0x00000000
;
...
...
@@ -106,10 +121,9 @@ g94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
static
int
g94_sor_dp_drv_ctl
(
struct
nvkm_output_dp
*
outp
,
int
ln
,
int
vs
,
int
pe
,
int
pc
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
const
u32
shift
=
g94_sor_dp_lane_map
(
d
isp
,
ln
);
const
u32
shift
=
g94_sor_dp_lane_map
(
d
evice
,
ln
);
const
u32
loff
=
g94_sor_loff
(
outp
);
u32
addr
,
data
[
3
];
u8
ver
,
hdr
,
cnt
,
len
;
...
...
@@ -118,12 +132,12 @@ g94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
addr
=
nvbios_dpout_match
(
bios
,
outp
->
base
.
info
.
hasht
,
outp
->
base
.
info
.
hashm
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info
);
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info
);
if
(
!
addr
)
return
-
ENODEV
;
addr
=
nvbios_dpcfg_match
(
bios
,
addr
,
0
,
vs
,
pe
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
ocfg
);
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
ocfg
);
if
(
!
addr
)
return
-
EINVAL
;
...
...
@@ -138,17 +152,17 @@ g94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
return
0
;
}
struct
nvkm_output_dp_impl
g94_sor_dp_impl
=
{
.
base
.
base
.
handle
=
DCB_OUTPUT_DP
,
.
base
.
base
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_output_dp_ctor
,
.
dtor
=
_nvkm_output_dp_dtor
,
.
init
=
_nvkm_output_dp_init
,
.
fini
=
_nvkm_output_dp_fini
,
},
static
const
struct
nvkm_output_dp_func
g94_sor_dp_func
=
{
.
pattern
=
g94_sor_dp_pattern
,
.
lnk_pwr
=
g94_sor_dp_lnk_pwr
,
.
lnk_ctl
=
g94_sor_dp_lnk_ctl
,
.
drv_ctl
=
g94_sor_dp_drv_ctl
,
};
int
g94_sor_dp_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_dp_new_
(
&
g94_sor_dp_func
,
disp
,
index
,
dcbE
,
poutp
);
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c
浏览文件 @
f2c906fc
...
...
@@ -39,8 +39,7 @@ gf110_sor_loff(struct nvkm_output_dp *outp)
static
int
gf110_sor_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
loff
=
gf110_sor_loff
(
outp
);
nvkm_mask
(
device
,
0x61c110
+
loff
,
0x0f0f0f0f
,
0x01010101
*
pattern
);
return
0
;
...
...
@@ -49,8 +48,7 @@ gf110_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
int
gf110_sor_dp_lnk_ctl
(
struct
nvkm_output_dp
*
outp
,
int
nr
,
int
bw
,
bool
ef
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
gf110_sor_soff
(
outp
);
const
u32
loff
=
gf110_sor_loff
(
outp
);
u32
dpctrl
=
0x00000000
;
...
...
@@ -70,10 +68,9 @@ static int
gf110_sor_dp_drv_ctl
(
struct
nvkm_output_dp
*
outp
,
int
ln
,
int
vs
,
int
pe
,
int
pc
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
const
u32
shift
=
g94_sor_dp_lane_map
(
d
isp
,
ln
);
const
u32
shift
=
g94_sor_dp_lane_map
(
d
evice
,
ln
);
const
u32
loff
=
gf110_sor_loff
(
outp
);
u32
addr
,
data
[
4
];
u8
ver
,
hdr
,
cnt
,
len
;
...
...
@@ -104,17 +101,17 @@ gf110_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
return
0
;
}
struct
nvkm_output_dp_impl
gf110_sor_dp_impl
=
{
.
base
.
base
.
handle
=
DCB_OUTPUT_DP
,
.
base
.
base
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_output_dp_ctor
,
.
dtor
=
_nvkm_output_dp_dtor
,
.
init
=
_nvkm_output_dp_init
,
.
fini
=
_nvkm_output_dp_fini
,
},
static
const
struct
nvkm_output_dp_func
gf110_sor_dp_func
=
{
.
pattern
=
gf110_sor_dp_pattern
,
.
lnk_pwr
=
g94_sor_dp_lnk_pwr
,
.
lnk_ctl
=
gf110_sor_dp_lnk_ctl
,
.
drv_ctl
=
gf110_sor_dp_drv_ctl
,
};
int
gf110_sor_dp_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_dp_new_
(
&
gf110_sor_dp_func
,
disp
,
index
,
dcbE
,
poutp
);
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c
浏览文件 @
f2c906fc
...
...
@@ -41,8 +41,7 @@ gm204_sor_loff(struct nvkm_output_dp *outp)
void
gm204_sor_magic
(
struct
nvkm_output
*
outp
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
outp
->
or
*
0x100
;
const
u32
data
=
outp
->
or
+
1
;
if
(
outp
->
info
.
sorconf
.
link
&
1
)
...
...
@@ -52,7 +51,7 @@ gm204_sor_magic(struct nvkm_output *outp)
}
static
inline
u32
gm204_sor_dp_lane_map
(
struct
nv
50_disp
*
disp
,
u8
lane
)
gm204_sor_dp_lane_map
(
struct
nv
km_device
*
device
,
u8
lane
)
{
return
lane
*
0x08
;
}
...
...
@@ -60,8 +59,7 @@ gm204_sor_dp_lane_map(struct nv50_disp *disp, u8 lane)
static
int
gm204_sor_dp_pattern
(
struct
nvkm_output_dp
*
outp
,
int
pattern
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
gm204_sor_soff
(
outp
);
const
u32
data
=
0x01010101
*
pattern
;
if
(
outp
->
base
.
info
.
sorconf
.
link
&
1
)
...
...
@@ -74,14 +72,13 @@ gm204_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
static
int
gm204_sor_dp_lnk_pwr
(
struct
nvkm_output_dp
*
outp
,
int
nr
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
const
u32
soff
=
gm204_sor_soff
(
outp
);
const
u32
loff
=
gm204_sor_loff
(
outp
);
u32
mask
=
0
,
i
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
mask
|=
1
<<
(
gm204_sor_dp_lane_map
(
d
isp
,
i
)
>>
3
);
mask
|=
1
<<
(
gm204_sor_dp_lane_map
(
d
evice
,
i
)
>>
3
);
nvkm_mask
(
device
,
0x61c130
+
loff
,
0x0000000f
,
mask
);
nvkm_mask
(
device
,
0x61c034
+
soff
,
0x80000000
,
0x80000000
);
...
...
@@ -96,10 +93,9 @@ static int
gm204_sor_dp_drv_ctl
(
struct
nvkm_output_dp
*
outp
,
int
ln
,
int
vs
,
int
pe
,
int
pc
)
{
struct
nv50_disp
*
disp
=
(
void
*
)
nvkm_disp
(
outp
);
struct
nvkm_device
*
device
=
disp
->
base
.
engine
.
subdev
.
device
;
struct
nvkm_device
*
device
=
outp
->
base
.
disp
->
engine
.
subdev
.
device
;
struct
nvkm_bios
*
bios
=
device
->
bios
;
const
u32
shift
=
gm204_sor_dp_lane_map
(
d
isp
,
ln
);
const
u32
shift
=
gm204_sor_dp_lane_map
(
d
evice
,
ln
);
const
u32
loff
=
gm204_sor_loff
(
outp
);
u32
addr
,
data
[
4
];
u8
ver
,
hdr
,
cnt
,
len
;
...
...
@@ -131,17 +127,17 @@ gm204_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
return
0
;
}
struct
nvkm_output_dp_impl
gm204_sor_dp_impl
=
{
.
base
.
base
.
handle
=
DCB_OUTPUT_DP
,
.
base
.
base
.
ofuncs
=
&
(
struct
nvkm_ofuncs
)
{
.
ctor
=
_nvkm_output_dp_ctor
,
.
dtor
=
_nvkm_output_dp_dtor
,
.
init
=
_nvkm_output_dp_init
,
.
fini
=
_nvkm_output_dp_fini
,
},
static
const
struct
nvkm_output_dp_func
gm204_sor_dp_func
=
{
.
pattern
=
gm204_sor_dp_pattern
,
.
lnk_pwr
=
gm204_sor_dp_lnk_pwr
,
.
lnk_ctl
=
gf110_sor_dp_lnk_ctl
,
.
drv_ctl
=
gm204_sor_dp_drv_ctl
,
};
int
gm204_sor_dp_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_dp_new_
(
&
gm204_sor_dp_func
,
disp
,
index
,
dcbE
,
poutp
);
}
drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
浏览文件 @
f2c906fc
...
...
@@ -65,3 +65,15 @@ nv50_sor_power(NV50_DISP_MTHD_V1)
);
return
0
;
}
static
const
struct
nvkm_output_func
nv50_sor_output_func
=
{
};
int
nv50_sor_output_new
(
struct
nvkm_disp
*
disp
,
int
index
,
struct
dcb_output
*
dcbE
,
struct
nvkm_output
**
poutp
)
{
return
nvkm_output_new_
(
&
nv50_sor_output_func
,
disp
,
index
,
dcbE
,
poutp
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录