Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
cec2a270
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
cec2a270
编写于
6月 17, 2011
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nva3/pm: tidy and add some comments here and there
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
4fd2847e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
78 addition
and
47 deletion
+78
-47
drivers/gpu/drm/nouveau/nva3_pm.c
drivers/gpu/drm/nouveau/nva3_pm.c
+78
-47
未找到文件。
drivers/gpu/drm/nouveau/nva3_pm.c
浏览文件 @
cec2a270
...
...
@@ -28,15 +28,15 @@
#include "nouveau_pm.h"
static
u32
read_clk
(
struct
drm_device
*
,
int
,
bool
);
static
u32
read_pll
(
struct
drm_device
*
,
u32
,
int
);
static
u32
read_pll
(
struct
drm_device
*
,
int
,
u32
);
static
u32
read_vco
(
struct
drm_device
*
dev
,
int
clk
)
{
u32
sctl
=
nv_rd32
(
dev
,
0x4120
+
(
clk
*
4
));
if
((
sctl
&
0x00000030
)
!=
0x00000030
)
return
read_pll
(
dev
,
0x
00e820
,
0x41
);
return
read_pll
(
dev
,
0x
00e8a0
,
0x42
);
return
read_pll
(
dev
,
0x
41
,
0x00e820
);
return
read_pll
(
dev
,
0x
42
,
0x00e8a0
);
}
static
u32
...
...
@@ -44,6 +44,7 @@ read_clk(struct drm_device *dev, int clk, bool ignore_en)
{
u32
sctl
,
sdiv
,
sclk
;
/* refclk for the 0xe8xx plls always 27KHz */
if
(
clk
>=
0x40
)
return
27000
;
...
...
@@ -68,7 +69,7 @@ read_clk(struct drm_device *dev, int clk, bool ignore_en)
}
static
u32
read_pll
(
struct
drm_device
*
dev
,
u32
pll
,
int
clk
)
read_pll
(
struct
drm_device
*
dev
,
int
clk
,
u32
pll
)
{
u32
ctrl
=
nv_rd32
(
dev
,
pll
+
0
);
u32
sclk
,
P
=
1
,
N
=
1
,
M
=
1
;
...
...
@@ -78,6 +79,8 @@ read_pll(struct drm_device *dev, u32 pll, int clk)
M
=
(
coef
&
0x000000ff
)
>>
0
;
N
=
(
coef
&
0x0000ff00
)
>>
8
;
P
=
(
coef
&
0x003f0000
)
>>
16
;
/* not post-divider on these.. */
if
((
pll
&
0x00ff00
)
==
0x00e800
)
P
=
1
;
...
...
@@ -95,7 +98,7 @@ struct creg {
};
static
int
calc_clk
(
struct
drm_device
*
dev
,
u32
pll
,
int
clk
,
u32
khz
,
struct
creg
*
reg
)
calc_clk
(
struct
drm_device
*
dev
,
int
clk
,
u32
pll
,
u32
khz
,
struct
creg
*
reg
)
{
struct
pll_lims
limits
;
u32
oclk
,
sclk
,
sdiv
;
...
...
@@ -104,6 +107,10 @@ calc_clk(struct drm_device *dev, u32 pll, int clk, u32 khz, struct creg *reg)
reg
->
pll
=
0
;
reg
->
clk
=
0
;
if
(
!
khz
)
{
NV_DEBUG
(
dev
,
"no clock for 0x%04x/0x%02x
\n
"
,
pll
,
clk
);
return
0
;
}
switch
(
khz
)
{
case
27000
:
...
...
@@ -118,6 +125,14 @@ calc_clk(struct drm_device *dev, u32 pll, int clk, u32 khz, struct creg *reg)
default:
sclk
=
read_vco
(
dev
,
clk
);
sdiv
=
min
((
sclk
*
2
)
/
(
khz
-
2999
),
(
u32
)
65
);
/* if the clock has a PLL attached, and we can get a within
* [-2, 3) MHz of a divider, we'll disable the PLL and use
* the divider instead.
*
* divider can go as low as 2, limited here because NVIDIA
* and the VBIOS on my NVA8 seem to prefer using the PLL
* for 810MHz - is there a good reason?
*/
if
(
sdiv
>
4
)
{
oclk
=
(
sclk
*
2
)
/
sdiv
;
diff
=
khz
-
oclk
;
...
...
@@ -126,6 +141,12 @@ calc_clk(struct drm_device *dev, u32 pll, int clk, u32 khz, struct creg *reg)
return
oclk
;
}
}
if
(
!
pll
)
{
NV_ERROR
(
dev
,
"bad freq %02x: %d %d
\n
"
,
clk
,
khz
,
sclk
);
return
-
ERANGE
;
}
break
;
}
...
...
@@ -145,12 +166,53 @@ calc_clk(struct drm_device *dev, u32 pll, int clk, u32 khz, struct creg *reg)
return
ret
;
}
static
void
prog_pll
(
struct
drm_device
*
dev
,
int
clk
,
u32
pll
,
struct
creg
*
reg
)
{
const
u32
src0
=
0x004120
+
(
clk
*
4
);
const
u32
src1
=
0x004160
+
(
clk
*
4
);
const
u32
ctrl
=
pll
+
0
;
const
u32
coef
=
pll
+
4
;
u32
cntl
;
if
(
!
reg
->
clk
&&
!
reg
->
pll
)
{
NV_DEBUG
(
dev
,
"no clock for %02x
\n
"
,
clk
);
return
;
}
cntl
=
nv_rd32
(
dev
,
ctrl
)
&
0xfffffff2
;
if
(
reg
->
pll
)
{
nv_mask
(
dev
,
src0
,
0x00000101
,
0x00000101
);
nv_wr32
(
dev
,
coef
,
reg
->
pll
);
nv_wr32
(
dev
,
ctrl
,
cntl
|
0x00000015
);
nv_mask
(
dev
,
src1
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
src1
,
0x00000001
,
0x00000000
);
}
else
{
nv_mask
(
dev
,
src1
,
0x003f3141
,
0x00000101
|
reg
->
clk
);
nv_wr32
(
dev
,
ctrl
,
cntl
|
0x0000001d
);
nv_mask
(
dev
,
ctrl
,
0x00000001
,
0x00000000
);
nv_mask
(
dev
,
src0
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
src0
,
0x00000001
,
0x00000000
);
}
}
static
void
prog_clk
(
struct
drm_device
*
dev
,
int
clk
,
struct
creg
*
reg
)
{
if
(
!
reg
->
clk
)
{
NV_DEBUG
(
dev
,
"no clock for %02x
\n
"
,
clk
);
return
;
}
nv_mask
(
dev
,
0x004120
+
(
clk
*
4
),
0x003f3141
,
0x00000101
|
reg
->
clk
);
}
int
nva3_pm_clocks_get
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*
perflvl
)
{
perflvl
->
core
=
read_pll
(
dev
,
0x
4200
,
0
);
perflvl
->
shader
=
read_pll
(
dev
,
0x
4220
,
1
);
perflvl
->
memory
=
read_pll
(
dev
,
0x
4000
,
2
);
perflvl
->
core
=
read_pll
(
dev
,
0x
00
,
0x420
0
);
perflvl
->
shader
=
read_pll
(
dev
,
0x
01
,
0x4220
);
perflvl
->
memory
=
read_pll
(
dev
,
0x
02
,
0x4000
);
perflvl
->
unka0
=
read_clk
(
dev
,
0x20
,
false
);
perflvl
->
vdec
=
read_clk
(
dev
,
0x21
,
false
);
return
0
;
...
...
@@ -174,23 +236,23 @@ nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
if
(
!
info
)
return
ERR_PTR
(
-
ENOMEM
);
ret
=
calc_clk
(
dev
,
0x
4200
,
0x1
0
,
perflvl
->
core
,
&
info
->
nclk
);
ret
=
calc_clk
(
dev
,
0x
10
,
0x420
0
,
perflvl
->
core
,
&
info
->
nclk
);
if
(
ret
<
0
)
goto
out
;
ret
=
calc_clk
(
dev
,
0x
4220
,
0x11
,
perflvl
->
shader
,
&
info
->
sclk
);
ret
=
calc_clk
(
dev
,
0x
11
,
0x4220
,
perflvl
->
shader
,
&
info
->
sclk
);
if
(
ret
<
0
)
goto
out
;
ret
=
calc_clk
(
dev
,
0x
4000
,
0x12
,
perflvl
->
memory
,
&
info
->
mclk
);
ret
=
calc_clk
(
dev
,
0x
12
,
0x4000
,
perflvl
->
memory
,
&
info
->
mclk
);
if
(
ret
<
0
)
goto
out
;
ret
=
calc_clk
(
dev
,
0x
0000
,
0x2
0
,
perflvl
->
unka0
,
&
info
->
unka0
);
ret
=
calc_clk
(
dev
,
0x
20
,
0x000
0
,
perflvl
->
unka0
,
&
info
->
unka0
);
if
(
ret
<
0
)
goto
out
;
ret
=
calc_clk
(
dev
,
0x
0000
,
0x21
,
perflvl
->
vdec
,
&
info
->
vdec
);
ret
=
calc_clk
(
dev
,
0x
21
,
0x0000
,
perflvl
->
vdec
,
&
info
->
vdec
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -202,51 +264,20 @@ nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
return
info
;
}
static
void
prog_pll
(
struct
drm_device
*
dev
,
u32
pll
,
int
clk
,
struct
creg
*
reg
)
{
const
u32
src0
=
0x004120
+
(
clk
*
4
);
const
u32
src1
=
0x004160
+
(
clk
*
4
);
const
u32
ctrl
=
pll
+
0
;
const
u32
coef
=
pll
+
4
;
u32
cntl
;
cntl
=
nv_rd32
(
dev
,
ctrl
)
&
0xfffffff2
;
if
(
reg
->
pll
)
{
nv_mask
(
dev
,
src0
,
0x00000101
,
0x00000101
);
nv_wr32
(
dev
,
coef
,
reg
->
pll
);
nv_wr32
(
dev
,
ctrl
,
cntl
|
0x00000015
);
nv_mask
(
dev
,
src1
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
src1
,
0x00000001
,
0x00000000
);
}
else
{
nv_mask
(
dev
,
src1
,
0x003f3141
,
0x00000101
|
reg
->
clk
);
nv_wr32
(
dev
,
ctrl
,
cntl
|
0x0000001d
);
nv_mask
(
dev
,
ctrl
,
0x00000001
,
0x00000000
);
nv_mask
(
dev
,
src0
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
src0
,
0x00000001
,
0x00000000
);
}
}
static
void
prog_clk
(
struct
drm_device
*
dev
,
int
clk
,
struct
creg
*
reg
)
{
nv_mask
(
dev
,
0x004120
+
(
clk
*
4
),
0x003f3141
,
0x00000101
|
reg
->
clk
);
}
void
nva3_pm_clocks_set
(
struct
drm_device
*
dev
,
void
*
pre_state
)
{
struct
nva3_pm_state
*
info
=
pre_state
;
prog_pll
(
dev
,
0x00
4200
,
0
,
&
info
->
nclk
);
prog_pll
(
dev
,
0x0
04220
,
1
,
&
info
->
sclk
);
prog_pll
(
dev
,
0x00
,
0x00420
0
,
&
info
->
nclk
);
prog_pll
(
dev
,
0x0
1
,
0x004220
,
&
info
->
sclk
);
prog_clk
(
dev
,
0x20
,
&
info
->
unka0
);
prog_clk
(
dev
,
0x21
,
&
info
->
vdec
);
nv_wr32
(
dev
,
0x100210
,
0
);
nv_wr32
(
dev
,
0x1002dc
,
1
);
nv_wr32
(
dev
,
0x004018
,
0x00001000
);
prog_pll
(
dev
,
0x0
04000
,
2
,
&
info
->
mclk
);
prog_pll
(
dev
,
0x0
2
,
0x004000
,
&
info
->
mclk
);
if
(
nv_rd32
(
dev
,
0x4000
)
&
0x00000008
)
nv_wr32
(
dev
,
0x004018
,
0x1000d000
);
else
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录