Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
f2c906fc
Commit
f2c906fc
authored
Aug 20, 2015
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/nouveau/disp: transition outp/conn away from being based on nvkm_object
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
2aa5eac5
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
629 additions
and
635 deletions
+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
No files found.
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment