staging: emgd: experimental build 2667
[profile/ivi/intel-emgd-kmod.git] / emgd / drm / emgd_fb.c
1 /*
2  *-----------------------------------------------------------------------------
3  * Filename: emgd_fb.c
4  * $Revision: 1.11 $
5  *-----------------------------------------------------------------------------
6  * Copyright (c) 2002-2011, 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  *  Framebuffer / kernel mode setting functions.
29  *-----------------------------------------------------------------------------
30  */
31 #define MODULE_NAME hal.oal
32
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/device.h>
36 #include <linux/fb.h>
37 #include <linux/version.h>
38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
39 #include <linux/export.h>
40 #else
41 #include <linux/module.h>
42 #endif
43 #include <drmP.h>
44 #include <drm.h>
45 #include <drm_crtc.h>
46 #include <drm_crtc_helper.h>
47 #include <drm_fb_helper.h>
48 #include <linux/version.h>
49 #include <linux/vga_switcheroo.h>
50
51 #include "drm_emgd_private.h"
52 #include "emgd_drv.h"
53 #include "emgd_drm.h"
54 #include "memory.h"
55 #include "io.h"
56 #include "mode_dispatch.h"
57
58 /* Necessary to import page list for a PVR-allocated surface */
59 #include "pvr_bridge_km.h"
60
61
62
63 #if  (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
64 #define RETURN_PROBE_TYPE int
65 #define RETURN_PROBE return 0
66 #define PROBE_FUNC fb_changed
67 #else
68 #define RETURN_PROBE_TYPE void
69 #define RETURN_PROBE
70 #define PROBE_FUNC output_poll_changed
71 #endif
72
73
74
75 /*------------------------------------------------------------------------------
76  * Global Variables
77  *------------------------------------------------------------------------------
78  */
79 extern igd_framebuffer_info_t primary_fb_info;
80 extern mode_context_t         mode_context[1];
81 static struct drm_mode_set    panic_mode;
82 extern int                    drm_emgd_init;
83 extern emgd_drm_config_t      config_drm;
84
85 /* CRTC Dispatch Tables */
86 extern const struct drm_crtc_funcs emgd_crtc_funcs;
87 extern const struct drm_crtc_helper_funcs emgd_crtc_helper_funcs;
88
89 /* Encoder Dispatch Tables */
90 extern const struct drm_encoder_funcs emgd_encoder_funcs;
91 extern const struct drm_encoder_helper_funcs emgd_encoder_helper_funcs;
92
93 /* Connector Dispatch Tables */
94 extern const struct drm_connector_funcs emgd_connector_funcs;
95 extern const struct drm_connector_helper_funcs emgd_connector_helper_funcs;
96
97 /* FBCON Dispatch Table */
98 extern const struct fb_ops emgd_fb_ops;
99
100
101
102 /*------------------------------------------------------------------------------
103  * Formal Declaration
104  *------------------------------------------------------------------------------
105  */
106 extern int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev);
107
108 static int emgd_fbdev_init(drm_emgd_priv_t *priv);
109 static void emgd_fbdev_destroy(drm_emgd_priv_t *priv);
110
111
112
113 /*------------------------------------------------------------------------------
114  * FB Functions
115  *------------------------------------------------------------------------------
116  */
117 int emgd_framebuffer_init(struct drm_device *dev,
118                         emgd_framebuffer_t *emgd_fb,
119                         struct DRM_MODE_FB_CMD_TYPE *mode_cmd,
120                         unsigned long offset);
121 static struct drm_framebuffer *emgd_user_framebuffer_create(
122                                                                 struct drm_device *dev,
123                                                                 struct drm_file *filp,
124                                                                 struct DRM_MODE_FB_CMD_TYPE *r);
125 RETURN_PROBE_TYPE  emgd_fb_probe(struct drm_device *dev);
126 static int emgd_fb_panic(struct notifier_block *n,
127                         unsigned long res,
128                         void *panic_str);
129 static void emgd_user_framebuffer_destroy (struct drm_framebuffer *fb);
130 static int  emgd_user_framebuffer_create_handle(struct drm_framebuffer *fb,
131                                 struct drm_file *file_priv, unsigned int *handle);
132 static void emgd_fb_restore(void);
133
134
135 static const struct drm_mode_config_funcs emgd_mode_funcs = {
136         .fb_create  = emgd_user_framebuffer_create,
137         .PROBE_FUNC = emgd_fb_probe,
138         /*.output_poll_changed:  we don't support hotplug */
139 };
140
141
142 static struct notifier_block paniced = {
143         .notifier_call = emgd_fb_panic,
144 };
145
146
147 static const struct drm_framebuffer_funcs emgd_fb_funcs = {
148         .destroy       = emgd_user_framebuffer_destroy,
149         .create_handle = emgd_user_framebuffer_create_handle,
150 };
151
152
153 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
154 int convert_bpp_depth_to_drm_pixel_formal(unsigned int bpp, unsigned int depth)
155 {
156         switch(bpp){
157                 case 8:
158                         if(depth == 8)
159                                 return DRM_FORMAT_RGB332;
160
161                 case 16:
162                         if(depth == 15)
163                                 return DRM_FORMAT_XRGB1555;
164                         else
165                                 return DRM_FORMAT_RGB565;
166
167                 case 24:
168                         return DRM_FORMAT_RGB888;
169
170                 case 32:
171             if(depth == 24)
172                     return DRM_FORMAT_XRGB8888;
173             else if (depth == 30)
174                     return DRM_FORMAT_XRGB2101010;
175             else
176                     return DRM_FORMAT_ARGB8888;
177
178                 default:
179             EMGD_ERROR("bad bpp %d, assuming x8r8g8b8 pixel format", bpp);
180             return DRM_FORMAT_XRGB8888;
181         }
182 }
183 #endif
184
185 /*
186  * Called if something fails while trying to set up framebuffer based
187  * console.
188  */
189 static int emgd_fb_panic(struct notifier_block *n,
190                 unsigned long res,
191                 void *panic_str)
192 {
193         EMGD_DEBUG("Panic occurred, switch back to text console.");
194
195         emgd_fb_restore();
196
197         return 0;
198 }
199
200
201 /*
202  * emgd_fb_restore
203  *
204  * Restore the kernel's fbcon mode.
205  */
206 void emgd_fb_restore(void)
207 {
208         int ret;
209
210         EMGD_TRACE_ENTER;
211
212         /*
213          * FIXME: Need to have the real crtc saved so it can be restored.
214          */
215         if ((ret = drm_crtc_helper_set_config(&panic_mode)) != 0) {
216                 EMGD_ERROR("Failed to restore crtc configuration: %d", ret);
217         }
218
219         EMGD_TRACE_EXIT;
220 }
221
222
223 /* Workqueue task function; needed during CRTC init */
224 void emgd_flip_worker(struct work_struct *w);
225
226 /*
227  * create_crtcs
228  *
229  * Creates crtcs. This function loops through the valid pipes, creating
230  * one crtc for each pipe.  This function assumes that dsp_alloc() has
231  * been run.
232  *
233  * TODO:  Move this to emgd_crtc.c?
234  *
235  * @param dev     (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
236  *
237  * @return None
238  */
239 void create_crtcs(struct drm_device *dev)
240 {
241         emgd_crtc_t *emgd_crtc = NULL;
242         drm_emgd_priv_t *dev_priv = NULL;
243         igd_context_t *context = NULL;
244         igd_display_pipe_t *pipe = NULL;
245         int i, index = 0;
246         unsigned short *r, *g, *b;
247
248         EMGD_TRACE_ENTER;
249
250         dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
251         context = dev_priv->context;
252
253         while ((pipe = context->mod_dispatch.dsp_get_next_pipe(context, pipe, 0))) {
254
255                 /* FIXME: Why are we allocating the extra space for the
256                  * connectors here? */
257                 emgd_crtc = kzalloc(sizeof(emgd_crtc_t) +
258                         (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
259                         GFP_KERNEL);
260
261                 if (emgd_crtc == NULL) {
262                         EMGD_ERROR("create_crtcs: Failed to allocate CRTC structure.");
263                         return;
264                 }
265
266                 spin_lock_init(&emgd_crtc->crtc_lock);
267
268                 emgd_crtc->crtc_id     = 1 << index;
269                 emgd_crtc->igd_pipe    = pipe;
270                 dev_priv->crtcs[index] = emgd_crtc;
271                 EMGD_DEBUG("Creating CRTC with ID: 0x%x, igd_pipe=0x%lx",
272                         emgd_crtc->crtc_id, (unsigned long)pipe);
273
274
275                 /* Hook up crtc functions */
276                 drm_crtc_init(dev, &emgd_crtc->base, &emgd_crtc_funcs);
277                 EMGD_DEBUG("  Created CRTC [%d]", emgd_crtc->base.base.id);
278
279                 /* gamma */
280                 drm_mode_crtc_set_gamma_size(&emgd_crtc->base, 256);
281
282                 /* Set initial gamma values */
283                 r = emgd_crtc->base.gamma_store;
284                 g = emgd_crtc->base.gamma_store + 256;
285                 b = emgd_crtc->base.gamma_store + 512;
286                 for (i = 0; i < 256; i++) {
287                         emgd_crtc->lut_r[i] = i;
288                         emgd_crtc->lut_g[i] = i;
289                         emgd_crtc->lut_b[i] = i;
290                         emgd_crtc->lut_a[i] = 0;
291                         r[i] = (i << 8);
292                         g[i] = (i << 8);
293                         b[i] = (i << 8);
294                 }
295
296                 /* Initialize workqueue task to wait for render completion on flips */
297                 INIT_WORK(&emgd_crtc->flip_work, emgd_flip_worker);
298                 emgd_crtc->flip_work_queued = 0;
299
300                 /* Target FB that we're in the process of changing to */
301                 emgd_crtc->newfb = NULL;
302
303                 /* Target "ops complete" watermark to allow flip to proceed */
304                 emgd_crtc->render_complete_at = 0;
305
306                 /*
307                  * Are we expected to perform flip cleanup (sending userspace event
308                  * and such) on next vblank event?
309                  */
310                 emgd_crtc->vblank_expected = 0;
311
312                 /* Userspace 'flip done' event */
313                 emgd_crtc->flip_event = NULL;
314
315                 /* TODO: Create connector list */
316                 emgd_crtc->mode_set.crtc       = &emgd_crtc->base;
317                 emgd_crtc->mode_set.connectors =
318                                                                 (struct drm_connector **)(emgd_crtc + 1);
319                 emgd_crtc->mode_set.num_connectors = 0;
320
321                 /* Hook up crtc helper functions */
322                 drm_crtc_helper_add(&emgd_crtc->base, &emgd_crtc_helper_funcs);
323                 index++;
324         }
325
326         EMGD_TRACE_EXIT;
327 }
328
329
330
331 /**
332  * create_encoder
333  *
334  * Creates an encoder for the igd_port in the parameter.
335  *
336  * @param dev      (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
337  * @param igd_port (IN) pointer to IGD display port.  (pd_driver must be valid)
338  *
339  * @return None
340  */
341 static void create_encoder(struct drm_device *dev, igd_display_port_t *igd_port)
342 {
343         emgd_encoder_t  *emgd_encoder;
344         emgd_crtc_t     *emgd_crtc;
345         struct drm_crtc *crtc;
346         unsigned long    drm_encoder_type;
347
348
349         EMGD_TRACE_ENTER;
350
351         /* Find the corresponding DRM encoder type */
352         switch(igd_port->port_type) {
353                 case IGD_PORT_LVDS:
354                         drm_encoder_type = DRM_MODE_ENCODER_LVDS;
355                         break;
356
357                 case IGD_PORT_DIGITAL:
358                         drm_encoder_type = DRM_MODE_ENCODER_TMDS;
359                         break;
360
361                 case IGD_PORT_ANALOG:
362                 case IGD_PORT_RGBA:
363                 case IGD_PORT_TV:
364                 case IGD_PORT_SDVO_ST:
365                 case IGD_PORT_SDVO_ST_GPIO:
366                 default:
367                         EMGD_ERROR("Invalid Port Type");
368                         return;
369         }
370
371
372         emgd_encoder = kzalloc(sizeof(emgd_encoder_t), GFP_KERNEL);
373         if (!emgd_encoder) {
374                 EMGD_ERROR("Out of memory!");
375                 return;
376         }
377
378
379         /* What we call "TWIN" is what KMS calls "CLONE".  None of the
380          * platforms we currently support allow TWIN, so just set
381          * the bits equal to the port type since a port can always
382          * "TWIN" with itself */
383     emgd_encoder->clone_mask = igd_port->port_type;
384         /*
385          * crtc's are identified by a 1 that is shifted over:
386          * 11
387          * ||_ pipe 0
388          * |__ pipe 1
389          * The order of the pipes is based on how they are initialized
390          * in the drm.
391          */
392         emgd_encoder->crtc_mask  = KMS_PIPE_ID(igd_port->port_features);
393         emgd_encoder->igd_port   = igd_port;
394         emgd_encoder->state.port = igd_port;
395         emgd_encoder->flags |= ENCODER_FLAG_FIRST_DPMS | ENCODER_FLAG_FIRST_ALTER;
396
397
398         /* Since we do not support TWIN and pipe assignment is fixed, the
399          * current configuration is the only possible configuration */
400         emgd_encoder->base.possible_crtcs  = emgd_encoder->crtc_mask;
401         emgd_encoder->base.possible_clones = emgd_encoder->clone_mask;
402
403         /* Initialize the CRTC associated with this encoder.  We should
404          * probably use the crtc_mask here to do the matching, but we
405          * have the same info in our internal structures. */
406         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
407                 emgd_crtc = container_of(crtc, emgd_crtc_t, base);
408
409                 if ((emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) ==
410                         emgd_encoder->igd_port->port_type) {
411                         emgd_encoder->base.crtc = crtc;
412                         break;
413                 }
414         }
415
416
417         EMGD_DEBUG("Creating encoder=0x%lx on pipe=0x%lx, of port=0x%lx, "
418                 "port_type=0x%lx",
419                 (unsigned long)&(emgd_encoder->base), emgd_encoder->crtc_mask,
420                 igd_port->port_number, igd_port->port_type);
421
422         drm_encoder_init(dev, &emgd_encoder->base, &emgd_encoder_funcs,
423                                                 drm_encoder_type);
424         drm_encoder_helper_add(&emgd_encoder->base, &emgd_encoder_helper_funcs);
425 }
426
427
428
429 /**
430  * create_connector_properties
431  *
432  * Creates properties associated with the input connector.  Connector properties
433  * are what EMGD calls "port attributes."  The only difference is EMGD's port
434  * attributes are per-encoder, not per-connector.  For this implementation, we
435  * are assuming one connector per encoder.  With this assumption, we can draw
436  * a direct connection between "port attributes" and "connector properties."
437  *
438  * @param dev            (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
439  * @param emgd_connector (IN) Selected connector
440  *
441  * @return None
442  */
443 static void create_connector_properties(struct drm_device *dev,
444                                 emgd_connector_t *emgd_connector)
445 {
446         igd_display_port_t *igd_port = emgd_connector->encoder->igd_port;
447         drm_emgd_priv_t    *priv     = emgd_connector->priv;
448         unsigned long       num_of_attributes = 0, num_of_properties = 0;
449         unsigned long       i, current_value;
450         pd_attr_t          *attributes;
451
452         struct drm_connector *drm_connector = &emgd_connector->base;
453         struct drm_property  *new_prop;
454
455
456         EMGD_TRACE_ENTER;
457
458         /* Get port attributes from the port driver */
459         priv->context->dispatch.get_attrs(priv->context,
460                                                                 igd_port->port_number,
461                                                                 &num_of_attributes,
462                                                                 &attributes);
463
464
465         /* If the connector has no attributes, then return */
466         if (0 >= num_of_attributes) {
467                 EMGD_TRACE_EXIT;
468                 return;
469         }
470
471         emgd_connector->properties =
472                 (struct drm_property **) kzalloc(sizeof(struct drm_property *) *
473                                                                         num_of_attributes, GFP_KERNEL);
474
475         if (NULL == emgd_connector->properties) {
476                 EMGD_ERROR_EXIT("Failed to allocate emgd_connector->properties");
477         }
478
479
480         /* Convert port attributes to connector properties and attach them */
481         for(i = 0; i < num_of_attributes; i++) {
482
483                 /* Invisible attributes are not settable so don't even report
484                  * it was a property */
485                 if (attributes[i].flags & PD_ATTR_FLAG_USER_INVISIBLE) {
486                         continue;
487                 }
488
489                 /* Instead of using DRM_MODE_PROP_xxxx types, it may be possible
490          * to use the PD_ATTR_TYPE_xxxx types, since the 2nd parameter
491                  * to drm_property_create is a flag */
492                 switch (attributes[i].type) {
493                         case PD_ATTR_TYPE_RANGE:
494                         {
495                                 igd_range_attr_t *attr = (igd_range_attr_t *) &attributes[i];
496
497
498                                 new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
499                                                                         attr->name, 3);
500
501                                 if (NULL == new_prop) {
502                                         EMGD_ERROR("Failed to allocate new property");
503                                         continue;
504                                 }
505
506                                 new_prop->values[0] = attr->id;
507                                 new_prop->values[1] = attr->min;
508                                 new_prop->values[2] = attr->max;
509                                 current_value       = attr->current_value;
510
511                                 break;
512                         }
513
514                         case PD_ATTR_TYPE_BOOL:
515                         {
516                                 igd_bool_attr_t *attr = (igd_bool_attr_t *) &attributes[i];
517
518
519                                 new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
520                                                                         attr->name, 2);
521
522                                 if (NULL == new_prop) {
523                                         EMGD_ERROR("Failed to allocate new property");
524                                         continue;
525                                 }
526
527                                 new_prop->values[0] = false;
528                                 new_prop->values[1] = true;
529                                 current_value       = attr->current_value;
530
531                                 break;
532                         }
533
534                         case PD_ATTR_TYPE_LIST:
535                         case PD_ATTR_TYPE_LIST_ENTRY:
536                         case PD_ATTR_TYPE_BUFFER:
537                         default:
538                                 EMGD_ERROR("Unsupported PD Attribute type");
539                                 continue;
540                 }
541
542                 drm_connector_attach_property(drm_connector, new_prop, current_value);
543                 emgd_connector->properties[num_of_properties++] = new_prop;
544         }
545
546         EMGD_TRACE_EXIT;
547 }
548
549
550
551 /**
552  * create_connectors
553  *
554  * Creates connectors associated with the encoder.
555  *
556  * This function currently supports one connector per encoder.  Further
557  * development required in the future to support encoders that have more
558  * than one connector.
559  *
560  * @param dev          (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
561  * @param emgd_encoder (IN) Encoder to be examined.
562  *
563  * @return None
564  */
565 static void create_connectors(struct drm_device *dev,
566                                 emgd_encoder_t *emgd_encoder)
567 {
568         igd_display_port_t    *port = emgd_encoder->igd_port;
569         pd_driver_t           *pd   = port->pd_driver;
570         unsigned long          connector_type = DRM_MODE_CONNECTOR_LVDS;
571         emgd_connector_t      *emgd_connector;
572
573
574         EMGD_TRACE_ENTER;
575
576         switch (pd->type) {
577                 case PD_DISPLAY_LVDS_EXT:
578                 case PD_DISPLAY_LVDS_INT:
579                         connector_type = DRM_MODE_CONNECTOR_LVDS;
580                         break;
581
582                 case PD_DISPLAY_FP:
583                         connector_type = DRM_MODE_CONNECTOR_DVID;
584                         break;
585
586                 case PD_DISPLAY_CRT_EXT:
587                 case PD_DISPLAY_CRT:
588                         connector_type = DRM_MODE_CONNECTOR_VGA;
589                         break;
590
591                 case PD_DISPLAY_HDMI_INT:
592                         connector_type = DRM_MODE_CONNECTOR_HDMIA;
593                         break;
594
595                 case PD_DISPLAY_HDMI_EXT:
596                         connector_type = DRM_MODE_CONNECTOR_HDMIA;
597                         break;
598
599                 case PD_DISPLAY_DP_INT:
600                         connector_type = DRM_MODE_CONNECTOR_DisplayPort;
601                         break;
602
603                 case PD_DISPLAY_TVOUT:
604                 case PD_DISPLAY_TVFP:
605                 case PD_DISPLAY_RGBA:
606                 case PD_DISPLAY_TVOUT_INT:
607                 case PD_DISPLAY_DRGB:
608                         EMGD_ERROR("Unsupported connector type");
609                         return;
610
611                 default:
612                         EMGD_ERROR("Unknown connector type");
613                         return;
614         }
615
616
617         /* Allocate a new connector */
618         emgd_connector = kzalloc(sizeof(emgd_connector_t), GFP_KERNEL);
619         if (!emgd_connector) {
620                 EMGD_ERROR("Out of memory!");
621                 return;
622         }
623
624         drm_connector_init(dev, &emgd_connector->base, &emgd_connector_funcs,
625                                                 connector_type);
626
627         drm_mode_connector_attach_encoder(&emgd_connector->base,
628                 &emgd_encoder->base);
629
630         drm_connector_helper_add(&emgd_connector->base,
631                 &emgd_connector_helper_funcs);
632
633         EMGD_DEBUG("Creating connector=0x%lx, encoder=0x%lx, type=0x%lx",
634                 (unsigned long)&(emgd_connector->base),
635                 (unsigned long)&(emgd_encoder->base), connector_type);
636
637         emgd_connector->encoder                          = emgd_encoder;
638         emgd_connector->priv                             = dev->dev_private;
639         emgd_connector->base.display_info.subpixel_order = SubPixelHorizontalRGB;
640         emgd_connector->base.interlace_allowed           = false;
641         emgd_connector->base.doublescan_allowed          = false;
642         emgd_connector->base.encoder                     = &emgd_encoder->base;
643
644         /* Create and attach connector properties */
645         create_connector_properties(dev, emgd_connector);
646
647
648 #if 0
649         drm_connector_attach_property(&connector->base,
650                         dev->mode_config.scaling_mode_property,
651                         DRM_MODE_SCALE_FULLSCREEN);
652         drm_connector_attach_property(&connector->base,
653                        dev->mode_config.edid_property, 0);
654         drm_connector_attach_property(&connector->base,
655                        dev->mode_config.dpms_property, 0);
656 #endif
657
658
659         drm_sysfs_connector_add(&emgd_connector->base);
660
661         EMGD_TRACE_EXIT;
662 }
663
664
665
666 /**
667  * emgd_setup_outputs
668  *
669  * This function enumerates all the available outputs (physical connectors) by
670  * first initializing all the encoders in the system, and then querying
671  * the encoders for the connectors.
672  *
673  * Because we are adapting from EMGD, the real work behind detecting encoders
674  * has already been done by the time we get to this function.  Therefore,
675  * all we need to do is using existing EMGD HAL dispatch functions to complete
676  * the task.
677  *
678  * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
679  *
680  * @return
681  */
682 void emgd_setup_outputs(struct drm_device *dev)
683 {
684         drm_emgd_priv_t         *priv            = dev->dev_private;
685         igd_context_t           *igd_context     = priv->context;
686         inter_module_dispatch_t *module_dispatch = &igd_context->mod_dispatch;
687         igd_display_port_t      *port            = NULL;
688         struct drm_encoder      *encoder;
689
690         EMGD_TRACE_ENTER;
691
692         /* Loop through all available ports.  What KMS calls "encoder" is a
693      * subset of what EMGD calls "port."
694      */
695         while ((port = module_dispatch->dsp_get_next_port(igd_context, port, 0))) {
696
697                 /* If there is a port driver, then there's an encoder */
698                 if (port->pd_driver) {
699                         create_encoder(dev, port);
700                 }
701         }
702
703
704         /* For each encoder, create the connectors on the encoder */
705         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
706                 emgd_encoder_t *emgd_encoder;
707
708                 emgd_encoder = container_of(encoder, emgd_encoder_t, base);
709                 create_connectors(dev, emgd_encoder);
710         }
711
712         EMGD_TRACE_EXIT;
713 }
714
715
716
717 /**
718  * emgd_modeset_init
719  *
720  * This is the main initialization entry point.  Called during driver load
721  * and does basic setup.
722  *
723  * @param dev      (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
724  * @param full_kms (IN) If we are running with KMS enabled, then set this
725  *                      to true to do the full KMS initialization.  If not,
726  *                      then set this to false.
727  *
728  * @return None
729  */
730 void emgd_modeset_init(struct drm_device *dev)
731 {
732         drm_emgd_priv_t *devpriv = (drm_emgd_priv_t *)dev->dev_private;
733         int ret;
734         struct drm_encoder *encoder;
735
736         EMGD_TRACE_ENTER;
737         drm_mode_config_init(dev);  /* drm helper function */
738
739         dev->mode_config.min_width  = 0;
740         dev->mode_config.max_width  = 4096;
741         dev->mode_config.min_height = 0;
742         dev->mode_config.max_height = 2048;
743         dev->mode_config.funcs      = (void *)&emgd_mode_funcs;
744
745
746         /* OTC uses dev->agp->base for fb_base */
747         dev->mode_config.fb_base = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
748
749         /* Initialize VBLANK handling */
750         dev->irq_enabled      = true;
751         dev->max_vblank_count = 0xffffff; /* 24-bit frame counter */
752
753         ret = drm_vblank_init(dev, devpriv->num_crtc);
754         if (ret) {
755                 EMGD_ERROR("Call to drm_vblank_init() failed.  drmWaitVBlank() "
756                         "will not work.");
757                 dev->irq_enabled = false;
758         }
759
760
761         /* Create the crtc's */
762         create_crtcs(dev);
763
764         drm_mode_create_scaling_mode_property(dev);
765         emgd_setup_outputs(dev);
766
767         /* The encoders need to be turned off to prevent the locking of some
768            of the registers - before doing a modeset */
769     list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
770         struct drm_encoder_helper_funcs *e_funcs = encoder->helper_private;
771         (*e_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
772     }
773
774         drm_helper_disable_unused_functions(dev);
775
776         /* Initialize the framebuffer device */
777         emgd_fbdev_init(devpriv);
778
779         EMGD_TRACE_EXIT;
780 }
781
782
783
784 /**
785  * emgd_modeset_destroy
786  *
787  * Clean up resources allocated in emgd_modeset_init.  Called during driver
788  * unload
789  *
790  * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
791  *
792  * @return None
793  */
794 void emgd_modeset_destroy(struct drm_device *dev)
795 {
796         drm_emgd_priv_t *priv = NULL;
797
798         EMGD_TRACE_ENTER;
799
800         priv = dev->dev_private;
801         emgd_fbdev_destroy(priv);
802         kfree(priv->emgd_fbdev);
803         priv->emgd_fbdev = NULL;
804
805         EMGD_TRACE_EXIT;
806 }
807
808
809
810 /*
811  * emgd_fb_probe
812  *
813  * Registers panic mode for the DRM to switch to.
814  *
815  * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
816  *
817  * @return TBD
818  */
819 RETURN_PROBE_TYPE emgd_fb_probe(struct drm_device *dev)
820 {
821         EMGD_TRACE_ENTER;
822
823         /* Set Panic Mode to 1024x768 because it is an acceptably generic mode */
824         //memset(&panic_mode, 0, sizeof(struct drm_mode_set));
825
826         /* In later kernels this function changes to "output_poll_changed", as
827          * such, it is unclear if we need to implement it at all since we do not
828          * support hot-plug
829          */
830
831
832         /* Register a notifier to switch back to kernel console on panic */
833         atomic_notifier_chain_register(&panic_notifier_list, &paniced);
834
835         EMGD_TRACE_EXIT;
836         RETURN_PROBE;
837 }
838 EXPORT_SYMBOL(emgd_fb_probe);
839
840
841 /**
842  * emgd_user_framebuffer_create
843  *
844  * Creates an instance for the framebuffer.
845  *
846  * @param dev      (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
847  * @param filp     (IN)
848  * @param mode_cmd (IN) Input from the DRM_IOCTL_MODE_ADDFB
849  *
850  * @return pointer to allocated FB instance
851  */
852 static struct drm_framebuffer *emgd_user_framebuffer_create(
853                                                                 struct drm_device *dev,
854                                                                 struct drm_file *filp,
855                                                                 struct DRM_MODE_FB_CMD_TYPE *mode_cmd)
856 {
857         emgd_framebuffer_t *emgd_fb;
858         int                 ret;
859
860         EMGD_TRACE_ENTER;
861
862         emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
863         if (!emgd_fb) {
864                 EMGD_ERROR("Failed to allocate an emgd_framebuffer_t");
865                 return NULL;
866         }
867
868         /* Create a framebuffer instance */
869         ret = emgd_framebuffer_init(dev, emgd_fb, mode_cmd,
870                         (unsigned long)mode_cmd->DRMMODE_HANDLE);
871         if (ret) {
872                 EMGD_ERROR("Failed to create framebuffer instance.");
873                 /* TODO: Free the allocation at mode_cmd->handle */
874                 kfree(emgd_fb);
875                 emgd_fb = NULL;
876                 return NULL;
877         }
878
879         EMGD_TRACE_EXIT;
880         return &emgd_fb->base;
881 }
882
883
884 /**
885  * emgd_framebuffer_init
886  *
887  * Creates an instance for the framebuffer.
888  *
889  * Maps an existing surface, which has been allocated via the PVR services,
890  * into the GTT to make it displayable and returns a 'drm_framebuffer'
891  * struct that can be used to refer to this surface in future KMS
892  * operations.  This function is called as a result of drmModeAddFB()
893  * being called in userspace; the handle passed to drmModeAddFB() should
894  * be the kernel meminfo handle (i.e., meminfo->hKernelMemInfo in userspace).
895  *
896  * @param dev      (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
897  * @param emgd_fb  (IN)
898  * @param mode_cmd (IN) Input from the DRM_IOCTL_MODE_ADDFB
899  * @param handle   (IN) Handle of allocation.  The handle will be the
900  *                      PVR meminfo handle.  The initial framebuffer,
901  *                      which is allocated directly by the GMM before
902  *                      the PVR services starts up is a special case;
903  *                      a handle of 0 will refer to the initial framebuffer.
904  *
905  * @return int return value
906  */
907 int emgd_framebuffer_init(struct drm_device *dev,
908                 emgd_framebuffer_t *emgd_fb,
909                 struct DRM_MODE_FB_CMD_TYPE *mode_cmd,
910                 unsigned long handle)
911 {
912         drm_emgd_priv_t *dev_priv = NULL;
913         igd_context_t *context = NULL;
914         PVRSRV_PER_PROCESS_DATA *pvr_perproc;
915         PVRSRV_KERNEL_MEM_INFO *pvr_meminfo;
916         struct page **pagelist;
917         unsigned long numpages, gtt_offset, page_offset;
918         int ret, pid;
919
920         EMGD_TRACE_ENTER;
921
922         dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
923         context = dev_priv->context;
924
925         if (handle == EMGD_INITIAL_FRAMEBUFFER) {
926                 /*
927                  * Special case:  initial EMGD framebuffer is allocated via GTT instead
928                  * of through the PVR services.  It has no PVR meminfo handle.
929                  */
930                 ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
931                 if (ret) {
932                     EMGD_ERROR("Failed to create framebuffer instance.");
933                     return -ENOMEM;
934                 }
935
936                 drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
937
938                 /*
939                  * Initial framebuffer offset is stored in the device
940                  * private structure.
941                  */
942                 emgd_fb->type       = GMM_FRAMEBUFFER;
943                 emgd_fb->gtt_offset = dev_priv->initfb_info.fb_base_offset;
944                 emgd_fb->handle     = handle;
945
946         } else {
947                 /* Fetch PVR services 'per-process' data structure */
948                 pid = OSGetCurrentProcessIDKM();
949                 pvr_perproc = PVRSRVPerProcessData(pid);
950
951                 /* Look up the kernel-side meminfo for the handle passed in*/
952                 ret = PVRSRVLookupHandle(pvr_perproc->psHandleBase,
953                                 (void**)&pvr_meminfo,
954                         (IMG_HANDLE)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
955                 if (ret != PVRSRV_OK) {
956                         EMGD_ERROR("Buffer handle is not a valid PVR surface.");
957                         return -EINVAL;
958                 }
959
960                 /*
961                  * Now fetch the page list, number of pages, and offset into the first
962                  * page for this buffer.
963                  */
964                 ret = PVRSRVGetPageListKM(pvr_meminfo, &pagelist, &numpages,
965                                 &page_offset);
966                 if (ret != PVRSRV_OK) {
967                         EMGD_ERROR("Failed to get pagelist for PVR surface.");
968                         return -EINVAL;
969                 }
970
971                 /* Map this page list into the GTT */
972                 ret = context->dispatch.gmm_import_pages((void**)pagelist, &gtt_offset,
973                         numpages);
974                 if (ret < 0) {
975                         EMGD_ERROR("Failed to map pagelist into GTT.");
976                         return -ENOMEM;
977                 }
978
979                 /* Create a framebuffer instance */
980                 ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
981                 if (ret) {
982                         EMGD_ERROR("Failed to create framebuffer instance.");
983                         return -ENOMEM;
984                 }
985
986                 /* Fill the EMGD framebuffer structure */
987                 drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
988
989                 emgd_fb->type = PVR_FRAMEBUFFER;
990                 emgd_fb->pvr_meminfo = pvr_meminfo;
991                 emgd_fb->pagelist = pagelist;
992                 emgd_fb->gtt_offset = gtt_offset + page_offset;
993                 emgd_fb->handle     = handle;
994         }
995
996         EMGD_TRACE_EXIT;
997         return 0;
998 }
999
1000
1001
1002 /*
1003  * emgd_user_framebuffer_destroy
1004  *
1005  * clean up and remove a framebuffer instance.
1006  *
1007  */
1008 static void emgd_user_framebuffer_destroy (struct drm_framebuffer *fb)
1009 {
1010         drm_emgd_priv_t *dev_priv = NULL;
1011         emgd_framebuffer_t *emgd_fb = NULL;
1012         igd_context_t *context = NULL;
1013
1014         EMGD_TRACE_ENTER;
1015
1016         dev_priv = ((drm_emgd_priv_t *)fb->dev->dev_private);
1017         context = dev_priv->context;
1018         emgd_fb = container_of(fb, emgd_framebuffer_t, base);
1019
1020         /* Unmap pages from GTT */
1021         if (emgd_fb->type == PVR_FRAMEBUFFER) {
1022                 /* PVR-allocated pages imported into GTT:  just unmap */
1023                 EMGD_DEBUG("Unmapping imported PVR framebuffer pages at %lu.", emgd_fb->gtt_offset);
1024                 context->dispatch.gmm_release_import(emgd_fb->gtt_offset);
1025         } else {
1026                 /* GMM-allocated pages (initial framebuffer): unmap and free pages */
1027                 EMGD_DEBUG("Unmapping and freeing GMM framebuffer pages at %lu.", emgd_fb->gtt_offset);
1028                 context->dispatch.gmm_free(emgd_fb->gtt_offset);
1029         }
1030
1031         drm_framebuffer_cleanup(fb);
1032         kfree(emgd_fb);
1033
1034         EMGD_TRACE_EXIT;
1035 }
1036
1037
1038
1039 /*
1040  * emgd_user_framebuffer_create_handle
1041  *
1042  * Returns 'a' handle associated with the drm_framebuffer given in the
1043  * parameter.  In our case, we return 'the' handle because our handles
1044  * are already cross-process compatible, and PVR is keeping track of
1045  * the reference count so buffers don't get destroyed unless it is not
1046  * used.
1047  *
1048  * @param fb (IN)        DRM framebuffer to look up
1049  * @param file_priv (IN) Not used
1050  * @param handle (OUT)
1051  *
1052  * @return 0 on success
1053  * @return -EINVAL on failure
1054  */
1055 static int emgd_user_framebuffer_create_handle(struct drm_framebuffer *fb,
1056                 struct drm_file *file_priv,
1057                 unsigned int *handle)
1058 {
1059         emgd_framebuffer_t *emgd_fb;
1060         int ret = -EINVAL;
1061
1062         EMGD_TRACE_ENTER;
1063
1064         /* To avoid compiler warning. */
1065         (void)file_priv;
1066
1067         emgd_fb = container_of(fb, emgd_framebuffer_t, base);
1068
1069         if (NULL != emgd_fb) {
1070                 *handle = emgd_fb->handle;
1071         }
1072
1073
1074         EMGD_TRACE_EXIT;
1075
1076         return ret;
1077 }
1078
1079
1080
1081 /**
1082  * emgd_fbdev_init
1083  *
1084  * Allocates and initializes a framebuffer device.  Through
1085  * drm_fb_helper_initial_config(), this function will set a sane mode and
1086  * allocate a framebuffer surface to go with the framebuffer device.
1087  *
1088  * @param priv (IN) EMGD private DRM data structure
1089  *
1090  * @return 0 on success
1091  */
1092
1093 static int emgd_fbdev_init(drm_emgd_priv_t *priv)
1094 {
1095         emgd_fbdev_t *emgd_fbdev;
1096
1097         EMGD_TRACE_ENTER;
1098
1099         emgd_fbdev = kzalloc(sizeof(emgd_fbdev_t), GFP_KERNEL);
1100         if (!emgd_fbdev) {
1101                 return -ENOMEM;
1102         }
1103
1104         emgd_fbdev->priv         = priv;
1105         priv->emgd_fbdev         = emgd_fbdev;
1106
1107         emgd_fbcon_initial_config(emgd_fbdev);
1108
1109         EMGD_TRACE_EXIT;
1110         return 0;
1111 }
1112
1113
1114
1115 /**
1116  * emgd_fbdev_destroy
1117  *
1118  * Cleans up resources allocated during emgd_fbdev_init.
1119  * Since emgd_fbdev_init() calls drm_fb_helper_initial_config() which leads
1120  * to a call to emgd_fb_find_or_create_single(), we are also cleaning up
1121  * resources allocated in that function as well.  It is unclear if this
1122  * clean up is necessary because KMS APIs maybe smart enough to call
1123  * the corresponding destory function.
1124  *
1125  * @param priv (IN) EMGD private DRM data structure
1126  *
1127  * @return None
1128  */
1129 static void emgd_fbdev_destroy(drm_emgd_priv_t *priv)
1130 {
1131         emgd_fbdev_t           *emgd_fbdev = NULL;
1132         struct drm_framebuffer *fb         = NULL;
1133         struct fb_info         *info       = NULL;
1134
1135         EMGD_TRACE_ENTER;
1136
1137         emgd_fbdev = priv->emgd_fbdev;
1138         fb         = &emgd_fbdev->emgd_fb->base;
1139
1140         if (priv->fbdev) {
1141                 info = priv->fbdev;
1142
1143                 unregister_framebuffer(info);
1144
1145                 if (info->cmap.len) {
1146                         fb_dealloc_cmap(&info->cmap);
1147                 }
1148
1149                 priv->context->dispatch.gmm_unmap(info->screen_base);
1150                 framebuffer_release(info);
1151         }
1152
1153         drm_framebuffer_cleanup(fb); /* Is this the right place to call this? */
1154         priv->context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1155
1156         kfree(emgd_fbdev->emgd_fb);
1157         emgd_fbdev->emgd_fb = NULL;
1158
1159         EMGD_TRACE_EXIT;
1160 }
1161
1162
1163
1164 #if 0
1165 /*------------------------------------------------------------------------------
1166  * drm_fb_helper related functions.  These will be removed once we have our
1167  * own version of drm_fb_helper (in emgd_fbcon.c)
1168  *------------------------------------------------------------------------------
1169  */
1170 static int emgd_fb_find_or_create_single(struct drm_fb_helper *helper,
1171                         struct drm_fb_helper_surface_size *sizes);
1172 static void emgd_fb_gamma_set(struct drm_crtc *crtc,
1173                                 u16 red, u16 green, u16 blue, int regno);
1174 static void emgd_fb_gamma_get(struct drm_crtc *crtc,
1175                                 u16 *red, u16 *green, u16 *blue, int regno);
1176
1177
1178
1179 /* FIXME:  This should be removed. */
1180 static struct drm_fb_helper_funcs emgd_fb_helper_funcs = {
1181         .gamma_set = emgd_fb_gamma_set,
1182         .gamma_get = emgd_fb_gamma_get,
1183         .fb_probe  = emgd_fb_find_or_create_single,
1184 };
1185
1186
1187
1188 /**
1189  * emgd_fb_create
1190  *
1191  * This function creates a frame buffer using the surface information contained
1192  * in surface_info.  The working assumption is this function will only be
1193  * called once at initialization time.  So the buffer allocated here is
1194  * for the console.
1195  *
1196  * @param emgd_fbdev   (IN) Framebuffer devices to attach the new FB to
1197  * @param surface_info (IN) Information about the surface to be allocated
1198  */
1199 static int emgd_fb_create(emgd_fbdev_t *emgd_fbdev,
1200                 struct drm_fb_helper_surface_size *surface_info)
1201 {
1202         drm_emgd_priv_t        *priv    = emgd_fbdev->priv;
1203         struct drm_device      *dev     = priv->ddev;
1204         struct fb_info         *info    = NULL;
1205         struct drm_mode_fb_cmd  mode_cmd;
1206         struct drm_framebuffer *fb       = NULL;
1207         igd_context_t          *context  = NULL;
1208         int                     ret;
1209         unsigned long           size;
1210         unsigned long           offset = 0;
1211
1212         EMGD_TRACE_ENTER;
1213
1214
1215         context = priv->context;
1216
1217         priv->initfb_info.width        = surface_info->surface_width;
1218         priv->initfb_info.height       = surface_info->surface_height;
1219         priv->initfb_info.screen_pitch = 0;
1220         priv->initfb_info.pixel_format = IGD_PF_ARGB32;
1221
1222         ret = context->dispatch.gmm_alloc_surface(
1223                                                                 &priv->initfb_info.fb_base_offset,
1224                                                                  priv->initfb_info.pixel_format,
1225                                                                 &priv->initfb_info.width,
1226                                                                 &priv->initfb_info.height,
1227                                                                 &priv->initfb_info.screen_pitch,
1228                                                                 &size,
1229                                                                 IGD_GMM_ALLOC_TYPE_RESERVATION,
1230                                                                 &priv->initfb_info.flags);
1231         if (ret) {
1232                 EMGD_ERROR_EXIT("Allocation of buffer failed: %d", ret);
1233                 return -ENOMEM;
1234         }
1235
1236         priv->initfb_info.allocated = 1;
1237         priv->initfb_info.visible_offset = 0;
1238
1239         mode_cmd.handle = EMGD_INITIAL_FRAMEBUFFER;
1240         mode_cmd.pitch  = priv->initfb_info.screen_pitch;
1241         mode_cmd.width  = surface_info->surface_width;
1242         mode_cmd.height = surface_info->surface_height;
1243         mode_cmd.bpp    = surface_info->surface_bpp;
1244         mode_cmd.depth  = surface_info->surface_depth;
1245
1246         /* Allocate fb_info */
1247         info = kzalloc(sizeof(struct fb_info), GFP_KERNEL);
1248         if (info == NULL) {
1249                 EMGD_ERROR_EXIT("Allocation of fb_info failed");
1250                 context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1251                 return -ENOMEM;
1252         }
1253         info->par   = emgd_fbdev;
1254
1255         /* Allocate emgd_framebuffer_t */
1256         emgd_fbdev->emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
1257         if (!emgd_fbdev->emgd_fb) {
1258                 EMGD_ERROR_EXIT("Allocation of emgd_framebuffer_t failed");
1259                 context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1260                 kfree(info);
1261                 info = NULL;
1262                 return -ENOMEM;
1263         }
1264
1265         /* Initialize the framebuffer */
1266         ret = emgd_framebuffer_init(dev, emgd_fbdev->emgd_fb, &mode_cmd,
1267                         EMGD_INITIAL_FRAMEBUFFER);
1268         if (ret) {
1269                 context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1270                 kfree(info);
1271                 info = NULL;
1272                 kfree(emgd_fbdev->emgd_fb);
1273                 emgd_fbdev->emgd_fb = NULL;
1274                 return ret;
1275         }
1276
1277
1278
1279         info->flags = FBINFO_DEFAULT /* | FBINFO_CAN_FORCE_OUTPUT */;
1280         info->fbops = (struct fb_ops*) &emgd_fb_ops;
1281         strcpy(info->fix.id, "emgdfb"); /* fix.id is 16 bytes long */
1282         fb = &emgd_fbdev->emgd_fb->base;
1283         emgd_fbdev->helper.fb    = fb;
1284         emgd_fbdev->helper.fbdev = info;
1285         priv->fbdev              = info;
1286
1287         EMGD_DEBUG("EMGD: Call fb_alloc_cmap()");
1288         ret = fb_alloc_cmap(&info->cmap, 256, 0);
1289         if (ret) {
1290                 EMGD_ERROR("%s: Can't allocate color map", info->fix.id);
1291                 //mutex_unlock(&dev->struct_mutex);
1292                 return -ENOMEM;
1293         }
1294
1295         /*
1296          * Does this need to be filled in and if so, with what?  Right now
1297          * I'm trying to reuse the framebuffer that was already configured by
1298          * the EMGD code.
1299          *
1300          * setup aperture base/size for vesafb takeover
1301          */
1302         info->apertures = alloc_apertures(1);
1303         if (!info->apertures) {
1304                 EMGD_ERROR("%s: Can't allocate apertures", info->fix.id);
1305                 //mutex_unlock(&dev->struct_mutex);
1306                 return -ENOMEM;
1307         }
1308
1309         info->apertures->ranges[0].base =
1310                 (unsigned long)priv->context->device_context.virt_gttadr;
1311         info->apertures->ranges[0].size =
1312                 priv->context->device_context.gatt_pages << PAGE_SHIFT;
1313
1314         //mutex_unlock(&dev->struct_mutex);
1315         /*
1316          * FIXME: What is fix.smem_start vs screen_base?
1317          *
1318          * smem_start is the start of frame buffer mem (physical address), does
1319          * that mean GTT or that it expects a physical contigous block in real
1320          * memory?
1321          *
1322          * screen_base is a virtual address
1323          *
1324          */
1325         /* Set up framebuffer surface */
1326         EMGD_DEBUG("EMGD: Call pci_resource_start()");
1327         info->fix.smem_start =  pci_resource_start(dev->pdev, PSB_GATT_RESOURCE) +
1328                 priv->initfb_info.fb_base_offset;
1329         info->fix.smem_len = size;
1330
1331         /* Get kernel virtual memory address of framebuffer */
1332         EMGD_DEBUG("EMGD: Call gmm_map()");
1333         info->screen_base =
1334                 priv->context->dispatch.gmm_map(priv->initfb_info.fb_base_offset);
1335         if (!info->screen_base) {
1336                 EMGD_ERROR("%s: Can't map framebuffer surface", info->fix.id);
1337                 return -ENOSPC;
1338         }
1339         info->screen_size = size;
1340
1341         info->pixmap.size         = 64 * 1024;
1342         info->pixmap.buf_align    = 8;
1343         info->pixmap.access_align = 32;
1344         info->pixmap.flags        = FB_PIXMAP_SYSTEM;
1345         info->pixmap.scan_align   = 1;
1346
1347         EMGD_DEBUG("Frame buffer %dx%d @ 0x%08lx",
1348                         fb->width, fb->height, offset);
1349
1350         EMGD_DEBUG("EMGD: Call vga_switcheroo_client_fb_set()");
1351         vga_switcheroo_client_fb_set(dev->pdev, info);
1352
1353         EMGD_TRACE_EXIT;
1354         return 0;
1355 }
1356
1357
1358
1359 /*
1360  * emgd_fb_gamma_set
1361  *
1362  * Set the gamma values for a framebuffer for a particular
1363  * index.
1364  *
1365  * @param crtc     (IN) the drm pipe
1366  * @param red      (IN) red gamma value
1367  * @param green    (IN) green gamma value
1368  * @param blue     (IN) blue gamma value
1369  * @param regno    (IN) index value which we are setting
1370  *
1371  * @return None
1372  */
1373 static void emgd_fb_gamma_set(struct drm_crtc *crtc,
1374                 u16 red, u16 green, u16 blue,
1375                 int regno)
1376 {
1377         emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
1378
1379         EMGD_TRACE_ENTER;
1380         emgd_crtc->lut_r[regno] = red >> 8;
1381         emgd_crtc->lut_g[regno] = green >> 8;
1382         emgd_crtc->lut_b[regno] = blue >> 8;
1383         EMGD_TRACE_EXIT;
1384 }
1385
1386
1387 /*
1388  * emgd_fb_gamma_get
1389  *
1390  * Set the gamma values for a framebuffer for a particular
1391  * index.
1392  *
1393  * @param crtc     (IN) the drm pipe
1394  * @param red      (OUT) red gamma value
1395  * @param green    (OUT) green gamma value
1396  * @param blue     (OUT) blue gamma value
1397  * @param regno    (IN) index value which we are getting
1398  *
1399  * @return None
1400  */
1401 static void emgd_fb_gamma_get(struct drm_crtc *crtc,
1402                 u16 *red, u16 *green, u16 *blue,
1403                 int regno)
1404 {
1405         emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
1406
1407         EMGD_TRACE_ENTER;
1408         *red = (emgd_crtc->lut_r[regno] << 8);
1409         *blue = (emgd_crtc->lut_b[regno] << 8);
1410         *green = (emgd_crtc->lut_g[regno] << 8);
1411         EMGD_TRACE_EXIT;
1412 }
1413
1414
1415
1416 /**
1417  * emgd_fb_find_or_create_single
1418  *
1419  * If there is no frame buffer associated with "helper", then allocate a new
1420  * one.  Otherwise, reuse the existing one.
1421  *
1422  * @param helper       (IN) TBD
1423  * @param surface_info (IN) Surface info
1424  *
1425  * @return None
1426  */
1427 static int emgd_fb_find_or_create_single(struct drm_fb_helper *helper,
1428                         struct drm_fb_helper_surface_size *surface_info)
1429 {
1430         emgd_fbdev_t *fbdev  = container_of(helper, emgd_fbdev_t, helper);
1431         int           new_fb = false;
1432
1433
1434         EMGD_TRACE_ENTER;
1435
1436         if (!helper->fb) {
1437                 int ret = emgd_fb_create(fbdev, surface_info);
1438                 if (ret) {
1439                         return ret;
1440                 }
1441
1442                 new_fb = true;
1443         }
1444
1445         EMGD_TRACE_EXIT;
1446
1447         return new_fb;
1448 }
1449
1450 #endif