brintos

brintos / linux-shallow public Read only

0
0
Text · 19.6 KiB · 80a6b01 Raw
694 lines · c
1/*2 * Copyright 2009 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Ben Skeggs23 */24 25/* NVIDIA context programs handle a number of other conditions which are26 * not implemented in our versions.  It's not clear why NVIDIA context27 * programs have this code, nor whether it's strictly necessary for28 * correct operation.  We'll implement additional handling if/when we29 * discover it's necessary.30 *31 * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state"32 *   flag is set, this gets saved into the context.33 * - On context save, the context program for all cards load nsource34 *   into a flag register and check for ILLEGAL_MTHD.  If it's set,35 *   opcode 0x60000d is called before resuming normal operation.36 * - Some context programs check more conditions than the above.  NV4437 *   checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001))38 *   and calls 0x60000d before resuming normal operation.39 * - At the very beginning of NVIDIA's context programs, flag 9 is checked40 *   and if true 0x800001 is called with count=0, pos=0, the flag is cleared41 *   and then the ctxprog is aborted.  It looks like a complicated NOP,42 *   its purpose is unknown.43 * - In the section of code that loads the per-vs state, NVIDIA check44 *   flag 10.  If it's set, they only transfer the small 0x300 byte block45 *   of state + the state for a single vs as opposed to the state for46 *   all vs units.  It doesn't seem likely that it'll occur in normal47 *   operation, especially seeing as it appears NVIDIA may have screwed48 *   up the ctxprogs for some cards and have an invalid instruction49 *   rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction.50 * - There's a number of places where context offset 0 (where we place51 *   the PRAMIN offset of the context) is loaded into either 0x408000,52 *   0x408004 or 0x408008.  Not sure what's up there either.53 * - The ctxprogs for some cards save 0x400a00 again during the cleanup54 *   path for auto-loadctx.55 */56 57#define CP_FLAG_CLEAR                 058#define CP_FLAG_SET                   159#define CP_FLAG_SWAP_DIRECTION        ((0 * 32) + 0)60#define CP_FLAG_SWAP_DIRECTION_LOAD   061#define CP_FLAG_SWAP_DIRECTION_SAVE   162#define CP_FLAG_USER_SAVE             ((0 * 32) + 5)63#define CP_FLAG_USER_SAVE_NOT_PENDING 064#define CP_FLAG_USER_SAVE_PENDING     165#define CP_FLAG_USER_LOAD             ((0 * 32) + 6)66#define CP_FLAG_USER_LOAD_NOT_PENDING 067#define CP_FLAG_USER_LOAD_PENDING     168#define CP_FLAG_STATUS                ((3 * 32) + 0)69#define CP_FLAG_STATUS_IDLE           070#define CP_FLAG_STATUS_BUSY           171#define CP_FLAG_AUTO_SAVE             ((3 * 32) + 4)72#define CP_FLAG_AUTO_SAVE_NOT_PENDING 073#define CP_FLAG_AUTO_SAVE_PENDING     174#define CP_FLAG_AUTO_LOAD             ((3 * 32) + 5)75#define CP_FLAG_AUTO_LOAD_NOT_PENDING 076#define CP_FLAG_AUTO_LOAD_PENDING     177#define CP_FLAG_UNK54                 ((3 * 32) + 6)78#define CP_FLAG_UNK54_CLEAR           079#define CP_FLAG_UNK54_SET             180#define CP_FLAG_ALWAYS                ((3 * 32) + 8)81#define CP_FLAG_ALWAYS_FALSE          082#define CP_FLAG_ALWAYS_TRUE           183#define CP_FLAG_UNK57                 ((3 * 32) + 9)84#define CP_FLAG_UNK57_CLEAR           085#define CP_FLAG_UNK57_SET             186 87#define CP_CTX                   0x0010000088#define CP_CTX_COUNT             0x000fc00089#define CP_CTX_COUNT_SHIFT               1490#define CP_CTX_REG               0x00003fff91#define CP_LOAD_SR               0x0020000092#define CP_LOAD_SR_VALUE         0x000fffff93#define CP_BRA                   0x0040000094#define CP_BRA_IP                0x0000ff0095#define CP_BRA_IP_SHIFT                   896#define CP_BRA_IF_CLEAR          0x0000008097#define CP_BRA_FLAG              0x0000007f98#define CP_WAIT                  0x0050000099#define CP_WAIT_SET              0x00000080100#define CP_WAIT_FLAG             0x0000007f101#define CP_SET                   0x00700000102#define CP_SET_1                 0x00000080103#define CP_SET_FLAG              0x0000007f104#define CP_NEXT_TO_SWAP          0x00600007105#define CP_NEXT_TO_CURRENT       0x00600009106#define CP_SET_CONTEXT_POINTER   0x0060000a107#define CP_END                   0x0060000e108#define CP_LOAD_MAGIC_UNK01      0x00800001 /* unknown */109#define CP_LOAD_MAGIC_NV44TCL    0x00800029 /* per-vs state (0x4497) */110#define CP_LOAD_MAGIC_NV40TCL    0x00800041 /* per-vs state (0x4097) */111 112#include "ctxnv40.h"113#include "nv40.h"114 115/* TODO:116 *  - get vs count from 0x1540117 */118 119static int120nv40_gr_vs_count(struct nvkm_device *device)121{122 123	switch (device->chipset) {124	case 0x47:125	case 0x49:126	case 0x4b:127		return 8;128	case 0x40:129		return 6;130	case 0x41:131	case 0x42:132		return 5;133	case 0x43:134	case 0x44:135	case 0x46:136	case 0x4a:137		return 3;138	case 0x4c:139	case 0x4e:140	case 0x67:141	default:142		return 1;143	}144}145 146 147enum cp_label {148	cp_check_load = 1,149	cp_setup_auto_load,150	cp_setup_load,151	cp_setup_save,152	cp_swap_state,153	cp_swap_state3d_3_is_save,154	cp_prepare_exit,155	cp_exit,156};157 158static void159nv40_gr_construct_general(struct nvkm_grctx *ctx)160{161	struct nvkm_device *device = ctx->device;162	int i;163 164	cp_ctx(ctx, 0x4000a4, 1);165	gr_def(ctx, 0x4000a4, 0x00000008);166	cp_ctx(ctx, 0x400144, 58);167	gr_def(ctx, 0x400144, 0x00000001);168	cp_ctx(ctx, 0x400314, 1);169	gr_def(ctx, 0x400314, 0x00000000);170	cp_ctx(ctx, 0x400400, 10);171	cp_ctx(ctx, 0x400480, 10);172	cp_ctx(ctx, 0x400500, 19);173	gr_def(ctx, 0x400514, 0x00040000);174	gr_def(ctx, 0x400524, 0x55555555);175	gr_def(ctx, 0x400528, 0x55555555);176	gr_def(ctx, 0x40052c, 0x55555555);177	gr_def(ctx, 0x400530, 0x55555555);178	cp_ctx(ctx, 0x400560, 6);179	gr_def(ctx, 0x400568, 0x0000ffff);180	gr_def(ctx, 0x40056c, 0x0000ffff);181	cp_ctx(ctx, 0x40057c, 5);182	cp_ctx(ctx, 0x400710, 3);183	gr_def(ctx, 0x400710, 0x20010001);184	gr_def(ctx, 0x400714, 0x0f73ef00);185	cp_ctx(ctx, 0x400724, 1);186	gr_def(ctx, 0x400724, 0x02008821);187	cp_ctx(ctx, 0x400770, 3);188	if (device->chipset == 0x40) {189		cp_ctx(ctx, 0x400814, 4);190		cp_ctx(ctx, 0x400828, 5);191		cp_ctx(ctx, 0x400840, 5);192		gr_def(ctx, 0x400850, 0x00000040);193		cp_ctx(ctx, 0x400858, 4);194		gr_def(ctx, 0x400858, 0x00000040);195		gr_def(ctx, 0x40085c, 0x00000040);196		gr_def(ctx, 0x400864, 0x80000000);197		cp_ctx(ctx, 0x40086c, 9);198		gr_def(ctx, 0x40086c, 0x80000000);199		gr_def(ctx, 0x400870, 0x80000000);200		gr_def(ctx, 0x400874, 0x80000000);201		gr_def(ctx, 0x400878, 0x80000000);202		gr_def(ctx, 0x400888, 0x00000040);203		gr_def(ctx, 0x40088c, 0x80000000);204		cp_ctx(ctx, 0x4009c0, 8);205		gr_def(ctx, 0x4009cc, 0x80000000);206		gr_def(ctx, 0x4009dc, 0x80000000);207	} else {208		cp_ctx(ctx, 0x400840, 20);209		if (nv44_gr_class(ctx->device)) {210			for (i = 0; i < 8; i++)211				gr_def(ctx, 0x400860 + (i * 4), 0x00000001);212		}213		gr_def(ctx, 0x400880, 0x00000040);214		gr_def(ctx, 0x400884, 0x00000040);215		gr_def(ctx, 0x400888, 0x00000040);216		cp_ctx(ctx, 0x400894, 11);217		gr_def(ctx, 0x400894, 0x00000040);218		if (!nv44_gr_class(ctx->device)) {219			for (i = 0; i < 8; i++)220				gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000);221		}222		cp_ctx(ctx, 0x4008e0, 2);223		cp_ctx(ctx, 0x4008f8, 2);224		if (device->chipset == 0x4c ||225		    (device->chipset & 0xf0) == 0x60)226			cp_ctx(ctx, 0x4009f8, 1);227	}228	cp_ctx(ctx, 0x400a00, 73);229	gr_def(ctx, 0x400b0c, 0x0b0b0b0c);230	cp_ctx(ctx, 0x401000, 4);231	cp_ctx(ctx, 0x405004, 1);232	switch (device->chipset) {233	case 0x47:234	case 0x49:235	case 0x4b:236		cp_ctx(ctx, 0x403448, 1);237		gr_def(ctx, 0x403448, 0x00001010);238		break;239	default:240		cp_ctx(ctx, 0x403440, 1);241		switch (device->chipset) {242		case 0x40:243			gr_def(ctx, 0x403440, 0x00000010);244			break;245		case 0x44:246		case 0x46:247		case 0x4a:248			gr_def(ctx, 0x403440, 0x00003010);249			break;250		case 0x41:251		case 0x42:252		case 0x43:253		case 0x4c:254		case 0x4e:255		case 0x67:256		default:257			gr_def(ctx, 0x403440, 0x00001010);258			break;259		}260		break;261	}262}263 264static void265nv40_gr_construct_state3d(struct nvkm_grctx *ctx)266{267	struct nvkm_device *device = ctx->device;268	int i;269 270	if (device->chipset == 0x40) {271		cp_ctx(ctx, 0x401880, 51);272		gr_def(ctx, 0x401940, 0x00000100);273	} else274	if (device->chipset == 0x46 || device->chipset == 0x47 ||275	    device->chipset == 0x49 || device->chipset == 0x4b) {276		cp_ctx(ctx, 0x401880, 32);277		for (i = 0; i < 16; i++)278			gr_def(ctx, 0x401880 + (i * 4), 0x00000111);279		if (device->chipset == 0x46)280			cp_ctx(ctx, 0x401900, 16);281		cp_ctx(ctx, 0x401940, 3);282	}283	cp_ctx(ctx, 0x40194c, 18);284	gr_def(ctx, 0x401954, 0x00000111);285	gr_def(ctx, 0x401958, 0x00080060);286	gr_def(ctx, 0x401974, 0x00000080);287	gr_def(ctx, 0x401978, 0xffff0000);288	gr_def(ctx, 0x40197c, 0x00000001);289	gr_def(ctx, 0x401990, 0x46400000);290	if (device->chipset == 0x40) {291		cp_ctx(ctx, 0x4019a0, 2);292		cp_ctx(ctx, 0x4019ac, 5);293	} else {294		cp_ctx(ctx, 0x4019a0, 1);295		cp_ctx(ctx, 0x4019b4, 3);296	}297	gr_def(ctx, 0x4019bc, 0xffff0000);298	switch (device->chipset) {299	case 0x46:300	case 0x47:301	case 0x49:302	case 0x4b:303		cp_ctx(ctx, 0x4019c0, 18);304		for (i = 0; i < 16; i++)305			gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888);306		break;307	}308	cp_ctx(ctx, 0x401a08, 8);309	gr_def(ctx, 0x401a10, 0x0fff0000);310	gr_def(ctx, 0x401a14, 0x0fff0000);311	gr_def(ctx, 0x401a1c, 0x00011100);312	cp_ctx(ctx, 0x401a2c, 4);313	cp_ctx(ctx, 0x401a44, 26);314	for (i = 0; i < 16; i++)315		gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000);316	gr_def(ctx, 0x401a8c, 0x4b7fffff);317	if (device->chipset == 0x40) {318		cp_ctx(ctx, 0x401ab8, 3);319	} else {320		cp_ctx(ctx, 0x401ab8, 1);321		cp_ctx(ctx, 0x401ac0, 1);322	}323	cp_ctx(ctx, 0x401ad0, 8);324	gr_def(ctx, 0x401ad0, 0x30201000);325	gr_def(ctx, 0x401ad4, 0x70605040);326	gr_def(ctx, 0x401ad8, 0xb8a89888);327	gr_def(ctx, 0x401adc, 0xf8e8d8c8);328	cp_ctx(ctx, 0x401b10, device->chipset == 0x40 ? 2 : 1);329	gr_def(ctx, 0x401b10, 0x40100000);330	cp_ctx(ctx, 0x401b18, device->chipset == 0x40 ? 6 : 5);331	gr_def(ctx, 0x401b28, device->chipset == 0x40 ?332			      0x00000004 : 0x00000000);333	cp_ctx(ctx, 0x401b30, 25);334	gr_def(ctx, 0x401b34, 0x0000ffff);335	gr_def(ctx, 0x401b68, 0x435185d6);336	gr_def(ctx, 0x401b6c, 0x2155b699);337	gr_def(ctx, 0x401b70, 0xfedcba98);338	gr_def(ctx, 0x401b74, 0x00000098);339	gr_def(ctx, 0x401b84, 0xffffffff);340	gr_def(ctx, 0x401b88, 0x00ff7000);341	gr_def(ctx, 0x401b8c, 0x0000ffff);342	if (device->chipset != 0x44 && device->chipset != 0x4a &&343	    device->chipset != 0x4e)344		cp_ctx(ctx, 0x401b94, 1);345	cp_ctx(ctx, 0x401b98, 8);346	gr_def(ctx, 0x401b9c, 0x00ff0000);347	cp_ctx(ctx, 0x401bc0, 9);348	gr_def(ctx, 0x401be0, 0x00ffff00);349	cp_ctx(ctx, 0x401c00, 192);350	for (i = 0; i < 16; i++) { /* fragment texture units */351		gr_def(ctx, 0x401c40 + (i * 4), 0x00018488);352		gr_def(ctx, 0x401c80 + (i * 4), 0x00028202);353		gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4);354		gr_def(ctx, 0x401d40 + (i * 4), 0x01012000);355		gr_def(ctx, 0x401d80 + (i * 4), 0x00080008);356		gr_def(ctx, 0x401e00 + (i * 4), 0x00100008);357	}358	for (i = 0; i < 4; i++) { /* vertex texture units */359		gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80);360		gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202);361		gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008);362		gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008);363	}364	cp_ctx(ctx, 0x400f5c, 3);365	gr_def(ctx, 0x400f5c, 0x00000002);366	cp_ctx(ctx, 0x400f84, 1);367}368 369static void370nv40_gr_construct_state3d_2(struct nvkm_grctx *ctx)371{372	struct nvkm_device *device = ctx->device;373	int i;374 375	cp_ctx(ctx, 0x402000, 1);376	cp_ctx(ctx, 0x402404, device->chipset == 0x40 ? 1 : 2);377	switch (device->chipset) {378	case 0x40:379		gr_def(ctx, 0x402404, 0x00000001);380		break;381	case 0x4c:382	case 0x4e:383	case 0x67:384		gr_def(ctx, 0x402404, 0x00000020);385		break;386	case 0x46:387	case 0x49:388	case 0x4b:389		gr_def(ctx, 0x402404, 0x00000421);390		break;391	default:392		gr_def(ctx, 0x402404, 0x00000021);393	}394	if (device->chipset != 0x40)395		gr_def(ctx, 0x402408, 0x030c30c3);396	switch (device->chipset) {397	case 0x44:398	case 0x46:399	case 0x4a:400	case 0x4c:401	case 0x4e:402	case 0x67:403		cp_ctx(ctx, 0x402440, 1);404		gr_def(ctx, 0x402440, 0x00011001);405		break;406	default:407		break;408	}409	cp_ctx(ctx, 0x402480, device->chipset == 0x40 ? 8 : 9);410	gr_def(ctx, 0x402488, 0x3e020200);411	gr_def(ctx, 0x40248c, 0x00ffffff);412	switch (device->chipset) {413	case 0x40:414		gr_def(ctx, 0x402490, 0x60103f00);415		break;416	case 0x47:417		gr_def(ctx, 0x402490, 0x40103f00);418		break;419	case 0x41:420	case 0x42:421	case 0x49:422	case 0x4b:423		gr_def(ctx, 0x402490, 0x20103f00);424		break;425	default:426		gr_def(ctx, 0x402490, 0x0c103f00);427		break;428	}429	gr_def(ctx, 0x40249c, device->chipset <= 0x43 ?430			      0x00020000 : 0x00040000);431	cp_ctx(ctx, 0x402500, 31);432	gr_def(ctx, 0x402530, 0x00008100);433	if (device->chipset == 0x40)434		cp_ctx(ctx, 0x40257c, 6);435	cp_ctx(ctx, 0x402594, 16);436	cp_ctx(ctx, 0x402800, 17);437	gr_def(ctx, 0x402800, 0x00000001);438	switch (device->chipset) {439	case 0x47:440	case 0x49:441	case 0x4b:442		cp_ctx(ctx, 0x402864, 1);443		gr_def(ctx, 0x402864, 0x00001001);444		cp_ctx(ctx, 0x402870, 3);445		gr_def(ctx, 0x402878, 0x00000003);446		if (device->chipset != 0x47) { /* belong at end!! */447			cp_ctx(ctx, 0x402900, 1);448			cp_ctx(ctx, 0x402940, 1);449			cp_ctx(ctx, 0x402980, 1);450			cp_ctx(ctx, 0x4029c0, 1);451			cp_ctx(ctx, 0x402a00, 1);452			cp_ctx(ctx, 0x402a40, 1);453			cp_ctx(ctx, 0x402a80, 1);454			cp_ctx(ctx, 0x402ac0, 1);455		}456		break;457	case 0x40:458		cp_ctx(ctx, 0x402844, 1);459		gr_def(ctx, 0x402844, 0x00000001);460		cp_ctx(ctx, 0x402850, 1);461		break;462	default:463		cp_ctx(ctx, 0x402844, 1);464		gr_def(ctx, 0x402844, 0x00001001);465		cp_ctx(ctx, 0x402850, 2);466		gr_def(ctx, 0x402854, 0x00000003);467		break;468	}469 470	cp_ctx(ctx, 0x402c00, 4);471	gr_def(ctx, 0x402c00, device->chipset == 0x40 ?472			      0x80800001 : 0x00888001);473	switch (device->chipset) {474	case 0x47:475	case 0x49:476	case 0x4b:477		cp_ctx(ctx, 0x402c20, 40);478		for (i = 0; i < 32; i++)479			gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff);480		cp_ctx(ctx, 0x4030b8, 13);481		gr_def(ctx, 0x4030dc, 0x00000005);482		gr_def(ctx, 0x4030e8, 0x0000ffff);483		break;484	default:485		cp_ctx(ctx, 0x402c10, 4);486		if (device->chipset == 0x40)487			cp_ctx(ctx, 0x402c20, 36);488		else489		if (device->chipset <= 0x42)490			cp_ctx(ctx, 0x402c20, 24);491		else492		if (device->chipset <= 0x4a)493			cp_ctx(ctx, 0x402c20, 16);494		else495			cp_ctx(ctx, 0x402c20, 8);496		cp_ctx(ctx, 0x402cb0, device->chipset == 0x40 ? 12 : 13);497		gr_def(ctx, 0x402cd4, 0x00000005);498		if (device->chipset != 0x40)499			gr_def(ctx, 0x402ce0, 0x0000ffff);500		break;501	}502 503	cp_ctx(ctx, 0x403400, device->chipset == 0x40 ? 4 : 3);504	cp_ctx(ctx, 0x403410, device->chipset == 0x40 ? 4 : 3);505	cp_ctx(ctx, 0x403420, nv40_gr_vs_count(ctx->device));506	for (i = 0; i < nv40_gr_vs_count(ctx->device); i++)507		gr_def(ctx, 0x403420 + (i * 4), 0x00005555);508 509	if (device->chipset != 0x40) {510		cp_ctx(ctx, 0x403600, 1);511		gr_def(ctx, 0x403600, 0x00000001);512	}513	cp_ctx(ctx, 0x403800, 1);514 515	cp_ctx(ctx, 0x403c18, 1);516	gr_def(ctx, 0x403c18, 0x00000001);517	switch (device->chipset) {518	case 0x46:519	case 0x47:520	case 0x49:521	case 0x4b:522		cp_ctx(ctx, 0x405018, 1);523		gr_def(ctx, 0x405018, 0x08e00001);524		cp_ctx(ctx, 0x405c24, 1);525		gr_def(ctx, 0x405c24, 0x000e3000);526		break;527	}528	if (device->chipset != 0x4e)529		cp_ctx(ctx, 0x405800, 11);530	cp_ctx(ctx, 0x407000, 1);531}532 533static void534nv40_gr_construct_state3d_3(struct nvkm_grctx *ctx)535{536	int len = nv44_gr_class(ctx->device) ? 0x0084 : 0x0684;537 538	cp_out (ctx, 0x300000);539	cp_lsr (ctx, len - 4);540	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save);541	cp_lsr (ctx, len);542	cp_name(ctx, cp_swap_state3d_3_is_save);543	cp_out (ctx, 0x800001);544 545	ctx->ctxvals_pos += len;546}547 548static void549nv40_gr_construct_shader(struct nvkm_grctx *ctx)550{551	struct nvkm_device *device = ctx->device;552	struct nvkm_gpuobj *obj = ctx->data;553	int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset;554	int offset, i;555 556	vs_nr    = nv40_gr_vs_count(ctx->device);557	vs_nr_b0 = 363;558	vs_nr_b1 = device->chipset == 0x40 ? 128 : 64;559	if (device->chipset == 0x40) {560		b0_offset = 0x2200/4; /* 33a0 */561		b1_offset = 0x55a0/4; /* 1500 */562		vs_len = 0x6aa0/4;563	} else564	if (device->chipset == 0x41 || device->chipset == 0x42) {565		b0_offset = 0x2200/4; /* 2200 */566		b1_offset = 0x4400/4; /* 0b00 */567		vs_len = 0x4f00/4;568	} else {569		b0_offset = 0x1d40/4; /* 2200 */570		b1_offset = 0x3f40/4; /* 0b00 : 0a40 */571		vs_len = nv44_gr_class(device) ? 0x4980/4 : 0x4a40/4;572	}573 574	cp_lsr(ctx, vs_len * vs_nr + 0x300/4);575	cp_out(ctx, nv44_gr_class(device) ? 0x800029 : 0x800041);576 577	offset = ctx->ctxvals_pos;578	ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len));579 580	if (ctx->mode != NVKM_GRCTX_VALS)581		return;582 583	offset += 0x0280/4;584	for (i = 0; i < 16; i++, offset += 2)585		nvkm_wo32(obj, offset * 4, 0x3f800000);586 587	for (vs = 0; vs < vs_nr; vs++, offset += vs_len) {588		for (i = 0; i < vs_nr_b0 * 6; i += 6)589			nvkm_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001);590		for (i = 0; i < vs_nr_b1 * 4; i += 4)591			nvkm_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000);592	}593}594 595static void596nv40_grctx_generate(struct nvkm_grctx *ctx)597{598	/* decide whether we're loading/unloading the context */599	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);600	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);601 602	cp_name(ctx, cp_check_load);603	cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);604	cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);605	cp_bra (ctx, ALWAYS, TRUE, cp_exit);606 607	/* setup for context load */608	cp_name(ctx, cp_setup_auto_load);609	cp_wait(ctx, STATUS, IDLE);610	cp_out (ctx, CP_NEXT_TO_SWAP);611	cp_name(ctx, cp_setup_load);612	cp_wait(ctx, STATUS, IDLE);613	cp_set (ctx, SWAP_DIRECTION, LOAD);614	cp_out (ctx, 0x00910880); /* ?? */615	cp_out (ctx, 0x00901ffe); /* ?? */616	cp_out (ctx, 0x01940000); /* ?? */617	cp_lsr (ctx, 0x20);618	cp_out (ctx, 0x0060000b); /* ?? */619	cp_wait(ctx, UNK57, CLEAR);620	cp_out (ctx, 0x0060000c); /* ?? */621	cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);622 623	/* setup for context save */624	cp_name(ctx, cp_setup_save);625	cp_set (ctx, SWAP_DIRECTION, SAVE);626 627	/* general PGRAPH state */628	cp_name(ctx, cp_swap_state);629	cp_pos (ctx, 0x00020/4);630	nv40_gr_construct_general(ctx);631	cp_wait(ctx, STATUS, IDLE);632 633	/* 3D state, block 1 */634	cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit);635	nv40_gr_construct_state3d(ctx);636	cp_wait(ctx, STATUS, IDLE);637 638	/* 3D state, block 2 */639	nv40_gr_construct_state3d_2(ctx);640 641	/* Some other block of "random" state */642	nv40_gr_construct_state3d_3(ctx);643 644	/* Per-vertex shader state */645	cp_pos (ctx, ctx->ctxvals_pos);646	nv40_gr_construct_shader(ctx);647 648	/* pre-exit state updates */649	cp_name(ctx, cp_prepare_exit);650	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);651	cp_bra (ctx, USER_SAVE, PENDING, cp_exit);652	cp_out (ctx, CP_NEXT_TO_CURRENT);653 654	cp_name(ctx, cp_exit);655	cp_set (ctx, USER_SAVE, NOT_PENDING);656	cp_set (ctx, USER_LOAD, NOT_PENDING);657	cp_out (ctx, CP_END);658}659 660void661nv40_grctx_fill(struct nvkm_device *device, struct nvkm_gpuobj *mem)662{663	nv40_grctx_generate(&(struct nvkm_grctx) {664			     .device = device,665			     .mode = NVKM_GRCTX_VALS,666			     .data = mem,667			   });668}669 670int671nv40_grctx_init(struct nvkm_device *device, u32 *size)672{673	u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;674	struct nvkm_grctx ctx = {675		.device = device,676		.mode = NVKM_GRCTX_PROG,677		.ucode = ctxprog,678		.ctxprog_max = 256,679	};680 681	if (!ctxprog)682		return -ENOMEM;683 684	nv40_grctx_generate(&ctx);685 686	nvkm_wr32(device, 0x400324, 0);687	for (i = 0; i < ctx.ctxprog_len; i++)688		nvkm_wr32(device, 0x400328, ctxprog[i]);689	*size = ctx.ctxvals_pos * 4;690 691	kfree(ctxprog);692	return 0;693}694