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/class.h>
27 #include <core/engctx.h>
28 #include <core/namedb.h>
29 #include <core/handle.h>
30 #include <core/gpuobj.h>
31 #include <core/event.h>
33 #include <subdev/bar.h>
35 #include <engine/software.h>
36 #include <engine/disp.h>
38 struct nv50_software_priv
{
39 struct nouveau_software base
;
42 struct nv50_software_chan
{
43 struct nouveau_software_chan base
;
46 /*******************************************************************************
47 * software object classes
48 ******************************************************************************/
51 nv50_software_mthd_dma_vblsem(struct nouveau_object
*object
, u32 mthd
,
54 struct nv50_software_chan
*chan
= (void *)nv_engctx(object
->parent
);
55 struct nouveau_fifo_chan
*fifo
= (void *)nv_object(chan
)->parent
;
56 struct nouveau_handle
*handle
;
59 handle
= nouveau_namedb_get(nv_namedb(fifo
), *(u32
*)args
);
63 if (nv_iclass(handle
->object
, NV_GPUOBJ_CLASS
)) {
64 struct nouveau_gpuobj
*gpuobj
= nv_gpuobj(handle
->object
);
65 chan
->base
.vblank
.ctxdma
= gpuobj
->node
->offset
>> 4;
68 nouveau_namedb_put(handle
);
73 nv50_software_mthd_vblsem_offset(struct nouveau_object
*object
, u32 mthd
,
76 struct nv50_software_chan
*chan
= (void *)nv_engctx(object
->parent
);
77 chan
->base
.vblank
.offset
= *(u32
*)args
;
82 nv50_software_mthd_vblsem_value(struct nouveau_object
*object
, u32 mthd
,
85 struct nv50_software_chan
*chan
= (void *)nv_engctx(object
->parent
);
86 chan
->base
.vblank
.value
= *(u32
*)args
;
91 nv50_software_mthd_vblsem_release(struct nouveau_object
*object
, u32 mthd
,
94 struct nv50_software_chan
*chan
= (void *)nv_engctx(object
->parent
);
95 struct nouveau_disp
*disp
= nouveau_disp(object
);
96 u32 crtc
= *(u32
*)args
;
100 nouveau_event_get(disp
->vblank
, crtc
, &chan
->base
.vblank
.event
);
105 nv50_software_mthd_flip(struct nouveau_object
*object
, u32 mthd
,
106 void *args
, u32 size
)
108 struct nv50_software_chan
*chan
= (void *)nv_engctx(object
->parent
);
110 return chan
->base
.flip(chan
->base
.flip_data
);
114 static struct nouveau_omthds
115 nv50_software_omthds
[] = {
116 { 0x018c, 0x018c, nv50_software_mthd_dma_vblsem
},
117 { 0x0400, 0x0400, nv50_software_mthd_vblsem_offset
},
118 { 0x0404, 0x0404, nv50_software_mthd_vblsem_value
},
119 { 0x0408, 0x0408, nv50_software_mthd_vblsem_release
},
120 { 0x0500, 0x0500, nv50_software_mthd_flip
},
124 static struct nouveau_oclass
125 nv50_software_sclass
[] = {
126 { 0x506e, &nouveau_object_ofuncs
, nv50_software_omthds
},
130 /*******************************************************************************
132 ******************************************************************************/
135 nv50_software_vblsem_release(struct nouveau_eventh
*event
, int head
)
137 struct nouveau_software_chan
*chan
=
138 container_of(event
, struct nouveau_software_chan
, vblank
.event
);
139 struct nv50_software_priv
*priv
= (void *)nv_object(chan
)->engine
;
140 struct nouveau_bar
*bar
= nouveau_bar(priv
);
142 nv_wr32(priv
, 0x001704, chan
->vblank
.channel
);
143 nv_wr32(priv
, 0x001710, 0x80000000 | chan
->vblank
.ctxdma
);
146 if (nv_device(priv
)->chipset
== 0x50) {
147 nv_wr32(priv
, 0x001570, chan
->vblank
.offset
);
148 nv_wr32(priv
, 0x001574, chan
->vblank
.value
);
150 nv_wr32(priv
, 0x060010, chan
->vblank
.offset
);
151 nv_wr32(priv
, 0x060014, chan
->vblank
.value
);
154 return NVKM_EVENT_DROP
;
158 nv50_software_context_ctor(struct nouveau_object
*parent
,
159 struct nouveau_object
*engine
,
160 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
161 struct nouveau_object
**pobject
)
163 struct nv50_software_chan
*chan
;
166 ret
= nouveau_software_context_create(parent
, engine
, oclass
, &chan
);
167 *pobject
= nv_object(chan
);
171 chan
->base
.vblank
.channel
= nv_gpuobj(parent
->parent
)->addr
>> 12;
172 chan
->base
.vblank
.event
.func
= nv50_software_vblsem_release
;
176 static struct nouveau_oclass
177 nv50_software_cclass
= {
178 .handle
= NV_ENGCTX(SW
, 0x50),
179 .ofuncs
= &(struct nouveau_ofuncs
) {
180 .ctor
= nv50_software_context_ctor
,
181 .dtor
= _nouveau_software_context_dtor
,
182 .init
= _nouveau_software_context_init
,
183 .fini
= _nouveau_software_context_fini
,
187 /*******************************************************************************
188 * software engine/subdev functions
189 ******************************************************************************/
192 nv50_software_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
193 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
194 struct nouveau_object
**pobject
)
196 struct nv50_software_priv
*priv
;
199 ret
= nouveau_software_create(parent
, engine
, oclass
, &priv
);
200 *pobject
= nv_object(priv
);
204 nv_engine(priv
)->cclass
= &nv50_software_cclass
;
205 nv_engine(priv
)->sclass
= nv50_software_sclass
;
206 nv_subdev(priv
)->intr
= nv04_software_intr
;
210 struct nouveau_oclass
211 nv50_software_oclass
= {
212 .handle
= NV_ENGINE(SW
, 0x50),
213 .ofuncs
= &(struct nouveau_ofuncs
) {
214 .ctor
= nv50_software_ctor
,
215 .dtor
= _nouveau_software_dtor
,
216 .init
= _nouveau_software_init
,
217 .fini
= _nouveau_software_fini
,