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

Commit 9c704d14 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel into drm-next

Another attempt, this time rebased and without the pipe crc patches:
- display_info cleanups from Ville
- make prime/gem lookups faster with rbtrees (Chris)
- misc stuff all over

* tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel:
  drm/rockchip: analogix_dp: Refuse to enable PSR if panel doesn't support it
  drm/bridge: analogix_dp: Add analogix_dp_psr_supported
  drm/fb-helper: add DRM_FB_HELPER_DEFAULT_OPS for fb_ops
  drm: Document caveats around atomic event handling
  uapi: add missing install of sync_file.h
  drm: Simplify drm_printk to reduce object size quite a bit
  drm/i915: Account for sink max TMDS clock when checking the port clock
  drm/i915: Replace a bunch of connector->base.display_info with a local variable
  drm/edid: Move dvi_dual/max_tmds_clock parsing out from drm_edid_to_eld()
  drm/edid: Clear the old cea_rev when there's no CEA extension in the new EDID
  drm/edid: Reduce the number of times we parse the CEA extension block
  drm/edid: Don't pass around drm_display_info needlessly
  drm/edid: Move dvi_dual/max_tmds_clock to drm_display_info
  drm/edid: Make max_tmds_clock kHz instead of MHz
  drm/edid: Clear old dvi_dual/max_tmds_clock before parsing the new EDID
  drm/edid: Clear old audio latency values before parsing the new EDID
  drm: Convert prime dma-buf <-> handle to rbtree
  drm/mediatek: mark symbols static where possible
  drm/rockchip: mark symbols static where possible
  drm/rockchip: add missing header dependencies
parents a74feb65 0546d685
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -168,12 +168,12 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
		}
		}


		/* Any defined maximum tmds clock limit we must not exceed? */
		/* Any defined maximum tmds clock limit we must not exceed? */
		if (connector->max_tmds_clock > 0) {
		if (connector->display_info.max_tmds_clock > 0) {
			/* mode_clock is clock in kHz for mode to be modeset on this connector */
			/* mode_clock is clock in kHz for mode to be modeset on this connector */
			mode_clock = amdgpu_connector->pixelclock_for_modeset;
			mode_clock = amdgpu_connector->pixelclock_for_modeset;


			/* Maximum allowable input clock in kHz */
			/* Maximum allowable input clock in kHz */
			max_tmds_clock = connector->max_tmds_clock * 1000;
			max_tmds_clock = connector->display_info.max_tmds_clock;


			DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
			DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
				  connector->name, mode_clock, max_tmds_clock);
				  connector->name, mode_clock, max_tmds_clock);
+8 −0
Original line number Original line Diff line number Diff line
@@ -98,6 +98,14 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
	return 0;
	return 0;
}
}


int analogix_dp_psr_supported(struct device *dev)
{
	struct analogix_dp_device *dp = dev_get_drvdata(dev);

	return dp->psr_support;
}
EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);

int analogix_dp_enable_psr(struct device *dev)
int analogix_dp_enable_psr(struct device *dev)
{
{
	struct analogix_dp_device *dp = dev_get_drvdata(dev);
	struct analogix_dp_device *dp = dev_get_drvdata(dev);
+3 −2
Original line number Original line Diff line number Diff line
@@ -89,7 +89,6 @@ void drm_dev_printk(const struct device *dev, const char *level,
EXPORT_SYMBOL(drm_dev_printk);
EXPORT_SYMBOL(drm_dev_printk);


void drm_printk(const char *level, unsigned int category,
void drm_printk(const char *level, unsigned int category,
		const char *function_name, const char *prefix,
		const char *format, ...)
		const char *format, ...)
{
{
	struct va_format vaf;
	struct va_format vaf;
@@ -102,7 +101,9 @@ void drm_printk(const char *level, unsigned int category,
	vaf.fmt = format;
	vaf.fmt = format;
	vaf.va = &args;
	vaf.va = &args;


	printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
	printk("%s" "[" DRM_NAME ":%ps]%s %pV",
	       level, __builtin_return_address(0),
	       strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);


	va_end(args);
	va_end(args);
}
}
+129 −119
Original line number Original line Diff line number Diff line
@@ -3253,16 +3253,12 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
}
}


static void
static void
parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
{
{
	u8 len = cea_db_payload_len(db);
	u8 len = cea_db_payload_len(db);


	if (len >= 6) {
	if (len >= 6)
		connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
		connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
		connector->dvi_dual = db[6] & 1;
	}
	if (len >= 7)
		connector->max_tmds_clock = db[7] * 5;
	if (len >= 8) {
	if (len >= 8) {
		connector->latency_present[0] = db[8] >> 7;
		connector->latency_present[0] = db[8] >> 7;
		connector->latency_present[1] = (db[8] >> 6) & 1;
		connector->latency_present[1] = (db[8] >> 6) & 1;
@@ -3276,15 +3272,11 @@ parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
	if (len >= 12)
	if (len >= 12)
		connector->audio_latency[1] = db[12];
		connector->audio_latency[1] = db[12];


	DRM_DEBUG_KMS("HDMI: DVI dual %d, "
	DRM_DEBUG_KMS("HDMI: latency present %d %d, "
		    "max TMDS clock %d, "
		    "latency present %d %d, "
		      "video latency %d %d, "
		      "video latency %d %d, "
		      "audio latency %d %d\n",
		      "audio latency %d %d\n",
		    connector->dvi_dual,
		      connector->latency_present[0],
		    connector->max_tmds_clock,
		      connector->latency_present[1],
	      (int) connector->latency_present[0],
	      (int) connector->latency_present[1],
		      connector->video_latency[0],
		      connector->video_latency[0],
		      connector->video_latency[1],
		      connector->video_latency[1],
		      connector->audio_latency[0],
		      connector->audio_latency[0],
@@ -3358,6 +3350,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)


	memset(eld, 0, sizeof(connector->eld));
	memset(eld, 0, sizeof(connector->eld));


	connector->latency_present[0] = false;
	connector->latency_present[1] = false;
	connector->video_latency[0] = 0;
	connector->audio_latency[0] = 0;
	connector->video_latency[1] = 0;
	connector->audio_latency[1] = 0;

	cea = drm_find_cea_extension(edid);
	cea = drm_find_cea_extension(edid);
	if (!cea) {
	if (!cea) {
		DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
		DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
@@ -3407,7 +3406,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
			case VENDOR_BLOCK:
			case VENDOR_BLOCK:
				/* HDMI Vendor-Specific Data Block */
				/* HDMI Vendor-Specific Data Block */
				if (cea_db_is_hdmi_vsdb(db))
				if (cea_db_is_hdmi_vsdb(db))
					parse_hdmi_vsdb(connector, db);
					drm_parse_hdmi_vsdb_audio(connector, db);
				break;
				break;
			default:
			default:
				break;
				break;
@@ -3721,38 +3720,17 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
}
}
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);


/*
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
 * Parse the CEA extension according to CEA-861-B.
					   const u8 *hdmi)
 * Return true if HDMI deep color supported, false if not or unknown.
 */
static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
                                            struct drm_display_info *info,
                                            struct drm_connector *connector)
{
{
	u8 *edid_ext, *hdmi;
	struct drm_display_info *info = &connector->display_info;
	int i;
	int start_offset, end_offset;
	unsigned int dc_bpc = 0;
	unsigned int dc_bpc = 0;


	edid_ext = drm_find_cea_extension(edid);
	if (!edid_ext)
		return false;

	if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
		return false;

	/*
	 * Because HDMI identifier is in Vendor Specific Block,
	 * search it from all data blocks of CEA extension.
	 */
	for_each_cea_db(edid_ext, i, start_offset, end_offset) {
		if (cea_db_is_hdmi_vsdb(&edid_ext[i])) {
	/* HDMI supports at least 8 bpc */
	/* HDMI supports at least 8 bpc */
	info->bpc = 8;
	info->bpc = 8;


			hdmi = &edid_ext[i];
	if (cea_db_payload_len(hdmi) < 6)
	if (cea_db_payload_len(hdmi) < 6)
				return false;
		return;


	if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
	if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
		dc_bpc = 10;
		dc_bpc = 10;
@@ -3775,7 +3753,12 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
			  connector->name);
			  connector->name);
	}
	}


			if (dc_bpc > 0) {
	if (dc_bpc == 0) {
		DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
			  connector->name);
		return;
	}

	DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
	DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
		  connector->name, dc_bpc);
		  connector->name, dc_bpc);
	info->bpc = dc_bpc;
	info->bpc = dc_bpc;
@@ -3802,24 +3785,62 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
		DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
		DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
			  connector->name);
			  connector->name);
	}
	}

				return true;
			}
			else {
				DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
						  connector->name);
			}
}
}

static void
drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
{
	struct drm_display_info *info = &connector->display_info;
	u8 len = cea_db_payload_len(db);

	if (len >= 6)
		info->dvi_dual = db[6] & 1;
	if (len >= 7)
		info->max_tmds_clock = db[7] * 5000;

	DRM_DEBUG_KMS("HDMI: DVI dual %d, "
		      "max TMDS clock %d kHz\n",
		      info->dvi_dual,
		      info->max_tmds_clock);

	drm_parse_hdmi_deep_color_info(connector, db);
}
}


	return false;
static void drm_parse_cea_ext(struct drm_connector *connector,
			      struct edid *edid)
{
	struct drm_display_info *info = &connector->display_info;
	const u8 *edid_ext;
	int i, start, end;

	edid_ext = drm_find_cea_extension(edid);
	if (!edid_ext)
		return;

	info->cea_rev = edid_ext[1];

	/* The existence of a CEA block should imply RGB support */
	info->color_formats = DRM_COLOR_FORMAT_RGB444;
	if (edid_ext[3] & EDID_CEA_YCRCB444)
		info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
	if (edid_ext[3] & EDID_CEA_YCRCB422)
		info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;

	if (cea_db_offsets(edid_ext, &start, &end))
		return;

	for_each_cea_db(edid_ext, i, start, end) {
		const u8 *db = &edid_ext[i];

		if (cea_db_is_hdmi_vsdb(db))
			drm_parse_hdmi_vsdb_video(connector, db);
	}
}
}


static void drm_add_display_info(struct edid *edid,
static void drm_add_display_info(struct drm_connector *connector,
                                 struct drm_display_info *info,
				 struct edid *edid)
                                 struct drm_connector *connector)
{
{
	u8 *edid_ext;
	struct drm_display_info *info = &connector->display_info;


	info->width_mm = edid->width_cm * 10;
	info->width_mm = edid->width_cm * 10;
	info->height_mm = edid->height_cm * 10;
	info->height_mm = edid->height_cm * 10;
@@ -3827,6 +3848,9 @@ static void drm_add_display_info(struct edid *edid,
	/* driver figures it out in this case */
	/* driver figures it out in this case */
	info->bpc = 0;
	info->bpc = 0;
	info->color_formats = 0;
	info->color_formats = 0;
	info->cea_rev = 0;
	info->max_tmds_clock = 0;
	info->dvi_dual = false;


	if (edid->revision < 3)
	if (edid->revision < 3)
		return;
		return;
@@ -3834,21 +3858,7 @@ static void drm_add_display_info(struct edid *edid,
	if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
	if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
		return;
		return;


	/* Get data from CEA blocks if present */
	drm_parse_cea_ext(connector, edid);
	edid_ext = drm_find_cea_extension(edid);
	if (edid_ext) {
		info->cea_rev = edid_ext[1];

		/* The existence of a CEA block should imply RGB support */
		info->color_formats = DRM_COLOR_FORMAT_RGB444;
		if (edid_ext[3] & EDID_CEA_YCRCB444)
			info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
		if (edid_ext[3] & EDID_CEA_YCRCB422)
			info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
	}

	/* HDMI deep color modes supported? Assign to info, if so */
	drm_assign_hdmi_deep_color_info(edid, info, connector);


	/*
	/*
	 * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
	 * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
@@ -4084,7 +4094,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
		edid_fixup_preferred(connector, quirks);
		edid_fixup_preferred(connector, quirks);


	drm_add_display_info(edid, &connector->display_info, connector);
	drm_add_display_info(connector, edid);


	if (quirks & EDID_QUIRK_FORCE_6BPC)
	if (quirks & EDID_QUIRK_FORCE_6BPC)
		connector->display_info.bpc = 6;
		connector->display_info.bpc = 6;
+30 −2
Original line number Original line Diff line number Diff line
@@ -1008,6 +1008,31 @@ static void send_vblank_event(struct drm_device *dev,
 * period. This helper function implements exactly the required vblank arming
 * period. This helper function implements exactly the required vblank arming
 * behaviour.
 * behaviour.
 *
 *
 * NOTE: Drivers using this to send out the event in struct &drm_crtc_state
 * as part of an atomic commit must ensure that the next vblank happens at
 * exactly the same time as the atomic commit is committed to the hardware. This
 * function itself does **not** protect again the next vblank interrupt racing
 * with either this function call or the atomic commit operation. A possible
 * sequence could be:
 *
 * 1. Driver commits new hardware state into vblank-synchronized registers.
 * 2. A vblank happens, committing the hardware state. Also the corresponding
 *    vblank interrupt is fired off and fully processed by the interrupt
 *    handler.
 * 3. The atomic commit operation proceeds to call drm_crtc_arm_vblank_event().
 * 4. The event is only send out for the next vblank, which is wrong.
 *
 * An equivalent race can happen when the driver calls
 * drm_crtc_arm_vblank_event() before writing out the new hardware state.
 *
 * The only way to make this work safely is to prevent the vblank from firing
 * (and the hardware from committing anything else) until the entire atomic
 * commit sequence has run to completion. If the hardware does not have such a
 * feature (e.g. using a "go" bit), then it is unsafe to use this functions.
 * Instead drivers need to manually send out the event from their interrupt
 * handler by calling drm_crtc_send_vblank_event() and make sure that there's no
 * possible race with the hardware committing the atomic update.
 *
 * Caller must hold event lock. Caller must also hold a vblank reference for
 * Caller must hold event lock. Caller must also hold a vblank reference for
 * the event @e, which will be dropped when the next vblank arrives.
 * the event @e, which will be dropped when the next vblank arrives.
 */
 */
@@ -1030,8 +1055,11 @@ EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
 * @crtc: the source CRTC of the vblank event
 * @crtc: the source CRTC of the vblank event
 * @e: the event to send
 * @e: the event to send
 *
 *
 * Updates sequence # and timestamp on event, and sends it to userspace.
 * Updates sequence # and timestamp on event for the most recently processed
 * Caller must hold event lock.
 * vblank, and sends it to userspace.  Caller must hold event lock.
 *
 * See drm_crtc_arm_vblank_event() for a helper which can be used in certain
 * situation, especially to send out events for atomic commit operations.
 */
 */
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
				struct drm_pending_vblank_event *e)
				struct drm_pending_vblank_event *e)
Loading