]>
Commit | Line | Data |
---|---|---|
52fa0866 BS |
1 | /* |
2 | * Copyright 2016 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 <bskeggs@redhat.com> | |
23 | */ | |
24 | #include "ctxgf100.h" | |
25 | ||
26 | #include <subdev/fb.h> | |
27 | ||
28 | /******************************************************************************* | |
29 | * PGRAPH context implementation | |
30 | ******************************************************************************/ | |
31 | ||
424321be | 32 | void |
52fa0866 BS |
33 | gp100_grctx_generate_pagepool(struct gf100_grctx *info) |
34 | { | |
35 | const struct gf100_grctx_func *grctx = info->gr->func->grctx; | |
52fa0866 | 36 | const int s = 8; |
019e4d76 | 37 | const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); |
52fa0866 BS |
38 | mmio_refn(info, 0x40800c, 0x00000000, s, b); |
39 | mmio_wr32(info, 0x408010, 0x80000000); | |
40 | mmio_refn(info, 0x419004, 0x00000000, s, b); | |
41 | mmio_wr32(info, 0x419008, 0x00000000); | |
42 | } | |
43 | ||
44 | static void | |
45 | gp100_grctx_generate_attrib(struct gf100_grctx *info) | |
46 | { | |
47 | struct gf100_gr *gr = info->gr; | |
48 | const struct gf100_grctx_func *grctx = gr->func->grctx; | |
49 | const u32 alpha = grctx->alpha_nr; | |
50 | const u32 attrib = grctx->attrib_nr; | |
51 | const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); | |
52 | const u32 size = roundup(gr->tpc_total * pertpc, 0x80); | |
52fa0866 | 53 | const int s = 12; |
019e4d76 | 54 | const int b = mmio_vram(info, size, (1 << s), false); |
52fa0866 BS |
55 | const int max_batches = 0xffff; |
56 | u32 ao = 0; | |
57 | u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total; | |
58 | int gpc, ppc, n = 0; | |
59 | ||
60 | mmio_refn(info, 0x418810, 0x80000000, s, b); | |
61 | mmio_refn(info, 0x419848, 0x10000000, s, b); | |
62 | mmio_refn(info, 0x419c2c, 0x10000000, s, b); | |
63 | mmio_refn(info, 0x419b00, 0x00000000, s, b); | |
64 | mmio_wr32(info, 0x419b04, 0x80000000 | size >> 7); | |
65 | mmio_wr32(info, 0x405830, attrib); | |
66 | mmio_wr32(info, 0x40585c, alpha); | |
67 | mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); | |
68 | ||
69 | for (gpc = 0; gpc < gr->gpc_nr; gpc++) { | |
70 | for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { | |
71 | const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; | |
72 | const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc]; | |
73 | const u32 u = 0x418ea0 + (n * 0x04); | |
74 | const u32 o = PPC_UNIT(gpc, ppc, 0); | |
75 | if (!(gr->ppc_mask[gpc] & (1 << ppc))) | |
76 | continue; | |
77 | mmio_wr32(info, o + 0xc0, bs); | |
78 | mmio_wr32(info, o + 0xf4, bo); | |
79 | mmio_wr32(info, o + 0xf0, bs); | |
80 | bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc]; | |
81 | mmio_wr32(info, o + 0xe4, as); | |
82 | mmio_wr32(info, o + 0xf8, ao); | |
83 | ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; | |
84 | mmio_wr32(info, u, bs); | |
85 | } | |
86 | } | |
87 | ||
88 | mmio_wr32(info, 0x418eec, 0x00000000); | |
89 | mmio_wr32(info, 0x41befc, 0x00000000); | |
90 | } | |
91 | ||
6c86fa3e BS |
92 | void |
93 | gp100_grctx_generate_smid_config(struct gf100_gr *gr) | |
52fa0866 BS |
94 | { |
95 | struct nvkm_device *device = gr->base.engine.subdev.device; | |
96 | const u32 dist_nr = DIV_ROUND_UP(gr->tpc_total, 4); | |
6c86fa3e | 97 | u32 dist[TPC_MAX / 4] = {}, gpcs[16] = {}; |
52fa0866 BS |
98 | u8 tpcnr[GPC_MAX]; |
99 | int tpc, gpc, i; | |
100 | ||
101 | memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); | |
102 | ||
103 | /* won't result in the same distribution as the binary driver where | |
104 | * some of the gpcs have more tpcs than others, but this shall do | |
105 | * for the moment. the code for earlier gpus has this issue too. | |
106 | */ | |
107 | for (gpc = -1, i = 0; i < gr->tpc_total; i++) { | |
108 | do { | |
109 | gpc = (gpc + 1) % gr->gpc_nr; | |
110 | } while(!tpcnr[gpc]); | |
111 | tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; | |
112 | ||
113 | dist[i / 4] |= ((gpc << 4) | tpc) << ((i % 4) * 8); | |
6c86fa3e | 114 | gpcs[gpc + (gr->func->gpc_nr * (tpc / 4))] |= i << (tpc * 8); |
52fa0866 BS |
115 | } |
116 | ||
117 | for (i = 0; i < dist_nr; i++) | |
118 | nvkm_wr32(device, 0x405b60 + (i * 4), dist[i]); | |
6c86fa3e | 119 | for (i = 0; i < ARRAY_SIZE(gpcs); i++) |
52fa0866 BS |
120 | nvkm_wr32(device, 0x405ba0 + (i * 4), gpcs[i]); |
121 | } | |
122 | ||
424321be | 123 | void |
52fa0866 BS |
124 | gp100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) |
125 | { | |
126 | struct nvkm_device *device = gr->base.engine.subdev.device; | |
127 | const struct gf100_grctx_func *grctx = gr->func->grctx; | |
128 | u32 idle_timeout, tmp; | |
129 | int i; | |
130 | ||
131 | gf100_gr_mmio(gr, gr->fuc_sw_ctx); | |
132 | ||
133 | idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); | |
134 | ||
135 | grctx->pagepool(info); | |
136 | grctx->bundle(info); | |
137 | grctx->attrib(info); | |
138 | grctx->unkn(gr); | |
139 | ||
140 | gm200_grctx_generate_tpcid(gr); | |
141 | gf100_grctx_generate_r406028(gr); | |
142 | gk104_grctx_generate_r418bb8(gr); | |
143 | ||
144 | for (i = 0; i < 8; i++) | |
145 | nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); | |
146 | nvkm_wr32(device, 0x406500, 0x00000000); | |
147 | ||
148 | nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); | |
149 | ||
150 | for (tmp = 0, i = 0; i < gr->gpc_nr; i++) | |
6c86fa3e | 151 | tmp |= ((1 << gr->tpc_nr[i]) - 1) << (i * gr->func->tpc_nr); |
52fa0866 BS |
152 | nvkm_wr32(device, 0x4041c4, tmp); |
153 | ||
6c86fa3e | 154 | gp100_grctx_generate_smid_config(gr); |
52fa0866 BS |
155 | |
156 | gf100_gr_icmd(gr, gr->fuc_bundle); | |
157 | nvkm_wr32(device, 0x404154, idle_timeout); | |
158 | gf100_gr_mthd(gr, gr->fuc_method); | |
159 | } | |
160 | ||
161 | const struct gf100_grctx_func | |
162 | gp100_grctx = { | |
163 | .main = gp100_grctx_generate_main, | |
164 | .unkn = gk104_grctx_generate_unkn, | |
165 | .bundle = gm107_grctx_generate_bundle, | |
166 | .bundle_size = 0x3000, | |
167 | .bundle_min_gpm_fifo_depth = 0x180, | |
168 | .bundle_token_limit = 0x1080, | |
169 | .pagepool = gp100_grctx_generate_pagepool, | |
170 | .pagepool_size = 0x20000, | |
171 | .attrib = gp100_grctx_generate_attrib, | |
172 | .attrib_nr_max = 0x660, | |
173 | .attrib_nr = 0x440, | |
174 | .alpha_nr_max = 0xc00, | |
175 | .alpha_nr = 0x800, | |
6c86fa3e BS |
176 | .tpc_mask = gm200_grctx_generate_tpc_mask, |
177 | .smid_config = gp100_grctx_generate_smid_config, | |
52fa0866 | 178 | }; |