2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
27 #include <core/client.h>
28 #include <core/ramht.h>
29 #include <subdev/timer.h>
31 #include <nvif/class.h>
32 #include <nvif/cl5070.h>
33 #include <nvif/unpack.h>
36 nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0
)
38 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
39 const u32 blanke
= nvkm_rd32(device
, 0x610aec + (head
* 0x540));
40 const u32 blanks
= nvkm_rd32(device
, 0x610af4 + (head
* 0x540));
41 const u32 total
= nvkm_rd32(device
, 0x610afc + (head
* 0x540));
43 struct nv50_disp_scanoutpos_v0 v0
;
47 nvif_ioctl(object
, "disp scanoutpos size %d\n", size
);
48 if (nvif_unpack(args
->v0
, 0, 0, false)) {
49 nvif_ioctl(object
, "disp scanoutpos vers %d\n",
51 args
->v0
.vblanke
= (blanke
& 0xffff0000) >> 16;
52 args
->v0
.hblanke
= (blanke
& 0x0000ffff);
53 args
->v0
.vblanks
= (blanks
& 0xffff0000) >> 16;
54 args
->v0
.hblanks
= (blanks
& 0x0000ffff);
55 args
->v0
.vtotal
= ( total
& 0xffff0000) >> 16;
56 args
->v0
.htotal
= ( total
& 0x0000ffff);
57 args
->v0
.time
[0] = ktime_to_ns(ktime_get());
58 args
->v0
.vline
= /* vline read locks hline */
59 nvkm_rd32(device
, 0x616340 + (head
* 0x800)) & 0xffff;
60 args
->v0
.time
[1] = ktime_to_ns(ktime_get());
62 nvkm_rd32(device
, 0x616344 + (head
* 0x800)) & 0xffff;
70 nv50_disp_root_mthd_(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
73 struct nv50_disp_mthd_v0 v0
;
74 struct nv50_disp_mthd_v1 v1
;
76 struct nv50_disp_root
*root
= nv50_disp_root(object
);
77 struct nv50_disp
*disp
= root
->disp
;
78 const struct nv50_disp_func
*func
= disp
->func
;
79 struct nvkm_output
*outp
= NULL
;
80 struct nvkm_output
*temp
;
84 if (mthd
!= NV50_DISP_MTHD
)
87 nvif_ioctl(object
, "disp mthd size %d\n", size
);
88 if (nvif_unpack(args
->v0
, 0, 0, true)) {
89 nvif_ioctl(object
, "disp mthd vers %d mthd %02x head %d\n",
90 args
->v0
.version
, args
->v0
.method
, args
->v0
.head
);
91 mthd
= args
->v0
.method
;
94 if (nvif_unpack(args
->v1
, 1, 1, true)) {
95 nvif_ioctl(object
, "disp mthd vers %d mthd %02x "
96 "type %04x mask %04x\n",
97 args
->v1
.version
, args
->v1
.method
,
98 args
->v1
.hasht
, args
->v1
.hashm
);
99 mthd
= args
->v1
.method
;
100 type
= args
->v1
.hasht
;
101 mask
= args
->v1
.hashm
;
102 head
= ffs((mask
>> 8) & 0x0f) - 1;
106 if (head
< 0 || head
>= disp
->base
.head
.nr
)
110 list_for_each_entry(temp
, &disp
->base
.outp
, head
) {
111 if ((temp
->info
.hasht
== type
) &&
112 (temp
->info
.hashm
& mask
) == mask
) {
122 case NV50_DISP_SCANOUTPOS
:
123 return func
->head
.scanoutpos(object
, disp
, data
, size
, head
);
128 switch (mthd
* !!outp
) {
129 case NV50_DISP_MTHD_V1_DAC_PWR
:
130 return func
->dac
.power(object
, disp
, data
, size
, head
, outp
);
131 case NV50_DISP_MTHD_V1_DAC_LOAD
:
132 return func
->dac
.sense(object
, disp
, data
, size
, head
, outp
);
133 case NV50_DISP_MTHD_V1_SOR_PWR
:
134 return func
->sor
.power(object
, disp
, data
, size
, head
, outp
);
135 case NV50_DISP_MTHD_V1_SOR_HDA_ELD
:
136 if (!func
->sor
.hda_eld
)
138 return func
->sor
.hda_eld(object
, disp
, data
, size
, head
, outp
);
139 case NV50_DISP_MTHD_V1_SOR_HDMI_PWR
:
142 return func
->sor
.hdmi(object
, disp
, data
, size
, head
, outp
);
143 case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT
: {
145 struct nv50_disp_sor_lvds_script_v0 v0
;
147 nvif_ioctl(object
, "disp sor lvds script size %d\n", size
);
148 if (nvif_unpack(args
->v0
, 0, 0, false)) {
149 nvif_ioctl(object
, "disp sor lvds script "
150 "vers %d name %04x\n",
151 args
->v0
.version
, args
->v0
.script
);
152 disp
->sor
.lvdsconf
= args
->v0
.script
;
158 case NV50_DISP_MTHD_V1_SOR_DP_PWR
: {
159 struct nvkm_output_dp
*outpdp
= nvkm_output_dp(outp
);
161 struct nv50_disp_sor_dp_pwr_v0 v0
;
163 nvif_ioctl(object
, "disp sor dp pwr size %d\n", size
);
164 if (nvif_unpack(args
->v0
, 0, 0, false)) {
165 nvif_ioctl(object
, "disp sor dp pwr vers %d state %d\n",
166 args
->v0
.version
, args
->v0
.state
);
167 if (args
->v0
.state
== 0) {
168 nvkm_notify_put(&outpdp
->irq
);
169 outpdp
->func
->lnk_pwr(outpdp
, 0);
170 atomic_set(&outpdp
->lt
.done
, 0);
173 if (args
->v0
.state
!= 0) {
174 nvkm_output_dp_train(&outpdp
->base
, 0, true);
181 case NV50_DISP_MTHD_V1_PIOR_PWR
:
182 if (!func
->pior
.power
)
184 return func
->pior
.power(object
, disp
, data
, size
, head
, outp
);
193 nv50_disp_root_dmac_new_(const struct nvkm_oclass
*oclass
,
194 void *data
, u32 size
, struct nvkm_object
**pobject
)
196 const struct nv50_disp_dmac_oclass
*sclass
= oclass
->priv
;
197 struct nv50_disp_root
*root
= nv50_disp_root(oclass
->parent
);
198 return sclass
->ctor(sclass
->func
, sclass
->mthd
, root
, sclass
->chid
,
199 oclass
, data
, size
, pobject
);
203 nv50_disp_root_pioc_new_(const struct nvkm_oclass
*oclass
,
204 void *data
, u32 size
, struct nvkm_object
**pobject
)
206 const struct nv50_disp_pioc_oclass
*sclass
= oclass
->priv
;
207 struct nv50_disp_root
*root
= nv50_disp_root(oclass
->parent
);
208 return sclass
->ctor(sclass
->func
, sclass
->mthd
, root
, sclass
->chid
,
209 oclass
, data
, size
, pobject
);
213 nv50_disp_root_child_get_(struct nvkm_object
*object
, int index
,
214 struct nvkm_oclass
*sclass
)
216 struct nv50_disp_root
*root
= nv50_disp_root(object
);
218 if (index
< ARRAY_SIZE(root
->func
->dmac
)) {
219 sclass
->base
= root
->func
->dmac
[index
]->base
;
220 sclass
->priv
= root
->func
->dmac
[index
];
221 sclass
->ctor
= nv50_disp_root_dmac_new_
;
225 index
-= ARRAY_SIZE(root
->func
->dmac
);
227 if (index
< ARRAY_SIZE(root
->func
->pioc
)) {
228 sclass
->base
= root
->func
->pioc
[index
]->base
;
229 sclass
->priv
= root
->func
->pioc
[index
];
230 sclass
->ctor
= nv50_disp_root_pioc_new_
;
238 nv50_disp_root_fini_(struct nvkm_object
*object
, bool suspend
)
240 struct nv50_disp_root
*root
= nv50_disp_root(object
);
241 root
->func
->fini(root
);
246 nv50_disp_root_init_(struct nvkm_object
*object
)
248 struct nv50_disp_root
*root
= nv50_disp_root(object
);
249 return root
->func
->init(root
);
253 nv50_disp_root_dtor_(struct nvkm_object
*object
)
255 struct nv50_disp_root
*root
= nv50_disp_root(object
);
256 nvkm_ramht_del(&root
->ramht
);
257 nvkm_gpuobj_del(&root
->instmem
);
261 static const struct nvkm_object_func
263 .dtor
= nv50_disp_root_dtor_
,
264 .init
= nv50_disp_root_init_
,
265 .fini
= nv50_disp_root_fini_
,
266 .mthd
= nv50_disp_root_mthd_
,
267 .ntfy
= nvkm_disp_ntfy
,
268 .sclass
= nv50_disp_root_child_get_
,
272 nv50_disp_root_new_(const struct nv50_disp_root_func
*func
,
273 struct nvkm_disp
*base
, const struct nvkm_oclass
*oclass
,
274 void *data
, u32 size
, struct nvkm_object
**pobject
)
276 struct nv50_disp
*disp
= nv50_disp(base
);
277 struct nv50_disp_root
*root
;
278 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
281 if (!(root
= kzalloc(sizeof(*root
), GFP_KERNEL
)))
283 *pobject
= &root
->object
;
285 nvkm_object_ctor(&nv50_disp_root_
, oclass
, &root
->object
);
289 ret
= nvkm_gpuobj_new(disp
->base
.engine
.subdev
.device
, 0x10000, 0x10000,
290 false, NULL
, &root
->instmem
);
294 return nvkm_ramht_new(device
, 0x1000, 0, root
->instmem
, &root
->ramht
);
298 nv50_disp_root_fini(struct nv50_disp_root
*root
)
300 struct nvkm_device
*device
= root
->disp
->base
.engine
.subdev
.device
;
301 /* disable all interrupts */
302 nvkm_wr32(device
, 0x610024, 0x00000000);
303 nvkm_wr32(device
, 0x610020, 0x00000000);
307 nv50_disp_root_init(struct nv50_disp_root
*root
)
309 struct nv50_disp
*disp
= root
->disp
;
310 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
314 /* The below segments of code copying values from one register to
315 * another appear to inform EVO of the display capabilities or
316 * something similar. NFI what the 0x614004 caps are for..
318 tmp
= nvkm_rd32(device
, 0x614004);
319 nvkm_wr32(device
, 0x610184, tmp
);
322 for (i
= 0; i
< disp
->base
.head
.nr
; i
++) {
323 tmp
= nvkm_rd32(device
, 0x616100 + (i
* 0x800));
324 nvkm_wr32(device
, 0x610190 + (i
* 0x10), tmp
);
325 tmp
= nvkm_rd32(device
, 0x616104 + (i
* 0x800));
326 nvkm_wr32(device
, 0x610194 + (i
* 0x10), tmp
);
327 tmp
= nvkm_rd32(device
, 0x616108 + (i
* 0x800));
328 nvkm_wr32(device
, 0x610198 + (i
* 0x10), tmp
);
329 tmp
= nvkm_rd32(device
, 0x61610c + (i
* 0x800));
330 nvkm_wr32(device
, 0x61019c + (i
* 0x10), tmp
);
334 for (i
= 0; i
< disp
->func
->dac
.nr
; i
++) {
335 tmp
= nvkm_rd32(device
, 0x61a000 + (i
* 0x800));
336 nvkm_wr32(device
, 0x6101d0 + (i
* 0x04), tmp
);
340 for (i
= 0; i
< disp
->func
->sor
.nr
; i
++) {
341 tmp
= nvkm_rd32(device
, 0x61c000 + (i
* 0x800));
342 nvkm_wr32(device
, 0x6101e0 + (i
* 0x04), tmp
);
346 for (i
= 0; i
< disp
->func
->pior
.nr
; i
++) {
347 tmp
= nvkm_rd32(device
, 0x61e000 + (i
* 0x800));
348 nvkm_wr32(device
, 0x6101f0 + (i
* 0x04), tmp
);
351 /* steal display away from vbios, or something like that */
352 if (nvkm_rd32(device
, 0x610024) & 0x00000100) {
353 nvkm_wr32(device
, 0x610024, 0x00000100);
354 nvkm_mask(device
, 0x6194e8, 0x00000001, 0x00000000);
355 if (nvkm_msec(device
, 2000,
356 if (!(nvkm_rd32(device
, 0x6194e8) & 0x00000002))
362 /* point at display engine memory area (hash table, objects) */
363 nvkm_wr32(device
, 0x610010, (root
->instmem
->addr
>> 8) | 9);
365 /* enable supervisor interrupts, disable everything else */
366 nvkm_wr32(device
, 0x61002c, 0x00000370);
367 nvkm_wr32(device
, 0x610028, 0x00000000);
371 static const struct nv50_disp_root_func
373 .init
= nv50_disp_root_init
,
374 .fini
= nv50_disp_root_fini
,
376 &nv50_disp_core_oclass
,
377 &nv50_disp_base_oclass
,
378 &nv50_disp_ovly_oclass
,
381 &nv50_disp_oimm_oclass
,
382 &nv50_disp_curs_oclass
,
387 nv50_disp_root_new(struct nvkm_disp
*disp
, const struct nvkm_oclass
*oclass
,
388 void *data
, u32 size
, struct nvkm_object
**pobject
)
390 return nv50_disp_root_new_(&nv50_disp_root
, disp
, oclass
,
391 data
, size
, pobject
);
394 const struct nvkm_disp_oclass
395 nv50_disp_root_oclass
= {
396 .base
.oclass
= NV50_DISP
,
399 .ctor
= nv50_disp_root_new
,