2 *-----------------------------------------------------------------------------
5 *-----------------------------------------------------------------------------
6 * Copyright (c) 2002-2011, 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 * Framebuffer / kernel mode setting functions.
29 *-----------------------------------------------------------------------------
31 #define MODULE_NAME hal.oal
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/device.h>
37 #include <linux/version.h>
38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
39 #include <linux/export.h>
41 #include <linux/module.h>
46 #include <drm_crtc_helper.h>
47 #include <drm_fb_helper.h>
48 #include <linux/version.h>
49 #include <linux/vga_switcheroo.h>
51 #include "drm_emgd_private.h"
56 #include "mode_dispatch.h"
58 /* Necessary to import page list for a PVR-allocated surface */
59 #include "pvr_bridge_km.h"
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
68 #define RETURN_PROBE_TYPE void
70 #define PROBE_FUNC output_poll_changed
75 /*------------------------------------------------------------------------------
77 *------------------------------------------------------------------------------
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;
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;
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;
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;
97 /* FBCON Dispatch Table */
98 extern const struct fb_ops emgd_fb_ops;
102 /*------------------------------------------------------------------------------
104 *------------------------------------------------------------------------------
106 extern int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev);
108 static int emgd_fbdev_init(drm_emgd_priv_t *priv);
109 static void emgd_fbdev_destroy(drm_emgd_priv_t *priv);
113 /*------------------------------------------------------------------------------
115 *------------------------------------------------------------------------------
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,
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);
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 */
142 static struct notifier_block paniced = {
143 .notifier_call = emgd_fb_panic,
147 static const struct drm_framebuffer_funcs emgd_fb_funcs = {
148 .destroy = emgd_user_framebuffer_destroy,
149 .create_handle = emgd_user_framebuffer_create_handle,
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)
159 return DRM_FORMAT_RGB332;
163 return DRM_FORMAT_XRGB1555;
165 return DRM_FORMAT_RGB565;
168 return DRM_FORMAT_RGB888;
172 return DRM_FORMAT_XRGB8888;
173 else if (depth == 30)
174 return DRM_FORMAT_XRGB2101010;
176 return DRM_FORMAT_ARGB8888;
179 EMGD_ERROR("bad bpp %d, assuming x8r8g8b8 pixel format", bpp);
180 return DRM_FORMAT_XRGB8888;
186 * Called if something fails while trying to set up framebuffer based
189 static int emgd_fb_panic(struct notifier_block *n,
193 EMGD_DEBUG("Panic occurred, switch back to text console.");
204 * Restore the kernel's fbcon mode.
206 void emgd_fb_restore(void)
213 * FIXME: Need to have the real crtc saved so it can be restored.
215 if ((ret = drm_crtc_helper_set_config(&panic_mode)) != 0) {
216 EMGD_ERROR("Failed to restore crtc configuration: %d", ret);
223 /* Workqueue task function; needed during CRTC init */
224 void emgd_flip_worker(struct work_struct *w);
229 * Creates crtcs. This function loops through the valid pipes, creating
230 * one crtc for each pipe. This function assumes that dsp_alloc() has
233 * TODO: Move this to emgd_crtc.c?
235 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
239 void create_crtcs(struct drm_device *dev)
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;
246 unsigned short *r, *g, *b;
250 dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
251 context = dev_priv->context;
253 while ((pipe = context->mod_dispatch.dsp_get_next_pipe(context, pipe, 0))) {
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 *)),
261 if (emgd_crtc == NULL) {
262 EMGD_ERROR("create_crtcs: Failed to allocate CRTC structure.");
266 spin_lock_init(&emgd_crtc->crtc_lock);
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);
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);
280 drm_mode_crtc_set_gamma_size(&emgd_crtc->base, 256);
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;
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;
300 /* Target FB that we're in the process of changing to */
301 emgd_crtc->newfb = NULL;
303 /* Target "ops complete" watermark to allow flip to proceed */
304 emgd_crtc->render_complete_at = 0;
307 * Are we expected to perform flip cleanup (sending userspace event
308 * and such) on next vblank event?
310 emgd_crtc->vblank_expected = 0;
312 /* Userspace 'flip done' event */
313 emgd_crtc->flip_event = NULL;
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;
321 /* Hook up crtc helper functions */
322 drm_crtc_helper_add(&emgd_crtc->base, &emgd_crtc_helper_funcs);
334 * Creates an encoder for the igd_port in the parameter.
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)
341 static void create_encoder(struct drm_device *dev, igd_display_port_t *igd_port)
343 emgd_encoder_t *emgd_encoder;
344 emgd_crtc_t *emgd_crtc;
345 struct drm_crtc *crtc;
346 unsigned long drm_encoder_type;
351 /* Find the corresponding DRM encoder type */
352 switch(igd_port->port_type) {
354 drm_encoder_type = DRM_MODE_ENCODER_LVDS;
357 case IGD_PORT_DIGITAL:
358 drm_encoder_type = DRM_MODE_ENCODER_TMDS;
361 case IGD_PORT_ANALOG:
364 case IGD_PORT_SDVO_ST:
365 case IGD_PORT_SDVO_ST_GPIO:
367 EMGD_ERROR("Invalid Port Type");
372 emgd_encoder = kzalloc(sizeof(emgd_encoder_t), GFP_KERNEL);
374 EMGD_ERROR("Out of memory!");
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;
385 * crtc's are identified by a 1 that is shifted over:
389 * The order of the pipes is based on how they are initialized
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;
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;
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);
409 if ((emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) ==
410 emgd_encoder->igd_port->port_type) {
411 emgd_encoder->base.crtc = crtc;
417 EMGD_DEBUG("Creating encoder=0x%lx on pipe=0x%lx, of port=0x%lx, "
419 (unsigned long)&(emgd_encoder->base), emgd_encoder->crtc_mask,
420 igd_port->port_number, igd_port->port_type);
422 drm_encoder_init(dev, &emgd_encoder->base, &emgd_encoder_funcs,
424 drm_encoder_helper_add(&emgd_encoder->base, &emgd_encoder_helper_funcs);
430 * create_connector_properties
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."
438 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
439 * @param emgd_connector (IN) Selected connector
443 static void create_connector_properties(struct drm_device *dev,
444 emgd_connector_t *emgd_connector)
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;
452 struct drm_connector *drm_connector = &emgd_connector->base;
453 struct drm_property *new_prop;
458 /* Get port attributes from the port driver */
459 priv->context->dispatch.get_attrs(priv->context,
460 igd_port->port_number,
465 /* If the connector has no attributes, then return */
466 if (0 >= num_of_attributes) {
471 emgd_connector->properties =
472 (struct drm_property **) kzalloc(sizeof(struct drm_property *) *
473 num_of_attributes, GFP_KERNEL);
475 if (NULL == emgd_connector->properties) {
476 EMGD_ERROR_EXIT("Failed to allocate emgd_connector->properties");
480 /* Convert port attributes to connector properties and attach them */
481 for(i = 0; i < num_of_attributes; i++) {
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) {
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:
495 igd_range_attr_t *attr = (igd_range_attr_t *) &attributes[i];
498 new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
501 if (NULL == new_prop) {
502 EMGD_ERROR("Failed to allocate new property");
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;
514 case PD_ATTR_TYPE_BOOL:
516 igd_bool_attr_t *attr = (igd_bool_attr_t *) &attributes[i];
519 new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
522 if (NULL == new_prop) {
523 EMGD_ERROR("Failed to allocate new property");
527 new_prop->values[0] = false;
528 new_prop->values[1] = true;
529 current_value = attr->current_value;
534 case PD_ATTR_TYPE_LIST:
535 case PD_ATTR_TYPE_LIST_ENTRY:
536 case PD_ATTR_TYPE_BUFFER:
538 EMGD_ERROR("Unsupported PD Attribute type");
542 drm_connector_attach_property(drm_connector, new_prop, current_value);
543 emgd_connector->properties[num_of_properties++] = new_prop;
554 * Creates connectors associated with the encoder.
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.
560 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
561 * @param emgd_encoder (IN) Encoder to be examined.
565 static void create_connectors(struct drm_device *dev,
566 emgd_encoder_t *emgd_encoder)
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;
577 case PD_DISPLAY_LVDS_EXT:
578 case PD_DISPLAY_LVDS_INT:
579 connector_type = DRM_MODE_CONNECTOR_LVDS;
583 connector_type = DRM_MODE_CONNECTOR_DVID;
586 case PD_DISPLAY_CRT_EXT:
588 connector_type = DRM_MODE_CONNECTOR_VGA;
591 case PD_DISPLAY_HDMI_INT:
592 connector_type = DRM_MODE_CONNECTOR_HDMIA;
595 case PD_DISPLAY_HDMI_EXT:
596 connector_type = DRM_MODE_CONNECTOR_HDMIA;
599 case PD_DISPLAY_DP_INT:
600 connector_type = DRM_MODE_CONNECTOR_DisplayPort;
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");
612 EMGD_ERROR("Unknown connector type");
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!");
624 drm_connector_init(dev, &emgd_connector->base, &emgd_connector_funcs,
627 drm_mode_connector_attach_encoder(&emgd_connector->base,
628 &emgd_encoder->base);
630 drm_connector_helper_add(&emgd_connector->base,
631 &emgd_connector_helper_funcs);
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);
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;
644 /* Create and attach connector properties */
645 create_connector_properties(dev, emgd_connector);
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);
659 drm_sysfs_connector_add(&emgd_connector->base);
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.
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
678 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
682 void emgd_setup_outputs(struct drm_device *dev)
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;
692 /* Loop through all available ports. What KMS calls "encoder" is a
693 * subset of what EMGD calls "port."
695 while ((port = module_dispatch->dsp_get_next_port(igd_context, port, 0))) {
697 /* If there is a port driver, then there's an encoder */
698 if (port->pd_driver) {
699 create_encoder(dev, port);
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;
708 emgd_encoder = container_of(encoder, emgd_encoder_t, base);
709 create_connectors(dev, emgd_encoder);
720 * This is the main initialization entry point. Called during driver load
721 * and does basic setup.
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.
730 void emgd_modeset_init(struct drm_device *dev)
732 drm_emgd_priv_t *devpriv = (drm_emgd_priv_t *)dev->dev_private;
734 struct drm_encoder *encoder;
737 drm_mode_config_init(dev); /* drm helper function */
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;
746 /* OTC uses dev->agp->base for fb_base */
747 dev->mode_config.fb_base = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
749 /* Initialize VBLANK handling */
750 dev->irq_enabled = true;
751 dev->max_vblank_count = 0xffffff; /* 24-bit frame counter */
753 ret = drm_vblank_init(dev, devpriv->num_crtc);
755 EMGD_ERROR("Call to drm_vblank_init() failed. drmWaitVBlank() "
757 dev->irq_enabled = false;
761 /* Create the crtc's */
764 drm_mode_create_scaling_mode_property(dev);
765 emgd_setup_outputs(dev);
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);
774 drm_helper_disable_unused_functions(dev);
776 /* Initialize the framebuffer device */
777 emgd_fbdev_init(devpriv);
785 * emgd_modeset_destroy
787 * Clean up resources allocated in emgd_modeset_init. Called during driver
790 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
794 void emgd_modeset_destroy(struct drm_device *dev)
796 drm_emgd_priv_t *priv = NULL;
800 priv = dev->dev_private;
801 emgd_fbdev_destroy(priv);
802 kfree(priv->emgd_fbdev);
803 priv->emgd_fbdev = NULL;
813 * Registers panic mode for the DRM to switch to.
815 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
819 RETURN_PROBE_TYPE emgd_fb_probe(struct drm_device *dev)
823 /* Set Panic Mode to 1024x768 because it is an acceptably generic mode */
824 //memset(&panic_mode, 0, sizeof(struct drm_mode_set));
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
832 /* Register a notifier to switch back to kernel console on panic */
833 atomic_notifier_chain_register(&panic_notifier_list, &paniced);
838 EXPORT_SYMBOL(emgd_fb_probe);
842 * emgd_user_framebuffer_create
844 * Creates an instance for the framebuffer.
846 * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
848 * @param mode_cmd (IN) Input from the DRM_IOCTL_MODE_ADDFB
850 * @return pointer to allocated FB instance
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)
857 emgd_framebuffer_t *emgd_fb;
862 emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
864 EMGD_ERROR("Failed to allocate an emgd_framebuffer_t");
868 /* Create a framebuffer instance */
869 ret = emgd_framebuffer_init(dev, emgd_fb, mode_cmd,
870 (unsigned long)mode_cmd->DRMMODE_HANDLE);
872 EMGD_ERROR("Failed to create framebuffer instance.");
873 /* TODO: Free the allocation at mode_cmd->handle */
880 return &emgd_fb->base;
885 * emgd_framebuffer_init
887 * Creates an instance for the framebuffer.
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).
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.
905 * @return int return value
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)
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;
922 dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
923 context = dev_priv->context;
925 if (handle == EMGD_INITIAL_FRAMEBUFFER) {
927 * Special case: initial EMGD framebuffer is allocated via GTT instead
928 * of through the PVR services. It has no PVR meminfo handle.
930 ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
932 EMGD_ERROR("Failed to create framebuffer instance.");
936 drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
939 * Initial framebuffer offset is stored in the device
942 emgd_fb->type = GMM_FRAMEBUFFER;
943 emgd_fb->gtt_offset = dev_priv->initfb_info.fb_base_offset;
944 emgd_fb->handle = handle;
947 /* Fetch PVR services 'per-process' data structure */
948 pid = OSGetCurrentProcessIDKM();
949 pvr_perproc = PVRSRVPerProcessData(pid);
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.");
961 * Now fetch the page list, number of pages, and offset into the first
962 * page for this buffer.
964 ret = PVRSRVGetPageListKM(pvr_meminfo, &pagelist, &numpages,
966 if (ret != PVRSRV_OK) {
967 EMGD_ERROR("Failed to get pagelist for PVR surface.");
971 /* Map this page list into the GTT */
972 ret = context->dispatch.gmm_import_pages((void**)pagelist, >t_offset,
975 EMGD_ERROR("Failed to map pagelist into GTT.");
979 /* Create a framebuffer instance */
980 ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
982 EMGD_ERROR("Failed to create framebuffer instance.");
986 /* Fill the EMGD framebuffer structure */
987 drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
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;
1003 * emgd_user_framebuffer_destroy
1005 * clean up and remove a framebuffer instance.
1008 static void emgd_user_framebuffer_destroy (struct drm_framebuffer *fb)
1010 drm_emgd_priv_t *dev_priv = NULL;
1011 emgd_framebuffer_t *emgd_fb = NULL;
1012 igd_context_t *context = NULL;
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);
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);
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);
1031 drm_framebuffer_cleanup(fb);
1040 * emgd_user_framebuffer_create_handle
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
1048 * @param fb (IN) DRM framebuffer to look up
1049 * @param file_priv (IN) Not used
1050 * @param handle (OUT)
1052 * @return 0 on success
1053 * @return -EINVAL on failure
1055 static int emgd_user_framebuffer_create_handle(struct drm_framebuffer *fb,
1056 struct drm_file *file_priv,
1057 unsigned int *handle)
1059 emgd_framebuffer_t *emgd_fb;
1064 /* To avoid compiler warning. */
1067 emgd_fb = container_of(fb, emgd_framebuffer_t, base);
1069 if (NULL != emgd_fb) {
1070 *handle = emgd_fb->handle;
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.
1088 * @param priv (IN) EMGD private DRM data structure
1090 * @return 0 on success
1093 static int emgd_fbdev_init(drm_emgd_priv_t *priv)
1095 emgd_fbdev_t *emgd_fbdev;
1099 emgd_fbdev = kzalloc(sizeof(emgd_fbdev_t), GFP_KERNEL);
1104 emgd_fbdev->priv = priv;
1105 priv->emgd_fbdev = emgd_fbdev;
1107 emgd_fbcon_initial_config(emgd_fbdev);
1116 * emgd_fbdev_destroy
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.
1125 * @param priv (IN) EMGD private DRM data structure
1129 static void emgd_fbdev_destroy(drm_emgd_priv_t *priv)
1131 emgd_fbdev_t *emgd_fbdev = NULL;
1132 struct drm_framebuffer *fb = NULL;
1133 struct fb_info *info = NULL;
1137 emgd_fbdev = priv->emgd_fbdev;
1138 fb = &emgd_fbdev->emgd_fb->base;
1143 unregister_framebuffer(info);
1145 if (info->cmap.len) {
1146 fb_dealloc_cmap(&info->cmap);
1149 priv->context->dispatch.gmm_unmap(info->screen_base);
1150 framebuffer_release(info);
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);
1156 kfree(emgd_fbdev->emgd_fb);
1157 emgd_fbdev->emgd_fb = NULL;
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 *------------------------------------------------------------------------------
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);
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,
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
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
1199 static int emgd_fb_create(emgd_fbdev_t *emgd_fbdev,
1200 struct drm_fb_helper_surface_size *surface_info)
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;
1210 unsigned long offset = 0;
1215 context = priv->context;
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;
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,
1229 IGD_GMM_ALLOC_TYPE_RESERVATION,
1230 &priv->initfb_info.flags);
1232 EMGD_ERROR_EXIT("Allocation of buffer failed: %d", ret);
1236 priv->initfb_info.allocated = 1;
1237 priv->initfb_info.visible_offset = 0;
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;
1246 /* Allocate fb_info */
1247 info = kzalloc(sizeof(struct fb_info), GFP_KERNEL);
1249 EMGD_ERROR_EXIT("Allocation of fb_info failed");
1250 context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1253 info->par = emgd_fbdev;
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);
1265 /* Initialize the framebuffer */
1266 ret = emgd_framebuffer_init(dev, emgd_fbdev->emgd_fb, &mode_cmd,
1267 EMGD_INITIAL_FRAMEBUFFER);
1269 context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
1272 kfree(emgd_fbdev->emgd_fb);
1273 emgd_fbdev->emgd_fb = NULL;
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;
1287 EMGD_DEBUG("EMGD: Call fb_alloc_cmap()");
1288 ret = fb_alloc_cmap(&info->cmap, 256, 0);
1290 EMGD_ERROR("%s: Can't allocate color map", info->fix.id);
1291 //mutex_unlock(&dev->struct_mutex);
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
1300 * setup aperture base/size for vesafb takeover
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);
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;
1314 //mutex_unlock(&dev->struct_mutex);
1316 * FIXME: What is fix.smem_start vs screen_base?
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
1322 * screen_base is a virtual address
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;
1331 /* Get kernel virtual memory address of framebuffer */
1332 EMGD_DEBUG("EMGD: Call gmm_map()");
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);
1339 info->screen_size = size;
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;
1347 EMGD_DEBUG("Frame buffer %dx%d @ 0x%08lx",
1348 fb->width, fb->height, offset);
1350 EMGD_DEBUG("EMGD: Call vga_switcheroo_client_fb_set()");
1351 vga_switcheroo_client_fb_set(dev->pdev, info);
1362 * Set the gamma values for a framebuffer for a particular
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
1373 static void emgd_fb_gamma_set(struct drm_crtc *crtc,
1374 u16 red, u16 green, u16 blue,
1377 emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
1380 emgd_crtc->lut_r[regno] = red >> 8;
1381 emgd_crtc->lut_g[regno] = green >> 8;
1382 emgd_crtc->lut_b[regno] = blue >> 8;
1390 * Set the gamma values for a framebuffer for a particular
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
1401 static void emgd_fb_gamma_get(struct drm_crtc *crtc,
1402 u16 *red, u16 *green, u16 *blue,
1405 emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
1408 *red = (emgd_crtc->lut_r[regno] << 8);
1409 *blue = (emgd_crtc->lut_b[regno] << 8);
1410 *green = (emgd_crtc->lut_g[regno] << 8);
1417 * emgd_fb_find_or_create_single
1419 * If there is no frame buffer associated with "helper", then allocate a new
1420 * one. Otherwise, reuse the existing one.
1422 * @param helper (IN) TBD
1423 * @param surface_info (IN) Surface info
1427 static int emgd_fb_find_or_create_single(struct drm_fb_helper *helper,
1428 struct drm_fb_helper_surface_size *surface_info)
1430 emgd_fbdev_t *fbdev = container_of(helper, emgd_fbdev_t, helper);
1437 int ret = emgd_fb_create(fbdev, surface_info);