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
nexedi
linux
Commits
330c5988
Commit
330c5988
authored
Sep 16, 2010
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/nouveau: import initial work on vbios performance table parsing
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
4709bff0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
678 additions
and
0 deletions
+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
No files found.
drivers/gpu/drm/nouveau/Makefile
View file @
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
\
...
...
drivers/gpu/drm/nouveau/nouveau_drv.h
View file @
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
{
...
...
drivers/gpu/drm/nouveau/nouveau_perf.c
0 → 100644
View file @
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
)
{
}
drivers/gpu/drm/nouveau/nouveau_pm.c
0 → 100644
View file @
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
);
}
drivers/gpu/drm/nouveau/nouveau_pm.h
0 → 100644
View file @
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
drivers/gpu/drm/nouveau/nouveau_state.c
View file @
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
);
...
...
drivers/gpu/drm/nouveau/nouveau_volt.c
0 → 100644
View file @
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
);
}
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