2 *-----------------------------------------------------------------------------
5 *-----------------------------------------------------------------------------
6 * Copyright (c) 2002-2010, Intel Corporation.
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 *-----------------------------------------------------------------------------
28 * This is the implementation file for the register module's main API's called
29 * by external devices.
30 *-----------------------------------------------------------------------------
33 #define MODULE_NAME hal.state
39 #include <igd_errno.h>
51 #include "reg_dispatch.h"
54 * @addtogroup state_group
58 typedef struct _reg_context {
59 unsigned long flags; /* IGD_DRIVER_SAVE_RESTORE */
60 reg_dispatch_t *dispatch;
61 reg_buffer_t *device_state;
65 extern emgd_drm_config_t config_drm;
66 static reg_context_t reg_ctx[1];
67 static reg_buffer_t *console_state;
68 void *console_gmm_state;
69 static reg_buffer_t *misc_state;
72 static dispatch_table_t reg_dispatch_list[] = {
75 {PCI_DEVICE_ID_VGA_PLB, ®_dispatch_plb},
78 {PCI_DEVICE_ID_VGA_TNC, ®_dispatch_tnc},
83 void *reg_alloc(igd_context_t *context,
86 return (void *)reg_ctx->dispatch->reg_alloc(context, flags,
87 reg_ctx->dispatch->platform_context);
90 void reg_free(igd_context_t *context,
93 reg_ctx->dispatch->reg_free(context, (reg_buffer_t *)reg_set,
94 reg_ctx->dispatch->platform_context);
97 int reg_save(igd_context_t *context,
100 return reg_ctx->dispatch->reg_save(context, (reg_buffer_t *)reg_set,
101 reg_ctx->dispatch->platform_context);
104 int reg_restore(igd_context_t *context,
107 return reg_ctx->dispatch->reg_restore(context, (reg_buffer_t *)reg_set,
108 reg_ctx->dispatch->platform_context);
111 void reg_crtc_lut_get(igd_context_t *context,
114 reg_ctx->dispatch->reg_crtc_lut_get(context, (emgd_crtc_t *)emgd_crtc);
117 void reg_crtc_lut_set(igd_context_t *context,
120 reg_ctx->dispatch->reg_crtc_lut_set(context, (emgd_crtc_t *)emgd_crtc);
124 * This function calls reg_save() to save the state of the graphics engine
125 * and then reg_restore to restore the previous state.
127 * @param driver_handle our driver context
129 * @return 0 on success
130 * @return -IGD_INVAL on failure
132 static int igd_driver_save_restore(igd_driver_h driver_handle,
135 igd_context_t *context = (igd_context_t *)driver_handle;
136 reg_buffer_t *reg_state;
139 EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
142 * If the gmm_state exists, the registers are not setup, so we should not
143 * try to save the GTT, the ring buffer and appcontext, or it will cause a
144 * sync which will not be fulfilled, so it will wait forever. We can
145 * however save everything else. If the gmm_state is null, then everything
146 * is still setup and we can save everything including the GTT, ring buffer
149 if (reg_ctx->gmm_state) {
150 flags = flags & ~IGD_REG_SAVE_GTT & ~IGD_REG_SAVE_RB;
153 /* Save current state. We have to save the current state first before
154 * restoring the GART bindings. Otherwise we will end up restoring wrong
155 * pages when return back to the graphic mode console */
156 reg_state = reg_ctx->dispatch->reg_alloc(context, flags,
157 reg_ctx->dispatch->platform_context);
158 reg_ctx->dispatch->reg_save(context, reg_state,
159 reg_ctx->dispatch->platform_context);
161 /* Restore GART bindings, if saved */
162 if (reg_ctx->gmm_state && context->mod_dispatch.gmm_restore) {
163 context->mod_dispatch.gmm_restore(context, reg_ctx->gmm_state);
164 reg_ctx->gmm_state = NULL;
168 /* restore previously saved state */
171 * NAPA class seems to work much better all the display stuff is
172 * turned off prior to restoring the registers.
174 context->mod_dispatch.mode_reset_plane_pipe_ports(context);
177 reg_ctx->dispatch->reg_restore(context, reg_ctx->device_state,
178 reg_ctx->dispatch->platform_context);
179 reg_ctx->dispatch->reg_free(context, reg_ctx->device_state,
180 reg_ctx->dispatch->platform_context);
182 reg_ctx->device_state = reg_state;
184 /* Free GART bindings, if not already saved */
185 if (!restored && !reg_ctx->gmm_state &&
186 context->mod_dispatch.gmm_save) {
187 context->mod_dispatch.gmm_save(context, &(reg_ctx->gmm_state));
194 * This function calls reg_save() to save the state of the register
196 * @param driver_handle our driver context
197 * @param flags specifies which states to save
199 * @return 0 on success
200 * @return -IGD_INVAL on failure
202 static int igd_driver_save(igd_driver_h driver_handle,
203 const unsigned long flags)
205 igd_context_t *context = (igd_context_t *)driver_handle;
206 reg_buffer_t *reg_state;
207 reg_buffer_t **reg_location = NULL;
209 EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
211 switch (flags & IGD_REG_SAVE_TYPE_MASK) {
212 case IGD_REG_SAVE_TYPE_REG:
213 reg_location = ®_ctx->device_state;
215 case IGD_REG_SAVE_TYPE_CON:
216 reg_location = &console_state;
218 case IGD_REG_SAVE_TYPE_MISC:
219 reg_location = &misc_state;
222 EMGD_ERROR("Called igd_driver_save without a valid save flag.");
227 reg_ctx->dispatch->reg_free(context, *reg_location,
228 reg_ctx->dispatch->platform_context);
231 /* Save current state */
232 reg_state = reg_ctx->dispatch->reg_alloc(context, flags,
233 reg_ctx->dispatch->platform_context);
234 reg_ctx->dispatch->reg_save(context, reg_state,
235 reg_ctx->dispatch->platform_context);
237 *reg_location = reg_state;
239 /* Free GART bindings, if not already saved */
240 if ((flags & IGD_REG_SAVE_TYPE_REG) &&
241 !reg_ctx->gmm_state &&
242 context->mod_dispatch.gmm_save) {
243 context->mod_dispatch.gmm_save(context, &(reg_ctx->gmm_state));
247 /* igd_driver_save */
250 * This function calls reg_restore() to restore previously saved
252 * @param driver_handle our driver context
254 * @return 0 on success
255 * @return -IGD_INVAL on failure
257 static int igd_driver_restore(igd_driver_h driver_handle,
258 const unsigned long flags)
260 igd_context_t *context;
261 reg_buffer_t *reg_state = NULL;
263 EMGD_ASSERT(driver_handle, "Null driver_handle!\n", -IGD_ERROR_INVAL);
265 context = (igd_context_t *)driver_handle;
266 switch (flags & IGD_REG_SAVE_TYPE_MASK) {
267 case IGD_REG_SAVE_TYPE_REG:
268 reg_state = reg_ctx->device_state;
270 case IGD_REG_SAVE_TYPE_CON:
271 reg_state = console_state;
273 case IGD_REG_SAVE_TYPE_MISC:
274 reg_state = misc_state;
277 EMGD_ERROR("Not a valida restore flag specified.");
282 * NAPA class seems to work much better all the display stuff is
283 * turned off prior to restoring the registers.
284 * context->mod_dispatch.mode_reset_plane_pipe_ports(context);
286 context->mod_dispatch.mode_reset_plane_pipe_ports(context);
288 /* restore previously saved state */
290 reg_ctx->dispatch->reg_restore(context, reg_state,
291 reg_ctx->dispatch->platform_context);
292 reg_ctx->dispatch->reg_free(context, reg_state,
293 reg_ctx->dispatch->platform_context);
295 /* Restore GART bindings, if saved */
296 if ((flags & IGD_REG_SAVE_TYPE_REG) &&
297 reg_ctx->gmm_state &&
298 context->mod_dispatch.gmm_restore) {
299 context->mod_dispatch.gmm_restore(context, reg_ctx->gmm_state);
300 reg_ctx->gmm_state = NULL;
303 EMGD_ERROR("Previous state was not saved, so can't restore.");
315 * @return 0 on success
316 * @return -IGD_ERROR_INVAL on failure
318 static int reg_get_mod_state(reg_state_id_t id, module_state_h **state,
319 unsigned long **flags)
321 if(!reg_ctx->device_state && !console_state) {
326 case REG_MODE_STATE_REG:
327 *flags = ®_ctx->device_state->flags;
328 if((**flags & IGD_REG_SAVE_MODE)){
329 *state = ®_ctx->device_state->mode_buffer;
334 case REG_MODE_STATE_CON:
335 *flags = &console_state->flags;
336 if((**flags & IGD_REG_SAVE_MODE)){
337 *state = &console_state->mode_buffer;
344 return -IGD_ERROR_INVAL;
351 * Free any memory allocated for registry state info.
357 void _reg_shutdown(igd_context_t *context)
359 reg_buffer_t *restore_state;
362 if (!config_drm.init) {
363 restore_state = reg_ctx[0].device_state;
365 if (config_drm.kms) {
366 restore_state = console_state;
368 restore_state = console_state;
369 //restore_state = reg_ctx[0].device_state;
374 context->mod_dispatch.mode_reset_plane_pipe_ports(context);
376 EMGD_DEBUG("Restoring register values prior to exit...");
377 reg_ctx->dispatch->reg_restore(context, restore_state,
378 reg_ctx->dispatch->platform_context);
379 reg_ctx->dispatch->reg_free(context, restore_state,
380 reg_ctx->dispatch->platform_context);
383 OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
389 * Initialize the registry state context for registry save
390 * /restore operations.
395 * @return 0 on success
396 * @return 1 on failure
398 int _reg_init(igd_context_t *context, unsigned long flags)
400 reg_dispatch_t *dispatch;
404 dispatch = (reg_dispatch_t *)dispatch_acquire(context, reg_dispatch_list);
406 return -IGD_ERROR_NODEV;
409 OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
411 reg_ctx->dispatch = dispatch;
414 * Hook up functions in dispatch table.
416 context->dispatch.driver_save_restore = igd_driver_save_restore;
417 context->dispatch.driver_save = igd_driver_save;
418 context->dispatch.driver_restore = igd_driver_restore;
419 context->mod_dispatch.reg_get_mod_state = reg_get_mod_state;
420 context->mod_dispatch.reg_alloc = reg_alloc;
421 context->mod_dispatch.reg_free = reg_free;
422 context->mod_dispatch.reg_save = reg_save;
423 context->mod_dispatch.reg_restore = reg_restore;
424 context->mod_dispatch.reg_shutdown = _reg_shutdown;
425 context->mod_dispatch.reg_crtc_lut_get = reg_crtc_lut_get;
426 context->mod_dispatch.reg_crtc_lut_set = reg_crtc_lut_set;
428 if(flags & IGD_DRIVER_SAVE_RESTORE) {
429 reg_ctx->flags |= IGD_DRIVER_SAVE_RESTORE;
430 EMGD_DEBUG("Saving Device State");
432 reg_ctx->device_state = reg_ctx->dispatch->reg_alloc(context,
433 IGD_REG_SAVE_STATE|IGD_REG_SAVE_MODE|IGD_REG_SAVE_TYPE_REG,
434 reg_ctx->dispatch->platform_context);
435 reg_ctx->dispatch->reg_save(context, reg_ctx->device_state,
436 reg_ctx->dispatch->platform_context);
439 if (config_drm.init) {
440 console_state = reg_ctx->dispatch->reg_alloc(context,
441 IGD_REG_SAVE_STATE|IGD_REG_SAVE_MODE|IGD_REG_SAVE_TYPE_CON,
442 reg_ctx->dispatch->platform_context);
443 reg_ctx->dispatch->reg_save(context, console_state,
444 reg_ctx->dispatch->platform_context);