drm/nouveau/disp: port vblank handling to event interface
[deliverable/linux.git] / drivers / gpu / drm / nouveau / core / engine / software / nvc0.c
CommitLineData
ebb945a9
BS
1/*
2 * Copyright 2012 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 <core/os.h>
26#include <core/class.h>
27#include <core/engctx.h>
1d7c71a3
BS
28#include <core/event.h>
29
30#include <subdev/bar.h>
ebb945a9
BS
31
32#include <engine/software.h>
33#include <engine/disp.h>
34
35struct nvc0_software_priv {
36 struct nouveau_software base;
37};
38
39struct nvc0_software_chan {
40 struct nouveau_software_chan base;
41};
42
43/*******************************************************************************
44 * software object classes
45 ******************************************************************************/
46
47static int
48nvc0_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd,
49 void *args, u32 size)
50{
51 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
52 u64 data = *(u32 *)args;
53 if (mthd == 0x0400) {
54 chan->base.vblank.offset &= 0x00ffffffffULL;
55 chan->base.vblank.offset |= data << 32;
56 } else {
57 chan->base.vblank.offset &= 0xff00000000ULL;
58 chan->base.vblank.offset |= data;
59 }
60 return 0;
61}
62
63static int
64nvc0_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd,
65 void *args, u32 size)
66{
67 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
68 chan->base.vblank.value = *(u32 *)args;
69 return 0;
70}
71
72static int
73nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
74 void *args, u32 size)
75{
76 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
77 struct nouveau_disp *disp = nouveau_disp(object);
ebb945a9
BS
78 u32 crtc = *(u32 *)args;
79
80 if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3)
81 return -EINVAL;
82
1d7c71a3 83 nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
ebb945a9
BS
84 return 0;
85}
86
87static int
88nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd,
89 void *args, u32 size)
90{
91 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
92 if (chan->base.flip)
93 return chan->base.flip(chan->base.flip_data);
94 return -EINVAL;
95}
96
97static struct nouveau_omthds
98nvc0_software_omthds[] = {
fb445b3c
BS
99 { 0x0400, 0x0400, nvc0_software_mthd_vblsem_offset },
100 { 0x0404, 0x0404, nvc0_software_mthd_vblsem_offset },
101 { 0x0408, 0x0408, nvc0_software_mthd_vblsem_value },
102 { 0x040c, 0x040c, nvc0_software_mthd_vblsem_release },
103 { 0x0500, 0x0500, nvc0_software_mthd_flip },
ebb945a9
BS
104 {}
105};
106
107static struct nouveau_oclass
108nvc0_software_sclass[] = {
109 { 0x906e, &nouveau_object_ofuncs, nvc0_software_omthds },
110 {}
111};
112
113/*******************************************************************************
114 * software context
115 ******************************************************************************/
116
1d7c71a3
BS
117static int
118nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)
119{
120 struct nouveau_software_chan *chan =
121 container_of(event, struct nouveau_software_chan, vblank.event);
122 struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine;
123 struct nouveau_bar *bar = nouveau_bar(priv);
124
125 nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
126 bar->flush(bar);
127 nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
128 nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
129 nv_wr32(priv, 0x060014, chan->vblank.value);
130
131 return NVKM_EVENT_DROP;
132}
133
ebb945a9
BS
134static int
135nvc0_software_context_ctor(struct nouveau_object *parent,
136 struct nouveau_object *engine,
137 struct nouveau_oclass *oclass, void *data, u32 size,
138 struct nouveau_object **pobject)
139{
140 struct nvc0_software_chan *chan;
141 int ret;
142
143 ret = nouveau_software_context_create(parent, engine, oclass, &chan);
144 *pobject = nv_object(chan);
145 if (ret)
146 return ret;
147
148 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
1d7c71a3 149 chan->base.vblank.event.func = nvc0_software_vblsem_release;
ebb945a9
BS
150 return 0;
151}
152
153static struct nouveau_oclass
154nvc0_software_cclass = {
155 .handle = NV_ENGCTX(SW, 0xc0),
156 .ofuncs = &(struct nouveau_ofuncs) {
157 .ctor = nvc0_software_context_ctor,
158 .dtor = _nouveau_software_context_dtor,
159 .init = _nouveau_software_context_init,
160 .fini = _nouveau_software_context_fini,
161 },
162};
163
164/*******************************************************************************
165 * software engine/subdev functions
166 ******************************************************************************/
167
168static int
169nvc0_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
170 struct nouveau_oclass *oclass, void *data, u32 size,
171 struct nouveau_object **pobject)
172{
173 struct nvc0_software_priv *priv;
174 int ret;
175
176 ret = nouveau_software_create(parent, engine, oclass, &priv);
177 *pobject = nv_object(priv);
178 if (ret)
179 return ret;
180
181 nv_engine(priv)->cclass = &nvc0_software_cclass;
182 nv_engine(priv)->sclass = nvc0_software_sclass;
757833cc 183 nv_subdev(priv)->intr = nv04_software_intr;
ebb945a9
BS
184 return 0;
185}
186
187struct nouveau_oclass
188nvc0_software_oclass = {
189 .handle = NV_ENGINE(SW, 0xc0),
190 .ofuncs = &(struct nouveau_ofuncs) {
191 .ctor = nvc0_software_ctor,
192 .dtor = _nouveau_software_dtor,
193 .init = _nouveau_software_init,
194 .fini = _nouveau_software_fini,
195 },
196};
This page took 0.057409 seconds and 5 git commands to generate.