Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
ca94a71f
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
ca94a71f
编写于
6月 17, 2011
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nva3/pm: rewrite clock_set, and switch to new interfaces
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
77e7da68
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
147 addition
and
143 deletion
+147
-143
drivers/gpu/drm/nouveau/nouveau_pm.h
drivers/gpu/drm/nouveau/nouveau_pm.h
+3
-4
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_state.c
+3
-3
drivers/gpu/drm/nouveau/nva3_pm.c
drivers/gpu/drm/nouveau/nva3_pm.c
+141
-136
未找到文件。
drivers/gpu/drm/nouveau/nouveau_pm.h
浏览文件 @
ca94a71f
...
...
@@ -59,10 +59,9 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
void
nv50_pm_clock_set
(
struct
drm_device
*
,
void
*
);
/* nva3_pm.c */
int
nva3_pm_clock_get
(
struct
drm_device
*
,
u32
id
);
void
*
nva3_pm_clock_pre
(
struct
drm_device
*
,
struct
nouveau_pm_level
*
,
u32
id
,
int
khz
);
void
nva3_pm_clock_set
(
struct
drm_device
*
,
void
*
);
int
nva3_pm_clocks_get
(
struct
drm_device
*
,
struct
nouveau_pm_level
*
);
void
*
nva3_pm_clocks_pre
(
struct
drm_device
*
,
struct
nouveau_pm_level
*
);
void
nva3_pm_clocks_set
(
struct
drm_device
*
,
void
*
);
/* nouveau_temp.c */
void
nouveau_temp_init
(
struct
drm_device
*
dev
);
...
...
drivers/gpu/drm/nouveau/nouveau_state.c
浏览文件 @
ca94a71f
...
...
@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine
->
pm
.
clock_set
=
nv50_pm_clock_set
;
break
;
default:
engine
->
pm
.
clock
_get
=
nva3_pm_clock
_get
;
engine
->
pm
.
clock
_pre
=
nva3_pm_clock
_pre
;
engine
->
pm
.
clock
_set
=
nva3_pm_clock
_set
;
engine
->
pm
.
clock
s_get
=
nva3_pm_clocks
_get
;
engine
->
pm
.
clock
s_pre
=
nva3_pm_clocks
_pre
;
engine
->
pm
.
clock
s_set
=
nva3_pm_clocks
_set
;
break
;
}
engine
->
pm
.
voltage_get
=
nouveau_voltage_gpio_get
;
...
...
drivers/gpu/drm/nouveau/nva3_pm.c
浏览文件 @
ca94a71f
...
...
@@ -27,11 +27,20 @@
#include "nouveau_bios.h"
#include "nouveau_pm.h"
static
u32
read_
pll
(
struct
drm_device
*
dev
,
u32
pll
,
int
clk
);
static
u32
read_
clk
(
struct
drm_device
*
dev
,
int
clk
);
static
u32
read_
clk
(
struct
drm_device
*
,
int
,
bool
);
static
u32
read_
pll
(
struct
drm_device
*
,
u32
,
int
);
static
u32
read_clk
(
struct
drm_device
*
dev
,
int
clk
)
read_vco
(
struct
drm_device
*
dev
,
int
clk
)
{
u32
sctl
=
nv_rd32
(
dev
,
0x4120
+
(
clk
*
4
));
if
((
sctl
&
0x00000030
)
!=
0x00000030
)
return
read_pll
(
dev
,
0x00e820
,
0x41
);
return
read_pll
(
dev
,
0x00e8a0
,
0x42
);
}
static
u32
read_clk
(
struct
drm_device
*
dev
,
int
clk
,
bool
ignore_en
)
{
u32
sctl
,
sdiv
,
sclk
;
...
...
@@ -39,20 +48,19 @@ read_clk(struct drm_device *dev, int clk)
return
27000
;
sctl
=
nv_rd32
(
dev
,
0x4120
+
(
clk
*
4
));
switch
(
sctl
&
0x00003100
)
{
case
0x00000100
:
if
(
!
ignore_en
&&
!
(
sctl
&
0x00000100
))
return
0
;
switch
(
sctl
&
0x00003000
)
{
case
0x00000000
:
return
27000
;
case
0x00002
1
00
:
case
0x00002
0
00
:
if
(
sctl
&
0x00000040
)
return
108000
;
return
100000
;
case
0x00003100
:
case
0x00003000
:
sclk
=
read_vco
(
dev
,
clk
);
sdiv
=
((
sctl
&
0x003f0000
)
>>
16
)
+
2
;
if
((
sctl
&
0x00000030
)
!=
0x00000030
)
sclk
=
read_pll
(
dev
,
0x00e820
,
0x41
);
else
sclk
=
read_pll
(
dev
,
0x00e8a0
,
0x42
);
return
(
sclk
*
2
)
/
sdiv
;
default:
return
0
;
...
...
@@ -73,161 +81,158 @@ read_pll(struct drm_device *dev, u32 pll, int clk)
if
((
pll
&
0x00ff00
)
==
0x00e800
)
P
=
1
;
sclk
=
read_clk
(
dev
,
0x00
+
clk
);
sclk
=
read_clk
(
dev
,
0x00
+
clk
,
false
);
}
else
{
sclk
=
read_clk
(
dev
,
0x10
+
clk
);
sclk
=
read_clk
(
dev
,
0x10
+
clk
,
false
);
}
return
sclk
*
N
/
(
M
*
P
);
}
struct
nva3_pm_state
{
enum
pll_types
type
;
u32
src0
;
u32
src1
;
u32
ctrl
;
u32
coef
;
u32
old_pnm
;
u32
new_pnm
;
u32
new_div
;
struct
creg
{
u32
clk
;
u32
pll
;
};
static
int
nva3_pm_pll_offset
(
u32
id
)
calc_clk
(
struct
drm_device
*
dev
,
u32
pll
,
int
clk
,
u32
khz
,
struct
creg
*
reg
)
{
static
const
u32
pll_map
[]
=
{
0x00
,
PLL_CORE
,
0x01
,
PLL_SHADER
,
0x02
,
PLL_MEMORY
,
0x00
,
0x00
};
const
u32
*
map
=
pll_map
;
while
(
map
[
1
])
{
if
(
id
==
map
[
1
])
return
map
[
0
];
map
+=
2
;
struct
pll_lims
limits
;
u32
oclk
,
sclk
,
sdiv
;
int
P
,
N
,
M
,
diff
;
int
ret
;
reg
->
pll
=
0
;
reg
->
clk
=
0
;
switch
(
khz
)
{
case
27000
:
reg
->
clk
=
0x00000100
;
return
khz
;
case
100000
:
reg
->
clk
=
0x00002100
;
return
khz
;
case
108000
:
reg
->
clk
=
0x00002140
;
return
khz
;
default:
sclk
=
read_vco
(
dev
,
clk
);
sdiv
=
min
((
sclk
*
2
)
/
(
khz
-
2999
),
(
u32
)
65
);
if
(
sdiv
>
4
)
{
oclk
=
(
sclk
*
2
)
/
sdiv
;
diff
=
khz
-
oclk
;
if
(
!
pll
||
(
diff
>=
-
2000
&&
diff
<
3000
))
{
reg
->
clk
=
(((
sdiv
-
2
)
<<
16
)
|
0x00003100
);
return
oclk
;
}
}
break
;
}
return
-
ENOENT
;
ret
=
get_pll_limits
(
dev
,
pll
,
&
limits
);
if
(
ret
)
return
ret
;
limits
.
refclk
=
read_clk
(
dev
,
clk
-
0x10
,
true
);
if
(
!
limits
.
refclk
)
return
-
EINVAL
;
ret
=
nva3_calc_pll
(
dev
,
&
limits
,
khz
,
&
N
,
NULL
,
&
M
,
&
P
);
if
(
ret
>=
0
)
{
reg
->
clk
=
nv_rd32
(
dev
,
0x4120
+
(
clk
*
4
));
reg
->
pll
=
(
P
<<
16
)
|
(
N
<<
8
)
|
M
;
}
return
ret
;
}
int
nva3_pm_clock
_get
(
struct
drm_device
*
dev
,
u32
id
)
nva3_pm_clock
s_get
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*
perflvl
)
{
switch
(
id
)
{
case
PLL_CORE
:
return
read_pll
(
dev
,
0x4200
,
0
);
case
PLL_SHADER
:
return
read_pll
(
dev
,
0x4220
,
1
);
case
PLL_MEMORY
:
return
read_pll
(
dev
,
0x4000
,
2
);
default:
return
-
ENOENT
;
}
perflvl
->
core
=
read_pll
(
dev
,
0x4200
,
0
);
perflvl
->
shader
=
read_pll
(
dev
,
0x4220
,
1
);
perflvl
->
memory
=
read_pll
(
dev
,
0x4000
,
2
);
return
0
;
}
struct
nva3_pm_state
{
struct
creg
nclk
;
struct
creg
sclk
;
struct
creg
mclk
;
};
void
*
nva3_pm_clock_pre
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*
perflvl
,
u32
id
,
int
khz
)
nva3_pm_clocks_pre
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*
perflvl
)
{
struct
nva3_pm_state
*
pll
;
struct
pll_lims
limits
;
int
N
,
M
,
P
,
diff
;
int
ret
,
off
;
struct
nva3_pm_state
*
info
;
int
ret
;
ret
=
get_pll_limits
(
dev
,
id
,
&
limits
);
info
=
kzalloc
(
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
return
ERR_PTR
(
-
ENOMEM
);
ret
=
calc_clk
(
dev
,
0x4200
,
0x10
,
perflvl
->
core
,
&
info
->
nclk
);
if
(
ret
<
0
)
return
(
ret
==
-
ENOENT
)
?
NULL
:
ERR_PTR
(
ret
)
;
goto
out
;
off
=
nva3_pm_pll_offset
(
id
);
if
(
id
<
0
)
return
ERR_PTR
(
-
EINVAL
)
;
ret
=
calc_clk
(
dev
,
0x4220
,
0x11
,
perflvl
->
shader
,
&
info
->
sclk
);
if
(
ret
<
0
)
goto
out
;
ret
=
calc_clk
(
dev
,
0x4000
,
0x12
,
perflvl
->
memory
,
&
info
->
mclk
);
if
(
ret
<
0
)
goto
out
;
pll
=
kzalloc
(
sizeof
(
*
pll
),
GFP_KERNEL
);
if
(
!
pll
)
return
ERR_PTR
(
-
ENOMEM
);
pll
->
type
=
id
;
pll
->
src0
=
0x004120
+
(
off
*
4
);
pll
->
src1
=
0x004160
+
(
off
*
4
);
pll
->
ctrl
=
limits
.
reg
+
0
;
pll
->
coef
=
limits
.
reg
+
4
;
/* If target clock is within [-2, 3) MHz of a divisor, we'll
* use that instead of calculating MNP values
*/
pll
->
new_div
=
min
((
limits
.
refclk
*
2
)
/
(
khz
-
2999
),
16
);
if
(
pll
->
new_div
)
{
diff
=
khz
-
((
limits
.
refclk
*
2
)
/
pll
->
new_div
);
if
(
diff
<
-
2000
||
diff
>=
3000
)
pll
->
new_div
=
0
;
out:
if
(
ret
<
0
)
{
kfree
(
info
);
info
=
ERR_PTR
(
ret
);
}
return
info
;
}
if
(
!
pll
->
new_div
)
{
ret
=
nva3_calc_pll
(
dev
,
&
limits
,
khz
,
&
N
,
NULL
,
&
M
,
&
P
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
pll
->
new_pnm
=
(
P
<<
16
)
|
(
N
<<
8
)
|
M
;
pll
->
new_div
=
2
-
1
;
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
{
pll
->
new_pnm
=
0
;
pll
->
new_div
--
;
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
);
}
if
((
nv_rd32
(
dev
,
pll
->
src1
)
&
0x00000101
)
!=
0x00000101
)
pll
->
old_pnm
=
nv_rd32
(
dev
,
pll
->
coef
);
return
pll
;
}
void
nva3_pm_clock_set
(
struct
drm_device
*
dev
,
void
*
pre_state
)
nva3_pm_clock
s
_set
(
struct
drm_device
*
dev
,
void
*
pre_state
)
{
struct
nva3_pm_state
*
pll
=
pre_state
;
u32
ctrl
=
0
;
/* For the memory clock, NVIDIA will build a "script" describing
* the reclocking process and ask PDAEMON to execute it.
*/
if
(
pll
->
type
==
PLL_MEMORY
)
{
nv_wr32
(
dev
,
0x100210
,
0
);
nv_wr32
(
dev
,
0x1002dc
,
1
);
nv_wr32
(
dev
,
0x004018
,
0x00001000
);
ctrl
=
0x18000100
;
}
if
(
pll
->
old_pnm
||
!
pll
->
new_pnm
)
{
nv_mask
(
dev
,
pll
->
src1
,
0x003c0101
,
0x00000101
|
(
pll
->
new_div
<<
18
));
nv_wr32
(
dev
,
pll
->
ctrl
,
0x0001001d
|
ctrl
);
nv_mask
(
dev
,
pll
->
ctrl
,
0x00000001
,
0x00000000
);
}
if
(
pll
->
new_pnm
)
{
nv_mask
(
dev
,
pll
->
src0
,
0x00000101
,
0x00000101
);
nv_wr32
(
dev
,
pll
->
coef
,
pll
->
new_pnm
);
nv_wr32
(
dev
,
pll
->
ctrl
,
0x0001001d
|
ctrl
);
nv_mask
(
dev
,
pll
->
ctrl
,
0x00000010
,
0x00000000
);
nv_mask
(
dev
,
pll
->
ctrl
,
0x00020010
,
0x00020010
);
nv_wr32
(
dev
,
pll
->
ctrl
,
0x00010015
|
ctrl
);
nv_mask
(
dev
,
pll
->
src1
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
pll
->
src1
,
0x00000001
,
0x00000000
);
if
(
pll
->
type
==
PLL_MEMORY
)
nv_wr32
(
dev
,
0x4018
,
0x10005000
);
}
else
{
nv_mask
(
dev
,
pll
->
ctrl
,
0x00000001
,
0x00000000
);
nv_mask
(
dev
,
pll
->
src0
,
0x00000100
,
0x00000000
);
nv_mask
(
dev
,
pll
->
src0
,
0x00000001
,
0x00000000
);
if
(
pll
->
type
==
PLL_MEMORY
)
nv_wr32
(
dev
,
0x4018
,
0x1000d000
);
}
if
(
pll
->
type
==
PLL_MEMORY
)
{
nv_wr32
(
dev
,
0x1002dc
,
0
);
nv_wr32
(
dev
,
0x100210
,
0x80000000
);
}
kfree
(
pll
);
struct
nva3_pm_state
*
info
=
pre_state
;
prog_pll
(
dev
,
0x004200
,
0
,
&
info
->
nclk
);
prog_pll
(
dev
,
0x004220
,
1
,
&
info
->
sclk
);
nv_wr32
(
dev
,
0x100210
,
0
);
nv_wr32
(
dev
,
0x1002dc
,
1
);
nv_wr32
(
dev
,
0x004018
,
0x00001000
);
prog_pll
(
dev
,
0x004000
,
2
,
&
info
->
mclk
);
if
(
nv_rd32
(
dev
,
0x4000
)
&
0x00000008
)
nv_wr32
(
dev
,
0x004018
,
0x1000d000
);
else
nv_wr32
(
dev
,
0x004018
,
0x10005000
);
nv_wr32
(
dev
,
0x1002dc
,
0
);
nv_wr32
(
dev
,
0x100210
,
0x80000000
);
kfree
(
info
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录