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.
26 #include <core/device.h>
27 #include <core/handle.h>
28 #include <core/namedb.h>
29 #include <engine/disp.h>
30 #include <subdev/bar.h>
32 #include <nvif/event.h>
34 /*******************************************************************************
35 * software object classes
36 ******************************************************************************/
39 nv50_sw_mthd_dma_vblsem(struct nvkm_object
*object
, u32 mthd
,
42 struct nv50_sw_chan
*chan
= (void *)nv_engctx(object
->parent
);
43 struct nvkm_fifo_chan
*fifo
= (void *)nv_object(chan
)->parent
;
44 struct nvkm_handle
*handle
;
47 handle
= nvkm_namedb_get(nv_namedb(fifo
), *(u32
*)args
);
51 if (nv_iclass(handle
->object
, NV_GPUOBJ_CLASS
)) {
52 struct nvkm_gpuobj
*gpuobj
= nv_gpuobj(handle
->object
);
53 chan
->vblank
.ctxdma
= gpuobj
->node
->offset
>> 4;
56 nvkm_namedb_put(handle
);
61 nv50_sw_mthd_vblsem_offset(struct nvkm_object
*object
, u32 mthd
,
64 struct nv50_sw_chan
*chan
= (void *)nv_engctx(object
->parent
);
65 chan
->vblank
.offset
= *(u32
*)args
;
70 nv50_sw_mthd_vblsem_value(struct nvkm_object
*object
, u32 mthd
,
73 struct nv50_sw_chan
*chan
= (void *)nv_engctx(object
->parent
);
74 chan
->vblank
.value
= *(u32
*)args
;
79 nv50_sw_mthd_vblsem_release(struct nvkm_object
*object
, u32 mthd
,
82 struct nv50_sw_chan
*chan
= (void *)nv_engctx(object
->parent
);
83 u32 head
= *(u32
*)args
;
84 if (head
>= nvkm_disp(chan
)->vblank
.index_nr
)
87 nvkm_notify_get(&chan
->vblank
.notify
[head
]);
92 nv50_sw_mthd_flip(struct nvkm_object
*object
, u32 mthd
, void *args
, u32 size
)
94 struct nv50_sw_chan
*chan
= (void *)nv_engctx(object
->parent
);
96 return chan
->base
.flip(chan
->base
.flip_data
);
100 static struct nvkm_omthds
102 { 0x018c, 0x018c, nv50_sw_mthd_dma_vblsem
},
103 { 0x0400, 0x0400, nv50_sw_mthd_vblsem_offset
},
104 { 0x0404, 0x0404, nv50_sw_mthd_vblsem_value
},
105 { 0x0408, 0x0408, nv50_sw_mthd_vblsem_release
},
106 { 0x0500, 0x0500, nv50_sw_mthd_flip
},
110 static struct nvkm_oclass
112 { 0x506e, &nvkm_object_ofuncs
, nv50_sw_omthds
},
116 /*******************************************************************************
118 ******************************************************************************/
121 nv50_sw_vblsem_release(struct nvkm_notify
*notify
)
123 struct nv50_sw_chan
*chan
=
124 container_of(notify
, typeof(*chan
), vblank
.notify
[notify
->index
]);
125 struct nv50_sw_priv
*priv
= (void *)nv_object(chan
)->engine
;
126 struct nvkm_bar
*bar
= nvkm_bar(priv
);
128 nv_wr32(priv
, 0x001704, chan
->vblank
.channel
);
129 nv_wr32(priv
, 0x001710, 0x80000000 | chan
->vblank
.ctxdma
);
132 if (nv_device(priv
)->chipset
== 0x50) {
133 nv_wr32(priv
, 0x001570, chan
->vblank
.offset
);
134 nv_wr32(priv
, 0x001574, chan
->vblank
.value
);
136 nv_wr32(priv
, 0x060010, chan
->vblank
.offset
);
137 nv_wr32(priv
, 0x060014, chan
->vblank
.value
);
140 return NVKM_NOTIFY_DROP
;
144 nv50_sw_context_dtor(struct nvkm_object
*object
)
146 struct nv50_sw_chan
*chan
= (void *)object
;
149 for (i
= 0; i
< ARRAY_SIZE(chan
->vblank
.notify
); i
++)
150 nvkm_notify_fini(&chan
->vblank
.notify
[i
]);
152 nvkm_sw_context_destroy(&chan
->base
);
156 nv50_sw_context_ctor(struct nvkm_object
*parent
, struct nvkm_object
*engine
,
157 struct nvkm_oclass
*oclass
, void *data
, u32 size
,
158 struct nvkm_object
**pobject
)
160 struct nvkm_disp
*pdisp
= nvkm_disp(parent
);
161 struct nv50_sw_cclass
*pclass
= (void *)oclass
;
162 struct nv50_sw_chan
*chan
;
165 ret
= nvkm_sw_context_create(parent
, engine
, oclass
, &chan
);
166 *pobject
= nv_object(chan
);
170 for (i
= 0; pdisp
&& i
< pdisp
->vblank
.index_nr
; i
++) {
171 ret
= nvkm_notify_init(NULL
, &pdisp
->vblank
, pclass
->vblank
,
173 &(struct nvif_notify_head_req_v0
) {
176 sizeof(struct nvif_notify_head_req_v0
),
177 sizeof(struct nvif_notify_head_rep_v0
),
178 &chan
->vblank
.notify
[i
]);
183 chan
->vblank
.channel
= nv_gpuobj(parent
->parent
)->addr
>> 12;
187 static struct nv50_sw_cclass
189 .base
.handle
= NV_ENGCTX(SW
, 0x50),
190 .base
.ofuncs
= &(struct nvkm_ofuncs
) {
191 .ctor
= nv50_sw_context_ctor
,
192 .dtor
= nv50_sw_context_dtor
,
193 .init
= _nvkm_sw_context_init
,
194 .fini
= _nvkm_sw_context_fini
,
196 .vblank
= nv50_sw_vblsem_release
,
199 /*******************************************************************************
200 * software engine/subdev functions
201 ******************************************************************************/
204 nv50_sw_ctor(struct nvkm_object
*parent
, struct nvkm_object
*engine
,
205 struct nvkm_oclass
*oclass
, void *data
, u32 size
,
206 struct nvkm_object
**pobject
)
208 struct nv50_sw_oclass
*pclass
= (void *)oclass
;
209 struct nv50_sw_priv
*priv
;
212 ret
= nvkm_sw_create(parent
, engine
, oclass
, &priv
);
213 *pobject
= nv_object(priv
);
217 nv_engine(priv
)->cclass
= pclass
->cclass
;
218 nv_engine(priv
)->sclass
= pclass
->sclass
;
219 nv_subdev(priv
)->intr
= nv04_sw_intr
;
224 nv50_sw_oclass
= &(struct nv50_sw_oclass
) {
225 .base
.handle
= NV_ENGINE(SW
, 0x50),
226 .base
.ofuncs
= &(struct nvkm_ofuncs
) {
227 .ctor
= nv50_sw_ctor
,
228 .dtor
= _nvkm_sw_dtor
,
229 .init
= _nvkm_sw_init
,
230 .fini
= _nvkm_sw_fini
,
232 .cclass
= &nv50_sw_cclass
.base
,
233 .sclass
= nv50_sw_sclass
,