Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / gf119.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 #include "nv50.h"
25 #include "head.h"
26 #include "ior.h"
27 #include "channv50.h"
28 #include "rootnv50.h"
29
30 #include <core/ramht.h>
31 #include <subdev/timer.h>
32
33 void
34 gf119_disp_super(struct work_struct *work)
35 {
36         struct nv50_disp *disp =
37                 container_of(work, struct nv50_disp, supervisor);
38         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
39         struct nvkm_device *device = subdev->device;
40         struct nvkm_head *head;
41         u32 mask[4];
42
43         nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super));
44         list_for_each_entry(head, &disp->base.head, head) {
45                 mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
46                 HEAD_DBG(head, "%08x", mask[head->id]);
47         }
48
49         if (disp->super & 0x00000001) {
50                 nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
51                 nv50_disp_super_1(disp);
52                 list_for_each_entry(head, &disp->base.head, head) {
53                         if (!(mask[head->id] & 0x00001000))
54                                 continue;
55                         nv50_disp_super_1_0(disp, head);
56                 }
57         } else
58         if (disp->super & 0x00000002) {
59                 list_for_each_entry(head, &disp->base.head, head) {
60                         if (!(mask[head->id] & 0x00001000))
61                                 continue;
62                         nv50_disp_super_2_0(disp, head);
63                 }
64                 nvkm_outp_route(&disp->base);
65                 list_for_each_entry(head, &disp->base.head, head) {
66                         if (!(mask[head->id] & 0x00010000))
67                                 continue;
68                         nv50_disp_super_2_1(disp, head);
69                 }
70                 list_for_each_entry(head, &disp->base.head, head) {
71                         if (!(mask[head->id] & 0x00001000))
72                                 continue;
73                         nv50_disp_super_2_2(disp, head);
74                 }
75         } else
76         if (disp->super & 0x00000004) {
77                 list_for_each_entry(head, &disp->base.head, head) {
78                         if (!(mask[head->id] & 0x00001000))
79                                 continue;
80                         nv50_disp_super_3_0(disp, head);
81                 }
82         }
83
84         list_for_each_entry(head, &disp->base.head, head)
85                 nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
86         nvkm_wr32(device, 0x6101d0, 0x80000000);
87 }
88
89 void
90 gf119_disp_intr_error(struct nv50_disp *disp, int chid)
91 {
92         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
93         struct nvkm_device *device = subdev->device;
94         u32 stat = nvkm_rd32(device, 0x6101f0 + (chid * 12));
95         u32 type = (stat & 0x00007000) >> 12;
96         u32 mthd = (stat & 0x00000ffc);
97         u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12));
98         u32 code = nvkm_rd32(device, 0x6101f8 + (chid * 12));
99         const struct nvkm_enum *reason =
100                 nvkm_enum_find(nv50_disp_intr_error_type, type);
101
102         nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x "
103                            "data %08x code %08x\n",
104                    chid, stat, type, reason ? reason->name : "",
105                    mthd, data, code);
106
107         if (chid < ARRAY_SIZE(disp->chan)) {
108                 switch (mthd) {
109                 case 0x0080:
110                         nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
111                         break;
112                 default:
113                         break;
114                 }
115         }
116
117         nvkm_wr32(device, 0x61009c, (1 << chid));
118         nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000);
119 }
120
121 void
122 gf119_disp_intr(struct nv50_disp *disp)
123 {
124         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
125         struct nvkm_device *device = subdev->device;
126         struct nvkm_head *head;
127         u32 intr = nvkm_rd32(device, 0x610088);
128
129         if (intr & 0x00000001) {
130                 u32 stat = nvkm_rd32(device, 0x61008c);
131                 while (stat) {
132                         int chid = __ffs(stat); stat &= ~(1 << chid);
133                         nv50_disp_chan_uevent_send(disp, chid);
134                         nvkm_wr32(device, 0x61008c, 1 << chid);
135                 }
136                 intr &= ~0x00000001;
137         }
138
139         if (intr & 0x00000002) {
140                 u32 stat = nvkm_rd32(device, 0x61009c);
141                 int chid = ffs(stat) - 1;
142                 if (chid >= 0)
143                         disp->func->intr_error(disp, chid);
144                 intr &= ~0x00000002;
145         }
146
147         if (intr & 0x00100000) {
148                 u32 stat = nvkm_rd32(device, 0x6100ac);
149                 if (stat & 0x00000007) {
150                         disp->super = (stat & 0x00000007);
151                         queue_work(disp->wq, &disp->supervisor);
152                         nvkm_wr32(device, 0x6100ac, disp->super);
153                         stat &= ~0x00000007;
154                 }
155
156                 if (stat) {
157                         nvkm_warn(subdev, "intr24 %08x\n", stat);
158                         nvkm_wr32(device, 0x6100ac, stat);
159                 }
160
161                 intr &= ~0x00100000;
162         }
163
164         list_for_each_entry(head, &disp->base.head, head) {
165                 const u32 hoff = head->id * 0x800;
166                 u32 mask = 0x01000000 << head->id;
167                 if (mask & intr) {
168                         u32 stat = nvkm_rd32(device, 0x6100bc + hoff);
169                         if (stat & 0x00000001)
170                                 nvkm_disp_vblank(&disp->base, head->id);
171                         nvkm_mask(device, 0x6100bc + hoff, 0, 0);
172                         nvkm_rd32(device, 0x6100c0 + hoff);
173                 }
174         }
175 }
176
177 void
178 gf119_disp_fini(struct nv50_disp *disp)
179 {
180         struct nvkm_device *device = disp->base.engine.subdev.device;
181         /* disable all interrupts */
182         nvkm_wr32(device, 0x6100b0, 0x00000000);
183 }
184
185 int
186 gf119_disp_init(struct nv50_disp *disp)
187 {
188         struct nvkm_device *device = disp->base.engine.subdev.device;
189         struct nvkm_head *head;
190         u32 tmp;
191         int i;
192
193         /* The below segments of code copying values from one register to
194          * another appear to inform EVO of the display capabilities or
195          * something similar.
196          */
197
198         /* ... CRTC caps */
199         list_for_each_entry(head, &disp->base.head, head) {
200                 const u32 hoff = head->id * 0x800;
201                 tmp = nvkm_rd32(device, 0x616104 + hoff);
202                 nvkm_wr32(device, 0x6101b4 + hoff, tmp);
203                 tmp = nvkm_rd32(device, 0x616108 + hoff);
204                 nvkm_wr32(device, 0x6101b8 + hoff, tmp);
205                 tmp = nvkm_rd32(device, 0x61610c + hoff);
206                 nvkm_wr32(device, 0x6101bc + hoff, tmp);
207         }
208
209         /* ... DAC caps */
210         for (i = 0; i < disp->dac.nr; i++) {
211                 tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800));
212                 nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp);
213         }
214
215         /* ... SOR caps */
216         for (i = 0; i < disp->sor.nr; i++) {
217                 tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800));
218                 nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp);
219         }
220
221         /* steal display away from vbios, or something like that */
222         if (nvkm_rd32(device, 0x6100ac) & 0x00000100) {
223                 nvkm_wr32(device, 0x6100ac, 0x00000100);
224                 nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000);
225                 if (nvkm_msec(device, 2000,
226                         if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002))
227                                 break;
228                 ) < 0)
229                         return -EBUSY;
230         }
231
232         /* point at display engine memory area (hash table, objects) */
233         nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9);
234
235         /* enable supervisor interrupts, disable everything else */
236         nvkm_wr32(device, 0x610090, 0x00000000);
237         nvkm_wr32(device, 0x6100a0, 0x00000000);
238         nvkm_wr32(device, 0x6100b0, 0x00000307);
239
240         /* disable underflow reporting, preventing an intermittent issue
241          * on some gk104 boards where the production vbios left this
242          * setting enabled by default.
243          *
244          * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt
245          */
246         list_for_each_entry(head, &disp->base.head, head) {
247                 const u32 hoff = head->id * 0x800;
248                 nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010);
249         }
250
251         return 0;
252 }
253
254 static const struct nv50_disp_func
255 gf119_disp = {
256         .init = gf119_disp_init,
257         .fini = gf119_disp_fini,
258         .intr = gf119_disp_intr,
259         .intr_error = gf119_disp_intr_error,
260         .uevent = &gf119_disp_chan_uevent,
261         .super = gf119_disp_super,
262         .root = &gf119_disp_root_oclass,
263         .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
264         .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new },
265         .sor = { .cnt = gf119_sor_cnt, .new = gf119_sor_new },
266 };
267
268 int
269 gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
270 {
271         return nv50_disp_new_(&gf119_disp, device, index, pdisp);
272 }