packaging: update the changelog
[profile/ivi/intel-emgd-kmod.git] / drivers / emgd / state / reg / cmn / reg.c
1 /*
2  *-----------------------------------------------------------------------------
3  * Filename: reg.c
4  * $Revision: 1.16 $
5  *-----------------------------------------------------------------------------
6  * Copyright (c) 2002-2010, Intel Corporation.
7  *
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:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
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
24  * THE SOFTWARE.
25  *
26  *-----------------------------------------------------------------------------
27  * Description:
28  *  This is the implementation file for the register module's main API's called
29  *  by external devices.
30  *-----------------------------------------------------------------------------
31  */
32
33 #define MODULE_NAME hal.state
34
35 #include <io.h>
36
37 #include <igd_init.h>
38 #include <igd_mode.h>
39 #include <igd_errno.h>
40
41 #include <context.h>
42 #include <utils.h>
43 #include <dsp.h>
44 #include <mode.h>
45 #include <memory.h>
46 #include <utils.h>
47
48 #include <intelpci.h>
49 #include <dispatch.h>
50
51 #include "reg_dispatch.h"
52
53 /*!
54  * @addtogroup state_group
55  * @{
56  */
57
58 typedef struct _reg_context {
59         unsigned long flags;     /* IGD_DRIVER_SAVE_RESTORE */
60         reg_dispatch_t *dispatch;
61         reg_buffer_t *device_state;
62         void *gmm_state;
63 } reg_context_t;
64
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;
70 void *misc_gmm_state;
71
72 static dispatch_table_t reg_dispatch_list[] = {
73
74 #ifdef CONFIG_PLB
75         {PCI_DEVICE_ID_VGA_PLB, &reg_dispatch_plb},
76 #endif
77 #ifdef CONFIG_TNC
78         {PCI_DEVICE_ID_VGA_TNC, &reg_dispatch_tnc},
79 #endif
80         {0, NULL}
81 };
82
83 void *reg_alloc(igd_context_t *context,
84         unsigned long flags)
85 {
86         return (void *)reg_ctx->dispatch->reg_alloc(context, flags,
87                 reg_ctx->dispatch->platform_context);
88 }
89
90 void reg_free(igd_context_t *context,
91         void *reg_set)
92 {
93         reg_ctx->dispatch->reg_free(context, (reg_buffer_t *)reg_set,
94                 reg_ctx->dispatch->platform_context);
95 }
96
97 int reg_save(igd_context_t *context,
98         void *reg_set)
99 {
100         return reg_ctx->dispatch->reg_save(context, (reg_buffer_t *)reg_set,
101                 reg_ctx->dispatch->platform_context);
102 }
103
104 int reg_restore(igd_context_t *context,
105         void *reg_set)
106 {
107         return reg_ctx->dispatch->reg_restore(context, (reg_buffer_t *)reg_set,
108                 reg_ctx->dispatch->platform_context);
109 }
110
111 void reg_crtc_lut_get(igd_context_t *context,
112         void *emgd_crtc)
113 {
114         reg_ctx->dispatch->reg_crtc_lut_get(context, (emgd_crtc_t *)emgd_crtc);
115 }
116
117 void reg_crtc_lut_set(igd_context_t *context,
118         void *emgd_crtc)
119 {
120         reg_ctx->dispatch->reg_crtc_lut_set(context, (emgd_crtc_t *)emgd_crtc);
121 }
122
123 /*!
124  * This function calls reg_save() to save the state of the graphics engine
125  * and then reg_restore to restore the previous state.
126  *
127  * @param driver_handle  our driver context
128  *
129  * @return 0 on success
130  * @return -IGD_INVAL on failure
131  */
132 static int igd_driver_save_restore(igd_driver_h driver_handle,
133         unsigned long flags)
134 {
135         igd_context_t *context = (igd_context_t *)driver_handle;
136         reg_buffer_t *reg_state;
137         short restored = 0;
138
139         EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
140
141         /*
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
147          * and appcontext.
148          */
149         if (reg_ctx->gmm_state) {
150                 flags = flags & ~IGD_REG_SAVE_GTT & ~IGD_REG_SAVE_RB;
151         }
152
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);
160
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;
165                 restored = 1;
166         }
167
168         /* restore previously saved state */
169
170         /*
171          * NAPA class seems to work much better all the display stuff is
172          * turned off prior to restoring the registers.
173          */
174         context->mod_dispatch.mode_reset_plane_pipe_ports(context);
175
176
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);
181
182         reg_ctx->device_state = reg_state;
183
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));
188         }
189
190         return 0;
191 }
192
193 /*!
194  * This function calls reg_save() to save the state of the register
195  *
196  * @param driver_handle our driver context
197  * @param flags specifies which states to save
198  *
199  * @return 0 on success
200  * @return -IGD_INVAL on failure
201  */
202 static int igd_driver_save(igd_driver_h driver_handle,
203         const unsigned long flags)
204 {
205         igd_context_t *context = (igd_context_t *)driver_handle;
206         reg_buffer_t *reg_state;
207         reg_buffer_t **reg_location = NULL;
208
209         EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
210
211         switch (flags & IGD_REG_SAVE_TYPE_MASK) {
212         case IGD_REG_SAVE_TYPE_REG:
213                 reg_location = &reg_ctx->device_state;
214                 break;
215         case IGD_REG_SAVE_TYPE_CON:
216                 reg_location = &console_state;
217                 break;
218         case IGD_REG_SAVE_TYPE_MISC:
219                 reg_location = &misc_state;
220                 break;
221         default:
222                 EMGD_ERROR("Called igd_driver_save without a valid save flag.");
223                 return 0;
224         }
225
226         if (*reg_location) {
227                 reg_ctx->dispatch->reg_free(context, *reg_location,
228                         reg_ctx->dispatch->platform_context);
229         }
230
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);
236
237         *reg_location = reg_state;
238
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));
244         }
245         return 0;
246 }
247 /* igd_driver_save */
248
249 /*!
250  * This function calls reg_restore() to restore previously saved
251  *
252  * @param driver_handle our driver context
253  *
254  * @return 0 on success
255  * @return -IGD_INVAL on failure
256  */
257 static int igd_driver_restore(igd_driver_h driver_handle,
258         const unsigned long flags)
259 {
260         igd_context_t *context;
261         reg_buffer_t *reg_state = NULL;
262
263         EMGD_ASSERT(driver_handle, "Null driver_handle!\n", -IGD_ERROR_INVAL);
264
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;
269                 break;
270         case IGD_REG_SAVE_TYPE_CON:
271                 reg_state = console_state;
272                 break;
273         case IGD_REG_SAVE_TYPE_MISC:
274                 reg_state = misc_state;
275                 break;
276         default:
277                 EMGD_ERROR("Not a valida restore flag specified.");
278                 return 0;
279         }
280
281         /*
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);
285          */
286         context->mod_dispatch.mode_reset_plane_pipe_ports(context);
287
288         /* restore previously saved state */
289         if (reg_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);
294
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;
301                 }
302         } else {
303                 EMGD_ERROR("Previous state was not saved, so can't restore.");
304         }
305
306         return 0;
307 }
308
309 /*!
310  *
311  * @param id
312  * @param state
313  * @param flags
314  *
315  * @return 0 on success
316  * @return -IGD_ERROR_INVAL on failure
317  */
318 static int reg_get_mod_state(reg_state_id_t id, module_state_h **state,
319         unsigned long **flags)
320 {
321         if(!reg_ctx->device_state && !console_state) {
322                 return 0;
323         }
324
325         switch(id) {
326         case REG_MODE_STATE_REG:
327                 *flags = &reg_ctx->device_state->flags;
328                         if((**flags & IGD_REG_SAVE_MODE)){
329                                 *state = &reg_ctx->device_state->mode_buffer;
330                         } else {
331                                 state = NULL;
332                         }
333                 break;
334         case REG_MODE_STATE_CON:
335                 *flags = &console_state->flags;
336                         if((**flags & IGD_REG_SAVE_MODE)){
337                                 *state = &console_state->mode_buffer;
338                         } else {
339                                 state = NULL;
340                         }
341                 break;
342         default:
343                 state = NULL;
344                 return -IGD_ERROR_INVAL;
345         }
346
347         return 0;
348 }
349
350 /*!
351  * Free any memory allocated for registry state info.
352  *
353  * @param context
354  *
355  * @return void
356  */
357 void _reg_shutdown(igd_context_t *context)
358 {
359         reg_buffer_t *restore_state;
360         EMGD_TRACE_ENTER;
361
362         if (!config_drm.init) {
363                 restore_state = reg_ctx[0].device_state;
364         } else {
365                 if (config_drm.kms) {
366                         restore_state = console_state;
367                 } else {
368                         restore_state = console_state;
369                         //restore_state = reg_ctx[0].device_state;
370                 }
371         }
372
373         if(restore_state) {
374                 context->mod_dispatch.mode_reset_plane_pipe_ports(context);
375
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);
381
382         }
383         OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
384
385         EMGD_TRACE_EXIT;
386 }
387
388 /*!
389  * Initialize the registry state context for registry save
390  * /restore operations.
391  *
392  * @param context
393  * @param flags
394  *
395  * @return 0 on success
396  * @return 1 on failure
397  */
398 int _reg_init(igd_context_t *context, unsigned long flags)
399 {
400         reg_dispatch_t *dispatch;
401
402         EMGD_TRACE_ENTER;
403
404         dispatch = (reg_dispatch_t *)dispatch_acquire(context, reg_dispatch_list);
405         if(!dispatch) {
406                 return -IGD_ERROR_NODEV;
407         }
408
409         OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
410
411         reg_ctx->dispatch = dispatch;
412
413         /*
414          * Hook up functions in dispatch table.
415          */
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;
427
428         if(flags & IGD_DRIVER_SAVE_RESTORE) {
429                 reg_ctx->flags |= IGD_DRIVER_SAVE_RESTORE;
430                 EMGD_DEBUG("Saving Device State");
431
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);
437         }
438
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);
445         }
446
447         EMGD_TRACE_EXIT;
448
449         return 0;
450 }
451