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
nexedi
linux
Commits
2bd651ea
Commit
2bd651ea
authored
May 21, 2014
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/gf119/disp: start removing direct vbios parsing from supervisor
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
415f12ef
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
83 additions
and
75 deletions
+83
-75
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+83
-75
No files found.
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
View file @
2bd651ea
...
@@ -915,19 +915,20 @@ nvd0_disp_sclass[] = {
...
@@ -915,19 +915,20 @@ nvd0_disp_sclass[] = {
* Display engine implementation
* Display engine implementation
******************************************************************************/
******************************************************************************/
static
u16
static
struct
nvkm_output
*
exec_lookup
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
o
utp
,
u32
ctrl
,
exec_lookup
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
o
r
,
u32
ctrl
,
struct
dcb_output
*
dcb
,
u8
*
ver
,
u8
*
hdr
,
u8
*
cnt
,
u8
*
len
,
u32
*
data
,
u8
*
ver
,
u8
*
hdr
,
u8
*
cnt
,
u8
*
len
,
struct
nvbios_outp
*
info
)
struct
nvbios_outp
*
info
)
{
{
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
u16
mask
,
type
,
data
;
struct
nvkm_output
*
outp
;
u16
mask
,
type
;
if
(
o
utp
<
4
)
{
if
(
o
r
<
4
)
{
type
=
DCB_OUTPUT_ANALOG
;
type
=
DCB_OUTPUT_ANALOG
;
mask
=
0
;
mask
=
0
;
}
else
{
}
else
{
o
utp
-=
4
;
o
r
-=
4
;
switch
(
ctrl
&
0x00000f00
)
{
switch
(
ctrl
&
0x00000f00
)
{
case
0x00000000
:
type
=
DCB_OUTPUT_LVDS
;
mask
=
1
;
break
;
case
0x00000000
:
type
=
DCB_OUTPUT_LVDS
;
mask
=
1
;
break
;
case
0x00000100
:
type
=
DCB_OUTPUT_TMDS
;
mask
=
1
;
break
;
case
0x00000100
:
type
=
DCB_OUTPUT_TMDS
;
mask
=
1
;
break
;
...
@@ -939,47 +940,53 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
...
@@ -939,47 +940,53 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
nv_error
(
priv
,
"unknown SOR mc 0x%08x
\n
"
,
ctrl
);
nv_error
(
priv
,
"unknown SOR mc 0x%08x
\n
"
,
ctrl
);
return
0x0000
;
return
0x0000
;
}
}
dcb
->
sorconf
.
link
=
mask
;
}
}
mask
=
0x00c0
&
(
mask
<<
6
);
mask
=
0x00c0
&
(
mask
<<
6
);
mask
|=
0x0001
<<
o
utp
;
mask
|=
0x0001
<<
o
r
;
mask
|=
0x0100
<<
head
;
mask
|=
0x0100
<<
head
;
data
=
dcb_outp_match
(
bios
,
type
,
mask
,
ver
,
hdr
,
dcb
);
list_for_each_entry
(
outp
,
&
priv
->
base
.
outp
,
head
)
{
if
(
!
data
)
if
((
outp
->
info
.
hasht
&
0xff
)
==
type
&&
return
0x0000
;
(
outp
->
info
.
hashm
&
mask
)
==
mask
)
{
*
data
=
nvbios_outp_match
(
bios
,
outp
->
info
.
hasht
,
outp
->
info
.
hashm
,
ver
,
hdr
,
cnt
,
len
,
info
);
if
(
!*
data
)
return
NULL
;
return
outp
;
}
}
return
nvbios_outp_match
(
bios
,
type
,
mask
,
ver
,
hdr
,
cnt
,
len
,
info
)
;
return
NULL
;
}
}
static
bool
static
bool
exec_script
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
id
)
exec_script
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
id
)
{
{
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nvkm_output
*
outp
;
struct
nvbios_outp
info
;
struct
nvbios_outp
info
;
struct
dcb_output
dcb
;
u8
ver
,
hdr
,
cnt
,
len
;
u8
ver
,
hdr
,
cnt
,
len
;
u32
ctrl
=
0x00000000
;
u32
data
,
ctrl
=
0
;
u16
data
;
int
or
;
int
outp
;
for
(
o
utp
=
0
;
!
(
ctrl
&
(
1
<<
head
))
&&
outp
<
8
;
outp
++
)
{
for
(
o
r
=
0
;
!
(
ctrl
&
(
1
<<
head
))
&&
or
<
8
;
or
++
)
{
ctrl
=
nv_rd32
(
priv
,
0x640180
+
(
o
utp
*
0x20
));
ctrl
=
nv_rd32
(
priv
,
0x640180
+
(
o
r
*
0x20
));
if
(
ctrl
&
(
1
<<
head
))
if
(
ctrl
&
(
1
<<
head
))
break
;
break
;
}
}
if
(
o
utp
==
8
)
if
(
o
r
==
8
)
return
false
;
return
false
;
data
=
exec_lookup
(
priv
,
head
,
outp
,
ctrl
,
&
dcb
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info
);
outp
=
exec_lookup
(
priv
,
head
,
or
,
ctrl
,
&
data
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info
);
if
(
data
)
{
if
(
outp
)
{
struct
nvbios_init
init
=
{
struct
nvbios_init
init
=
{
.
subdev
=
nv_subdev
(
priv
),
.
subdev
=
nv_subdev
(
priv
),
.
bios
=
bios
,
.
bios
=
bios
,
.
offset
=
info
.
script
[
id
],
.
offset
=
info
.
script
[
id
],
.
outp
=
&
dcb
,
.
outp
=
&
outp
->
info
,
.
crtc
=
head
,
.
crtc
=
head
,
.
execute
=
1
,
.
execute
=
1
,
};
};
...
@@ -990,50 +997,49 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
...
@@ -990,50 +997,49 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
return
false
;
return
false
;
}
}
static
u32
static
struct
nvkm_output
*
exec_clkcmp
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
id
,
exec_clkcmp
(
struct
nv50_disp_priv
*
priv
,
int
head
,
int
id
,
u32
pclk
,
u32
*
conf
)
u32
pclk
,
struct
dcb_output
*
dcb
)
{
{
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nvkm_output
*
outp
;
struct
nvbios_outp
info1
;
struct
nvbios_outp
info1
;
struct
nvbios_ocfg
info2
;
struct
nvbios_ocfg
info2
;
u8
ver
,
hdr
,
cnt
,
len
;
u8
ver
,
hdr
,
cnt
,
len
;
u32
ctrl
=
0x00000000
;
u32
data
,
ctrl
=
0
;
u32
data
,
conf
=
~
0
;
int
or
;
int
outp
;
for
(
o
utp
=
0
;
!
(
ctrl
&
(
1
<<
head
))
&&
outp
<
8
;
outp
++
)
{
for
(
o
r
=
0
;
!
(
ctrl
&
(
1
<<
head
))
&&
or
<
8
;
or
++
)
{
ctrl
=
nv_rd32
(
priv
,
0x660180
+
(
o
utp
*
0x20
));
ctrl
=
nv_rd32
(
priv
,
0x660180
+
(
o
r
*
0x20
));
if
(
ctrl
&
(
1
<<
head
))
if
(
ctrl
&
(
1
<<
head
))
break
;
break
;
}
}
if
(
o
utp
==
8
)
if
(
o
r
==
8
)
return
conf
;
return
NULL
;
data
=
exec_lookup
(
priv
,
head
,
outp
,
ctrl
,
dcb
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info1
);
outp
=
exec_lookup
(
priv
,
head
,
or
,
ctrl
,
&
data
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info1
);
if
(
data
==
0x0000
)
if
(
!
outp
)
return
conf
;
return
NULL
;
switch
(
dcb
->
type
)
{
switch
(
outp
->
info
.
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_TMDS
:
conf
=
(
ctrl
&
0x00000f00
)
>>
8
;
*
conf
=
(
ctrl
&
0x00000f00
)
>>
8
;
if
(
pclk
>=
165000
)
if
(
pclk
>=
165000
)
conf
|=
0x0100
;
*
conf
|=
0x0100
;
break
;
break
;
case
DCB_OUTPUT_LVDS
:
case
DCB_OUTPUT_LVDS
:
conf
=
priv
->
sor
.
lvdsconf
;
*
conf
=
priv
->
sor
.
lvdsconf
;
break
;
break
;
case
DCB_OUTPUT_DP
:
case
DCB_OUTPUT_DP
:
conf
=
(
ctrl
&
0x00000f00
)
>>
8
;
*
conf
=
(
ctrl
&
0x00000f00
)
>>
8
;
break
;
break
;
case
DCB_OUTPUT_ANALOG
:
case
DCB_OUTPUT_ANALOG
:
default:
default:
conf
=
0x00ff
;
*
conf
=
0x00ff
;
break
;
break
;
}
}
data
=
nvbios_ocfg_match
(
bios
,
data
,
conf
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info2
);
data
=
nvbios_ocfg_match
(
bios
,
data
,
*
conf
,
&
ver
,
&
hdr
,
&
cnt
,
&
len
,
&
info2
);
if
(
data
&&
id
<
0xff
)
{
if
(
data
&&
id
<
0xff
)
{
data
=
nvbios_oclk_match
(
bios
,
info2
.
clkcmp
[
id
],
pclk
);
data
=
nvbios_oclk_match
(
bios
,
info2
.
clkcmp
[
id
],
pclk
);
if
(
data
)
{
if
(
data
)
{
...
@@ -1041,7 +1047,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
...
@@ -1041,7 +1047,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
.
subdev
=
nv_subdev
(
priv
),
.
subdev
=
nv_subdev
(
priv
),
.
bios
=
bios
,
.
bios
=
bios
,
.
offset
=
data
,
.
offset
=
data
,
.
outp
=
dcb
,
.
outp
=
&
outp
->
info
,
.
crtc
=
head
,
.
crtc
=
head
,
.
execute
=
1
,
.
execute
=
1
,
};
};
...
@@ -1050,7 +1056,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
...
@@ -1050,7 +1056,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
}
}
}
}
return
conf
;
return
outp
;
}
}
static
void
static
void
...
@@ -1124,49 +1130,51 @@ nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head,
...
@@ -1124,49 +1130,51 @@ nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head,
static
void
static
void
nvd0_disp_intr_unk2_2
(
struct
nv50_disp_priv
*
priv
,
int
head
)
nvd0_disp_intr_unk2_2
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
{
struct
dcb_output
outp
;
struct
nvkm_output
*
outp
;
u32
pclk
=
nv_rd32
(
priv
,
0x660450
+
(
head
*
0x300
))
/
1000
;
u32
pclk
=
nv_rd32
(
priv
,
0x660450
+
(
head
*
0x300
))
/
1000
;
u32
conf
=
exec_clkcmp
(
priv
,
head
,
0xff
,
pclk
,
&
outp
);
u32
conf
,
addr
,
data
;
if
(
conf
!=
~
0
)
{
u32
addr
,
data
;
outp
=
exec_clkcmp
(
priv
,
head
,
0xff
,
pclk
,
&
conf
);
if
(
!
outp
)
if
(
outp
.
type
==
DCB_OUTPUT_DP
)
{
return
;
u32
sync
=
nv_rd32
(
priv
,
0x660404
+
(
head
*
0x300
));
switch
((
sync
&
0x000003c0
)
>>
6
)
{
if
(
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
{
case
6
:
pclk
=
pclk
*
30
/
8
;
break
;
u32
sync
=
nv_rd32
(
priv
,
0x660404
+
(
head
*
0x300
));
case
5
:
pclk
=
pclk
*
24
/
8
;
break
;
switch
((
sync
&
0x000003c0
)
>>
6
)
{
case
2
:
case
6
:
pclk
=
pclk
*
30
/
8
;
break
;
default:
case
5
:
pclk
=
pclk
*
24
/
8
;
break
;
pclk
=
pclk
*
18
/
8
;
case
2
:
break
;
default:
}
pclk
=
pclk
*
18
/
8
;
break
;
nouveau_dp_train
(
&
priv
->
base
,
priv
->
sor
.
dp
,
&
outp
,
head
,
pclk
);
}
}
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
outp
);
nouveau_dp_train
(
&
priv
->
base
,
priv
->
sor
.
dp
,
&
outp
->
info
,
head
,
pclk
);
}
if
(
outp
.
type
==
DCB_OUTPUT_ANALOG
)
{
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
conf
);
addr
=
0x612280
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
data
=
0x00000000
;
}
else
{
if
(
outp
.
type
==
DCB_OUTPUT_DP
)
nvd0_disp_intr_unk2_2_tu
(
priv
,
head
,
&
outp
);
addr
=
0x612300
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
data
=
(
conf
&
0x0100
)
?
0x00000101
:
0x00000000
;
}
nv_mask
(
priv
,
addr
,
0x00000707
,
data
);
if
(
outp
->
info
.
type
==
DCB_OUTPUT_ANALOG
)
{
addr
=
0x612280
+
(
ffs
(
outp
->
info
.
or
)
-
1
)
*
0x800
;
data
=
0x00000000
;
}
else
{
if
(
outp
->
info
.
type
==
DCB_OUTPUT_DP
)
nvd0_disp_intr_unk2_2_tu
(
priv
,
head
,
&
outp
->
info
);
addr
=
0x612300
+
(
ffs
(
outp
->
info
.
or
)
-
1
)
*
0x800
;
data
=
(
conf
&
0x0100
)
?
0x00000101
:
0x00000000
;
}
}
nv_mask
(
priv
,
addr
,
0x00000707
,
data
);
}
}
static
void
static
void
nvd0_disp_intr_unk4_0
(
struct
nv50_disp_priv
*
priv
,
int
head
)
nvd0_disp_intr_unk4_0
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
{
struct
dcb_output
outp
;
u32
pclk
=
nv_rd32
(
priv
,
0x660450
+
(
head
*
0x300
))
/
1000
;
u32
pclk
=
nv_rd32
(
priv
,
0x660450
+
(
head
*
0x300
))
/
1000
;
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
outp
);
u32
conf
;
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
conf
);
}
}
void
void
...
...
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