]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nvc0_software.c
Merge tag 'dm-3.5-changes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/agk...
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nvc0_software.c
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 "drmP.h"
26
27 #include "nouveau_drv.h"
28 #include "nouveau_ramht.h"
29 #include "nouveau_software.h"
30
31 #include "nv50_display.h"
32
33 struct nvc0_software_priv {
34         struct nouveau_software_priv base;
35 };
36
37 struct nvc0_software_chan {
38         struct nouveau_software_chan base;
39         struct nouveau_vma dispc_vma[4];
40 };
41
42 u64
43 nvc0_software_crtc(struct nouveau_channel *chan, int crtc)
44 {
45         struct nvc0_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
46         return pch->dispc_vma[crtc].offset;
47 }
48
49 static int
50 nvc0_software_context_new(struct nouveau_channel *chan, int engine)
51 {
52         struct drm_device *dev = chan->dev;
53         struct drm_nouveau_private *dev_priv = dev->dev_private;
54         struct nvc0_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW);
55         struct nvc0_software_chan *pch;
56         int ret = 0, i;
57
58         pch = kzalloc(sizeof(*pch), GFP_KERNEL);
59         if (!pch)
60                 return -ENOMEM;
61
62         nouveau_software_context_new(&pch->base);
63         chan->engctx[engine] = pch;
64
65         /* map display semaphore buffers into channel's vm */
66         for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
67                 struct nouveau_bo *bo;
68                 if (dev_priv->card_type >= NV_D0)
69                         bo = nvd0_display_crtc_sema(dev, i);
70                 else
71                         bo = nv50_display(dev)->crtc[i].sem.bo;
72
73                 ret = nouveau_bo_vma_add(bo, chan->vm, &pch->dispc_vma[i]);
74         }
75
76         if (ret)
77                 psw->base.base.context_del(chan, engine);
78         return ret;
79 }
80
81 static void
82 nvc0_software_context_del(struct nouveau_channel *chan, int engine)
83 {
84         struct drm_device *dev = chan->dev;
85         struct drm_nouveau_private *dev_priv = dev->dev_private;
86         struct nvc0_software_chan *pch = chan->engctx[engine];
87         int i;
88
89         if (dev_priv->card_type >= NV_D0) {
90                 for (i = 0; i < dev->mode_config.num_crtc; i++) {
91                         struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i);
92                         nouveau_bo_vma_del(bo, &pch->dispc_vma[i]);
93                 }
94         } else
95         if (dev_priv->card_type >= NV_50) {
96                 struct nv50_display *disp = nv50_display(dev);
97                 for (i = 0; i < dev->mode_config.num_crtc; i++) {
98                         struct nv50_display_crtc *dispc = &disp->crtc[i];
99                         nouveau_bo_vma_del(dispc->sem.bo, &pch->dispc_vma[i]);
100                 }
101         }
102
103         chan->engctx[engine] = NULL;
104         kfree(pch);
105 }
106
107 static int
108 nvc0_software_object_new(struct nouveau_channel *chan, int engine,
109                          u32 handle, u16 class)
110 {
111         return 0;
112 }
113
114 static int
115 nvc0_software_init(struct drm_device *dev, int engine)
116 {
117         return 0;
118 }
119
120 static int
121 nvc0_software_fini(struct drm_device *dev, int engine, bool suspend)
122 {
123         return 0;
124 }
125
126 static void
127 nvc0_software_destroy(struct drm_device *dev, int engine)
128 {
129         struct nvc0_software_priv *psw = nv_engine(dev, engine);
130
131         NVOBJ_ENGINE_DEL(dev, SW);
132         kfree(psw);
133 }
134
135 int
136 nvc0_software_create(struct drm_device *dev)
137 {
138         struct nvc0_software_priv *psw = kzalloc(sizeof(*psw), GFP_KERNEL);
139         if (!psw)
140                 return -ENOMEM;
141
142         psw->base.base.destroy = nvc0_software_destroy;
143         psw->base.base.init = nvc0_software_init;
144         psw->base.base.fini = nvc0_software_fini;
145         psw->base.base.context_new = nvc0_software_context_new;
146         psw->base.base.context_del = nvc0_software_context_del;
147         psw->base.base.object_new = nvc0_software_object_new;
148         nouveau_software_create(&psw->base);
149
150         NVOBJ_ENGINE_ADD(dev, SW, &psw->base.base);
151         NVOBJ_CLASS(dev, 0x906e, SW);
152         return 0;
153 }