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

Commit 5536141d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-3.16' of git://people.freedesktop.org/~agd5f/linux into drm-next

Highlights:
- GPUVM opimtizations
- HDMI audio cleanups
- Deep color HDMI support
- more bug fixes, cleanups

* 'drm-next-3.16' of git://people.freedesktop.org/~agd5f/linux: (29 commits)
  drm/edid: Add quirk for Sony PVM-2541A to get 12 bpc hdmi deep color.
  drm/edid: Parse and handle HDMI deep color modes.
  drm/radeon: Limit hdmi deep color bit depth to 12 bpc.
  drm/radeon: Setup HDMI_CONTROL for hdmi deep color gcp's (v2)
  drm/radeon: fix pll setup for hdmi deep color (v7)
  drm/radeon: use hw cts/n values for deep color
  drm/radeon: only apply hdmi bpc pll flags when encoder mode is hdmi
  drm/radeon/atom: fix dithering on certain panels
  drm/radeon: optimize CIK VM handling v2
  drm/radeon: optimize SI VM handling
  drm/radeon: add define for flags used in R600+ GTT
  drm/radeon: rework page flip handling v3
  drm/radeon: separate vblank and pflip crtc handling
  drm/radeon: split page flip and pending callback
  drm/radeon: remove drm_vblank_get|put from pflip handling
  drm/radeon: remove (pre|post)_page_flip callbacks
  drm/radeon/dp: fix lane/clock setup for dp 1.2 capable devices
  drm/radeon: fix typo in radeon_connector_is_dp12_capable()
  radeon: Remove useless quirk for zx1/FireGL X1 combo introduced with fdo #7770
  vgaswitcheroo: switch the mux to the igp on power down when runpm is enabled
  ...
parents c4e85412 bc5b9641
Loading
Loading
Loading
Loading
+116 −2
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@
#define EDID_QUIRK_FORCE_REDUCED_BLANKING	(1 << 7)
/* Force 8bpc */
#define EDID_QUIRK_FORCE_8BPC			(1 << 8)
/* Force 12bpc */
#define EDID_QUIRK_FORCE_12BPC			(1 << 9)

struct detailed_mode_closure {
	struct drm_connector *connector;
@@ -125,6 +127,9 @@ static struct edid_quirk {
	{ "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
	{ "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },

	/* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */
	{ "SNY", 0x2541, EDID_QUIRK_FORCE_12BPC },

	/* ViewSonic VA2026w */
	{ "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },

@@ -3422,17 +3427,117 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
}
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.
 *
 * Parse the CEA extension according to CEA-861-B.
 * 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;
	int i;
	int start_offset, end_offset;
	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 */
			info->bpc = 8;

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

			if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
				dc_bpc = 10;
				DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
						  drm_get_connector_name(connector));
			}

			if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
				dc_bpc = 12;
				DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
						  drm_get_connector_name(connector));
			}

			if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
				dc_bpc = 16;
				DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
						  drm_get_connector_name(connector));
			}

			if (dc_bpc > 0) {
				DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
						  drm_get_connector_name(connector), dc_bpc);
				info->bpc = dc_bpc;

				/*
				 * Deep color support mandates RGB444 support for all video
				 * modes and forbids YCRCB422 support for all video modes per
				 * HDMI 1.3 spec.
				 */
				info->color_formats = DRM_COLOR_FORMAT_RGB444;

				/* YCRCB444 is optional according to spec. */
				if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
					info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
					DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
							  drm_get_connector_name(connector));
				}

				/*
				 * Spec says that if any deep color mode is supported at all,
				 * then deep color 36 bit must be supported.
				 */
				if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
					DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
							  drm_get_connector_name(connector));
				}

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

	return false;
}

/**
 * drm_add_display_info - pull display info out if present
 * @edid: EDID data
 * @info: display info (attached to connector)
 * @connector: connector whose edid is used to build display info
 *
 * Grab any available display info and stuff it into the drm_display_info
 * structure that's part of the connector.  Useful for tracking bpp and
 * color spaces.
 */
static void drm_add_display_info(struct edid *edid,
				 struct drm_display_info *info)
                                 struct drm_display_info *info,
                                 struct drm_connector *connector)
{
	u8 *edid_ext;

@@ -3462,6 +3567,9 @@ static void drm_add_display_info(struct edid *edid,
			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);

	/* Only defined for 1.4 with digital displays */
	if (edid->revision < 4)
		return;
@@ -3491,6 +3599,9 @@ static void drm_add_display_info(struct edid *edid,
		break;
	}

	DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
			  drm_get_connector_name(connector), info->bpc);

	info->color_formats |= DRM_COLOR_FORMAT_RGB444;
	if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
		info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
@@ -3549,11 +3660,14 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
		edid_fixup_preferred(connector, quirks);

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

	if (quirks & EDID_QUIRK_FORCE_8BPC)
		connector->display_info.bpc = 8;

	if (quirks & EDID_QUIRK_FORCE_12BPC)
		connector->display_info.bpc = 12;

	return num_modes;
}
EXPORT_SYMBOL(drm_add_edid_modes);
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
	r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \
	evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
	evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
+60 −29
Original line number Diff line number Diff line
@@ -559,6 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
	u32 adjusted_clock = mode->clock;
	int encoder_mode = atombios_get_encoder_mode(encoder);
	u32 dp_clock = mode->clock;
	u32 clock = mode->clock;
	int bpc = radeon_crtc->bpc;
	bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);

@@ -634,6 +635,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
			radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
	}

	/* adjust pll for deep color modes */
	if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
		switch (bpc) {
		case 8:
		default:
			break;
		case 10:
			clock = (clock * 5) / 4;
			break;
		case 12:
			clock = (clock * 3) / 2;
			break;
		case 16:
			clock = clock * 2;
			break;
		}
	}

	/* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
	 * accordingly based on the encoder/transmitter to work around
	 * special hw requirements.
@@ -655,7 +674,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
			switch (crev) {
			case 1:
			case 2:
				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
				args.v1.usPixelClock = cpu_to_le16(clock / 10);
				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
				args.v1.ucEncodeMode = encoder_mode;
				if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)
@@ -667,7 +686,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
				adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
				break;
			case 3:
				args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10);
				args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10);
				args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
				args.v3.sInput.ucEncodeMode = encoder_mode;
				args.v3.sInput.ucDispPllConfig = 0;
@@ -681,10 +700,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
					args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
				} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
					if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
						/* deep color support */
						args.v3.sInput.usPixelClock =
							cpu_to_le16((mode->clock * bpc / 8) / 10);
					if (dig->coherent_mode)
						args.v3.sInput.ucDispPllConfig |=
							DISPPLL_CONFIG_COHERENT_MODE;
@@ -864,15 +879,22 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
			args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
			if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
				args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
			if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
				switch (bpc) {
				case 8:
				default:
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
					break;
				case 10:
					/* yes this is correct, the atom define is wrong */
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
					break;
				case 12:
					/* yes this is correct, the atom define is wrong */
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
					break;
				}
			}
			args.v5.ucTransmitterID = encoder_id;
			args.v5.ucEncoderMode = encoder_mode;
			args.v5.ucPpll = pll_id;
@@ -886,21 +908,23 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
			args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
			if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
				args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
			if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
				switch (bpc) {
				case 8:
				default:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
					break;
				case 10:
				args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP;
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
					break;
				case 12:
				args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP;
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
					break;
				case 16:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
					break;
				}
			}
			args.v6.ucTransmitterID = encoder_id;
			args.v6.ucEncoderMode = encoder_mode;
			args.v6.ucPpll = pll_id;
@@ -1021,10 +1045,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
	struct radeon_encoder *radeon_encoder =
		to_radeon_encoder(radeon_crtc->encoder);
	u32 pll_clock = mode->clock;
	u32 clock = mode->clock;
	u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
	struct radeon_pll *pll;
	int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);

	/* pass the actual clock to atombios_crtc_program_pll for DCE5,6 for HDMI */
	if (ASIC_IS_DCE5(rdev) && !ASIC_IS_DCE8(rdev) &&
	    (encoder_mode == ATOM_ENCODER_MODE_HDMI) &&
	    (radeon_crtc->bpc > 8))
		clock = radeon_crtc->adjusted_clock;

	switch (radeon_crtc->pll_id) {
	case ATOM_PPLL1:
		pll = &rdev->clock.p1pll;
@@ -1059,7 +1090,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
				 radeon_crtc->crtc_id, &radeon_crtc->ss);

	atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
				  encoder_mode, radeon_encoder->encoder_id, mode->clock,
				  encoder_mode, radeon_encoder->encoder_id, clock,
				  ref_div, fb_div, frac_fb_div, post_div,
				  radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);

+29 −6
Original line number Diff line number Diff line
@@ -95,9 +95,12 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
	int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
	unsigned char *base;
	int recv_bytes;
	int r = 0;

	memset(&args, 0, sizeof(args));

	mutex_lock(&chan->mutex);

	base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);

	radeon_atom_copy_swap(base, send, send_bytes, true);
@@ -117,19 +120,22 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
	/* timeout */
	if (args.v1.ucReplyStatus == 1) {
		DRM_DEBUG_KMS("dp_aux_ch timeout\n");
		return -ETIMEDOUT;
		r = -ETIMEDOUT;
		goto done;
	}

	/* flags not zero */
	if (args.v1.ucReplyStatus == 2) {
		DRM_DEBUG_KMS("dp_aux_ch flags not zero\n");
		return -EBUSY;
		r = -EBUSY;
		goto done;
	}

	/* error */
	if (args.v1.ucReplyStatus == 3) {
		DRM_DEBUG_KMS("dp_aux_ch error\n");
		return -EIO;
		r = -EIO;
		goto done;
	}

	recv_bytes = args.v1.ucDataOutLen;
@@ -139,7 +145,11 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
	if (recv && recv_size)
		radeon_atom_copy_swap(recv, base + 16, recv_bytes, false);

	return recv_bytes;
	r = recv_bytes;
done:
	mutex_unlock(&chan->mutex);

	return r;
}

#define BARE_ADDRESS_SIZE 3
@@ -281,6 +291,19 @@ static int dp_get_max_dp_pix_clock(int link_rate,

/***** radeon specific DP functions *****/

static int radeon_dp_get_max_link_rate(struct drm_connector *connector,
				       u8 dpcd[DP_DPCD_SIZE])
{
	int max_link_rate;

	if (radeon_connector_is_dp12_capable(connector))
		max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000);
	else
		max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000);

	return max_link_rate;
}

/* First get the min lane# when low rate is used according to pixel clock
 * (prefer low rate), second check max lane# supported by DP panel,
 * if the max lane# < low rate lane# then use max lane# instead.
@@ -290,7 +313,7 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
					int pix_clock)
{
	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
	int max_link_rate = drm_dp_max_link_rate(dpcd);
	int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd);
	int max_lane_num = drm_dp_max_lane_count(dpcd);
	int lane_num;
	int max_dp_pix_clock;
@@ -328,7 +351,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
			return 540000;
	}

	return drm_dp_max_link_rate(dpcd);
	return radeon_dp_get_max_link_rate(connector, dpcd);
}

static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
+4 −1
Original line number Diff line number Diff line
@@ -1884,8 +1884,11 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
				else
					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
			} else
			} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
				args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
			} else {
				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
			}
			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
Loading