From 78598fdaa8b23a199880a63b79f17cfd7f14cb0f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Apr 2007 07:07:54 -0700 Subject: [PATCH] Various changes for in-kernel modesetting: - allow drm_buffer_object_create to be called w/o dev_mapping - fixup i915 init code to allocate memory, fb and set modes right - pass fb to drm_initial_config for setup - change some debug output to make it easier to spot - fixup lvds code to use DDC probing correctly --- linux-core/drm_bo.c | 10 ++++--- linux-core/drm_crtc.c | 40 ++++++++++++++-------------- linux-core/drm_crtc.h | 5 +++- linux-core/intel_display.c | 2 -- linux-core/intel_lvds.c | 21 ++++++++++++--- shared-core/i915_init.c | 65 +++++++++++++++++++++++++++++++++++++++------- 6 files changed, 102 insertions(+), 41 deletions(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 17d6fbc0..2107a3a8 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1530,7 +1530,7 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle, return ret; } -int drm_buffer_object_create(drm_file_t * priv, +int drm_buffer_object_create(drm_device_t *dev, unsigned long size, drm_bo_type_t type, uint32_t mask, @@ -1539,7 +1539,6 @@ int drm_buffer_object_create(drm_file_t * priv, unsigned long buffer_start, drm_buffer_object_t ** buf_obj) { - drm_device_t *dev = priv->head->dev; drm_buffer_manager_t *bm = &dev->bm; drm_buffer_object_t *bo; int ret = 0; @@ -1615,6 +1614,7 @@ int drm_buffer_object_create(drm_file_t * priv, drm_bo_usage_deref_unlocked(bo); return ret; } +EXPORT_SYMBOL(drm_buffer_object_create); static int drm_bo_add_user_object(drm_file_t * priv, drm_buffer_object_t * bo, int shareable) @@ -1670,7 +1670,8 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS) switch (req->op) { case drm_bo_create: rep.ret = - drm_buffer_object_create(priv, req->size, + drm_buffer_object_create(priv->head->dev, + req->size, req->type, req->mask, req->hint, @@ -2301,6 +2302,9 @@ void drm_bo_unmap_virtual(drm_buffer_object_t * bo) loff_t offset = ((loff_t) bo->map_list.hash.key) << PAGE_SHIFT; loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT; + if (!dev->dev_mapping) + return; + unmap_mapping_range(dev->dev_mapping, offset, holelen, 1); } diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1c1c3006..b349527d 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -57,6 +57,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) return fb; } +EXPORT_SYMBOL(drm_framebuffer_create); void drm_framebuffer_destroy(struct drm_framebuffer *fb) { @@ -493,30 +494,28 @@ out_err: return ret; } -bool drm_initial_config(drm_device_t *dev, bool can_grow) +/** + * drm_initial_config - setup a sane initial output configuration + * @dev: DRM device + * @fb: framebuffer backing for new setup + * @can_grow: this configuration is growable + * + * Scan the CRTCs and outputs and try to put together an initial setup. + * At the moment, this is a cloned configuration across all heads with + * @fb as the backing store. + */ +bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, + bool can_grow) { /* do a hardcoded initial configuration here */ struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, *lvds_crtc = NULL; - struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; -#if 0 - fb = drm_framebuffer_create(dev); - if (!fb) - return false; - - fb->pitch = 1024; - fb->width = 1024; - fb->height = 768; - fb->depth = 24; - fb->bits_per_pixel = 32; -#endif - /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - // crtc->fb = fb; + crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; crtc->enabled = 1; @@ -527,8 +526,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; - } - else if (!dvi_crtc) { + } else if (!dvi_crtc) { dvi_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; @@ -536,7 +534,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } } - drm_crtc_probe_output_modes(dev, 1024, 768); + drm_crtc_probe_output_modes(dev, 2048, 2048); /* hard bind the CRTCS */ @@ -551,20 +549,20 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } if (!strncmp(output->name, "VGA", 3)) { output->crtc = vga_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; use_output = output; } else if (!strncmp(output->name, "TMDS", 4)) { output->crtc = vga_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; } else if (!strncmp(output->name, "LVDS", 3)) { output->crtc = lvds_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index d5d256d4..54c508c5 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -452,10 +452,13 @@ extern int drm_mode_vrefresh(struct drm_display_mode *mode); extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); -extern bool drm_initial_config(struct drm_device *dev, bool cangrow); +extern bool drm_initial_config(struct drm_device *dev, + struct drm_framebuffer *fb, bool cangrow); extern void drm_framebuffer_set_object(struct drm_device *dev, unsigned long handle); extern bool drm_set_desired_modes(struct drm_device *dev); +extern int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb); +extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); /* IOCTLs */ extern int drm_mode_getresources(struct inode *inode, struct file *filp, diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 04a6e086..bb6f7f23 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1128,11 +1128,9 @@ static void intel_setup_outputs(drm_device_t *dev) intel_crt_init(dev); -#if 0 /* Set up integrated LVDS */ if (IS_MOBILE(dev) && !IS_I830(dev)) intel_lvds_init(dev); -#endif if (IS_I9XX(dev)) { intel_sdvo_init(dev, SDVOB); diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c index 90a26109..8ecb204c 100644 --- a/linux-core/intel_lvds.c +++ b/linux-core/intel_lvds.c @@ -164,6 +164,7 @@ static bool intel_lvds_mode_fixup(struct drm_output *output, struct intel_crtc *intel_crtc = output->crtc->driver_private; struct drm_output *tmp_output; +#if 0 spin_lock(&dev->mode_config.config_lock); list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) { if (tmp_output != output && tmp_output->crtc == output->crtc) { @@ -173,6 +174,7 @@ static bool intel_lvds_mode_fixup(struct drm_output *output, } } spin_lock(&dev->mode_config.config_lock); +#endif if (intel_crtc->pipe == 0) { printk(KERN_ERR "Can't support LVDS on pipe A\n"); @@ -199,7 +201,7 @@ static bool intel_lvds_mode_fixup(struct drm_output *output, dev_priv->panel_fixed_mode->vsync_end; adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal; adjusted_mode->clock = dev_priv->panel_fixed_mode->clock; -// xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); } /* @@ -272,11 +274,11 @@ static int intel_lvds_get_modes(struct drm_output *output) "failed.\n"); return 0; } - intel_i2c_destroy(intel_output->ddc_bus); ret = intel_ddc_get_modes(output); if (ret) return ret; + intel_i2c_destroy(intel_output->ddc_bus); /* Didn't get an EDID */ if (!output->monitor_info) { @@ -359,19 +361,31 @@ void intel_lvds_init(struct drm_device *dev) output->interlace_allowed = FALSE; output->doublescan_allowed = FALSE; + /* Set up the DDC bus. */ + intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); + if (!intel_output->ddc_bus) { + dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " + "failed.\n"); + return; + } + /* * Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one. */ intel_ddc_get_modes(output); + intel_i2c_destroy(intel_output->ddc_bus); list_for_each_entry(scan, &output->probed_modes, head) { if (scan->type & DRM_MODE_TYPE_PREFERRED) break; } - if (scan) + if (scan) { dev_priv->panel_fixed_mode = scan; + DRM_DEBUG("LVDS panel_fixed: %s\n", scan->name); + } +#if 0 /* * If we didn't get EDID, try checking if the panel is already turned * on. If so, assume that whatever is currently programmed is the @@ -395,7 +409,6 @@ void intel_lvds_init(struct drm_device *dev) } /* No BIOS poking yet... */ -#if 0 /* Get the LVDS fixed mode out of the BIOS. We should support LVDS * with the BIOS being unavailable or broken, but lack the * configuration options for now. diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 5af86f82..d9fb485b 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -4,10 +4,23 @@ #include "i915_drm.h" #include "i915_drv.h" +/** + * i915_driver_load - setup chip and create an initial config + * @dev: DRM device + * @flags: startup flags + * + * The driver load routine has to do several things: + * - drive output discovery via intel_modeset_init() + * - initialize the memory manager + * - allocate initial config memory + * - setup the DRM framebuffer with the allocated memory + */ int i915_driver_load(drm_device_t *dev, unsigned long flags) { drm_i915_private_t *dev_priv; drm_i915_init_t init; + drm_buffer_object_t *entry; + struct drm_framebuffer *fb; int ret; dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); @@ -45,7 +58,6 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags) return ret; } -#if 0 ret = drm_setup(dev); if (ret) { DRM_ERROR("drm_setup failed\n"); @@ -60,17 +72,48 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags) return DRM_ERR(EINVAL); } - /* FIXME: where does the sarea_priv really go? */ - // dev_priv->sarea_priv = kmalloc(sizeof(drm_i915_sarea_t), GFP_KERNEL); + /* FIXME: assume sarea_priv is right after SAREA */ + dev_priv->sarea_priv = dev_priv->sarea->handle + sizeof(drm_sarea_t); - /* FIXME: need real front buffer offset */ - /// dev_priv->sarea_priv->front_handle = dev_priv->baseaddr + 1024*1024; -#endif + /* + * Initialize the memory manager for local and AGP space + */ drm_bo_driver_init(dev); - /* this probably doesn't belong here - TODO */ - //drm_framebuffer_set_object(dev, dev_priv->sarea_priv->front_handle); + /* FIXME: initial stolen area 8M init */ +#define SCANOUT_SIZE 1024*1024*8 /* big enough for 2048x1024 32bpp */ + drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0, dev->mode_config.fb_base, + SCANOUT_SIZE); + + /* Allocate scanout buffer and command ring */ + /* FIXME: types and other args correct? */ + drm_buffer_object_create(dev, SCANOUT_SIZE, drm_bo_type_dc, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE, + 0, PAGE_SIZE, 0, + &entry); + + DRM_DEBUG("allocated bo, start: 0x%lx, offset: 0x%lx\n", + entry->buffer_start, entry->offset); intel_modeset_init(dev); - // drm_set_desired_modes(dev); + + fb = drm_framebuffer_create(dev); + if (!fb) { + DRM_ERROR("failed to allocate fb\n"); + return -EINVAL; + } + + fb->width = 1024; + fb->height = 768; + fb->pitch = 1024; + fb->bits_per_pixel = 32; + fb->depth = 32; + fb->offset = entry->offset; + fb->bo = entry; + + drm_initial_config(dev, fb, false); + drmfb_probe(dev, fb); + drm_set_desired_modes(dev); + #if 0 /* FIXME: command ring needs AGP space, do we own it at this point? */ dev_priv->ring.Start = dev_priv->baseaddr; @@ -133,8 +176,10 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags) int i915_driver_unload(drm_device_t *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_framebuffer *fb; - intel_modeset_cleanup(dev); + /* FIXME: remove framebuffer */ + //intel_modeset_cleanup(dev); drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); dev->dev_private = NULL; -- 2.11.0