Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
16d4c031
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
16d4c031
编写于
2月 20, 2013
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nv50/disp: handle multiple actions from one set of supervisor intrs
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
a91ed42d
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
118 addition
and
108 deletion
+118
-108
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+118
-108
未找到文件。
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
浏览文件 @
16d4c031
...
...
@@ -972,21 +972,29 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
}
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
;
if
(
head
>=
0
)
{
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
if
(
head
>=
0
)
exec_script
(
priv
,
head
,
1
);
}
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
nv50_disp_intr_unk20_dp
(
struct
nv50_disp_priv
*
priv
,
struct
dcb_output
*
outp
,
u32
pclk
)
nv50_disp_intr_unk20_1
(
struct
nv50_disp_priv
*
priv
,
int
head
)
{
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
or
=
ffs
(
outp
->
or
)
-
1
;
...
...
@@ -1092,77 +1100,54 @@ nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv,
}
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
;
int
head
;
/* finish detaching encoder? */
head
=
ffs
((
super
&
0x00000180
)
>>
7
)
-
1
;
if
(
head
>=
0
)
exec_script
(
priv
,
head
,
2
);
/* check whether a vpll change is required */
head
=
ffs
((
super
&
0x00000600
)
>>
9
)
-
1
;
if
(
head
>=
0
)
{
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
if
(
pclk
)
{
struct
nouveau_clock
*
clk
=
nouveau_clock
(
priv
);
clk
->
pll_set
(
clk
,
PLL_VPLL0
+
head
,
pclk
);
}
}
/* (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
);
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
;
}
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
outp
);
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
;
}
nouveau_dp_train
(
&
priv
->
base
,
priv
->
sor
.
dp
,
&
outp
,
head
,
datarate
);
}
nv_mask
(
priv
,
hreg
,
0x0000000f
,
hval
);
nv_mask
(
priv
,
oreg
,
0x00000707
,
oval
);
exec_clkcmp
(
priv
,
head
,
0
,
pclk
,
&
outp
);
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
...
...
@@ -1174,7 +1159,7 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
* programmed for DisplayPort.
*/
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
);
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)
}
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
;
if
(
head
>=
0
)
{
struct
dcb_output
outp
;
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
if
(
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
outp
)
!=
~
0
)
{
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_TMDS
)
nv50_disp_intr_unk40_tmds
(
priv
,
&
outp
);
else
if
(
outp
.
location
==
1
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
u32
ctrl
=
nv_rd32
(
priv
,
0x610b84
+
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
->
pior
.
dp
,
&
outp
,
head
,
datarate
);
struct
dcb_output
outp
;
u32
pclk
=
nv_rd32
(
priv
,
0x610ad0
+
(
head
*
0x540
))
&
0x3fffff
;
if
(
exec_clkcmp
(
priv
,
head
,
1
,
pclk
,
&
outp
)
!=
~
0
)
{
if
(
outp
.
location
==
0
&&
outp
.
type
==
DCB_OUTPUT_TMDS
)
nv50_disp_intr_unk40_0_tmds
(
priv
,
&
outp
);
else
if
(
outp
.
location
==
1
&&
outp
.
type
==
DCB_OUTPUT_DP
)
{
u32
soff
=
(
ffs
(
outp
.
or
)
-
1
)
*
0x08
;
u32
ctrl
=
nv_rd32
(
priv
,
0x610b84
+
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
->
pior
.
dp
,
&
outp
,
head
,
datarate
);
}
}
nv_wr32
(
priv
,
0x610030
,
0x80000000
);
}
void
...
...
@@ -1227,15 +1207,45 @@ nv50_disp_intr_supervisor(struct work_struct *work)
struct
nv50_disp_priv
*
priv
=
container_of
(
work
,
struct
nv50_disp_priv
,
supervisor
);
u32
super
=
nv_rd32
(
priv
,
0x610030
);
int
head
;
nv_debug
(
priv
,
"supervisor 0x%08x 0x%08x
\n
"
,
priv
->
super
,
super
);
if
(
priv
->
super
&
0x00000010
)
nv50_disp_intr_unk10
(
priv
,
super
);
if
(
priv
->
super
&
0x00000020
)
nv50_disp_intr_unk20
(
priv
,
super
);
if
(
priv
->
super
&
0x00000040
)
nv50_disp_intr_unk40
(
priv
,
super
);
if
(
priv
->
super
&
0x00000010
)
{
for
(
head
=
0
;
head
<
priv
->
head
.
nr
;
head
++
)
{
if
(
!
(
super
&
(
0x00000020
<<
head
)))
continue
;
if
(
!
(
super
&
(
0x00000080
<<
head
)))
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
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录