diff options
| -rw-r--r-- | linux-core/Makefile.kernel | 2 | ||||
| -rw-r--r-- | linux-core/drm_crtc.c | 471 | ||||
| -rw-r--r-- | linux-core/drm_crtc.h | 43 | ||||
| -rw-r--r-- | linux-core/drm_crtc_helper.c | 515 | ||||
| -rw-r--r-- | linux-core/drm_crtc_helper.h | 69 | ||||
| -rw-r--r-- | linux-core/intel_crt.c | 17 | ||||
| -rw-r--r-- | linux-core/intel_display.c | 29 | ||||
| -rw-r--r-- | linux-core/intel_drv.h | 1 | ||||
| -rw-r--r-- | linux-core/intel_dvo.c | 15 | ||||
| -rw-r--r-- | linux-core/intel_fb.c | 6 | ||||
| -rw-r--r-- | linux-core/intel_lvds.c | 16 | ||||
| -rw-r--r-- | linux-core/intel_sdvo.c | 16 | ||||
| -rw-r--r-- | linux-core/intel_tv.c | 12 | ||||
| -rw-r--r-- | shared-core/i915_init.c | 3 | ||||
| -rw-r--r-- | shared-core/i915_irq.c | 11 | 
15 files changed, 688 insertions, 538 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index f77f8642..ac9baf02 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -15,7 +15,7 @@ drm-objs    := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \  		drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \  	        drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_crtc.o \  		drm_edid.o drm_modes.o drm_bo_lock.o drm_regman.o \ -		drm_vm_nopage_compat.o +		drm_vm_nopage_compat.o drm_crtc_helper.o  tdfx-objs   := tdfx_drv.o  r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o  mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e05466ee..a4a51080 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -418,133 +418,6 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)  }  EXPORT_SYMBOL(drm_crtc_probe_output_modes); -/** - * drm_crtc_set_mode - set a mode - * @crtc: CRTC to program - * @mode: mode to use - * @x: width of mode - * @y: height of mode - * - * LOCKING: - * Caller must hold mode config lock. - * - * Try to set @mode on @crtc.  Give @crtc and its associated outputs a chance - * to fixup or reject the mode prior to trying to set it. - * - * RETURNS: - * True if the mode was set successfully, or false otherwise. - */ -bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, -		       int x, int y) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_display_mode *adjusted_mode, saved_mode; -	int saved_x, saved_y; -	struct drm_output *output; -	bool ret = true; - -	adjusted_mode = drm_mode_duplicate(dev, mode); - -	crtc->enabled = drm_crtc_in_use(crtc); - -	if (!crtc->enabled) -		return true; - -	saved_mode = crtc->mode; -	saved_x = crtc->x; -	saved_y = crtc->y; -	 -	/* Update crtc values up front so the driver can rely on them for mode -	 * setting. -	 */ -	crtc->mode = *mode; -	crtc->x = x; -	crtc->y = y; - -	if (drm_mode_equal(&saved_mode, &crtc->mode)) { -		if (saved_x != crtc->x || saved_y != crtc->y) { -			crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); -			goto done; -		} -	} - -	/* Pass our mode to the outputs and the CRTC to give them a chance to -	 * adjust it according to limitations or output properties, and also -	 * a chance to reject the mode entirely. -	 */ -	list_for_each_entry(output, &dev->mode_config.output_list, head) { -		 -		if (output->crtc != crtc) -			continue; -		 -		if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) { -			goto done; -		} -	} -	 -	if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) { -		goto done; -	} - -	/* Prepare the outputs and CRTCs before setting the mode. */ -	list_for_each_entry(output, &dev->mode_config.output_list, head) { - -		if (output->crtc != crtc) -			continue; -		 -		/* Disable the output as the first thing we do. */ -		output->funcs->prepare(output); -	} -	 -	crtc->funcs->prepare(crtc); -	 -	/* Set up the DPLL and any output state that needs to adjust or depend -	 * on the DPLL. -	 */ -	crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); - -	list_for_each_entry(output, &dev->mode_config.output_list, head) { - -		if (output->crtc != crtc) -			continue; -		 -		DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id); - -		output->funcs->mode_set(output, mode, adjusted_mode); -	} -	 -	/* Now, enable the clocks, plane, pipe, and outputs that we set up. */ -	crtc->funcs->commit(crtc); - -	list_for_each_entry(output, &dev->mode_config.output_list, head) { - -		if (output->crtc != crtc) -			continue; -		 -		output->funcs->commit(output); - -#if 0 // TODO def RANDR_12_INTERFACE -		if (output->randr_output) -			RRPostPendingProperties (output->randr_output); -#endif -	} -	 -	/* XXX free adjustedmode */ -	drm_mode_destroy(dev, adjusted_mode); -	/* TODO */ -//	if (scrn->pScreen) -//		drm_crtc_set_screen_sub_pixel_order(dev); - -done: -	if (!ret) {  -		crtc->mode = saved_mode; -		crtc->x = saved_x; -		crtc->y = saved_y; -	} - -	return ret; -} -EXPORT_SYMBOL(drm_crtc_set_mode);  /**   * drm_disable_unused_functions - disable unused objects @@ -896,171 +769,8 @@ out_err:  	return ret;  } -/** - * drm_pick_crtcs - pick crtcs for output devices - * @dev: DRM device - * - * LOCKING: - * Caller must hold mode config lock. - */ -static void drm_pick_crtcs (struct drm_device *dev) -{ -	int c, o, assigned; -	struct drm_output *output, *output_equal; -	struct drm_crtc   *crtc; -	struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; -	int found; - -	list_for_each_entry(output, &dev->mode_config.output_list, head) { -       		output->crtc = NULL; -     -    		/* Don't hook up outputs that are disconnected ?? -		 * -		 * This is debateable. Do we want fixed /dev/fbX or -		 * dynamic on hotplug (need mode code for that though) ? -		 * -		 * If we don't hook up outputs now, then we only create -		 * /dev/fbX for the output that's enabled, that's good as -		 * the users console will be on that output. -		 * -		 * If we do hook up outputs that are disconnected now, then -		 * the user may end up having to muck about with the fbcon -		 * map flags to assign his console to the enabled output. Ugh. -		 */ -    		if (output->status != output_status_connected) -			continue; - -		if (list_empty(&output->modes)) -			continue; - -		des_mode = NULL; -		found = 0; -		list_for_each_entry(des_mode, &output->modes, head) { -			if (des_mode->type & DRM_MODE_TYPE_PREFERRED) { -				found = 1; -				break; -			} -		} - -		/* No preferred mode, let's just select the first available */ -		if (!found) { -			des_mode = NULL; -			list_for_each_entry(des_mode, &output->modes, head) { -				break; -			} -		} - -		c = -1; -		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -			assigned = 0; -			c++; -			if ((output->possible_crtcs & (1 << c)) == 0) -		    		continue; -	 -			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { -				if (output->id == output_equal->id) -					continue; - -				/* Find out if crtc has been assigned before */ -				if (output_equal->crtc == crtc) -					assigned = 1; -			} - -#if 1 /* continue for now */ -			if (assigned) -				continue; -#endif - -			o = -1; -			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { -				o++; -				if (output->id == output_equal->id) -					continue; - -				list_for_each_entry(modes, &output->modes, head) { -					list_for_each_entry(modes_equal, &output_equal->modes, head) { -						if (drm_mode_equal (modes, modes_equal)) { -							if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { -								printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones); -								des_mode = modes; -								assigned = 0; -								goto clone; -							} -						} -					} -				} -			} -clone: -			/* crtc has been assigned skip it */ -			if (assigned) -				continue; - -			/* Found a CRTC to attach to, do it ! */ -			output->crtc = crtc; -			output->crtc->desired_mode = des_mode; -			output->initial_x = 0; -			output->initial_y = 0; -			DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name); -			break; -    		} -	} -} -EXPORT_SYMBOL(drm_pick_crtcs); - -/** - * drm_initial_config - setup a sane initial output configuration - * @dev: DRM device - * @can_grow: this configuration is growable - * - * LOCKING: - * Called at init time, must take mode config lock. - * - * 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 - * a new framebuffer object as the backing store. - * - * RETURNS: - * Zero if everything went ok, nonzero otherwise. - */ -bool drm_initial_config(struct drm_device *dev, bool can_grow) -{ -	struct drm_output *output; -	struct drm_crtc *crtc; -	int ret = false; - -	mutex_lock(&dev->mode_config.mutex); - -	drm_crtc_probe_output_modes(dev, 2048, 2048); - -	drm_pick_crtcs(dev); - -	/* This is a little screwy, as we've already walked the outputs  -	 * above, but it's a little bit of magic too. There's the potential -	 * for things not to get setup above if an existing device gets -	 * re-assigned thus confusing the hardware. By walking the outputs -	 * this fixes up their crtc's. -	 */ -	list_for_each_entry(output, &dev->mode_config.output_list, head) { - -		/* can't setup the output if there's no assigned mode */ -		if (!output->crtc || !output->crtc->desired_mode) -			continue; - -		dev->driver->fb_probe(dev, output->crtc, output); - -		/* and needs an attached fb */ -		if (output->crtc->fb) -			drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); -	} - -	drm_disable_unused_functions(dev); - -	mutex_unlock(&dev->mode_config.mutex); -	return ret; -} -EXPORT_SYMBOL(drm_initial_config);  /**   * drm_mode_config_cleanup - free up DRM mode_config info @@ -1105,179 +815,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)  }  EXPORT_SYMBOL(drm_mode_config_cleanup); -/** - * drm_crtc_set_config - set a new config from userspace - * @crtc: CRTC to setup - * @crtc_info: user provided configuration - * @new_mode: new mode to set - * @output_set: set of outputs for the new config - * @fb: new framebuffer - * - * LOCKING: - * Caller must hold mode config lock. - * - * Setup a new configuration, provided by the user in @crtc_info, and enable - * it. - * - * RETURNS: - * Zero. (FIXME) - */ -int drm_crtc_set_config(struct drm_mode_set *set) -{ -	struct drm_device *dev; -	struct drm_crtc **save_crtcs, *new_crtc; -	bool save_enabled; -	bool changed = false; -	bool flip_or_move = false; -	struct drm_output *output; -	int count = 0, ro; - -	DRM_DEBUG("\n"); - -	if (!set) -		return -EINVAL; - -	if (!set->crtc) -		return -EINVAL; - -	DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y); -	dev = set->crtc->dev; - -	/* save previous config */ -	save_enabled = set->crtc->enabled; - -	/* this is meant to be num_output not num_crtc */ -	save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL); -	if (!save_crtcs) -		return -ENOMEM; - -	/* We should be able to check here if the fb has the same properties -	 * and then just flip_or_move it */ -	if (set->crtc->fb != set->fb) -		flip_or_move = true; -	if (set->x != set->crtc->x || set->y != set->crtc->y) -		flip_or_move = true; - -	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { -		DRM_DEBUG("modes are different\n"); -		drm_mode_debug_printmodeline(&set->crtc->mode); -		drm_mode_debug_printmodeline(set->mode); -		changed = true; -	} - -	list_for_each_entry(output, &dev->mode_config.output_list, head) { -		save_crtcs[count++] = output->crtc; - -		if (output->crtc == set->crtc) -			new_crtc = NULL; -		else -			new_crtc = output->crtc; - -		for (ro = 0; ro < set->num_outputs; ro++) { -			if (set->outputs[ro] == output) -				new_crtc = set->crtc; -		} -		if (new_crtc != output->crtc) { -			changed = true; -			output->crtc = new_crtc; -		} -	} - -	/* mode_set_base is not a required function */ -	if (flip_or_move && !set->crtc->funcs->mode_set_base) -		changed = true; - -	if (changed) { -		set->crtc->fb = set->fb; -		set->crtc->enabled = (set->mode != NULL); -		if (set->mode != NULL) { -			DRM_DEBUG("attempting to set mode from userspace\n"); -			drm_mode_debug_printmodeline(set->mode); -			if (!drm_crtc_set_mode(set->crtc, set->mode, set->x, -					       set->y)) { -				set->crtc->enabled = save_enabled; -				count = 0; -				list_for_each_entry(output, &dev->mode_config.output_list, head) -					output->crtc = save_crtcs[count++]; -				kfree(save_crtcs); -				return -EINVAL; -			} -			/* TODO are these needed? */ -			set->crtc->desired_x = set->x; -			set->crtc->desired_y = set->y; -			set->crtc->desired_mode = set->mode; -		} -		drm_disable_unused_functions(dev); -	} else if (flip_or_move) { -		if (set->crtc->fb != set->fb) -			set->crtc->fb = set->fb; -		set->crtc->funcs->mode_set_base(set->crtc, set->x, set->y); -	} - -	kfree(save_crtcs); -	return 0; -} -EXPORT_SYMBOL(drm_crtc_set_config); - -/** - * drm_hotplug_stage_two - * @dev DRM device - * @output hotpluged output - * - * LOCKING. - * Caller must hold mode config lock, function might grab struct lock. - * - * Stage two of a hotplug. - * - * RETURNS: - * Zero on success, errno on failure. - */ -int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, -			  bool connected) -{ -	int has_config = 0; - -	dev->mode_config.hotplug_counter++; - -	/* We might want to do something more here */ -	if (!connected) { -		DRM_DEBUG("not connected\n"); -		return 0; -	} - -	if (output->crtc && output->crtc->desired_mode) { -		DRM_DEBUG("drm thinks that the output already has a config\n"); -		has_config = 1; -	} - -	drm_crtc_probe_output_modes(dev, 2048, 2048); - -	if (!has_config) -		drm_pick_crtcs(dev); - -	if (!output->crtc || !output->crtc->desired_mode) { -		DRM_DEBUG("could not find a desired mode or crtc for output\n"); -		return 1; -	} - -	/* We should really check if there is a fb using this crtc */ -	if (!has_config) -		dev->driver->fb_probe(dev, output->crtc, output); -	else { -		dev->driver->fb_resize(dev, output->crtc); - -		if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) -			DRM_ERROR("failed to set mode after hotplug\n"); -	} - -	drm_sysfs_hotplug_event(dev); - -	drm_disable_unused_functions(dev); - -	return 0; -} -EXPORT_SYMBOL(drm_hotplug_stage_two);  int drm_mode_hotplug_ioctl(struct drm_device *dev,  			   void *data, struct drm_file *file_priv) @@ -1740,7 +1278,7 @@ int drm_mode_setcrtc(struct drm_device *dev,  	set.outputs = output_set;  	set.num_outputs = crtc_req->count_outputs;  	set.fb =fb; -	ret = drm_crtc_set_config(&set); +	ret = crtc->funcs->set_config(&set);  out:  	kfree(output_set); @@ -2535,7 +2073,6 @@ int drm_mode_replacefb(struct drm_device *dev,  {  	struct drm_mode_fb_cmd *r = data;  	struct drm_framebuffer *fb; -	struct drm_crtc *crtc;  	struct drm_buffer_object *bo;  	int found = 0;  	struct drm_framebuffer *fbl = NULL; @@ -2574,12 +2111,18 @@ int drm_mode_replacefb(struct drm_device *dev,  	fb->depth = r->depth;  	fb->bo = bo; +	if (dev->mode_config.funcs->resize_fb) +	  dev->mode_config.funcs->resize_fb(dev, fb); +	else +	  ret = -EINVAL; +#if 0  	/* find all crtcs connected to this fb */  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  		if (crtc->fb->id == r->buffer_id) {  			crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y);  		}  	} +#endif  out:  	mutex_unlock(&dev->mode_config.mutex);  	return ret; diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index ae2dd173..957ecc2c 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -14,6 +14,7 @@  #include <linux/fb.h>  struct drm_device; +struct drm_mode_set;  /*   * Note on terminology:  here, for brevity and convenience, we refer to output @@ -313,20 +314,6 @@ struct drm_crtc_funcs {  	/* Restore CRTC state */  	void (*restore)(struct drm_crtc *crtc); /* resume? */ -	void (*prepare)(struct drm_crtc *crtc); -	void (*commit)(struct drm_crtc *crtc); - -	/* Provider can fixup or change mode timings before modeset occurs */ -	bool (*mode_fixup)(struct drm_crtc *crtc, -			   struct drm_display_mode *mode, -			   struct drm_display_mode *adjusted_mode); -	/* Actually set the mode */ -	void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, -			 struct drm_display_mode *adjusted_mode, int x, int y); - -	/* Move the crtc on the current fb to the given position *optional* */ -	void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); -  	/* cursor controls */  	int (*cursor_set)(struct drm_crtc *crtc, struct drm_buffer_object *bo,  			  uint32_t width, uint32_t height); @@ -337,6 +324,8 @@ struct drm_crtc_funcs {  			  int regno);  	/* Driver cleanup routine */  	void (*cleanup)(struct drm_crtc *crtc); + +	int (*set_config)(struct drm_mode_set *set);  };  /** @@ -371,6 +360,9 @@ struct drm_crtc {  	int desired_x, desired_y;  	const struct drm_crtc_funcs *funcs;  	void *driver_private; + +	/* if you are using the helper */ +	void *helper_private;  };  extern struct drm_crtc *drm_crtc_create(struct drm_device *dev, @@ -399,21 +391,14 @@ struct drm_output_funcs {  	void (*dpms)(struct drm_output *output, int mode);  	void (*save)(struct drm_output *output);  	void (*restore)(struct drm_output *output); -	int (*mode_valid)(struct drm_output *output, -			  struct drm_display_mode *mode); -	bool (*mode_fixup)(struct drm_output *output, -			   struct drm_display_mode *mode, -			   struct drm_display_mode *adjusted_mode); -	void (*prepare)(struct drm_output *output); -	void (*commit)(struct drm_output *output); -	void (*mode_set)(struct drm_output *output, -			 struct drm_display_mode *mode, -			 struct drm_display_mode *adjusted_mode);  	enum drm_output_status (*detect)(struct drm_output *output);  	int (*get_modes)(struct drm_output *output);  	bool (*set_property)(struct drm_output *output, struct drm_property *property,  			     uint64_t val);  	void (*cleanup)(struct drm_output *output); +  	int (*mode_valid)(struct drm_output *output, +			  struct drm_display_mode *mode); +  };  #define DRM_OUTPUT_MAX_UMODES 16 @@ -468,6 +453,8 @@ struct drm_output {  	struct drm_property_blob *edid_blob_ptr;  	u32 property_ids[DRM_OUTPUT_MAX_PROPERTY];  	uint64_t property_values[DRM_OUTPUT_MAX_PROPERTY]; + +	void *helper_private;  };  /** @@ -501,7 +488,7 @@ struct drm_mode_set   * the CRTC<->output mappings as needed and update its view of the screen.   */  struct drm_mode_config_funcs { -	bool (*resize)(struct drm_device *dev, int width, int height); +	bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb);  };  /** @@ -597,18 +584,14 @@ extern int drm_output_property_get_value(struct drm_output *output,  					 struct drm_property *property,  					 uint64_t *value);  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 void drm_framebuffer_set_object(struct drm_device *dev,  				       unsigned long handle);  extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);  extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);  extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);  extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); -extern int drm_crtc_set_config(struct drm_mode_set *set); -extern bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, -		       int x, int y); +extern void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY);  extern bool drm_crtc_in_use(struct drm_crtc *crtc); -extern int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, bool connected);  extern int drm_output_attach_property(struct drm_output *output,  				      struct drm_property *property, uint64_t init_val); diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c new file mode 100644 index 00000000..f776dbed --- /dev/null +++ b/linux-core/drm_crtc_helper.c @@ -0,0 +1,515 @@ + +/* + * Copyright (c) 2006-2007 Intel Corporation + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  The copyright holders make no representations + * about the suitability of this software for any purpose.  It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + *      Keith Packard + *	Eric Anholt <eric@anholt.net> + *      Dave Airlie <airlied@linux.ie> + *      Jesse Barnes <jesse.barnes@intel.com> + */ + +#include "drmP.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + + +/** + * drm_pick_crtcs - pick crtcs for output devices + * @dev: DRM device + * + * LOCKING: + * Caller must hold mode config lock. + */ +static void drm_pick_crtcs (struct drm_device *dev) +{ +	int c, o, assigned; +	struct drm_output *output, *output_equal; +	struct drm_crtc   *crtc; +	struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; +	int found; + +	list_for_each_entry(output, &dev->mode_config.output_list, head) { +       		output->crtc = NULL; +     +    		/* Don't hook up outputs that are disconnected ?? +		 * +		 * This is debateable. Do we want fixed /dev/fbX or +		 * dynamic on hotplug (need mode code for that though) ? +		 * +		 * If we don't hook up outputs now, then we only create +		 * /dev/fbX for the output that's enabled, that's good as +		 * the users console will be on that output. +		 * +		 * If we do hook up outputs that are disconnected now, then +		 * the user may end up having to muck about with the fbcon +		 * map flags to assign his console to the enabled output. Ugh. +		 */ +    		if (output->status != output_status_connected) +			continue; + +		if (list_empty(&output->modes)) +			continue; + +		des_mode = NULL; +		found = 0; +		list_for_each_entry(des_mode, &output->modes, head) { +			if (des_mode->type & DRM_MODE_TYPE_PREFERRED) { +				found = 1; +				break; +			} +		} + +		/* No preferred mode, let's just select the first available */ +		if (!found) { +			des_mode = NULL; +			list_for_each_entry(des_mode, &output->modes, head) { +				break; +			} +		} + +		c = -1; +		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +			assigned = 0; + +			c++; +			if ((output->possible_crtcs & (1 << c)) == 0) +		    		continue; +	 +			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { +				if (output->id == output_equal->id) +					continue; + +				/* Find out if crtc has been assigned before */ +				if (output_equal->crtc == crtc) +					assigned = 1; +			} + +#if 1 /* continue for now */ +			if (assigned) +				continue; +#endif + +			o = -1; +			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { +				o++; +				if (output->id == output_equal->id) +					continue; + +				list_for_each_entry(modes, &output->modes, head) { +					list_for_each_entry(modes_equal, &output_equal->modes, head) { +						if (drm_mode_equal (modes, modes_equal)) { +							if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { +								printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones); +								des_mode = modes; +								assigned = 0; +								goto clone; +							} +						} +					} +				} +			} + +clone: +			/* crtc has been assigned skip it */ +			if (assigned) +				continue; + +			/* Found a CRTC to attach to, do it ! */ +			output->crtc = crtc; +			output->crtc->desired_mode = des_mode; +			output->initial_x = 0; +			output->initial_y = 0; +			DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name); +			break; +    		} +	} +} +EXPORT_SYMBOL(drm_pick_crtcs); + +/** + * drm_crtc_set_mode - set a mode + * @crtc: CRTC to program + * @mode: mode to use + * @x: width of mode + * @y: height of mode + * + * LOCKING: + * Caller must hold mode config lock. + * + * Try to set @mode on @crtc.  Give @crtc and its associated outputs a chance + * to fixup or reject the mode prior to trying to set it. + * + * RETURNS: + * True if the mode was set successfully, or false otherwise. + */ +bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, +			      int x, int y) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_display_mode *adjusted_mode, saved_mode; +	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +	struct drm_output_helper_funcs *output_funcs; +	int saved_x, saved_y; +	struct drm_output *output; +	bool ret = true; + +	adjusted_mode = drm_mode_duplicate(dev, mode); + +	crtc->enabled = drm_crtc_in_use(crtc); + +	if (!crtc->enabled) +		return true; + +	saved_mode = crtc->mode; +	saved_x = crtc->x; +	saved_y = crtc->y; +	 +	/* Update crtc values up front so the driver can rely on them for mode +	 * setting. +	 */ +	crtc->mode = *mode; +	crtc->x = x; +	crtc->y = y; + +	if (drm_mode_equal(&saved_mode, &crtc->mode)) { +		if (saved_x != crtc->x || saved_y != crtc->y) { +			crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y); +			goto done; +		} +	} + +	/* Pass our mode to the outputs and the CRTC to give them a chance to +	 * adjust it according to limitations or output properties, and also +	 * a chance to reject the mode entirely. +	 */ +	list_for_each_entry(output, &dev->mode_config.output_list, head) { +		 +		if (output->crtc != crtc) +			continue; +		output_funcs = output->helper_private; +		if (!(ret = output_funcs->mode_fixup(output, mode, adjusted_mode))) { +			goto done; +		} +	} +	 +	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { +		goto done; +	} + +	/* Prepare the outputs and CRTCs before setting the mode. */ +	list_for_each_entry(output, &dev->mode_config.output_list, head) { + +		if (output->crtc != crtc) +			continue; +		output_funcs = output->helper_private; +		/* Disable the output as the first thing we do. */ +		output_funcs->prepare(output); +	} +	 +	crtc_funcs->prepare(crtc); +	 +	/* Set up the DPLL and any output state that needs to adjust or depend +	 * on the DPLL. +	 */ +	crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y); + +	list_for_each_entry(output, &dev->mode_config.output_list, head) { + +		if (output->crtc != crtc) +			continue; +		 +		DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id); +		output_funcs = output->helper_private; +		output_funcs->mode_set(output, mode, adjusted_mode); +	} +	 +	/* Now, enable the clocks, plane, pipe, and outputs that we set up. */ +	crtc_funcs->commit(crtc); + +	list_for_each_entry(output, &dev->mode_config.output_list, head) { + +		if (output->crtc != crtc) +			continue; + +		output_funcs = output->helper_private;		 +		output_funcs->commit(output); + +#if 0 // TODO def RANDR_12_INTERFACE +		if (output->randr_output) +			RRPostPendingProperties (output->randr_output); +#endif +	} +	 +	/* XXX free adjustedmode */ +	drm_mode_destroy(dev, adjusted_mode); +	/* TODO */ +//	if (scrn->pScreen) +//		drm_crtc_set_screen_sub_pixel_order(dev); + +done: +	if (!ret) {  +		crtc->mode = saved_mode; +		crtc->x = saved_x; +		crtc->y = saved_y; +	} + +	return ret; +} +EXPORT_SYMBOL(drm_crtc_helper_set_mode); + + +/** + * drm_crtc_helper_set_config - set a new config from userspace + * @crtc: CRTC to setup + * @crtc_info: user provided configuration + * @new_mode: new mode to set + * @output_set: set of outputs for the new config + * @fb: new framebuffer + * + * LOCKING: + * Caller must hold mode config lock. + * + * Setup a new configuration, provided by the user in @crtc_info, and enable + * it. + * + * RETURNS: + * Zero. (FIXME) + */ +int drm_crtc_helper_set_config(struct drm_mode_set *set) +{ +	struct drm_device *dev; +	struct drm_crtc **save_crtcs, *new_crtc; +	bool save_enabled; +	bool changed = false; +	bool flip_or_move = false; +	struct drm_output *output; +	int count = 0, ro; +	struct drm_crtc_helper_funcs *crtc_funcs; + +	DRM_DEBUG("\n"); + +	if (!set) +		return -EINVAL; + +	if (!set->crtc) +		return -EINVAL; + +	if (!set->crtc->helper_private) +		return -EINVAL; +	 +	crtc_funcs = set->crtc->helper_private; +        +	DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y); +	dev = set->crtc->dev; + +	/* save previous config */ +	save_enabled = set->crtc->enabled; + +	/* this is meant to be num_output not num_crtc */ +	save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL); +	if (!save_crtcs) +		return -ENOMEM; + +	/* We should be able to check here if the fb has the same properties +	 * and then just flip_or_move it */ +	if (set->crtc->fb != set->fb) +		flip_or_move = true; + +	if (set->x != set->crtc->x || set->y != set->crtc->y) +		flip_or_move = true; + +	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { +		DRM_DEBUG("modes are different\n"); +		drm_mode_debug_printmodeline(&set->crtc->mode); +		drm_mode_debug_printmodeline(set->mode); +		changed = true; +	} + +	list_for_each_entry(output, &dev->mode_config.output_list, head) { +		save_crtcs[count++] = output->crtc; + +		if (output->crtc == set->crtc) +			new_crtc = NULL; +		else +			new_crtc = output->crtc; + +		for (ro = 0; ro < set->num_outputs; ro++) { +			if (set->outputs[ro] == output) +				new_crtc = set->crtc; +		} +		if (new_crtc != output->crtc) { +			changed = true; +			output->crtc = new_crtc; +		} +	} + +	/* mode_set_base is not a required function */ +	if (flip_or_move && !crtc_funcs->mode_set_base) +		changed = true; + +	if (changed) { +		set->crtc->fb = set->fb; +		set->crtc->enabled = (set->mode != NULL); +		if (set->mode != NULL) { +			DRM_DEBUG("attempting to set mode from userspace\n"); +			drm_mode_debug_printmodeline(set->mode); +			if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, +					       set->y)) { +				set->crtc->enabled = save_enabled; +				count = 0; +				list_for_each_entry(output, &dev->mode_config.output_list, head) +					output->crtc = save_crtcs[count++]; +				kfree(save_crtcs); +				return -EINVAL; +			} +			/* TODO are these needed? */ +			set->crtc->desired_x = set->x; +			set->crtc->desired_y = set->y; +			set->crtc->desired_mode = set->mode; +		} +		drm_disable_unused_functions(dev); +	} else if (flip_or_move) { +		if (set->crtc->fb != set->fb) +			set->crtc->fb = set->fb; +		crtc_funcs->mode_set_base(set->crtc, set->x, set->y); +	} + +	kfree(save_crtcs); +	return 0; +} +EXPORT_SYMBOL(drm_crtc_helper_set_config); + +/** + * drm_initial_config - setup a sane initial output configuration + * @dev: DRM device + * @can_grow: this configuration is growable + * + * LOCKING: + * Called at init time, must take mode config lock. + * + * 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 + * a new framebuffer object as the backing store. + * + * RETURNS: + * Zero if everything went ok, nonzero otherwise. + */ +bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) +{ +	struct drm_output *output; +	int ret = false; + +	mutex_lock(&dev->mode_config.mutex); + +	drm_crtc_probe_output_modes(dev, 2048, 2048); + +	drm_pick_crtcs(dev); + +	/* This is a little screwy, as we've already walked the outputs  +	 * above, but it's a little bit of magic too. There's the potential +	 * for things not to get setup above if an existing device gets +	 * re-assigned thus confusing the hardware. By walking the outputs +	 * this fixes up their crtc's. +	 */ +	list_for_each_entry(output, &dev->mode_config.output_list, head) { + +		/* can't setup the output if there's no assigned mode */ +		if (!output->crtc || !output->crtc->desired_mode) +			continue; + +		dev->driver->fb_probe(dev, output->crtc, output); + +		/* and needs an attached fb */ +		if (output->crtc->fb) +			drm_crtc_helper_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); +	} + +	drm_disable_unused_functions(dev); + +	mutex_unlock(&dev->mode_config.mutex); +	return ret; +} +EXPORT_SYMBOL(drm_helper_initial_config); + +/** + * drm_hotplug_stage_two + * @dev DRM device + * @output hotpluged output + * + * LOCKING. + * Caller must hold mode config lock, function might grab struct lock. + * + * Stage two of a hotplug. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, +				 bool connected) +{ +	int has_config = 0; + +	dev->mode_config.hotplug_counter++; + +	/* We might want to do something more here */ +	if (!connected) { +		DRM_DEBUG("not connected\n"); +		return 0; +	} + +	if (output->crtc && output->crtc->desired_mode) { +		DRM_DEBUG("drm thinks that the output already has a config\n"); +		has_config = 1; +	} + +	drm_crtc_probe_output_modes(dev, 2048, 2048); + +	if (!has_config) +		drm_pick_crtcs(dev); + +	if (!output->crtc || !output->crtc->desired_mode) { +		DRM_DEBUG("could not find a desired mode or crtc for output\n"); +		return 1; +	} + +	/* We should really check if there is a fb using this crtc */ +	if (!has_config) +		dev->driver->fb_probe(dev, output->crtc, output); +	else { +		dev->driver->fb_resize(dev, output->crtc); + +#if 0 +		if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) +			DRM_ERROR("failed to set mode after hotplug\n"); +#endif +	} + +	drm_sysfs_hotplug_event(dev); + +	drm_disable_unused_functions(dev); + +	return 0; +} +EXPORT_SYMBOL(drm_helper_hotplug_stage_two); diff --git a/linux-core/drm_crtc_helper.h b/linux-core/drm_crtc_helper.h new file mode 100644 index 00000000..f56b97c6 --- /dev/null +++ b/linux-core/drm_crtc_helper.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2006 Keith Packard + * Copyright © 2007 Intel Corporation + *   Jesse Barnes <jesse.barnes@intel.com> + */ + +/* + * The DRM mode setting helper functions are common code for drivers to use if they wish. + * Drivers are not forced to use this code in their implementations but it would be useful + * if they code they do use at least provides a consistent interface and operation to userspace + */ + +#ifndef __DRM_CRTC_HELPER_H__ +#define __DRM_CRTC_HELPER_H__ + +#include <linux/i2c.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/idr.h> + +#include <linux/fb.h> + +struct drm_crtc_helper_funcs { +  	void (*prepare)(struct drm_crtc *crtc); +	void (*commit)(struct drm_crtc *crtc); + +	/* Provider can fixup or change mode timings before modeset occurs */ +	bool (*mode_fixup)(struct drm_crtc *crtc, +			   struct drm_display_mode *mode, +			   struct drm_display_mode *adjusted_mode); +	/* Actually set the mode */ +	void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, +			 struct drm_display_mode *adjusted_mode, int x, int y); + +	/* Move the crtc on the current fb to the given position *optional* */ +	void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); +}; + +struct drm_output_helper_funcs { +	bool (*mode_fixup)(struct drm_output *output, +			   struct drm_display_mode *mode, +			   struct drm_display_mode *adjusted_mode); +	void (*prepare)(struct drm_output *output); +	void (*commit)(struct drm_output *output); +	void (*mode_set)(struct drm_output *output, +			 struct drm_display_mode *mode, +			 struct drm_display_mode *adjusted_mode); +}; + +extern int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, +					bool connected); +extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); +extern int drm_crtc_helper_set_config(struct drm_mode_set *set); +extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, +				     int x, int y); + +static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs) +{ +	crtc->helper_private = (void *)funcs; +} + +static inline void drm_output_helper_add(struct drm_output *output, const struct drm_output_helper_funcs *funcs) +{ +	output->helper_private = (void *)funcs; +} + + + +#endif diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c index ef40871e..3c5dae1a 100644 --- a/linux-core/intel_crt.c +++ b/linux-core/intel_crt.c @@ -28,6 +28,7 @@  #include "drmP.h"  #include "drm.h"  #include "drm_crtc.h" +#include "drm_crtc_helper.h"  #include "intel_drv.h"  #include "i915_drm.h"  #include "i915_drv.h" @@ -220,19 +221,24 @@ static bool intel_crt_set_property(struct drm_output *output,  /*   * Routines for controlling stuff on the analog port   */ + +static const struct drm_output_helper_funcs intel_crt_helper_funcs = { +	.mode_fixup = intel_crt_mode_fixup, +	.prepare = intel_output_prepare, +	.commit = intel_output_commit, +	.mode_set = intel_crt_mode_set, +}; +  static const struct drm_output_funcs intel_crt_output_funcs = {  	.dpms = intel_crt_dpms,  	.save = intel_crt_save,  	.restore = intel_crt_restore, -	.mode_valid = intel_crt_mode_valid, -	.mode_fixup = intel_crt_mode_fixup, -	.prepare = intel_output_prepare, -	.mode_set = intel_crt_mode_set, -	.commit = intel_output_commit,  	.detect = intel_crt_detect,  	.get_modes = intel_crt_get_modes,  	.cleanup = intel_crt_destroy,  	.set_property = intel_crt_set_property, +	.mode_valid = intel_crt_mode_valid, +  };  void intel_crt_init(struct drm_device *dev) @@ -261,6 +267,7 @@ void intel_crt_init(struct drm_device *dev)  	output->interlace_allowed = 0;  	output->doublescan_allowed = 0; +	drm_output_helper_add(output, &intel_crt_helper_funcs);  	drm_sysfs_output_add(output);  	drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorVGA); diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index e7162c2c..a2307a3d 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -30,6 +30,8 @@  #include "i915_drm.h"  #include "i915_drv.h" +#include "drm_crtc_helper.h" +  bool intel_pipe_has_type (struct drm_crtc *crtc, int type);  typedef struct { @@ -1090,6 +1092,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,  	struct drm_crtc *possible_crtc;  	struct drm_crtc *supported_crtc =NULL;  	struct drm_crtc *crtc = NULL; +	struct drm_output_helper_funcs *output_funcs;  	int i = -1;  	/* @@ -1147,14 +1150,15 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,  	if (!crtc->enabled) {  		if (!mode)  			mode = &load_detect_mode; -		drm_crtc_set_mode(crtc, mode, 0, 0); +		drm_crtc_helper_set_mode(crtc, mode, 0, 0);  	} else {  		if (intel_crtc->dpms_mode != DPMSModeOn)  			crtc->funcs->dpms(crtc, DPMSModeOn); +		output_funcs = output->helper_private;  		/* Add this output to the crtc */ -		output->funcs->mode_set(output, &crtc->mode, &crtc->mode); -		output->funcs->commit(output); +		output_funcs->mode_set(output, &crtc->mode, &crtc->mode); +		output_funcs->commit(output);  	}  	/* let the output get through one full cycle before testing */  	intel_wait_for_vblank(dev); @@ -1293,16 +1297,20 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,  	return mode;  } -static const struct drm_crtc_funcs intel_crtc_funcs = { -	.dpms = intel_crtc_dpms, +static const struct drm_crtc_helper_funcs intel_helper_funcs = {  	.mode_fixup = intel_crtc_mode_fixup,  	.mode_set = intel_crtc_mode_set,  	.mode_set_base = intel_pipe_set_base, +	.prepare = intel_crtc_prepare, +	.commit = intel_crtc_commit, +}; + +static const struct drm_crtc_funcs intel_crtc_funcs = { +	.dpms = intel_crtc_dpms,  	.cursor_set = intel_crtc_cursor_set,  	.cursor_move = intel_crtc_cursor_move,  	.gamma_set = intel_crtc_gamma_set, -	.prepare = intel_crtc_prepare, -	.commit = intel_crtc_commit, +	.set_config = drm_crtc_helper_set_config,  }; @@ -1331,6 +1339,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe)  	intel_crtc->cursor_addr = 0;  	intel_crtc->dpms_mode = DPMSModeOff; +	drm_crtc_helper_add(crtc, &intel_helper_funcs);  	crtc->driver_private = intel_crtc;  } @@ -1418,6 +1427,10 @@ static void intel_setup_outputs(struct drm_device *dev)  	}  } +static const struct drm_mode_config_funcs intel_mode_funcs = { +	.resize_fb = NULL, +}; +  void intel_modeset_init(struct drm_device *dev)  {  	int num_pipe; @@ -1428,6 +1441,8 @@ void intel_modeset_init(struct drm_device *dev)  	dev->mode_config.min_width = 0;  	dev->mode_config.min_height = 0; +	dev->mode_config.funcs = (void *)&intel_mode_funcs; +  	if (IS_I965G(dev)) {  		dev->mode_config.max_width = 8192;  		dev->mode_config.max_height = 8192; diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index e97117de..9f8ca8dd 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -11,6 +11,7 @@  #include <linux/i2c-algo-bit.h>  #include "drm_crtc.h" +#include "drm_crtc_helper.h"  /*   * Display related stuff   */ diff --git a/linux-core/intel_dvo.c b/linux-core/intel_dvo.c index 6f319107..5a7da276 100644 --- a/linux-core/intel_dvo.c +++ b/linux-core/intel_dvo.c @@ -325,19 +325,21 @@ static struct drm_crtc *intel_dvo_get_crtc(struct drm_output *output)  }  #endif +static const struct drm_output_helper_funcs intel_dvo_helper_funcs = { +	.mode_fixup = intel_dvo_mode_fixup, +	.prepare = intel_output_prepare, +	.mode_set = intel_dvo_mode_set, +	.commit = intel_output_commit, +};  static const struct drm_output_funcs intel_dvo_output_funcs = {  	.dpms = intel_dvo_dpms,  	.save = intel_dvo_save,  	.restore = intel_dvo_restore, -	.mode_valid = intel_dvo_mode_valid, -	.mode_fixup = intel_dvo_mode_fixup, -	.prepare = intel_output_prepare, -	.mode_set = intel_dvo_mode_set, -	.commit = intel_output_commit,  	.detect = intel_dvo_detect,  	.get_modes = intel_dvo_get_modes, -	.cleanup = intel_dvo_destroy +	.cleanup = intel_dvo_destroy, +	.mode_valid = intel_dvo_mode_valid,  };  /** @@ -457,6 +459,7 @@ void intel_dvo_init(struct drm_device *dev)  			goto free_i2c;  		} +		drm_output_helper_add(output, &intel_dvo_helper_funcs);  		output->driver_private = intel_output;  		output->display_info.subpixel_order = SubPixelHorizontalRGB;  		output->interlace_allowed = false; diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 4f5a0000..05fc3b29 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -341,7 +341,7 @@ static int intelfb_set_par(struct fb_info *info)  	return 0;  #else -	return drm_crtc_set_config(&par->set); +	return par->set.crtc->funcs->set_config(&par->set);  #endif  } @@ -496,11 +496,11 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var,  	struct intelfb_par *par = info->par;  	int ret;  	DRM_DEBUG("\n"); - +	  	par->set.x = var->xoffset;  	par->set.y = var->yoffset; -	ret = drm_crtc_set_config(&par->set); +	ret = par->set.crtc->funcs->set_config(&par->set);  	if (!ret) {  		info->var.xoffset = var->xoffset; diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c index 6b6d3162..f71dd436 100644 --- a/linux-core/intel_lvds.c +++ b/linux-core/intel_lvds.c @@ -332,18 +332,21 @@ static void intel_lvds_destroy(struct drm_output *output)  	kfree(output->driver_private);  } -static const struct drm_output_funcs intel_lvds_output_funcs = { -	.dpms = intel_lvds_dpms, -	.save = intel_lvds_save, -	.restore = intel_lvds_restore, -	.mode_valid = intel_lvds_mode_valid, +static const struct drm_output_helper_funcs intel_lvds_helper_funcs = {  	.mode_fixup = intel_lvds_mode_fixup,  	.prepare = intel_lvds_prepare,  	.mode_set = intel_lvds_mode_set,  	.commit = intel_lvds_commit, +}; + +static const struct drm_output_funcs intel_lvds_output_funcs = { +	.dpms = intel_lvds_dpms, +	.save = intel_lvds_save, +	.restore = intel_lvds_restore,  	.detect = intel_lvds_detect,  	.get_modes = intel_lvds_get_modes, -	.cleanup = intel_lvds_destroy +	.cleanup = intel_lvds_destroy, +	.mode_valid = intel_lvds_mode_valid,  };  /** @@ -375,6 +378,7 @@ void intel_lvds_init(struct drm_device *dev)  	}  	intel_output->type = INTEL_OUTPUT_LVDS; +	drm_output_helper_add(output, &intel_lvds_helper_funcs);  	output->driver_private = intel_output;  	output->display_info.subpixel_order = SubPixelHorizontalRGB;  	output->interlace_allowed = FALSE; diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index ba6fe9a8..41da034d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -972,18 +972,21 @@ static void intel_sdvo_destroy(struct drm_output *output)  	}  } -static const struct drm_output_funcs intel_sdvo_output_funcs = { -	.dpms = intel_sdvo_dpms, -	.save = intel_sdvo_save, -	.restore = intel_sdvo_restore, -	.mode_valid = intel_sdvo_mode_valid, +static const struct drm_output_helper_funcs intel_sdvo_helper_funcs = {  	.mode_fixup = intel_sdvo_mode_fixup,  	.prepare = intel_output_prepare,  	.mode_set = intel_sdvo_mode_set,  	.commit = intel_output_commit, +}; + +static const struct drm_output_funcs intel_sdvo_output_funcs = { +	.dpms = intel_sdvo_dpms, +	.save = intel_sdvo_save, +	.restore = intel_sdvo_restore,  	.detect = intel_sdvo_detect,  	.get_modes = intel_sdvo_get_modes, -	.cleanup = intel_sdvo_destroy +	.cleanup = intel_sdvo_destroy, +	.mode_valid = intel_sdvo_mode_valid,  };  void intel_sdvo_init(struct drm_device *dev, int output_device) @@ -1010,6 +1013,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)  	sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);  	intel_output->type = INTEL_OUTPUT_SDVO; +	drm_output_helper_add(output, &intel_sdvo_helper_funcs);  	output->driver_private = intel_output;  	output->interlace_allowed = 0;  	output->doublescan_allowed = 0; diff --git a/linux-core/intel_tv.c b/linux-core/intel_tv.c index 650c46f7..18fb1f37 100644 --- a/linux-core/intel_tv.c +++ b/linux-core/intel_tv.c @@ -1590,15 +1590,18 @@ out:  	return ret;  } +static const struct drm_output_helper_funcs intel_tv_helper_funcs = { +	.mode_fixup = intel_tv_mode_fixup, +	.prepare = intel_output_prepare, +	.mode_set = intel_tv_mode_set, +	.commit = intel_output_commit, +}; +  static const struct drm_output_funcs intel_tv_output_funcs = {  	.dpms = intel_tv_dpms,  	.save = intel_tv_save,  	.restore = intel_tv_restore,  	.mode_valid = intel_tv_mode_valid, -	.mode_fixup = intel_tv_mode_fixup, -	.prepare = intel_output_prepare, -	.mode_set = intel_tv_mode_set, -	.commit = intel_output_commit,  	.detect = intel_tv_detect,  	.get_modes = intel_tv_get_modes,  	.cleanup = intel_tv_destroy, @@ -1674,6 +1677,7 @@ intel_tv_init(struct drm_device *dev)  	tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL); +	drm_output_helper_add(output, &intel_tv_helper_funcs);  	output->driver_private = intel_output;  	output->interlace_allowed = FALSE;  	output->doublescan_allowed = FALSE; diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index bda15e01..f03f8949 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -13,6 +13,7 @@  #include "i915_drm.h"  #include "i915_drv.h"  #include "intel_bios.h" +#include "intel_drv.h"  /**   * i915_probe_agp - get AGP bootup configuration @@ -232,7 +233,7 @@ int i915_load_modeset_init(struct drm_device *dev)  	}  	intel_modeset_init(dev); -	drm_initial_config(dev, false); +	drm_helper_initial_config(dev, false);  	drm_mm_print(&dev->bm.man[DRM_BO_MEM_VRAM].manager, "VRAM");  	drm_mm_print(&dev->bm.man[DRM_BO_MEM_TT].manager, "TT"); diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 592e881b..ccedc70e 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -31,6 +31,7 @@  #include "i915_drm.h"  #include "i915_drv.h"  #include "intel_drv.h" +#include "drm_crtc_helper.h"  #define MAX_NOPID ((u32)~0) @@ -471,8 +472,8 @@ static void i915_hotplug_tv(struct drm_device *dev)  		goto unlock;  	status = output->funcs->detect(output); -	drm_hotplug_stage_two(dev, output, -			      status == output_status_connected ? 1 : 0); +	drm_helper_hotplug_stage_two(dev, output, +				     status == output_status_connected ? 1 : 0);  unlock:  	mutex_unlock(&dev->mode_config.mutex); @@ -497,7 +498,7 @@ static void i915_hotplug_crt(struct drm_device *dev, bool isconnected)  	if (iout == 0)  		goto unlock; -	drm_hotplug_stage_two(dev, output, isconnected); +	drm_helper_hotplug_stage_two(dev, output, isconnected);  unlock:  	mutex_unlock(&dev->mode_config.mutex); @@ -518,9 +519,9 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)  	status = output->funcs->detect(output);  	if (status != output_status_connected) -		drm_hotplug_stage_two(dev, output, false); +		drm_helper_hotplug_stage_two(dev, output, false);  	else -		drm_hotplug_stage_two(dev, output, true); +		drm_helper_hotplug_stage_two(dev, output, true);  	intel_sdvo_set_hotplug(output, 1); | 
