Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
330c5988
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看板
提交
330c5988
编写于
14年前
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nouveau: import initial work on vbios performance table parsing
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
4709bff0
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
678 addition
and
0 deletion
+678
-0
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/Makefile
+1
-0
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_drv.h
+46
-0
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_perf.c
+159
-0
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nouveau_pm.c
+214
-0
drivers/gpu/drm/nouveau/nouveau_pm.h
drivers/gpu/drm/nouveau/nouveau_pm.h
+44
-0
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_state.c
+5
-0
drivers/gpu/drm/nouveau/nouveau_volt.c
drivers/gpu/drm/nouveau/nouveau_volt.c
+209
-0
未找到文件。
drivers/gpu/drm/nouveau/Makefile
浏览文件 @
330c5988
...
...
@@ -10,6 +10,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o
\
nouveau_display.o nouveau_connector.o nouveau_fbcon.o
\
nouveau_dp.o nouveau_ramht.o
\
nouveau_pm.o nouveau_volt.o nouveau_perf.o
\
nv04_timer.o
\
nv04_mc.o nv40_mc.o nv50_mc.o
\
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o
\
...
...
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_drv.h
浏览文件 @
330c5988
...
...
@@ -359,6 +359,51 @@ struct nouveau_gpio_engine {
void
(
*
irq_enable
)(
struct
drm_device
*
,
enum
dcb_gpio_tag
,
bool
on
);
};
struct
nouveau_pm_voltage_level
{
u8
voltage
;
u8
vid
;
};
struct
nouveau_pm_voltage
{
bool
supported
;
u8
vid_mask
;
struct
nouveau_pm_voltage_level
*
level
;
int
nr_level
;
};
#define NOUVEAU_PM_MAX_LEVEL 8
struct
nouveau_pm_level
{
struct
device_attribute
dev_attr
;
char
name
[
32
];
int
id
;
u32
core
;
u32
memory
;
u32
shader
;
u32
unk05
;
u8
voltage
;
u8
fanspeed
;
};
struct
nouveau_pm_engine
{
struct
nouveau_pm_voltage
voltage
;
struct
nouveau_pm_level
perflvl
[
NOUVEAU_PM_MAX_LEVEL
];
int
nr_perflvl
;
struct
nouveau_pm_level
boot
;
struct
nouveau_pm_level
*
cur
;
int
(
*
clock_get
)(
struct
drm_device
*
,
u32
id
);
void
*
(
*
clock_pre
)(
struct
drm_device
*
,
u32
id
,
int
khz
);
void
(
*
clock_set
)(
struct
drm_device
*
,
void
*
);
int
(
*
voltage_get
)(
struct
drm_device
*
);
int
(
*
voltage_set
)(
struct
drm_device
*
,
int
voltage
);
int
(
*
fanspeed_get
)(
struct
drm_device
*
);
int
(
*
fanspeed_set
)(
struct
drm_device
*
,
int
fanspeed
);
};
struct
nouveau_engine
{
struct
nouveau_instmem_engine
instmem
;
struct
nouveau_mc_engine
mc
;
...
...
@@ -368,6 +413,7 @@ struct nouveau_engine {
struct
nouveau_fifo_engine
fifo
;
struct
nouveau_display_engine
display
;
struct
nouveau_gpio_engine
gpio
;
struct
nouveau_pm_engine
pm
;
};
struct
nouveau_pll_vals
{
...
...
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_perf.c
0 → 100644
浏览文件 @
330c5988
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_pm.h"
void
nouveau_perf_init
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
struct
nvbios
*
bios
=
&
dev_priv
->
vbios
;
struct
bit_entry
P
;
u8
version
,
headerlen
,
recordlen
,
entries
;
u8
*
perf
,
*
entry
;
int
vid
,
i
;
if
(
bios
->
type
==
NVBIOS_BIT
)
{
if
(
bit_table
(
dev
,
'P'
,
&
P
))
return
;
if
(
P
.
version
!=
1
&&
P
.
version
!=
2
)
{
NV_WARN
(
dev
,
"unknown perf for BIT P %d
\n
"
,
P
.
version
);
return
;
}
perf
=
ROMPTR
(
bios
,
P
.
data
[
0
]);
version
=
perf
[
0
];
headerlen
=
perf
[
1
];
if
(
version
<
0x40
)
{
recordlen
=
perf
[
3
]
+
(
perf
[
4
]
*
perf
[
5
]);
entries
=
perf
[
2
];
}
else
{
recordlen
=
perf
[
2
]
+
(
perf
[
3
]
*
perf
[
4
]);
entries
=
perf
[
5
];
}
}
else
{
if
(
bios
->
data
[
bios
->
offset
+
6
]
<
0x27
)
{
NV_DEBUG
(
dev
,
"BMP version too old for perf
\n
"
);
return
;
}
perf
=
ROMPTR
(
bios
,
bios
->
data
[
bios
->
offset
+
0x94
]);
if
(
!
perf
)
{
NV_DEBUG
(
dev
,
"perf table pointer invalid
\n
"
);
return
;
}
version
=
perf
[
1
];
headerlen
=
perf
[
0
];
recordlen
=
perf
[
3
];
entries
=
perf
[
2
];
}
entry
=
perf
+
headerlen
;
for
(
i
=
0
;
i
<
entries
;
i
++
)
{
struct
nouveau_pm_level
*
perflvl
=
&
pm
->
perflvl
[
pm
->
nr_perflvl
];
if
(
entry
[
0
]
==
0xff
)
{
entry
+=
recordlen
;
continue
;
}
switch
(
version
)
{
case
0x12
:
case
0x13
:
case
0x15
:
perflvl
->
fanspeed
=
entry
[
55
];
perflvl
->
voltage
=
entry
[
56
];
perflvl
->
core
=
ROM32
(
entry
[
1
])
/
100
;
perflvl
->
memory
=
ROM32
(
entry
[
5
])
/
100
;
break
;
case
0x21
:
case
0x23
:
case
0x24
:
perflvl
->
fanspeed
=
entry
[
4
];
perflvl
->
voltage
=
entry
[
5
];
perflvl
->
core
=
ROM16
(
entry
[
6
]);
perflvl
->
memory
=
ROM16
(
entry
[
11
]);
break
;
case
0x25
:
perflvl
->
fanspeed
=
entry
[
4
];
perflvl
->
voltage
=
entry
[
5
];
perflvl
->
core
=
ROM16
(
entry
[
6
]);
perflvl
->
shader
=
ROM16
(
entry
[
10
]);
perflvl
->
memory
=
ROM16
(
entry
[
12
]);
break
;
case
0x30
:
case
0x35
:
perflvl
->
fanspeed
=
entry
[
6
];
perflvl
->
voltage
=
entry
[
7
];
perflvl
->
core
=
ROM16
(
entry
[
8
]);
perflvl
->
shader
=
ROM16
(
entry
[
10
]);
perflvl
->
memory
=
ROM16
(
entry
[
12
]);
/*XXX: confirm on 0x35 */
perflvl
->
unk05
=
ROM16
(
entry
[
16
]);
break
;
case
0x40
:
#define subent(n) entry[perf[2] + ((n) * perf[3])]
perflvl
->
fanspeed
=
0
;
/*XXX*/
perflvl
->
voltage
=
0
;
/*XXX: entry[2] */
;
perflvl
->
core
=
ROM16
(
subent
(
0
))
&
0xfff
;
perflvl
->
shader
=
ROM16
(
subent
(
1
))
&
0xfff
;
perflvl
->
memory
=
ROM16
(
subent
(
2
))
&
0xfff
;
break
;
}
/* convert MHz -> KHz, it's more convenient */
perflvl
->
core
*=
1000
;
perflvl
->
memory
*=
1000
;
perflvl
->
shader
*=
1000
;
perflvl
->
unk05
*=
1000
;
/* make sure vid is valid */
if
(
pm
->
voltage
.
supported
&&
perflvl
->
voltage
)
{
vid
=
nouveau_volt_vid_lookup
(
dev
,
perflvl
->
voltage
);
if
(
vid
<
0
)
{
NV_DEBUG
(
dev
,
"drop perflvl %d, bad vid
\n
"
,
i
);
entry
+=
recordlen
;
continue
;
}
}
snprintf
(
perflvl
->
name
,
sizeof
(
perflvl
->
name
),
"performance_level_%d"
,
i
);
perflvl
->
id
=
i
;
pm
->
nr_perflvl
++
;
entry
+=
recordlen
;
}
}
void
nouveau_perf_fini
(
struct
drm_device
*
dev
)
{
}
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_pm.c
0 → 100644
浏览文件 @
330c5988
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_pm.h"
static
int
nouveau_pm_perflvl_get
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*
perflvl
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
int
ret
;
if
(
!
pm
->
clock_get
)
return
-
EINVAL
;
memset
(
perflvl
,
0
,
sizeof
(
*
perflvl
));
ret
=
pm
->
clock_get
(
dev
,
PLL_CORE
);
if
(
ret
>
0
)
perflvl
->
core
=
ret
;
ret
=
pm
->
clock_get
(
dev
,
PLL_MEMORY
);
if
(
ret
>
0
)
perflvl
->
memory
=
ret
;
ret
=
pm
->
clock_get
(
dev
,
PLL_SHADER
);
if
(
ret
>
0
)
perflvl
->
shader
=
ret
;
ret
=
pm
->
clock_get
(
dev
,
PLL_UNK05
);
if
(
ret
>
0
)
perflvl
->
unk05
=
ret
;
if
(
pm
->
voltage
.
supported
&&
pm
->
voltage_get
)
{
ret
=
pm
->
voltage_get
(
dev
);
if
(
ret
>
0
)
perflvl
->
voltage
=
ret
;
}
return
0
;
}
static
void
nouveau_pm_perflvl_info
(
struct
nouveau_pm_level
*
perflvl
,
char
*
ptr
,
int
len
)
{
char
s
[
16
],
v
[
16
],
f
[
16
];
s
[
0
]
=
'\0'
;
if
(
perflvl
->
shader
)
snprintf
(
s
,
sizeof
(
s
),
" shader %dMHz"
,
perflvl
->
shader
/
1000
);
v
[
0
]
=
'\0'
;
if
(
perflvl
->
voltage
)
snprintf
(
v
,
sizeof
(
v
),
" voltage %dmV"
,
perflvl
->
voltage
*
10
);
f
[
0
]
=
'\0'
;
if
(
perflvl
->
fanspeed
)
snprintf
(
f
,
sizeof
(
f
),
" fanspeed %d%%"
,
perflvl
->
fanspeed
);
snprintf
(
ptr
,
len
,
"core %dMHz memory %dMHz%s%s%s
\n
"
,
perflvl
->
core
/
1000
,
perflvl
->
memory
/
1000
,
s
,
v
,
f
);
}
static
ssize_t
nouveau_pm_get_perflvl_info
(
struct
device
*
d
,
struct
device_attribute
*
a
,
char
*
buf
)
{
struct
nouveau_pm_level
*
perflvl
=
(
struct
nouveau_pm_level
*
)
a
;
char
*
ptr
=
buf
;
int
len
=
PAGE_SIZE
;
snprintf
(
ptr
,
len
,
"%d: "
,
perflvl
->
id
);
ptr
+=
strlen
(
buf
);
len
-=
strlen
(
buf
);
nouveau_pm_perflvl_info
(
perflvl
,
ptr
,
len
);
return
strlen
(
buf
);
}
static
ssize_t
nouveau_pm_get_perflvl
(
struct
device
*
d
,
struct
device_attribute
*
a
,
char
*
buf
)
{
struct
drm_device
*
dev
=
pci_get_drvdata
(
to_pci_dev
(
d
));
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
struct
nouveau_pm_level
cur
;
int
len
=
PAGE_SIZE
,
ret
;
char
*
ptr
=
buf
;
if
(
!
pm
->
cur
)
snprintf
(
ptr
,
len
,
"setting: boot
\n
"
);
else
if
(
pm
->
cur
==
&
pm
->
boot
)
snprintf
(
ptr
,
len
,
"setting: boot
\n
c: "
);
else
snprintf
(
ptr
,
len
,
"setting: static %d
\n
c: "
,
pm
->
cur
->
id
);
ptr
+=
strlen
(
buf
);
len
-=
strlen
(
buf
);
ret
=
nouveau_pm_perflvl_get
(
dev
,
&
cur
);
if
(
ret
==
0
)
nouveau_pm_perflvl_info
(
&
cur
,
ptr
,
len
);
return
strlen
(
buf
);
}
static
ssize_t
nouveau_pm_set_perflvl
(
struct
device
*
d
,
struct
device_attribute
*
a
,
const
char
*
buf
,
size_t
count
)
{
return
-
EPERM
;
}
DEVICE_ATTR
(
performance_level
,
S_IRUGO
|
S_IWUSR
,
nouveau_pm_get_perflvl
,
nouveau_pm_set_perflvl
);
int
nouveau_pm_init
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
struct
device
*
d
=
&
dev
->
pdev
->
dev
;
char
info
[
256
];
int
ret
,
i
;
nouveau_volt_init
(
dev
);
nouveau_perf_init
(
dev
);
NV_INFO
(
dev
,
"%d available performance level(s)
\n
"
,
pm
->
nr_perflvl
);
for
(
i
=
0
;
i
<
pm
->
nr_perflvl
;
i
++
)
{
nouveau_pm_perflvl_info
(
&
pm
->
perflvl
[
i
],
info
,
sizeof
(
info
));
NV_INFO
(
dev
,
"%d: %s"
,
pm
->
perflvl
[
i
].
id
,
info
);
}
/* determine current ("boot") performance level */
ret
=
nouveau_pm_perflvl_get
(
dev
,
&
pm
->
boot
);
if
(
ret
==
0
)
{
pm
->
cur
=
&
pm
->
boot
;
nouveau_pm_perflvl_info
(
&
pm
->
boot
,
info
,
sizeof
(
info
));
NV_INFO
(
dev
,
"c: %s"
,
info
);
}
/* initialise sysfs */
ret
=
device_create_file
(
d
,
&
dev_attr_performance_level
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
pm
->
nr_perflvl
;
i
++
)
{
struct
nouveau_pm_level
*
perflvl
=
&
pm
->
perflvl
[
i
];
perflvl
->
dev_attr
.
attr
.
name
=
perflvl
->
name
;
perflvl
->
dev_attr
.
attr
.
mode
=
S_IRUGO
;
perflvl
->
dev_attr
.
show
=
nouveau_pm_get_perflvl_info
;
perflvl
->
dev_attr
.
store
=
NULL
;
sysfs_attr_init
(
&
perflvl
->
dev_attr
.
attr
);
ret
=
device_create_file
(
d
,
&
perflvl
->
dev_attr
);
if
(
ret
)
{
NV_ERROR
(
dev
,
"failed pervlvl %d sysfs: %d
\n
"
,
perflvl
->
id
,
i
);
perflvl
->
dev_attr
.
attr
.
name
=
NULL
;
nouveau_pm_fini
(
dev
);
return
ret
;
}
}
return
0
;
}
void
nouveau_pm_fini
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
struct
device
*
d
=
&
dev
->
pdev
->
dev
;
int
i
;
device_remove_file
(
d
,
&
dev_attr_performance_level
);
for
(
i
=
0
;
i
<
pm
->
nr_perflvl
;
i
++
)
{
struct
nouveau_pm_level
*
pl
=
&
pm
->
perflvl
[
i
];
if
(
!
pl
->
dev_attr
.
attr
.
name
)
break
;
device_remove_file
(
d
,
&
pl
->
dev_attr
);
}
nouveau_perf_fini
(
dev
);
nouveau_volt_fini
(
dev
);
}
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_pm.h
0 → 100644
浏览文件 @
330c5988
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#ifndef __NOUVEAU_PM_H__
#define __NOUVEAU_PM_H__
/* nouveau_pm.c */
int
nouveau_pm_init
(
struct
drm_device
*
dev
);
void
nouveau_pm_fini
(
struct
drm_device
*
dev
);
/* nouveau_volt.c */
void
nouveau_volt_init
(
struct
drm_device
*
);
void
nouveau_volt_fini
(
struct
drm_device
*
);
int
nouveau_volt_vid_lookup
(
struct
drm_device
*
,
int
voltage
);
int
nouveau_volt_lvl_lookup
(
struct
drm_device
*
,
int
vid
);
int
nouveau_voltage_gpio_get
(
struct
drm_device
*
);
int
nouveau_voltage_gpio_set
(
struct
drm_device
*
,
int
voltage
);
/* nouveau_perf.c */
void
nouveau_perf_init
(
struct
drm_device
*
);
void
nouveau_perf_fini
(
struct
drm_device
*
);
#endif
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_state.c
浏览文件 @
330c5988
...
...
@@ -36,6 +36,7 @@
#include "nouveau_drm.h"
#include "nouveau_fbcon.h"
#include "nouveau_ramht.h"
#include "nouveau_pm.h"
#include "nv50_display.h"
static
void
nouveau_stub_takedown
(
struct
drm_device
*
dev
)
{}
...
...
@@ -527,6 +528,8 @@ nouveau_card_init(struct drm_device *dev)
if
(
ret
)
goto
out_display_early
;
nouveau_pm_init
(
dev
);
ret
=
nouveau_mem_vram_init
(
dev
);
if
(
ret
)
goto
out_bios
;
...
...
@@ -635,6 +638,7 @@ nouveau_card_init(struct drm_device *dev)
out_vram:
nouveau_mem_vram_fini
(
dev
);
out_bios:
nouveau_pm_fini
(
dev
);
nouveau_bios_takedown
(
dev
);
out_display_early:
engine
->
display
.
late_takedown
(
dev
);
...
...
@@ -677,6 +681,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
drm_irq_uninstall
(
dev
);
nouveau_pm_fini
(
dev
);
nouveau_bios_takedown
(
dev
);
vga_client_register
(
dev
->
pdev
,
NULL
,
NULL
,
NULL
);
...
...
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/nouveau/nouveau_volt.c
0 → 100644
浏览文件 @
330c5988
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_pm.h"
static
const
enum
dcb_gpio_tag
vidtag
[]
=
{
0x04
,
0x05
,
0x06
,
0x1a
};
static
int
nr_vidtag
=
sizeof
(
vidtag
)
/
sizeof
(
vidtag
[
0
]);
int
nouveau_voltage_gpio_get
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_gpio_engine
*
gpio
=
&
dev_priv
->
engine
.
gpio
;
struct
nouveau_pm_voltage
*
volt
=
&
dev_priv
->
engine
.
pm
.
voltage
;
u8
vid
=
0
;
int
i
;
for
(
i
=
0
;
i
<
nr_vidtag
;
i
++
)
{
if
(
!
(
volt
->
vid_mask
&
(
1
<<
i
)))
continue
;
vid
|=
gpio
->
get
(
dev
,
vidtag
[
i
])
<<
i
;
}
return
nouveau_volt_lvl_lookup
(
dev
,
vid
);
}
int
nouveau_voltage_gpio_set
(
struct
drm_device
*
dev
,
int
voltage
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_gpio_engine
*
gpio
=
&
dev_priv
->
engine
.
gpio
;
struct
nouveau_pm_voltage
*
volt
=
&
dev_priv
->
engine
.
pm
.
voltage
;
int
vid
,
i
;
vid
=
nouveau_volt_vid_lookup
(
dev
,
voltage
);
if
(
vid
<
0
)
return
vid
;
for
(
i
=
0
;
i
<
nr_vidtag
;
i
++
)
{
if
(
!
(
volt
->
vid_mask
&
(
1
<<
i
)))
continue
;
gpio
->
set
(
dev
,
vidtag
[
i
],
!!
(
vid
&
(
1
<<
i
)));
}
return
0
;
}
int
nouveau_volt_vid_lookup
(
struct
drm_device
*
dev
,
int
voltage
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_voltage
*
volt
=
&
dev_priv
->
engine
.
pm
.
voltage
;
int
i
;
for
(
i
=
0
;
i
<
volt
->
nr_level
;
i
++
)
{
if
(
volt
->
level
[
i
].
voltage
==
voltage
)
return
volt
->
level
[
i
].
vid
;
}
return
-
ENOENT
;
}
int
nouveau_volt_lvl_lookup
(
struct
drm_device
*
dev
,
int
vid
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_voltage
*
volt
=
&
dev_priv
->
engine
.
pm
.
voltage
;
int
i
;
for
(
i
=
0
;
i
<
volt
->
nr_level
;
i
++
)
{
if
(
volt
->
level
[
i
].
vid
==
vid
)
return
volt
->
level
[
i
].
voltage
;
}
return
-
ENOENT
;
}
void
nouveau_volt_init
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_engine
*
pm
=
&
dev_priv
->
engine
.
pm
;
struct
nouveau_pm_voltage
*
voltage
=
&
pm
->
voltage
;
struct
nvbios
*
bios
=
&
dev_priv
->
vbios
;
struct
bit_entry
P
;
u8
*
volt
=
NULL
,
*
entry
;
int
i
,
recordlen
,
entries
,
vidmask
,
vidshift
;
if
(
bios
->
type
==
NVBIOS_BIT
)
{
if
(
bit_table
(
dev
,
'P'
,
&
P
))
return
;
if
(
P
.
version
==
1
)
volt
=
ROMPTR
(
bios
,
P
.
data
[
16
]);
else
if
(
P
.
version
==
2
)
volt
=
ROMPTR
(
bios
,
P
.
data
[
12
]);
else
{
NV_WARN
(
dev
,
"unknown volt for BIT P %d
\n
"
,
P
.
version
);
}
}
else
{
if
(
bios
->
data
[
bios
->
offset
+
6
]
<
0x27
)
{
NV_DEBUG
(
dev
,
"BMP version too old for voltage
\n
"
);
return
;
}
volt
=
ROMPTR
(
bios
,
bios
->
data
[
bios
->
offset
+
0x98
]);
}
if
(
!
volt
)
{
NV_DEBUG
(
dev
,
"voltage table pointer invalid
\n
"
);
return
;
}
switch
(
volt
[
0
])
{
case
0x10
:
case
0x11
:
case
0x12
:
recordlen
=
5
;
entries
=
volt
[
2
];
vidshift
=
0
;
vidmask
=
volt
[
4
];
break
;
case
0x20
:
recordlen
=
volt
[
3
];
entries
=
volt
[
2
];
vidshift
=
0
;
/* could be vidshift like 0x30? */
vidmask
=
volt
[
5
];
break
;
case
0x30
:
recordlen
=
volt
[
2
];
entries
=
volt
[
3
];
vidshift
=
hweight8
(
volt
[
5
]);
vidmask
=
volt
[
4
];
break
;
default:
NV_WARN
(
dev
,
"voltage table 0x%02x unknown
\n
"
,
volt
[
0
]);
return
;
}
/* validate vid mask */
voltage
->
vid_mask
=
vidmask
;
if
(
!
voltage
->
vid_mask
)
return
;
i
=
0
;
while
(
vidmask
)
{
if
(
i
>
nr_vidtag
)
{
NV_DEBUG
(
dev
,
"vid bit %d unknown
\n
"
,
i
);
return
;
}
if
(
!
nouveau_bios_gpio_entry
(
dev
,
vidtag
[
i
]))
{
NV_DEBUG
(
dev
,
"vid bit %d has no gpio tag
\n
"
,
i
);
return
;
}
vidmask
>>=
1
;
i
++
;
}
/* parse vbios entries into common format */
voltage
->
level
=
kcalloc
(
entries
,
sizeof
(
*
voltage
->
level
),
GFP_KERNEL
);
if
(
!
voltage
->
level
)
return
;
entry
=
volt
+
volt
[
1
];
for
(
i
=
0
;
i
<
entries
;
i
++
,
entry
+=
recordlen
)
{
voltage
->
level
[
i
].
voltage
=
entry
[
0
];
voltage
->
level
[
i
].
vid
=
entry
[
1
]
>>
vidshift
;
}
voltage
->
nr_level
=
entries
;
voltage
->
supported
=
true
;
}
void
nouveau_volt_fini
(
struct
drm_device
*
dev
)
{
struct
drm_nouveau_private
*
dev_priv
=
dev
->
dev_private
;
struct
nouveau_pm_voltage
*
volt
=
&
dev_priv
->
engine
.
pm
.
voltage
;
kfree
(
volt
->
level
);
}
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
反馈
建议
客服
返回
顶部