Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0ee755f authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel into drm-next

So small drm stuff all over for 3.18. Biggest one is the cmdline parsing
from Chris with a few fixes from me to make it work for stupid kernel
configs.

Plus the atomic prep series.

Tested for more than a week in -nightly and Ville/Imre indeed discovered
some fun which is now fixed (and i915 vblank patches postponed since the
fixups need this branch plus drm-intel-next merged together).

* tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel:
  drm: Use the type of the array element when reallocating
  drm: Don't return 0 for a value used as a denominator
  drm: Docbook fixes
  drm/irq: Implement a generic vblank_wait function
  drm: Add a plane->reset hook
  drm: trylock modest locking for fbdev panics
  drm: Move ->old_fb from crtc to plane
  drm: Handle legacy per-crtc locking with full acquire ctx
  drm: Move modeset_lock_all helpers to drm_modeset_lock.[hc]
  drm: Add drm_plane/connector_index
  drm: idiot-proof vblank
  drm: Warn when leaking flip events on close
  drm: Perform cmdline mode parsing during connector initialisation
  video/fbdev: Always built-in video= cmdline parsing
  drm: Don't grab an fb reference for the idr
parents 52addcf9 14f476fa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ menuconfig DRM
	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
	depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
	select HDMI
	select FB_CMDLINE
	select I2C
	select I2C_ALGOBIT
	select DMA_SHARED_BUFFER
+165 −141
Original line number Diff line number Diff line
@@ -45,101 +45,6 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
							struct drm_mode_fb_cmd2 *r,
							struct drm_file *file_priv);

/**
 * drm_modeset_lock_all - take all modeset locks
 * @dev: drm device
 *
 * This function takes all modeset locks, suitable where a more fine-grained
 * scheme isn't (yet) implemented. Locks must be dropped with
 * drm_modeset_unlock_all.
 */
void drm_modeset_lock_all(struct drm_device *dev)
{
	struct drm_mode_config *config = &dev->mode_config;
	struct drm_modeset_acquire_ctx *ctx;
	int ret;

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (WARN_ON(!ctx))
		return;

	mutex_lock(&config->mutex);

	drm_modeset_acquire_init(ctx, 0);

retry:
	ret = drm_modeset_lock(&config->connection_mutex, ctx);
	if (ret)
		goto fail;
	ret = drm_modeset_lock_all_crtcs(dev, ctx);
	if (ret)
		goto fail;

	WARN_ON(config->acquire_ctx);

	/* now we hold the locks, so now that it is safe, stash the
	 * ctx for drm_modeset_unlock_all():
	 */
	config->acquire_ctx = ctx;

	drm_warn_on_modeset_not_all_locked(dev);

	return;

fail:
	if (ret == -EDEADLK) {
		drm_modeset_backoff(ctx);
		goto retry;
	}
}
EXPORT_SYMBOL(drm_modeset_lock_all);

/**
 * drm_modeset_unlock_all - drop all modeset locks
 * @dev: device
 *
 * This function drop all modeset locks taken by drm_modeset_lock_all.
 */
void drm_modeset_unlock_all(struct drm_device *dev)
{
	struct drm_mode_config *config = &dev->mode_config;
	struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;

	if (WARN_ON(!ctx))
		return;

	config->acquire_ctx = NULL;
	drm_modeset_drop_locks(ctx);
	drm_modeset_acquire_fini(ctx);

	kfree(ctx);

	mutex_unlock(&dev->mode_config.mutex);
}
EXPORT_SYMBOL(drm_modeset_unlock_all);

/**
 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
 * @dev: device
 *
 * Useful as a debug assert.
 */
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
{
	struct drm_crtc *crtc;

	/* Locking is currently fubar in the panic handler. */
	if (oops_in_progress)
		return;

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));

	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
}
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);

/* Avoid boilerplate.  I'm tired of typing. */
#define DRM_ENUM_NAME_FN(fnname, list)				\
	const char *fnname(int val)				\
@@ -515,9 +420,6 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
	if (ret)
		goto out;

	/* Grab the idr reference. */
	drm_framebuffer_reference(fb);

	dev->mode_config.num_fb++;
	list_add(&fb->head, &dev->mode_config.fb_list);
out:
@@ -527,10 +429,34 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
}
EXPORT_SYMBOL(drm_framebuffer_init);

/* dev->mode_config.fb_lock must be held! */
static void __drm_framebuffer_unregister(struct drm_device *dev,
					 struct drm_framebuffer *fb)
{
	mutex_lock(&dev->mode_config.idr_mutex);
	idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
	mutex_unlock(&dev->mode_config.idr_mutex);

	fb->base.id = 0;
}

static void drm_framebuffer_free(struct kref *kref)
{
	struct drm_framebuffer *fb =
			container_of(kref, struct drm_framebuffer, refcount);
	struct drm_device *dev = fb->dev;

	/*
	 * The lookup idr holds a weak reference, which has not necessarily been
	 * removed at this point. Check for that.
	 */
	mutex_lock(&dev->mode_config.fb_lock);
	if (fb->base.id) {
		/* Mark fb as reaped and drop idr ref. */
		__drm_framebuffer_unregister(dev, fb);
	}
	mutex_unlock(&dev->mode_config.fb_lock);

	fb->funcs->destroy(fb);
}

@@ -567,8 +493,10 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,

	mutex_lock(&dev->mode_config.fb_lock);
	fb = __drm_framebuffer_lookup(dev, id);
	if (fb)
		drm_framebuffer_reference(fb);
	if (fb) {
		if (!kref_get_unless_zero(&fb->refcount))
			fb = NULL;
	}
	mutex_unlock(&dev->mode_config.fb_lock);

	return fb;
@@ -612,19 +540,6 @@ static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
	kref_put(&fb->refcount, drm_framebuffer_free_bug);
}

/* dev->mode_config.fb_lock must be held! */
static void __drm_framebuffer_unregister(struct drm_device *dev,
					 struct drm_framebuffer *fb)
{
	mutex_lock(&dev->mode_config.idr_mutex);
	idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
	mutex_unlock(&dev->mode_config.idr_mutex);

	fb->base.id = 0;

	__drm_framebuffer_unreference(fb);
}

/**
 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
 * @fb: fb to unregister
@@ -852,6 +767,59 @@ static void drm_mode_remove(struct drm_connector *connector,
	drm_mode_destroy(connector->dev, mode);
}

/**
 * drm_connector_get_cmdline_mode - reads the user's cmdline mode
 * @connector: connector to quwery
 * @mode: returned mode
 *
 * The kernel supports per-connector configration of its consoles through
 * use of the video= parameter. This function parses that option and
 * extracts the user's specified mode (or enable/disable status) for a
 * particular connector. This is typically only used during the early fbdev
 * setup.
 */
static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
{
	struct drm_cmdline_mode *mode = &connector->cmdline_mode;
	char *option = NULL;

	if (fb_get_options(connector->name, &option))
		return;

	if (!drm_mode_parse_command_line_for_connector(option,
						       connector,
						       mode))
		return;

	if (mode->force) {
		const char *s;

		switch (mode->force) {
		case DRM_FORCE_OFF:
			s = "OFF";
			break;
		case DRM_FORCE_ON_DIGITAL:
			s = "ON - dig";
			break;
		default:
		case DRM_FORCE_ON:
			s = "ON";
			break;
		}

		DRM_INFO("forcing %s connector %s\n", connector->name, s);
		connector->force = mode->force;
	}

	DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
		      connector->name,
		      mode->xres, mode->yres,
		      mode->refresh_specified ? mode->refresh : 60,
		      mode->rb ? " reduced blanking" : "",
		      mode->margins ? " with margins" : "",
		      mode->interlace ?  " interlaced" : "");
}

/**
 * drm_connector_init - Init a preallocated connector
 * @dev: DRM device
@@ -904,6 +872,8 @@ int drm_connector_init(struct drm_device *dev,
	connector->edid_blob_ptr = NULL;
	connector->status = connector_status_unknown;

	drm_connector_get_cmdline_mode(connector);

	list_add_tail(&connector->head, &dev->mode_config.connector_list);
	dev->mode_config.num_connector++;

@@ -956,6 +926,29 @@ void drm_connector_cleanup(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_connector_cleanup);

/**
 * drm_connector_index - find the index of a registered connector
 * @connector: connector to find index for
 *
 * Given a registered connector, return the index of that connector within a DRM
 * device's list of connectors.
 */
unsigned int drm_connector_index(struct drm_connector *connector)
{
	unsigned int index = 0;
	struct drm_connector *tmp;

	list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
		if (tmp == connector)
			return index;

		index++;
	}

	BUG();
}
EXPORT_SYMBOL(drm_connector_index);

/**
 * drm_connector_register - register a connector
 * @connector: the connector to register
@@ -1260,6 +1253,29 @@ void drm_plane_cleanup(struct drm_plane *plane)
}
EXPORT_SYMBOL(drm_plane_cleanup);

/**
 * drm_plane_index - find the index of a registered plane
 * @plane: plane to find index for
 *
 * Given a registered plane, return the index of that CRTC within a DRM
 * device's list of planes.
 */
unsigned int drm_plane_index(struct drm_plane *plane)
{
	unsigned int index = 0;
	struct drm_plane *tmp;

	list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
		if (tmp == plane)
			return index;

		index++;
	}

	BUG();
}
EXPORT_SYMBOL(drm_plane_index);

/**
 * drm_plane_force_disable - Forcibly disable a plane
 * @plane: plane to disable
@@ -1271,19 +1287,21 @@ EXPORT_SYMBOL(drm_plane_cleanup);
 */
void drm_plane_force_disable(struct drm_plane *plane)
{
	struct drm_framebuffer *old_fb = plane->fb;
	int ret;

	if (!old_fb)
	if (!plane->fb)
		return;

	plane->old_fb = plane->fb;
	ret = plane->funcs->disable_plane(plane);
	if (ret) {
		DRM_ERROR("failed to disable plane with busy fb\n");
		plane->old_fb = NULL;
		return;
	}
	/* disconnect the plane from the fb and crtc: */
	__drm_framebuffer_unreference(old_fb);
	__drm_framebuffer_unreference(plane->old_fb);
	plane->old_fb = NULL;
	plane->fb = NULL;
	plane->crtc = NULL;
}
@@ -2259,23 +2277,21 @@ static int setplane_internal(struct drm_plane *plane,
			     uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = plane->dev;
	struct drm_framebuffer *old_fb = NULL;
	int ret = 0;
	unsigned int fb_width, fb_height;
	int i;

	drm_modeset_lock_all(dev);
	/* No fb means shut it down */
	if (!fb) {
		drm_modeset_lock_all(dev);
		old_fb = plane->fb;
		plane->old_fb = plane->fb;
		ret = plane->funcs->disable_plane(plane);
		if (!ret) {
			plane->crtc = NULL;
			plane->fb = NULL;
		} else {
			old_fb = NULL;
			plane->old_fb = NULL;
		}
		drm_modeset_unlock_all(dev);
		goto out;
	}

@@ -2315,8 +2331,7 @@ static int setplane_internal(struct drm_plane *plane,
		goto out;
	}

	drm_modeset_lock_all(dev);
	old_fb = plane->fb;
	plane->old_fb = plane->fb;
	ret = plane->funcs->update_plane(plane, crtc, fb,
					 crtc_x, crtc_y, crtc_w, crtc_h,
					 src_x, src_y, src_w, src_h);
@@ -2325,15 +2340,16 @@ static int setplane_internal(struct drm_plane *plane,
		plane->fb = fb;
		fb = NULL;
	} else {
		old_fb = NULL;
		plane->old_fb = NULL;
	}
	drm_modeset_unlock_all(dev);

out:
	if (fb)
		drm_framebuffer_unreference(fb);
	if (old_fb)
		drm_framebuffer_unreference(old_fb);
	if (plane->old_fb)
		drm_framebuffer_unreference(plane->old_fb);
	plane->old_fb = NULL;
	drm_modeset_unlock_all(dev);

	return ret;

@@ -2440,7 +2456,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
	 * crtcs. Atomic modeset will have saner semantics ...
	 */
	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
		tmp->old_fb = tmp->primary->fb;
		tmp->primary->old_fb = tmp->primary->fb;

	fb = set->fb;

@@ -2453,8 +2469,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
		if (tmp->primary->fb)
			drm_framebuffer_reference(tmp->primary->fb);
		if (tmp->old_fb)
			drm_framebuffer_unreference(tmp->old_fb);
		if (tmp->primary->old_fb)
			drm_framebuffer_unreference(tmp->primary->old_fb);
		tmp->primary->old_fb = NULL;
	}

	return ret;
@@ -2785,7 +2802,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
	if (crtc->cursor)
		return drm_mode_cursor_universal(crtc, req, file_priv);

	drm_modeset_lock(&crtc->mutex, NULL);
	drm_modeset_lock_crtc(crtc);
	if (req->flags & DRM_MODE_CURSOR_BO) {
		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
			ret = -ENXIO;
@@ -2809,7 +2826,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
		}
	}
out:
	drm_modeset_unlock(&crtc->mutex);
	drm_modeset_unlock_crtc(crtc);

	return ret;

@@ -3495,9 +3512,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
 * @flags: flags specifying the property type
 * @name: name of the property
 * @props: enumeration lists with property bitflags
 * @num_values: number of pre-defined values
 * @num_props: size of the @props array
 * @supported_bits: bitmask of all supported enumeration values
 *
 * This creates a new generic drm property which can then be attached to a drm
 * This creates a new bitmask drm property which can then be attached to a drm
 * object with drm_object_attach_property. The returned property object must be
 * freed with drm_property_destroy.
 *
@@ -4529,7 +4547,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
{
	struct drm_mode_crtc_page_flip *page_flip = data;
	struct drm_crtc *crtc;
	struct drm_framebuffer *fb = NULL, *old_fb = NULL;
	struct drm_framebuffer *fb = NULL;
	struct drm_pending_vblank_event *e = NULL;
	unsigned long flags;
	int ret = -EINVAL;
@@ -4545,7 +4563,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
	if (!crtc)
		return -ENOENT;

	drm_modeset_lock(&crtc->mutex, NULL);
	drm_modeset_lock_crtc(crtc);
	if (crtc->primary->fb == NULL) {
		/* The framebuffer is currently unbound, presumably
		 * due to a hotplug event, that userspace has not
@@ -4601,7 +4619,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
			(void (*) (struct drm_pending_event *)) kfree;
	}

	old_fb = crtc->primary->fb;
	crtc->primary->old_fb = crtc->primary->fb;
	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
	if (ret) {
		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4611,7 +4629,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
			kfree(e);
		}
		/* Keep the old fb, don't unref it. */
		old_fb = NULL;
		crtc->primary->old_fb = NULL;
	} else {
		/*
		 * Warn if the driver hasn't properly updated the crtc->fb
@@ -4627,9 +4645,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
out:
	if (fb)
		drm_framebuffer_unreference(fb);
	if (old_fb)
		drm_framebuffer_unreference(old_fb);
	drm_modeset_unlock(&crtc->mutex);
	if (crtc->primary->old_fb)
		drm_framebuffer_unreference(crtc->primary->old_fb);
	crtc->primary->old_fb = NULL;
	drm_modeset_unlock_crtc(crtc);

	return ret;
}
@@ -4645,9 +4664,14 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
void drm_mode_config_reset(struct drm_device *dev)
{
	struct drm_crtc *crtc;
	struct drm_plane *plane;
	struct drm_encoder *encoder;
	struct drm_connector *connector;

	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
		if (plane->funcs->reset)
			plane->funcs->reset(plane);

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		if (crtc->funcs->reset)
			crtc->funcs->reset(crtc);
+2 −1
Original line number Diff line number Diff line
@@ -1772,7 +1772,7 @@ static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
	case DP_LINK_BW_5_4:
		return 10 * dp_link_count;
	}
	return 0;
	BUG();
}

/**
@@ -2071,6 +2071,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
 * @mgr: manager to notify irq for.
 * @esi: 4 bytes from SINK_COUNT_ESI
 * @handled: whether the hpd interrupt was consumed or not
 *
 * This should be called from the driver when it detects a short IRQ,
 * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
+1 −1
Original line number Diff line number Diff line
@@ -3433,10 +3433,10 @@ EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
/**
 * drm_assign_hdmi_deep_color_info - detect whether monitor supports
 * hdmi deep color modes and update drm_display_info if so.
 *
 * @edid: monitor EDID information
 * @info: Updated with maximum supported deep color bpc and color format
 *        if deep color supported.
 * @connector: DRM connector, used only for debug output
 *
 * Parse the CEA extension according to CEA-861-B.
 * Return true if HDMI deep color supported, false if not or unknown.
+9 −67
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_

	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
	if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
		temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
		temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
		if (!temp)
			return -ENOMEM;

@@ -171,60 +171,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
}
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);

static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
{
	struct drm_fb_helper_connector *fb_helper_conn;
	int i;

	for (i = 0; i < fb_helper->connector_count; i++) {
		struct drm_cmdline_mode *mode;
		struct drm_connector *connector;
		char *option = NULL;

		fb_helper_conn = fb_helper->connector_info[i];
		connector = fb_helper_conn->connector;
		mode = &fb_helper_conn->cmdline_mode;

		/* do something on return - turn off connector maybe */
		if (fb_get_options(connector->name, &option))
			continue;

		if (drm_mode_parse_command_line_for_connector(option,
							      connector,
							      mode)) {
			if (mode->force) {
				const char *s;
				switch (mode->force) {
				case DRM_FORCE_OFF:
					s = "OFF";
					break;
				case DRM_FORCE_ON_DIGITAL:
					s = "ON - dig";
					break;
				default:
				case DRM_FORCE_ON:
					s = "ON";
					break;
				}

				DRM_INFO("forcing %s connector %s\n",
					 connector->name, s);
				connector->force = mode->force;
			}

			DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
				      connector->name,
				      mode->xres, mode->yres,
				      mode->refresh_specified ? mode->refresh : 60,
				      mode->rb ? " reduced blanking" : "",
				      mode->margins ? " with margins" : "",
				      mode->interlace ?  " interlaced" : "");
		}

	}
	return 0;
}

static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
{
	uint16_t *r_base, *g_base, *b_base;
@@ -419,11 +365,11 @@ static bool drm_fb_helper_force_kernel_mode(void)
		if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
			continue;

		/* NOTE: we use lockless flag below to avoid grabbing other
		 * modeset locks.  So just trylock the underlying mutex
		 * directly:
		/*
		 * NOTE: Use trylock mode to avoid deadlocks and sleeping in
		 * panic context.
		 */
		if (!mutex_trylock(&dev->mode_config.mutex)) {
		if (__drm_modeset_lock_all(dev, true) != 0) {
			error = true;
			continue;
		}
@@ -432,7 +378,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
		if (ret)
			error = true;

		mutex_unlock(&dev->mode_config.mutex);
		drm_modeset_unlock_all(dev);
	}
	return error;
}
@@ -1013,7 +959,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
		struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
		struct drm_cmdline_mode *cmdline_mode;

		cmdline_mode = &fb_helper_conn->cmdline_mode;
		cmdline_mode = &fb_helper_conn->connector->cmdline_mode;

		if (cmdline_mode->bpp_specified) {
			switch (cmdline_mode->bpp) {
@@ -1260,9 +1206,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode);

static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
{
	struct drm_cmdline_mode *cmdline_mode;
	cmdline_mode = &fb_connector->cmdline_mode;
	return cmdline_mode->specified;
	return fb_connector->connector->cmdline_mode.specified;
}

struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
@@ -1272,7 +1216,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
	struct drm_display_mode *mode = NULL;
	bool prefer_non_interlace;

	cmdline_mode = &fb_helper_conn->cmdline_mode;
	cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
	if (cmdline_mode->specified == false)
		return mode;

@@ -1657,8 +1601,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
	struct drm_device *dev = fb_helper->dev;
	int count = 0;

	drm_fb_helper_parse_command_line(fb_helper);

	mutex_lock(&dev->mode_config.mutex);
	count = drm_fb_helper_probe_connector_modes(fb_helper,
						    dev->mode_config.max_width,
Loading