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
16d4c031
Commit
16d4c031
authored
Feb 20, 2013
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/nv50/disp: handle multiple actions from one set of supervisor intrs
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
a91ed42d
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
118 additions
and
108 deletions
+118
-108
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+118
-108
No files found.
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
View file @
16d4c031
...
@@ -972,21 +972,29 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
...
@@ -972,21 +972,29 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
}
}
static
void
static
void
nv50_disp_intr_unk10
(
struct
nv50_disp_priv
*
priv
,
u32
super
)
nv50_disp_intr_unk10
_0
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
{
int
head
=
ffs
((
super
&
0x00000060
)
>>
5
)
-
1
;
exec_script
(
priv
,
head
,
1
);
if
(
head
>=
0
)
{
}
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
if
(
head
>=
0
)
exec_script
(
priv
,
head
,
1
);
}
nv_wr32
(
priv
,
0x610030
,
0x80000000
);
static
void
nv50_disp_intr_unk20_0
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
exec_script
(
priv
,
head
,
2
);
}
}
static
void
static
void
nv50_disp_intr_unk20_dp
(
struct
nv50_disp_priv
*
priv
,
nv50_disp_intr_unk20_1
(
struct
nv50_disp_priv
*
priv
,
int
head
)
struct
dcb_output
*
outp
,
u32
pclk
)
{
struct
nouveau_clock
*
clk
=
nouveau_clock
(
priv
);
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
if
(
pclk
)
clk
->
pll_set
(
clk
,
PLL_VPLL0
+
head
,
pclk
);
}
static
void
nv50_disp_intr_unk20_2_dp
(
struct
nv50_disp_priv
*
priv
,
struct
dcb_output
*
outp
,
u32
pclk
)
{
{
const
int
link
=
!
(
outp
->
sorconf
.
link
&
1
);
const
int
link
=
!
(
outp
->
sorconf
.
link
&
1
);
const
int
or
=
ffs
(
outp
->
or
)
-
1
;
const
int
or
=
ffs
(
outp
->
or
)
-
1
;
...
@@ -1092,77 +1100,54 @@ nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv,
...
@@ -1092,77 +1100,54 @@ nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv,
}
}
static
void
static
void
nv50_disp_intr_unk20
(
struct
nv50_disp_priv
*
priv
,
u32
super
)
nv50_disp_intr_unk20
_2
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
{
struct
dcb_output
outp
;
struct
dcb_output
outp
;
int
head
;
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
u32
hval
,
hreg
=
0x614200
+
(
head
*
0x800
);
/* finish detaching encoder? */
u32
oval
,
oreg
;
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
u32
conf
=
exec_clkcmp
(
priv
,
head
,
0xff
,
pclk
,
&
outp
);
if
(
head
>=
0
)
if
(
conf
!=
~
0
)
{
exec_script
(
priv
,
head
,
2
);
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
/* check whether a vpll change is required */
u32
ctrl
=
nv_rd32
(
priv
,
0x610798
+
soff
);
head
=
ffs
((
super
&
0x00000600
)
>>
9
)
-
1
;
u32
datarate
;
if
(
head
>=
0
)
{
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
switch
((
ctrl
&
0x000f0000
)
>>
16
)
{
if
(
pclk
)
{
case
6
:
datarate
=
pclk
*
30
/
8
;
break
;
struct
nouveau_clock
*
clk
=
nouveau_clock
(
priv
);
case
5
:
datarate
=
pclk
*
24
/
8
;
break
;
clk
->
pll_set
(
clk
,
PLL_VPLL0
+
head
,
pclk
);
case
2
:
}
default:
}
datarate
=
pclk
*
18
/
8
;
break
;
/* (re)attach the relevant OR to the head */
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
if
(
head
>=
0
)
{
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
u32
hval
,
hreg
=
0x614200
+
(
head
*
0x800
);
u32
oval
,
oreg
;
u32
conf
=
exec_clkcmp
(
priv
,
head
,
0xff
,
pclk
,
&
outp
);
if
(
conf
!=
~
0
)
{
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
u32
ctrl
=
nv_rd32
(
priv
,
0x610798
+
soff
);
u32
datarate
;
switch
((
ctrl
&
0x000f0000
)
>>
16
)
{
case
6
:
datarate
=
pclk
*
30
/
8
;
break
;
case
5
:
datarate
=
pclk
*
24
/
8
;
break
;
case
2
:
default:
datarate
=
pclk
*
18
/
8
;
break
;
}
nouveau_dp_train
(
&
priv
->
base
,
priv
->
sor
.
dp
,
&
outp
,
head
,
datarate
);
}
}
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
outp
);
nouveau_dp_train
(
&
priv
->
base
,
priv
->
sor
.
dp
,
&
outp
,
head
,
datarate
);
if
(
!
outp
.
location
&&
outp
.
type
==
DCB_OUTPUT_ANALOG
)
{
}
oreg
=
0x614280
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
0x00000000
;
hval
=
0x00000000
;
}
else
if
(
!
outp
.
location
)
{
if
(
outp
.
type
==
DCB_OUTPUT_DP
)
nv50_disp_intr_unk20_dp
(
priv
,
&
outp
,
pclk
);
oreg
=
0x614300
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
(
conf
&
0x0100
)
?
0x0101
:
0x0000
;
hval
=
0x00000000
;
}
else
{
oreg
=
0x614380
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
0x00000001
;
hval
=
0x00000001
;
}
nv_mask
(
priv
,
hreg
,
0x0000000f
,
hval
);
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
outp
);
nv_mask
(
priv
,
oreg
,
0x00000707
,
oval
);
if
(
!
outp
.
location
&&
outp
.
type
==
DCB_OUTPUT_ANALOG
)
{
oreg
=
0x614280
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
0x00000000
;
hval
=
0x00000000
;
}
else
if
(
!
outp
.
location
)
{
if
(
outp
.
type
==
DCB_OUTPUT_DP
)
nv50_disp_intr_unk20_2_dp
(
priv
,
&
outp
,
pclk
);
oreg
=
0x614300
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
(
conf
&
0x0100
)
?
0x00000101
:
0x00000000
;
hval
=
0x00000000
;
}
else
{
oreg
=
0x614380
+
(
ffs
(
outp
.
or
)
-
1
)
*
0x800
;
oval
=
0x00000001
;
hval
=
0x00000001
;
}
}
}
nv_wr32
(
priv
,
0x610030
,
0x80000000
);
nv_mask
(
priv
,
hreg
,
0x0000000f
,
hval
);
nv_mask
(
priv
,
oreg
,
0x00000707
,
oval
);
}
}
}
/* If programming a TMDS output on a SOR that can also be configured for
/* If programming a TMDS output on a SOR that can also be configured for
...
@@ -1174,7 +1159,7 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
...
@@ -1174,7 +1159,7 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
* programmed for DisplayPort.
* programmed for DisplayPort.
*/
*/
static
void
static
void
nv50_disp_intr_unk40_tmds
(
struct
nv50_disp_priv
*
priv
,
struct
dcb_output
*
outp
)
nv50_disp_intr_unk40_
0_
tmds
(
struct
nv50_disp_priv
*
priv
,
struct
dcb_output
*
outp
)
{
{
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
struct
nouveau_bios
*
bios
=
nouveau_bios
(
priv
);
const
int
link
=
!
(
outp
->
sorconf
.
link
&
1
);
const
int
link
=
!
(
outp
->
sorconf
.
link
&
1
);
...
@@ -1188,37 +1173,32 @@ nv50_disp_intr_unk40_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
...
@@ -1188,37 +1173,32 @@ nv50_disp_intr_unk40_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
}
}
static
void
static
void
nv50_disp_intr_unk40
(
struct
nv50_disp_priv
*
priv
,
u32
super
)
nv50_disp_intr_unk40
_0
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
{
int
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
struct
dcb_output
outp
;
if
(
head
>=
0
)
{
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
struct
dcb_output
outp
;
if
(
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
outp
)
!=
~
0
)
{
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_TMDS
)
if
(
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
outp
)
!=
~
0
)
{
nv50_disp_intr_unk40_0_tmds
(
priv
,
&
outp
);
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_TMDS
)
else
nv50_disp_intr_unk40_tmds
(
priv
,
&
outp
);
if
(
outp
.
location
==
1
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
else
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
if
(
outp
.
location
==
1
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
u32
ctrl
=
nv_rd32
(
priv
,
0x610b84
+
soff
);
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
u32
datarate
;
u32
ctrl
=
nv_rd32
(
priv
,
0x610b84
+
soff
);
u32
datarate
;
switch
((
ctrl
&
0x000f0000
)
>>
16
)
{
case
6
:
datarate
=
pclk
*
30
/
8
;
break
;
switch
((
ctrl
&
0x000f0000
)
>>
16
)
{
case
5
:
datarate
=
pclk
*
24
/
8
;
break
;
case
6
:
datarate
=
pclk
*
30
/
8
;
break
;
case
2
:
case
5
:
datarate
=
pclk
*
24
/
8
;
break
;
default:
case
2
:
datarate
=
pclk
*
18
/
8
;
default:
break
;
datarate
=
pclk
*
18
/
8
;
break
;
}
nouveau_dp_train
(
&
priv
->
base
,
priv
->
pior
.
dp
,
&
outp
,
head
,
datarate
);
}
}
nouveau_dp_train
(
&
priv
->
base
,
priv
->
pior
.
dp
,
&
outp
,
head
,
datarate
);
}
}
}
}
nv_wr32
(
priv
,
0x610030
,
0x80000000
);
}
}
void
void
...
@@ -1227,15 +1207,45 @@ nv50_disp_intr_supervisor(struct work_struct *work)
...
@@ -1227,15 +1207,45 @@ nv50_disp_intr_supervisor(struct work_struct *work)
struct
nv50_disp_priv
*
priv
=
struct
nv50_disp_priv
*
priv
=
container_of
(
work
,
struct
nv50_disp_priv
,
supervisor
);
container_of
(
work
,
struct
nv50_disp_priv
,
supervisor
);
u32
super
=
nv_rd32
(
priv
,
0x610030
);
u32
super
=
nv_rd32
(
priv
,
0x610030
);
int
head
;
nv_debug
(
priv
,
"supervisor 0x%08x 0x%08x
\n
"
,
priv
->
super
,
super
);
nv_debug
(
priv
,
"supervisor 0x%08x 0x%08x
\n
"
,
priv
->
super
,
super
);
if
(
priv
->
super
&
0x00000010
)
if
(
priv
->
super
&
0x00000010
)
{
nv50_disp_intr_unk10
(
priv
,
super
);
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
priv
->
super
&
0x00000020
)
if
(
!
(
super
&
(
0x00000020
<<
head
)))
nv50_disp_intr_unk20
(
priv
,
super
);
continue
;
if
(
priv
->
super
&
0x00000040
)
if
(
!
(
super
&
(
0x00000080
<<
head
)))
nv50_disp_intr_unk40
(
priv
,
super
);
continue
;
nv50_disp_intr_unk10_0
(
priv
,
head
);
}
}
else
if
(
priv
->
super
&
0x00000020
)
{
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
!
(
super
&
(
0x00000080
<<
head
)))
continue
;
nv50_disp_intr_unk20_0
(
priv
,
head
);
}
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
!
(
super
&
(
0x00000200
<<
head
)))
continue
;
nv50_disp_intr_unk20_1
(
priv
,
head
);
}
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
!
(
super
&
(
0x00000080
<<
head
)))
continue
;
nv50_disp_intr_unk20_2
(
priv
,
head
);
}
}
else
if
(
priv
->
super
&
0x00000040
)
{
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
!
(
super
&
(
0x00000080
<<
head
)))
continue
;
nv50_disp_intr_unk40_0
(
priv
,
head
);
}
}
nv_wr32
(
priv
,
0x610030
,
0x80000000
);
}
}
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