1/*
2 * Copyright (C) 2007 Arthur Huillet.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28/*
29 * Authors:
30 *   Arthur Huillet <arthur.huillet AT free DOT fr>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "nouveau_drm.h"
36#include "nouveau_drv.h"
37#include "nouveau_reg.h"
38
39/*TODO: add a "card_type" attribute*/
40typedef struct{
41	uint32_t oclass; /* object class for this software method */
42	uint32_t mthd; /* method number */
43	void (*method_code)(struct drm_device *dev, uint32_t oclass, uint32_t mthd); /* pointer to the function that does the work */
44 } nouveau_software_method_t;
45
46
47 /* This function handles the NV04 setcontext software methods.
48One function for all because they are very similar.*/
49static void nouveau_NV04_setcontext_sw_method(struct drm_device *dev, uint32_t oclass, uint32_t mthd) {
50	struct drm_nouveau_private *dev_priv = dev->dev_private;
51	uint32_t inst_loc = NV_READ(NV04_PGRAPH_CTX_SWITCH4) & 0xFFFF;
52	uint32_t value_to_set = 0, bit_to_set = 0;
53
54	switch ( oclass ) {
55		case 0x4a:
56			switch ( mthd ) {
57				case 0x188 :
58				case 0x18c :
59					bit_to_set = 0;
60					break;
61				case 0x198 :
62					bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
63					break;
64				case 0x2fc :
65					bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
66					break;
67				default : ;
68				};
69			break;
70		case 0x5c:
71			switch ( mthd ) {
72				case 0x184:
73					bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
74					break;
75				case 0x188:
76				case 0x18c:
77					bit_to_set = 0;
78					break;
79				case 0x198:
80					bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
81					break;
82				case 0x2fc :
83					bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
84					break;
85			};
86			break;
87		case 0x5f:
88			switch ( mthd ) {
89				case 0x184 :
90					bit_to_set = 1 << 12; /*CHROMA_KEY_ENABLE*/
91					break;
92				case 0x188 :
93					bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
94					break;
95				case 0x18c :
96				case 0x190 :
97					bit_to_set = 0;
98					break;
99				case 0x19c :
100					bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
101					break;
102				case 0x2fc :
103					bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
104					break;
105			};
106			break;
107		case 0x61:
108			switch ( mthd ) {
109				case 0x188 :
110					bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
111					break;
112				case 0x18c :
113				case 0x190 :
114					bit_to_set = 0;
115					break;
116				case 0x19c :
117					bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
118					break;
119				case 0x2fc :
120					bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
121					break;
122			};
123			break;
124		case 0x77:
125			switch ( mthd ) {
126				case 0x198 :
127					bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
128					break;
129				case 0x304 :
130					bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; //PATCH_CONFIG
131					break;
132			};
133			break;
134		default :;
135		};
136
137	value_to_set = (NV_READ(0x00700000 | inst_loc << 4))| bit_to_set;
138
139	/*RAMIN*/
140	nouveau_wait_for_idle(dev);
141	NV_WRITE(0x00700000 | inst_loc << 4, value_to_set);
142
143	/*DRM_DEBUG("CTX_SWITCH1 value is %#x\n", NV_READ(NV04_PGRAPH_CTX_SWITCH1));*/
144	NV_WRITE(NV04_PGRAPH_CTX_SWITCH1, value_to_set);
145
146	/*DRM_DEBUG("CTX_CACHE1 + xxx value is %#x\n", NV_READ(NV04_PGRAPH_CTX_CACHE1 + (((NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7) << 2)));*/
147	NV_WRITE(NV04_PGRAPH_CTX_CACHE1 + (((NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7) << 2), value_to_set);
148}
149
150 nouveau_software_method_t nouveau_sw_methods[] = {
151	/*NV04 context software methods*/
152	{ 0x4a, 0x188, nouveau_NV04_setcontext_sw_method },
153	{ 0x4a, 0x18c, nouveau_NV04_setcontext_sw_method },
154	{ 0x4a, 0x198, nouveau_NV04_setcontext_sw_method },
155	{ 0x4a, 0x2fc, nouveau_NV04_setcontext_sw_method },
156	{ 0x5c, 0x184, nouveau_NV04_setcontext_sw_method },
157	{ 0x5c, 0x188, nouveau_NV04_setcontext_sw_method },
158	{ 0x5c, 0x18c, nouveau_NV04_setcontext_sw_method },
159	{ 0x5c, 0x198, nouveau_NV04_setcontext_sw_method },
160	{ 0x5c, 0x2fc, nouveau_NV04_setcontext_sw_method },
161	{ 0x5f, 0x184, nouveau_NV04_setcontext_sw_method },
162	{ 0x5f, 0x188, nouveau_NV04_setcontext_sw_method },
163	{ 0x5f, 0x18c, nouveau_NV04_setcontext_sw_method },
164	{ 0x5f, 0x190, nouveau_NV04_setcontext_sw_method },
165	{ 0x5f, 0x19c, nouveau_NV04_setcontext_sw_method },
166	{ 0x5f, 0x2fc, nouveau_NV04_setcontext_sw_method },
167	{ 0x61, 0x188, nouveau_NV04_setcontext_sw_method },
168	{ 0x61, 0x18c, nouveau_NV04_setcontext_sw_method },
169	{ 0x61, 0x190, nouveau_NV04_setcontext_sw_method },
170	{ 0x61, 0x19c, nouveau_NV04_setcontext_sw_method },
171	{ 0x61, 0x2fc, nouveau_NV04_setcontext_sw_method },
172	{ 0x77, 0x198, nouveau_NV04_setcontext_sw_method },
173	{ 0x77, 0x304, nouveau_NV04_setcontext_sw_method },
174	/*terminator*/
175	{ 0x0, 0x0, NULL, },
176 };
177
178 int nouveau_sw_method_execute(struct drm_device *dev, uint32_t oclass, uint32_t method) {
179	int i = 0;
180	while ( nouveau_sw_methods[ i ] . method_code != NULL )
181		{
182		if ( nouveau_sw_methods[ i ] . oclass == oclass && nouveau_sw_methods[ i ] . mthd == method )
183			{
184			nouveau_sw_methods[ i ] . method_code(dev, oclass, method);
185			return 0;
186			}
187		i ++;
188		}
189
190	 return 1;
191 }
192