Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
gpu
drm
nouveau
nv04_pm.c
Go to the documentation of this file.
1
/*
2
* Copyright 2010 Red Hat Inc.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
* OTHER DEALINGS IN THE SOFTWARE.
21
*
22
* Authors: Ben Skeggs
23
*/
24
25
#include <
drm/drmP.h
>
26
#include "
nouveau_drm.h
"
27
#include "
nouveau_reg.h
"
28
#include "
nouveau_hw.h
"
29
#include "
nouveau_pm.h
"
30
31
#include <
subdev/bios/pll.h
>
32
#include <
subdev/clock.h
>
33
#include <
subdev/timer.h
>
34
35
int
36
nv04_pm_clocks_get
(
struct
drm_device
*
dev
,
struct
nouveau_pm_level
*perflvl)
37
{
38
int
ret
;
39
40
ret =
nouveau_hw_get_clock
(dev,
PLL_CORE
);
41
if
(ret < 0)
42
return
ret
;
43
perflvl->
core
=
ret
;
44
45
ret =
nouveau_hw_get_clock
(dev,
PLL_MEMORY
);
46
if
(ret < 0)
47
return
ret
;
48
perflvl->
memory
=
ret
;
49
50
return
0;
51
}
52
53
struct
nv04_pm_clock
{
54
struct
nvbios_pll
pll
;
55
struct
nouveau_pll_vals
calc
;
56
};
57
58
struct
nv04_pm_state
{
59
struct
nv04_pm_clock
core
;
60
struct
nv04_pm_clock
memory
;
61
};
62
63
static
int
64
calc_pll(
struct
drm_device
*
dev
,
u32
id
,
int
khz,
struct
nv04_pm_clock
*
clk
)
65
{
66
struct
nouveau_device
*
device
= nouveau_dev(dev);
67
struct
nouveau_bios
*
bios
=
nouveau_bios
(device);
68
struct
nouveau_clock
*pclk =
nouveau_clock
(device);
69
int
ret
;
70
71
ret =
nvbios_pll_parse
(bios,
id
, &clk->
pll
);
72
if
(ret)
73
return
ret
;
74
75
ret = pclk->
pll_calc
(pclk, &clk->
pll
, khz, &clk->
calc
);
76
if
(!ret)
77
return
-
EINVAL
;
78
79
return
0;
80
}
81
82
void
*
83
nv04_pm_clocks_pre
(
struct
drm_device
*dev,
struct
nouveau_pm_level
*perflvl)
84
{
85
struct
nv04_pm_state
*
info
;
86
int
ret
;
87
88
info = kzalloc(
sizeof
(*info),
GFP_KERNEL
);
89
if
(!info)
90
return
ERR_PTR(-
ENOMEM
);
91
92
ret = calc_pll(dev,
PLL_CORE
, perflvl->
core
, &info->
core
);
93
if
(ret)
94
goto
error
;
95
96
if
(perflvl->
memory
) {
97
ret = calc_pll(dev,
PLL_MEMORY
, perflvl->
memory
, &info->
memory
);
98
if
(ret)
99
goto
error
;
100
}
101
102
return
info
;
103
error
:
104
kfree
(info);
105
return
ERR_PTR(ret);
106
}
107
108
static
void
109
prog_pll(
struct
drm_device
*dev,
struct
nv04_pm_clock
*clk)
110
{
111
struct
nouveau_device
*device = nouveau_dev(dev);
112
struct
nouveau_clock
*pclk =
nouveau_clock
(device);
113
u32
reg
= clk->
pll
.reg;
114
115
/* thank the insane nouveau_hw_setpll() interface for this */
116
if
(device->
card_type
>= NV_40)
117
reg += 4;
118
119
pclk->
pll_prog
(pclk, reg, &clk->
calc
);
120
}
121
122
int
123
nv04_pm_clocks_set
(
struct
drm_device
*dev,
void
*pre_state)
124
{
125
struct
nouveau_device
*device = nouveau_dev(dev);
126
struct
nouveau_timer
*ptimer =
nouveau_timer
(device);
127
struct
nv04_pm_state
*
state
= pre_state;
128
129
prog_pll(dev, &state->
core
);
130
131
if
(state->
memory
.pll.reg) {
132
prog_pll(dev, &state->
memory
);
133
if
(device->
card_type
< NV_30) {
134
if
(device->
card_type
== NV_20)
135
nv_mask(device, 0x1002c4, 0, 1 << 20);
136
137
/* Reset the DLLs */
138
nv_mask(device, 0x1002c0, 0, 1 << 8);
139
}
140
}
141
142
nv_ofuncs(ptimer)->init(nv_object(ptimer));
143
144
kfree
(state);
145
return
0;
146
}
Generated on Thu Jan 10 2013 13:32:53 for Linux Kernel by
1.8.2