1243791Sdim/*
2243791Sdim * Copyright 2013 Red Hat Inc.
3243791Sdim *
4243791Sdim * Permission is hereby granted, free of charge, to any person obtaining a
5243791Sdim * copy of this software and associated documentation files (the "Software"),
6243791Sdim * to deal in the Software without restriction, including without limitation
7243791Sdim * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8243791Sdim * and/or sell copies of the Software, and to permit persons to whom the
9243791Sdim * Software is furnished to do so, subject to the following conditions:
10243791Sdim *
11243791Sdim * The above copyright notice and this permission notice shall be included in
12243791Sdim * all copies or substantial portions of the Software.
13243791Sdim *
14243791Sdim * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15243791Sdim * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16243791Sdim * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17243791Sdim * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18243791Sdim * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19243791Sdim * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20243791Sdim * OTHER DEALINGS IN THE SOFTWARE.
21243791Sdim *
22243791Sdim * Authors: Ben Skeggs <bskeggs@redhat.com>
23249423Sdim */
24249423Sdim#include "ctxgf100.h"
25249423Sdim
26249423Sdim#include <subdev/fb.h>
27249423Sdim#include <subdev/mc.h>
28249423Sdim
29243791Sdim/*******************************************************************************
30243791Sdim * PGRAPH context register lists
31243791Sdim ******************************************************************************/
32249423Sdim
33249423Sdimstatic const struct gf100_gr_init
34249423Sdimgf117_grctx_init_ds_0[] = {
35249423Sdim	{ 0x405800,   1, 0x04, 0x0f8000bf },
36243791Sdim	{ 0x405830,   1, 0x04, 0x02180324 },
37243791Sdim	{ 0x405834,   1, 0x04, 0x08000000 },
38243791Sdim	{ 0x405838,   1, 0x04, 0x00000000 },
39249423Sdim	{ 0x405854,   1, 0x04, 0x00000000 },
40243791Sdim	{ 0x405870,   4, 0x04, 0x00000001 },
41243791Sdim	{ 0x405a00,   2, 0x04, 0x00000000 },
42243791Sdim	{ 0x405a18,   1, 0x04, 0x00000000 },
43243791Sdim	{}
44243791Sdim};
45243791Sdim
46243791Sdimstatic const struct gf100_gr_init
47249423Sdimgf117_grctx_init_pd_0[] = {
48249423Sdim	{ 0x406020,   1, 0x04, 0x000103c1 },
49249423Sdim	{ 0x406028,   4, 0x04, 0x00000001 },
50249423Sdim	{ 0x4064a8,   1, 0x04, 0x00000000 },
51249423Sdim	{ 0x4064ac,   1, 0x04, 0x00003fff },
52249423Sdim	{ 0x4064b4,   3, 0x04, 0x00000000 },
53249423Sdim	{ 0x4064c0,   1, 0x04, 0x801a0078 },
54249423Sdim	{ 0x4064c4,   1, 0x04, 0x00c9ffff },
55249423Sdim	{ 0x4064d0,   8, 0x04, 0x00000000 },
56249423Sdim	{}
57243791Sdim};
58243791Sdim
59243791Sdimstatic const struct gf100_gr_pack
60243791Sdimgf117_grctx_pack_hub[] = {
61243791Sdim	{ gf100_grctx_init_main_0 },
62243791Sdim	{ gf119_grctx_init_fe_0 },
63243791Sdim	{ gf100_grctx_init_pri_0 },
64243791Sdim	{ gf100_grctx_init_memfmt_0 },
65249423Sdim	{ gf117_grctx_init_ds_0 },
66243791Sdim	{ gf117_grctx_init_pd_0 },
67243791Sdim	{ gf100_grctx_init_rstr2d_0 },
68243791Sdim	{ gf100_grctx_init_scc_0 },
69243791Sdim	{ gf119_grctx_init_be_0 },
70243791Sdim	{}
71243791Sdim};
72249423Sdim
73243791Sdimstatic const struct gf100_gr_init
74243791Sdimgf117_grctx_init_setup_0[] = {
75243791Sdim	{ 0x418800,   1, 0x04, 0x7006860a },
76243791Sdim	{ 0x418808,   3, 0x04, 0x00000000 },
77243791Sdim	{ 0x418828,   1, 0x04, 0x00008442 },
78243791Sdim	{ 0x418830,   1, 0x04, 0x10000001 },
79243791Sdim	{ 0x4188d8,   1, 0x04, 0x00000008 },
80243791Sdim	{ 0x4188e0,   1, 0x04, 0x01000000 },
81249423Sdim	{ 0x4188e8,   5, 0x04, 0x00000000 },
82243791Sdim	{ 0x4188fc,   1, 0x04, 0x20100018 },
83243791Sdim	{}
84243791Sdim};
85243791Sdim
86243791Sdimstatic const struct gf100_gr_pack
87243791Sdimgf117_grctx_pack_gpc_0[] = {
88243791Sdim	{ gf100_grctx_init_gpc_unk_0 },
89243791Sdim	{ gf119_grctx_init_prop_0 },
90243791Sdim	{ gf119_grctx_init_gpc_unk_1 },
91243791Sdim	{ gf117_grctx_init_setup_0 },
92243791Sdim	{ gf100_grctx_init_zcull_0 },
93243791Sdim	{}
94243791Sdim};
95249423Sdim
96243791Sdimconst struct gf100_gr_pack
97243791Sdimgf117_grctx_pack_gpc_1[] = {
98243791Sdim	{ gf119_grctx_init_crstr_0 },
99243791Sdim	{ gf108_grctx_init_gpm_0 },
100243791Sdim	{ gf100_grctx_init_gcc_0 },
101243791Sdim	{}
102243791Sdim};
103243791Sdim
104243791Sdimconst struct gf100_gr_init
105243791Sdimgf117_grctx_init_pe_0[] = {
106243791Sdim	{ 0x419848,   1, 0x04, 0x00000000 },
107243791Sdim	{ 0x419864,   1, 0x04, 0x00000129 },
108243791Sdim	{ 0x419888,   1, 0x04, 0x00000000 },
109243791Sdim	{}
110243791Sdim};
111243791Sdim
112243791Sdimstatic const struct gf100_gr_init
113243791Sdimgf117_grctx_init_tex_0[] = {
114243791Sdim	{ 0x419a00,   1, 0x04, 0x000001f0 },
115243791Sdim	{ 0x419a04,   1, 0x04, 0x00000001 },
116243791Sdim	{ 0x419a08,   1, 0x04, 0x00000023 },
117243791Sdim	{ 0x419a0c,   1, 0x04, 0x00020000 },
118243791Sdim	{ 0x419a10,   1, 0x04, 0x00000000 },
119243791Sdim	{ 0x419a14,   1, 0x04, 0x00000200 },
120243791Sdim	{ 0x419a1c,   1, 0x04, 0x00008000 },
121243791Sdim	{ 0x419a20,   1, 0x04, 0x00000800 },
122243791Sdim	{ 0x419ac4,   1, 0x04, 0x0017f440 },
123243791Sdim	{}
124243791Sdim};
125243791Sdim
126243791Sdimstatic const struct gf100_gr_init
127243791Sdimgf117_grctx_init_mpc_0[] = {
128243791Sdim	{ 0x419c00,   1, 0x04, 0x0000000a },
129243791Sdim	{ 0x419c04,   1, 0x04, 0x00000006 },
130243791Sdim	{ 0x419c08,   1, 0x04, 0x00000002 },
131243791Sdim	{ 0x419c20,   1, 0x04, 0x00000000 },
132243791Sdim	{ 0x419c24,   1, 0x04, 0x00084210 },
133243791Sdim	{ 0x419c28,   1, 0x04, 0x3efbefbe },
134243791Sdim	{}
135243791Sdim};
136243791Sdim
137243791Sdimstatic const struct gf100_gr_pack
138243791Sdimgf117_grctx_pack_tpc[] = {
139243791Sdim	{ gf117_grctx_init_pe_0 },
140243791Sdim	{ gf117_grctx_init_tex_0 },
141243791Sdim	{ gf117_grctx_init_mpc_0 },
142243791Sdim	{ gf104_grctx_init_l1c_0 },
143243791Sdim	{ gf119_grctx_init_sm_0 },
144243791Sdim	{}
145243791Sdim};
146243791Sdim
147243791Sdimstatic const struct gf100_gr_init
148243791Sdimgf117_grctx_init_pes_0[] = {
149243791Sdim	{ 0x41be24,   1, 0x04, 0x00000002 },
150243791Sdim	{}
151243791Sdim};
152243791Sdim
153243791Sdimstatic const struct gf100_gr_init
154243791Sdimgf117_grctx_init_cbm_0[] = {
155243791Sdim	{ 0x41bec0,   1, 0x04, 0x12180000 },
156243791Sdim	{ 0x41bec4,   1, 0x04, 0x00003fff },
157243791Sdim	{ 0x41bee4,   1, 0x04, 0x03240218 },
158243791Sdim	{}
159243791Sdim};
160243791Sdim
161243791Sdimconst struct gf100_gr_init
162243791Sdimgf117_grctx_init_wwdx_0[] = {
163243791Sdim	{ 0x41bf00,   1, 0x04, 0x0a418820 },
164243791Sdim	{ 0x41bf04,   1, 0x04, 0x062080e6 },
165243791Sdim	{ 0x41bf08,   1, 0x04, 0x020398a4 },
166243791Sdim	{ 0x41bf0c,   1, 0x04, 0x0e629062 },
167243791Sdim	{ 0x41bf10,   1, 0x04, 0x0a418820 },
168243791Sdim	{ 0x41bf14,   1, 0x04, 0x000000e6 },
169243791Sdim	{ 0x41bfd0,   1, 0x04, 0x00900103 },
170243791Sdim	{ 0x41bfe0,   1, 0x04, 0x00400001 },
171243791Sdim	{ 0x41bfe4,   1, 0x04, 0x00000000 },
172243791Sdim	{}
173243791Sdim};
174243791Sdim
175243791Sdimstatic const struct gf100_gr_pack
176243791Sdimgf117_grctx_pack_ppc[] = {
177243791Sdim	{ gf117_grctx_init_pes_0 },
178249423Sdim	{ gf117_grctx_init_cbm_0 },
179249423Sdim	{ gf117_grctx_init_wwdx_0 },
180243791Sdim	{}
181249423Sdim};
182249423Sdim
183243791Sdim/*******************************************************************************
184243791Sdim * PGRAPH context implementation
185243791Sdim ******************************************************************************/
186249423Sdim
187249423Sdimvoid
188243791Sdimgf117_grctx_generate_dist_skip_table(struct gf100_gr *gr)
189243791Sdim{
190243791Sdim	struct nvkm_device *device = gr->base.engine.subdev.device;
191243791Sdim	int i;
192243791Sdim
193243791Sdim	for (i = 0; i < 8; i++)
194243791Sdim		nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000);
195249423Sdim}
196249423Sdim
197243791Sdimvoid
198249423Sdimgf117_grctx_generate_rop_mapping(struct gf100_gr *gr)
199249423Sdim{
200249423Sdim	struct nvkm_device *device = gr->base.engine.subdev.device;
201249423Sdim	u32 data[6] = {}, data2[2] = {};
202249423Sdim	u8  shift, ntpcv;
203249423Sdim	int i;
204249423Sdim
205249423Sdim	/* Pack tile map into register format. */
206249423Sdim	for (i = 0; i < 32; i++)
207249423Sdim		data[i / 6] |= (gr->tile[i] & 0x07) << ((i % 6) * 5);
208249423Sdim
209249423Sdim	/* Magic. */
210249423Sdim	shift = 0;
211249423Sdim	ntpcv = gr->tpc_total;
212249423Sdim	while (!(ntpcv & (1 << 4))) {
213249423Sdim		ntpcv <<= 1;
214249423Sdim		shift++;
215249423Sdim	}
216243791Sdim
217249423Sdim	data2[0]  = (ntpcv << 16);
218249423Sdim	data2[0] |= (shift << 21);
219249423Sdim	data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24);
220249423Sdim	for (i = 1; i < 7; i++)
221243791Sdim		data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5);
222249423Sdim
223243791Sdim	/* GPC_BROADCAST */
224243791Sdim	nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) |
225249423Sdim				     gr->screen_tile_row_offset);
226243791Sdim	for (i = 0; i < 6; i++)
227243791Sdim		nvkm_wr32(device, 0x418b08 + (i * 4), data[i]);
228243791Sdim
229243791Sdim	/* GPC_BROADCAST.TP_BROADCAST */
230249423Sdim	nvkm_wr32(device, 0x41bfd0, (gr->tpc_total << 8) |
231249423Sdim				     gr->screen_tile_row_offset | data2[0]);
232243791Sdim	nvkm_wr32(device, 0x41bfe4, data2[1]);
233249423Sdim	for (i = 0; i < 6; i++)
234249423Sdim		nvkm_wr32(device, 0x41bf00 + (i * 4), data[i]);
235249423Sdim
236243791Sdim	/* UNK78xx */
237243791Sdim	nvkm_wr32(device, 0x4078bc, (gr->tpc_total << 8) |
238243791Sdim				     gr->screen_tile_row_offset);
239243791Sdim	for (i = 0; i < 6; i++)
240249423Sdim		nvkm_wr32(device, 0x40780c + (i * 4), data[i]);
241249423Sdim}
242243791Sdim
243243791Sdimvoid
244243791Sdimgf117_grctx_generate_attrib(struct gf100_gr_chan *chan)
245243791Sdim{
246249423Sdim	struct gf100_gr *gr = chan->gr;
247249423Sdim	const struct gf100_grctx_func *grctx = gr->func->grctx;
248249423Sdim	const u32  alpha = grctx->alpha_nr;
249243791Sdim	const u32   beta = grctx->attrib_nr;
250243791Sdim	const int timeslice_mode = 1;
251243791Sdim	const int max_batches = 0xffff;
252243791Sdim	u32 bo = 0;
253243791Sdim	u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total;
254249423Sdim	int gpc, ppc;
255243791Sdim
256243791Sdim	gf100_grctx_patch_wr32(chan, 0x405830, (beta << 16) | alpha);
257243791Sdim	gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
258243791Sdim
259243791Sdim	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
260249423Sdim		for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) {
261249423Sdim			const u32 a = alpha * gr->ppc_tpc_nr[gpc][ppc];
262249423Sdim			const u32 b =  beta * gr->ppc_tpc_nr[gpc][ppc];
263243791Sdim			const u32 t = timeslice_mode;
264249423Sdim			const u32 o = PPC_UNIT(gpc, ppc, 0);
265249423Sdim
266249423Sdim			if (!(gr->ppc_mask[gpc] & (1 << ppc)))
267243791Sdim				continue;
268249423Sdim
269249423Sdim			gf100_grctx_patch_wr32(chan, o + 0xc0, (t << 28) | (b << 16) | bo);
270249423Sdim			bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc];
271249423Sdim			gf100_grctx_patch_wr32(chan, o + 0xe4, (a << 16) | ao);
272249423Sdim			ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
273249423Sdim		}
274249423Sdim	}
275249423Sdim}
276249423Sdim
277249423Sdimconst struct gf100_grctx_func
278249423Sdimgf117_grctx = {
279243791Sdim	.main  = gf100_grctx_generate_main,
280243791Sdim	.unkn  = gk104_grctx_generate_unkn,
281243791Sdim	.hub   = gf117_grctx_pack_hub,
282243791Sdim	.gpc_0 = gf117_grctx_pack_gpc_0,
283243791Sdim	.gpc_1 = gf117_grctx_pack_gpc_1,
284243791Sdim	.zcull = gf100_grctx_pack_zcull,
285243791Sdim	.tpc   = gf117_grctx_pack_tpc,
286243791Sdim	.ppc   = gf117_grctx_pack_ppc,
287249423Sdim	.icmd  = gf119_grctx_pack_icmd,
288243791Sdim	.mthd  = gf119_grctx_pack_mthd,
289243791Sdim	.bundle = gf100_grctx_generate_bundle,
290243791Sdim	.bundle_size = 0x1800,
291243791Sdim	.pagepool = gf100_grctx_generate_pagepool,
292249423Sdim	.pagepool_size = 0x8000,
293243791Sdim	.attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
294243791Sdim	.attrib_cb = gf100_grctx_generate_attrib_cb,
295249423Sdim	.attrib = gf117_grctx_generate_attrib,
296249423Sdim	.attrib_nr_max = 0x324,
297249423Sdim	.attrib_nr = 0x218,
298243791Sdim	.alpha_nr_max = 0x7ff,
299243791Sdim	.alpha_nr = 0x324,
300243791Sdim	.sm_id = gf100_grctx_generate_sm_id,
301243791Sdim	.tpc_nr = gf100_grctx_generate_tpc_nr,
302243791Sdim	.r4060a8 = gf100_grctx_generate_r4060a8,
303243791Sdim	.rop_mapping = gf117_grctx_generate_rop_mapping,
304249423Sdim	.alpha_beta_tables = gf100_grctx_generate_alpha_beta_tables,
305249423Sdim	.max_ways_evict = gf100_grctx_generate_max_ways_evict,
306243791Sdim	.dist_skip_table = gf117_grctx_generate_dist_skip_table,
307249423Sdim	.r419cb8 = gf100_grctx_generate_r419cb8,
308249423Sdim};
309249423Sdim