Example #1
0
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
				      enum pipe pipe)
{
	int reg;
	u32 val;

	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B);
	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C);
	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D);

	reg = PCH_ADPA;
	val = I915_READ(reg);
	if (ADPA_PIPE_ENABLED(val, pipe)) fprintf(stderr,
	     "PCH VGA enabled on transcoder %c, should be disabled\n",
	     pipe_name(pipe));

	reg = PCH_LVDS;
	val = I915_READ(reg);
	if (LVDS_PIPE_ENABLED(val, pipe)) fprintf(stderr,
	     "PCH LVDS enabled on transcoder %c, should be disabled\n",
	     pipe_name(pipe));

	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIB);
	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIC);
	assert_pch_hdmi_disabled(dev_priv, pipe, HDMID);
}
Example #2
0
static void intel_ddi_mode_set(struct intel_encoder *encoder)
{
	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
	int port = intel_ddi_get_encoder_port(encoder);
	int pipe = crtc->pipe;
	int type = encoder->type;
	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;

	DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
		      port_name(port), pipe_name(pipe));

	crtc->eld_vld = false;
	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
		struct intel_digital_port *intel_dig_port =
			enc_to_dig_port(&encoder->base);

		intel_dp->DP = intel_dig_port->saved_port_bits |
			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
		intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);

		if (intel_dp->has_audio) {
			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
					 pipe_name(crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("DP audio: write eld information\n");
			intel_write_eld(&encoder->base, adjusted_mode);
		}

		intel_dp_init_link_config(intel_dp);

	} else if (type == INTEL_OUTPUT_HDMI) {
		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);

		if (intel_hdmi->has_audio) {
			/* Proper support for digital audio needs a new logic
			 * and a new set of registers, so we leave it for future
			 * patch bombing.
			 */
			DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
					 pipe_name(crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
			intel_write_eld(&encoder->base, adjusted_mode);
		}

		intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
	}
}
Example #3
0
static struct intel_dp_mst_encoder *
intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum pipe pipe)
{
	struct intel_dp_mst_encoder *intel_mst;
	struct intel_encoder *intel_encoder;
	struct drm_device *dev = intel_dig_port->base.base.dev;

	intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL);

	if (!intel_mst)
		return NULL;

	intel_mst->pipe = pipe;
	intel_encoder = &intel_mst->base;
	intel_mst->primary = intel_dig_port;

	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
			 DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe));

	intel_encoder->type = INTEL_OUTPUT_DP_MST;
	intel_encoder->crtc_mask = 0x7;
	intel_encoder->cloneable = 0;

	intel_encoder->compute_config = intel_dp_mst_compute_config;
	intel_encoder->disable = intel_mst_disable_dp;
	intel_encoder->post_disable = intel_mst_post_disable_dp;
	intel_encoder->pre_enable = intel_mst_pre_enable_dp;
	intel_encoder->enable = intel_mst_enable_dp;
	intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state;
	intel_encoder->get_config = intel_dp_mst_enc_get_config;

	return intel_mst;

}
Example #4
0
static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
{
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
	struct intel_fbc *fbc = &dev_priv->fbc;
	struct intel_fbc_work *work = &fbc->work;

	WARN_ON(!mutex_is_locked(&fbc->lock));
	if (WARN_ON(!fbc->enabled))
		return;

	if (drm_crtc_vblank_get(&crtc->base)) {
		DRM_ERROR("vblank not available for FBC on pipe %c\n",
			  pipe_name(crtc->pipe));
		return;
	}

	/* It is useless to call intel_fbc_cancel_work() or cancel_work() in
	 * this function since we're not releasing fbc.lock, so it won't have an
	 * opportunity to grab it to discover that it was cancelled. So we just
	 * update the expected jiffy count. */
	work->scheduled = true;
	work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
	drm_crtc_vblank_put(&crtc->base);

	schedule_work(&work->work);
}
Example #5
0
static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
				  enum pipe pipe)
{
	int pp_reg, lvds_reg;
	u32 val;
	enum pipe panel_pipe = PIPE_A;
	bool locked = locked;

	if (HAS_PCH_SPLIT(dev_priv->dev)) {
		pp_reg = PCH_PP_CONTROL;
		lvds_reg = PCH_LVDS;
	} else {
		pp_reg = PP_CONTROL;
		lvds_reg = LVDS;
	}

	val = I915_READ(pp_reg);
	if (!(val & PANEL_POWER_ON) ||
	    ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS))
		locked = false;

	if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT)
		panel_pipe = PIPE_B;

	if (panel_pipe == pipe && locked) fprintf(stderr,
	     "panel assertion failure, pipe %c regs locked\n",
	     pipe_name(pipe));
}
Example #6
0
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
				     enum pipe pipe, int reg)
{
	u32 val = I915_READ(reg);
	if (HDMI_PIPE_ENABLED(val, pipe)) fprintf(stderr,
	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
	     reg, pipe_name(pipe));
}
Example #7
0
static void intel_fbc_work_fn(struct work_struct *__work)
{
	struct drm_i915_private *dev_priv =
		container_of(__work, struct drm_i915_private, fbc.work.work);
	struct intel_fbc *fbc = &dev_priv->fbc;
	struct intel_fbc_work *work = &fbc->work;
	struct intel_crtc *crtc = fbc->crtc;
	struct drm_vblank_crtc *vblank = &dev_priv->dev->vblank[crtc->pipe];

	if (drm_crtc_vblank_get(&crtc->base)) {
		DRM_ERROR("vblank not available for FBC on pipe %c\n",
			  pipe_name(crtc->pipe));

		mutex_lock(&fbc->lock);
		work->scheduled = false;
		mutex_unlock(&fbc->lock);
		return;
	}

retry:
	/* Delay the actual enabling to let pageflipping cease and the
	 * display to settle before starting the compression. Note that
	 * this delay also serves a second purpose: it allows for a
	 * vblank to pass after disabling the FBC before we attempt
	 * to modify the control registers.
	 *
	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
	 *
	 * It is also worth mentioning that since work->scheduled_vblank can be
	 * updated multiple times by the other threads, hitting the timeout is
	 * not an error condition. We'll just end up hitting the "goto retry"
	 * case below.
	 */
	wait_event_timeout(vblank->queue,
		drm_crtc_vblank_count(&crtc->base) != work->scheduled_vblank,
		msecs_to_jiffies(50));

	mutex_lock(&fbc->lock);

	/* Were we cancelled? */
	if (!work->scheduled)
		goto out;

	/* Were we delayed again while this function was sleeping? */
	if (drm_crtc_vblank_count(&crtc->base) == work->scheduled_vblank) {
		mutex_unlock(&fbc->lock);
		goto retry;
	}

	intel_fbc_hw_activate(dev_priv);

	work->scheduled = false;

out:
	mutex_unlock(&fbc->lock);
	drm_crtc_vblank_put(&crtc->base);
}
Example #8
0
static int display_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe)
{
	const char name = buf[0];

	if (name < 'A' || name >= pipe_name(I915_MAX_PIPES))
		return -EINVAL;

	*pipe = name - 'A';

	return 0;
}
Example #9
0
static int display_crc_ctl_show(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = m->private;
	enum pipe pipe;

	for_each_pipe(dev_priv, pipe)
		seq_printf(m, "%c %s\n", pipe_name(pipe),
			   pipe_crc_source_name(dev_priv->pipe_crc[pipe].source));

	return 0;
}
Example #10
0
static int display_crc_ctl_show(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = m->private;
	int i;

	for (i = 0; i < I915_MAX_PIPES; i++)
		seq_printf(m, "%c %s\n", pipe_name(i),
			   pipe_crc_source_name(dev_priv->pipe_crc[i].source));

	return 0;
}
Example #11
0
static int display_crc_ctl_parse_pipe(struct drm_i915_private *dev_priv,
				      const char *buf, enum pipe *pipe)
{
	const char name = buf[0];

	if (name < 'A' || name >= pipe_name(INTEL_INFO(dev_priv)->num_pipes))
		return -EINVAL;

	*pipe = name - 'A';

	return 0;
}
Example #12
0
static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
				       enum pipe pipe)
{
	int reg;
	u32 val;
	bool enabled;

	reg = TRANSCONF(pipe);
	val = I915_READ(reg);
	enabled = !!(val & TRANS_ENABLE);
	if (enabled) fprintf(stderr,
	     "transcoder assertion failed, should be off on pipe %c but is still active\n",
	     pipe_name(pipe));
}
Example #13
0
static void assert_pipe(struct drm_i915_private *dev_priv,
			enum pipe pipe, bool state)
{
	int reg;
	u32 val;
	bool cur_state;

	reg = PIPECONF(pipe);
	val = I915_READ(reg);
	cur_state = !!(val & PIPECONF_ENABLE);
	if (cur_state != state) fprintf(stderr,
	     "pipe %c assertion failure (expected %s, current %s)\n",
	     pipe_name(pipe), state_string(state), state_string(cur_state));
}
Example #14
0
u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg)
{
	u32 val = 0;

	vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
			SB_MRD_NP, reg, &val);

	/*
	 * FIXME: There might be some registers where all 1's is a valid value,
	 * so ideally we should check the register offset instead...
	 */
	WARN(val == 0xffffffff, "DPIO read pipe %c reg 0x%x == 0x%x\n",
	     pipe_name(pipe), reg, val);

	return val;
}
Example #15
0
/**
 * __intel_fbc_disable - disable FBC
 * @dev_priv: i915 device instance
 *
 * This is the low level function that actually disables FBC. Callers should
 * grab the FBC lock.
 */
static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
{
	struct intel_fbc *fbc = &dev_priv->fbc;
	struct intel_crtc *crtc = fbc->crtc;

	WARN_ON(!mutex_is_locked(&fbc->lock));
	WARN_ON(!fbc->enabled);
	WARN_ON(fbc->active);

	DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));

	__intel_fbc_cleanup_cfb(dev_priv);

	fbc->enabled = false;
	fbc->crtc = NULL;
}
Example #16
0
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
	u32 sdvox;

	sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
	if (!HAS_PCH_SPLIT(dev))
		sdvox |= intel_hdmi->color_range;
	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
		sdvox |= SDVO_HSYNC_ACTIVE_HIGH;

	if (intel_crtc->bpp > 24)
		sdvox |= COLOR_FORMAT_12bpc;
	else
		sdvox |= COLOR_FORMAT_8bpc;

	/* Required on CPT */
	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
		sdvox |= HDMI_MODE_SELECT;

	if (intel_hdmi->has_audio) {
		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
				 pipe_name(intel_crtc->pipe));
		sdvox |= SDVO_AUDIO_ENABLE;
		sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
		intel_write_eld(encoder, adjusted_mode);
	}

	if (HAS_PCH_CPT(dev))
		sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
	else if (intel_crtc->pipe == 1)
		sdvox |= SDVO_PIPE_B_SELECT;

	I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
	POSTING_READ(intel_hdmi->sdvox_reg);

	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
	intel_hdmi_set_spd_infoframe(encoder);
}
Example #17
0
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
	u32 hdmi_val;

	hdmi_val = SDVO_ENCODING_HDMI;
	if (!HAS_PCH_SPLIT(dev))
		hdmi_val |= intel_hdmi->color_range;
	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
		hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH;

	if (intel_crtc->config.pipe_bpp > 24)
		hdmi_val |= HDMI_COLOR_FORMAT_12bpc;
	else
		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;

	/* Required on CPT */
	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
		hdmi_val |= HDMI_MODE_SELECT_HDMI;

	if (intel_hdmi->has_audio) {
		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
				 pipe_name(intel_crtc->pipe));
		hdmi_val |= SDVO_AUDIO_ENABLE;
		hdmi_val |= HDMI_MODE_SELECT_HDMI;
		intel_write_eld(encoder, adjusted_mode);
	}

	if (HAS_PCH_CPT(dev))
		hdmi_val |= SDVO_PIPE_SEL_CPT(intel_crtc->pipe);
	else
		hdmi_val |= SDVO_PIPE_SEL(intel_crtc->pipe);

	I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val);
	POSTING_READ(intel_hdmi->hdmi_reg);

	intel_hdmi->set_infoframes(encoder, adjusted_mode);
}
Example #18
0
static void
intel_reference_shared_dpll(struct intel_shared_dpll *pll,
			    struct intel_crtc_state *crtc_state)
{
	struct intel_shared_dpll_config *shared_dpll;
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
	enum intel_dpll_id i = pll->id;

	shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);

	if (shared_dpll[i].crtc_mask == 0)
		shared_dpll[i].hw_state =
			crtc_state->dpll_hw_state;

	crtc_state->shared_dpll = pll;
	DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
			 pipe_name(crtc->pipe));

	intel_shared_dpll_config_get(shared_dpll, pll, crtc);
}
Example #19
0
HRESULT PipeStream::Create(const wchar_t* name, DWORD pipe_mode) {
  if (name == nullptr)
    return E_INVALIDARG;
  if (IsValid())
    return E_HANDLE;

  Reset();

  std::wstring pipe_name(L"\\\\.\\pipe\\");
  pipe_name.append(name);

  handle_ = CreateNamedPipeW(pipe_name.c_str(),
                             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                             pipe_mode, PIPE_UNLIMITED_INSTANCES, 0, 0, 0,
                             nullptr);
  if (handle_ == INVALID_HANDLE_VALUE)
    return HRESULT_FROM_LAST_ERROR();

  return S_OK;
}
Example #20
0
/**
 * intel_fbc_enable: tries to enable FBC on the CRTC
 * @crtc: the CRTC
 * @crtc_state: corresponding &drm_crtc_state for @crtc
 * @plane_state: corresponding &drm_plane_state for the primary plane of @crtc
 *
 * This function checks if the given CRTC was chosen for FBC, then enables it if
 * possible. Notice that it doesn't activate FBC. It is valid to call
 * intel_fbc_enable multiple times for the same pipe without an
 * intel_fbc_disable in the middle, as long as it is deactivated.
 */
void intel_fbc_enable(struct intel_crtc *crtc,
		      struct intel_crtc_state *crtc_state,
		      struct intel_plane_state *plane_state)
{
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
	struct intel_fbc *fbc = &dev_priv->fbc;

	if (!fbc_supported(dev_priv))
		return;

	mutex_lock(&fbc->lock);

	if (fbc->enabled) {
		WARN_ON(fbc->crtc == NULL);
		if (fbc->crtc == crtc) {
			WARN_ON(!crtc_state->enable_fbc);
			WARN_ON(fbc->active);
		}
		goto out;
	}

	if (!crtc_state->enable_fbc)
		goto out;

	WARN_ON(fbc->active);
	WARN_ON(fbc->crtc != NULL);

	intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
	if (intel_fbc_alloc_cfb(crtc)) {
		fbc->no_fbc_reason = "not enough stolen memory";
		goto out;
	}

	DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
	fbc->no_fbc_reason = "FBC enabled but not active yet\n";

	fbc->enabled = true;
	fbc->crtc = crtc;
out:
	mutex_unlock(&fbc->lock);
}
Example #21
0
static void assert_planes_disabled(struct drm_i915_private *dev_priv,
				   enum pipe pipe)
{
	int reg, i;
	u32 val;
	int cur_pipe;

	/* Planes are fixed to pipes on ILK+ */
	if (HAS_PCH_SPLIT(dev_priv->dev))
		return;

	/* Need to check both planes against the pipe */
	for (i = 0; i < 2; i++) {
		reg = DSPCNTR(i);
		val = I915_READ(reg);
		cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
			DISPPLANE_SEL_PIPE_SHIFT;
		if ((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe) fprintf(stderr,
		     "plane %c assertion failure, should be off on pipe %c but is still active\n",
		     plane_name(i), pipe_name(pipe));
	}
}
Example #22
0
HRESULT PipeStream::Open(const wchar_t* name, DWORD timeout) {
  if (name == nullptr)
    return E_INVALIDARG;
  if (IsValid())
    return E_HANDLE;

  Reset();

  std::wstring pipe_name(L"\\\\.\\pipe\\");
  pipe_name.append(name);

  if (!WaitNamedPipeW(pipe_name.c_str(), timeout))
    return HRESULT_FROM_LAST_ERROR();

  handle_ = CreateFileW(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
                        OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  if (handle_ == INVALID_HANDLE_VALUE)
    return HRESULT_FROM_LAST_ERROR();

  connected_ = true;

  return S_OK;
}
Example #23
0
static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
{
	struct drm_encoder *encoder = &intel_encoder->base;
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
	struct drm_display_mode *adjusted_mode =
		&intel_crtc->config.adjusted_mode;
	int pipe = intel_crtc->pipe;
	unsigned int bpp = intel_crtc->config.pipe_bpp;
	u32 val, tmp;

	DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));

	/* XXX: Location of the call */
	band_gap_reset(dev_priv);

	/* escape clock divider, 20MHz, shared for A and C. device ready must be
	 * off when doing this! txclkesc? */
	tmp = I915_READ(MIPI_CTRL(0));
	tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
	I915_WRITE(MIPI_CTRL(0), tmp | ESCAPE_CLOCK_DIVIDER_1);

	/* read request priority is per pipe */
	tmp = I915_READ(MIPI_CTRL(pipe));
	tmp &= ~READ_REQUEST_PRIORITY_MASK;
	I915_WRITE(MIPI_CTRL(pipe), tmp | READ_REQUEST_PRIORITY_HIGH);

	/* XXX: why here, why like this? handling in irq handler?! */
	I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
	I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);

	I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg);

	I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
		   adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
		   adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT);

	set_dsi_timings(encoder, adjusted_mode);

	val = intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT;
	if (is_cmd_mode(intel_dsi)) {
		val |= intel_dsi->channel << CMD_MODE_CHANNEL_NUMBER_SHIFT;
		val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */
	} else {
		val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT;

		/* XXX: cross-check bpp vs. pixel format? */
		val |= intel_dsi->pixel_format;
	}
	I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val);

	/* timeouts for recovery. one frame IIUC. if counter expires, EOT and
	 * stop state. */

	/*
	 * In burst mode, value greater than one DPI line Time in byte clock
	 * (txbyteclkhs) To timeout this timer 1+ of the above said value is
	 * recommended.
	 *
	 * In non-burst mode, Value greater than one DPI frame time in byte
	 * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
	 * is recommended.
	 *
	 * In DBI only mode, value greater than one DBI frame time in byte
	 * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
	 * is recommended.
	 */

	if (is_vid_mode(intel_dsi) &&
	    intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
		I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
			   txbyteclkhs(adjusted_mode->htotal, bpp,
				       intel_dsi->lane_count) + 1);
	} else {
		I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
			   txbyteclkhs(adjusted_mode->vtotal *
				       adjusted_mode->htotal,
				       bpp, intel_dsi->lane_count) + 1);
	}
	I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
	I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
	I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);

	/* dphy stuff */

	/* in terms of low power clock */
	I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100));

	/* recovery disables */
	I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable);

	/* in terms of txbyteclkhs. actual high to low switch +
	 * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK.
	 *
	 * XXX: write MIPI_STOP_STATE_STALL?
	 */
	I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
						intel_dsi->hs_to_lp_count);

	/* XXX: low power clock equivalence in terms of byte clock. the number
	 * of byte clocks occupied in one low power clock. based on txbyteclkhs
	 * and txclkesc. txclkesc time / txbyteclk time * (105 +
	 * MIPI_STOP_STATE_STALL) / 105.???
	 */
	I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);

	/* the bw essential for transmitting 16 long packets containing 252
	 * bytes meant for dcs write memory command is programmed in this
	 * register in terms of byte clocks. based on dsi transfer rate and the
	 * number of lanes configured the time taken to transmit 16 long packets
	 * in a dsi stream varies. */
	I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);

	I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
		   intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
		   intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);

	if (is_vid_mode(intel_dsi))
		I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
				intel_dsi->video_frmt_cfg_bits |
				intel_dsi->video_mode_format);
}
Example #24
0
static int video_pipeline_menu(struct advance_video_context* context, struct advance_ui_context* ui_context, int selected, unsigned input)
{
	struct ui_menu menu;
	unsigned mac;
	int exit_index;
	unsigned i;
	const struct video_stage_horz_struct* stage;
	char buffer[256];

	if (selected >= 1)
		selected = selected - 1;
	else
		selected = 0;

	advance_ui_menu_init(&menu);

	snprintf(buffer, sizeof(buffer), "Video Pipeline (%d)", context->state.blit_pipeline_index);
	advance_ui_menu_title_insert(&menu, buffer);

	for (i = 1, stage = video_pipeline_begin(&context->state.blit_pipeline[context->state.blit_pipeline_index]); stage != video_pipeline_end(&context->state.blit_pipeline[context->state.blit_pipeline_index]); ++stage, ++i) {
		if (stage == video_pipeline_pivot(&context->state.blit_pipeline[context->state.blit_pipeline_index])) {
			snprintf(buffer, sizeof(buffer), "(%d) %s", i, pipe_name(video_pipeline_vert(&context->state.blit_pipeline[context->state.blit_pipeline_index])->type));
			advance_ui_menu_text_insert(&menu, buffer);
			++i;
		}
		if (stage->sbpp != stage->sdp)
			snprintf(buffer, sizeof(buffer), "(%d) %s, p %d, dp %d", i, pipe_name(stage->type), stage->sbpp, stage->sdp);
		else
			snprintf(buffer, sizeof(buffer), "(%d) %s, p %d", i, pipe_name(stage->type), stage->sbpp);
		advance_ui_menu_text_insert(&menu, buffer);
	}
	if (stage == video_pipeline_pivot(&context->state.blit_pipeline[context->state.blit_pipeline_index])) {
		snprintf(buffer, sizeof(buffer), "(%d) %s", i, pipe_name(video_pipeline_vert(&context->state.blit_pipeline[context->state.blit_pipeline_index])->type));
		advance_ui_menu_text_insert(&menu, buffer);
		++i;
	}

	advance_ui_menu_title_insert(&menu, "Pipeline Blit Time");

	if (context->state.pipeline_measure_flag) {
		advance_ui_menu_text_insert(&menu, "Time measure not completed");
	} else {
		double timing = adv_measure_median(0.00001, 0.5, context->state.update_timing_map, PIPELINE_MEASURE_MAX);
		snprintf(buffer, sizeof(buffer), "Last render %.2f (ms)", timing * 1000);
		advance_ui_menu_text_insert(&menu, buffer);

		timing = adv_measure_median(0.00001, 0.5, context->state.pipeline_timing_map, PIPELINE_MEASURE_MAX);
		snprintf(buffer, sizeof(buffer), "Last write %.2f (ms)", timing * 1000);
		advance_ui_menu_text_insert(&menu, buffer);

		for (i = 0; i < PIPELINE_BLIT_MAX; ++i) {
			const char* desc;
			const char* select;
			if (context->state.blit_pipeline_index == i)
				select = "-> ";
			else
				select = "";
			switch (i) {
			case 0: desc = "Buffer"; break;
			case 1: desc = "Direct"; break;
			default: desc = "Unknown"; break;
			}
			snprintf(buffer, sizeof(buffer), "%s%s write %.2f (ms)", select, desc, context->state.pipeline_measure_result[i] * 1000);
			advance_ui_menu_text_insert(&menu, buffer);
		}
	}

	exit_index = advance_ui_menu_text_insert(&menu, "Return to Main Menu");

	mac = advance_ui_menu_done(&menu, ui_context, selected);

	if (input == OSD_INPUT_DOWN) {
		selected = (selected + 1) % mac;
	}

	if (input == OSD_INPUT_UP) {
		selected = (selected + mac - 1) % mac;
	}

	if (input == OSD_INPUT_SELECT) {
		if (selected == exit_index) {
			selected = -1;
		}
	}

	if (input == OSD_INPUT_CANCEL)
		selected = -1;

	if (input == OSD_INPUT_CONFIGURE)
		selected = -2;

	return selected + 1;
}
Example #25
0
/*
 * Try to read the BIOS display configuration and use it for the initial
 * fb configuration.
 *
 * The BIOS or boot loader will generally create an initial display
 * configuration for us that includes some set of active pipes and displays.
 * This routine tries to figure out which pipes and connectors are active
 * and stuffs them into the crtcs and modes array given to us by the
 * drm_fb_helper code.
 *
 * The overall sequence is:
 *   intel_fbdev_init - from driver load
 *     intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data
 *     drm_fb_helper_init - build fb helper structs
 *     drm_fb_helper_single_add_all_connectors - more fb helper structs
 *   intel_fbdev_initial_config - apply the config
 *     drm_fb_helper_initial_config - call ->probe then register_framebuffer()
 *         drm_setup_crtcs - build crtc config for fbdev
 *           intel_fb_initial_config - find active connectors etc
 *         drm_fb_helper_single_fb_probe - set up fbdev
 *           intelfb_create - re-use or alloc fb, build out fbdev structs
 *
 * Note that we don't make special consideration whether we could actually
 * switch to the selected modes without a full modeset. E.g. when the display
 * is in VGA mode we need to recalculate watermarks and set a new high-res
 * framebuffer anyway.
 */
static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                                    struct drm_fb_helper_crtc **crtcs,
                                    struct drm_display_mode **modes,
                                    bool *enabled, int width, int height)
{
    struct drm_device *dev = fb_helper->dev;
    int i, j;
    bool *save_enabled;
    bool fallback = true;
    int num_connectors_enabled = 0;
    int num_connectors_detected = 0;

    /*
     * If the user specified any force options, just bail here
     * and use that config.
     */
    for (i = 0; i < fb_helper->connector_count; i++) {
        struct drm_fb_helper_connector *fb_conn;
        struct drm_connector *connector;

        fb_conn = fb_helper->connector_info[i];
        connector = fb_conn->connector;

        if (!enabled[i])
            continue;

        if (connector->force != DRM_FORCE_UNSPECIFIED)
            return false;
    }

    save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
                           GFP_KERNEL);
    if (!save_enabled)
        return false;

    memcpy(save_enabled, enabled, dev->mode_config.num_connector);

    for (i = 0; i < fb_helper->connector_count; i++) {
        struct drm_fb_helper_connector *fb_conn;
        struct drm_connector *connector;
        struct drm_encoder *encoder;
        struct drm_fb_helper_crtc *new_crtc;

        fb_conn = fb_helper->connector_info[i];
        connector = fb_conn->connector;

        if (connector->status == connector_status_connected)
            num_connectors_detected++;

        if (!enabled[i]) {
            DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
                          connector->name);
            continue;
        }

        encoder = connector->encoder;
        if (!encoder || WARN_ON(!encoder->crtc)) {
            DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
                          connector->name);
            enabled[i] = false;
            continue;
        }

        num_connectors_enabled++;

        new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc);

        /*
         * Make sure we're not trying to drive multiple connectors
         * with a single CRTC, since our cloning support may not
         * match the BIOS.
         */
        for (j = 0; j < fb_helper->connector_count; j++) {
            if (crtcs[j] == new_crtc) {
                DRM_DEBUG_KMS("fallback: cloned configuration\n");
                fallback = true;
                goto out;
            }
        }

        DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
                      connector->name);

        /* go for command line mode first */
        modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);

        /* try for preferred next */
        if (!modes[i]) {
            DRM_DEBUG_KMS("looking for preferred mode on connector %s\n",
                          connector->name);
            modes[i] = drm_has_preferred_mode(fb_conn, width,
                                              height);
        }

        /* No preferred mode marked by the EDID? Are there any modes? */
        if (!modes[i] && !list_empty(&connector->modes)) {
            DRM_DEBUG_KMS("using first mode listed on connector %s\n",
                          connector->name);
            modes[i] = list_first_entry(&connector->modes,
                                        struct drm_display_mode,
                                        head);
        }

        /* last resort: use current mode */
        if (!modes[i]) {
            /*
             * IMPORTANT: We want to use the adjusted mode (i.e.
             * after the panel fitter upscaling) as the initial
             * config, not the input mode, which is what crtc->mode
             * usually contains. But since our current fastboot
             * code puts a mode derived from the post-pfit timings
             * into crtc->mode this works out correctly. We don't
             * use hwmode anywhere right now, so use it for this
             * since the fb helper layer wants a pointer to
             * something we own.
             */
            DRM_DEBUG_KMS("looking for current mode on connector %s\n",
                          connector->name);
            intel_mode_from_pipe_config(&encoder->crtc->hwmode,
                                        &to_intel_crtc(encoder->crtc)->config);
            modes[i] = &encoder->crtc->hwmode;
        }
        crtcs[i] = new_crtc;

        DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
                      connector->name,
                      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
                      encoder->crtc->base.id,
                      modes[i]->hdisplay, modes[i]->vdisplay,
                      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");

        fallback = false;
    }
Example #26
0
static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
			       enum pipe pipe,
			       enum intel_pipe_crc_source source)
{
	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
	enum intel_display_power_domain power_domain;
	u32 val = 0; /* shut up gcc */
	int ret;

	if (pipe_crc->source == source)
		return 0;

	/* forbid changing the source without going back to 'none' */
	if (pipe_crc->source && source)
		return -EINVAL;

	power_domain = POWER_DOMAIN_PIPE(pipe);
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
		DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
		return -EIO;
	}

	ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val);
	if (ret != 0)
		goto out;

	/* none -> real source transition */
	if (source) {
		struct intel_pipe_crc_entry *entries;

		DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n",
				 pipe_name(pipe), pipe_crc_source_name(source));

		entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR,
				  sizeof(pipe_crc->entries[0]),
				  GFP_KERNEL);
		if (!entries) {
			ret = -ENOMEM;
			goto out;
		}

		/*
		 * When IPS gets enabled, the pipe CRC changes. Since IPS gets
		 * enabled and disabled dynamically based on package C states,
		 * user space can't make reliable use of the CRCs, so let's just
		 * completely disable it.
		 */
		hsw_disable_ips(crtc);

		spin_lock_irq(&pipe_crc->lock);
		kfree(pipe_crc->entries);
		pipe_crc->entries = entries;
		pipe_crc->head = 0;
		pipe_crc->tail = 0;
		spin_unlock_irq(&pipe_crc->lock);
	}

	pipe_crc->source = source;

	I915_WRITE(PIPE_CRC_CTL(pipe), val);
	POSTING_READ(PIPE_CRC_CTL(pipe));

	/* real source -> none transition */
	if (!source) {
		struct intel_pipe_crc_entry *entries;
		struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
								  pipe);

		DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
				 pipe_name(pipe));

		drm_modeset_lock(&crtc->base.mutex, NULL);
		if (crtc->base.state->active)
			intel_wait_for_vblank(dev_priv, pipe);
		drm_modeset_unlock(&crtc->base.mutex);

		spin_lock_irq(&pipe_crc->lock);
		entries = pipe_crc->entries;
		pipe_crc->entries = NULL;
		pipe_crc->head = 0;
		pipe_crc->tail = 0;
		spin_unlock_irq(&pipe_crc->lock);

		kfree(entries);

		if (IS_G4X(dev_priv))
			g4x_undo_pipe_scramble_reset(dev_priv, pipe);
		else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
			vlv_undo_pipe_scramble_reset(dev_priv, pipe);
		else if (IS_HASWELL(dev_priv) && pipe == PIPE_A)
			hsw_trans_edp_pipe_A_crc_wa(dev_priv, false);

		hsw_enable_ips(crtc);
	}

	ret = 0;

out:
	intel_display_power_put(dev_priv, power_domain);

	return ret;
}
Example #27
0
void intel_ddi_mode_set(struct drm_encoder *encoder,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc = encoder->crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
	int port = intel_hdmi->ddi_port;
	int pipe = intel_crtc->pipe;
	int p, n2, r2, valid=0;
	u32 temp, i;

	/* On Haswell, we need to enable the clocks and prepare DDI function to
	 * work in HDMI mode for this pipe.
	 */
	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));

	for (i=0; i < DRM_ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
		if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
			p = wrpll_tmds_clock_table[i].p;
			n2 = wrpll_tmds_clock_table[i].n2;
			r2 = wrpll_tmds_clock_table[i].r2;

			DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
					crtc->mode.clock,
					p, n2, r2);

			valid = 1;
			break;
		}
	}

	if (!valid) {
		DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
				crtc->mode.clock);
		return;
	}

	/* Enable LCPLL if disabled */
	temp = I915_READ(LCPLL_CTL);
	if (temp & LCPLL_PLL_DISABLE)
		I915_WRITE(LCPLL_CTL,
				temp & ~LCPLL_PLL_DISABLE);

	/* Configure WR PLL 1, program the correct divider values for
	 * the desired frequency and wait for warmup */
	I915_WRITE(WRPLL_CTL1,
			WRPLL_PLL_ENABLE |
			WRPLL_PLL_SELECT_LCPLL_2700 |
			WRPLL_DIVIDER_REFERENCE(r2) |
			WRPLL_DIVIDER_FEEDBACK(n2) |
			WRPLL_DIVIDER_POST(p));

	DELAY(20);

	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
	 * this port for connection.
	 */
	I915_WRITE(PORT_CLK_SEL(port),
			PORT_CLK_SEL_WRPLL1);
	I915_WRITE(PIPE_CLK_SEL(pipe),
			PIPE_CLK_SEL_PORT(port));

	DELAY(20);

	if (intel_hdmi->has_audio) {
		/* Proper support for digital audio needs a new logic and a new set
		 * of registers, so we leave it for future patch bombing.
		 */
		DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
				 pipe_name(intel_crtc->pipe));
	}

	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
	temp = I915_READ(DDI_FUNC_CTL(pipe));
	temp &= ~PIPE_DDI_PORT_MASK;
	temp &= ~PIPE_DDI_BPC_12;
	temp |= PIPE_DDI_SELECT_PORT(port) |
			PIPE_DDI_MODE_SELECT_HDMI |
			((intel_crtc->bpp > 24) ?
				PIPE_DDI_BPC_12 :
				PIPE_DDI_BPC_8) |
			PIPE_DDI_FUNC_ENABLE;

	I915_WRITE(DDI_FUNC_CTL(pipe), temp);

	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
	intel_hdmi_set_spd_infoframe(encoder);
}
Example #28
0
static void intel_ddi_mode_set(struct drm_encoder *encoder,
			       struct drm_display_mode *mode,
			       struct drm_display_mode *adjusted_mode)
{
	struct drm_crtc *crtc = encoder->crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
	int port = intel_ddi_get_encoder_port(intel_encoder);
	int pipe = intel_crtc->pipe;
	int type = intel_encoder->type;

	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
		      port_name(port), pipe_name(pipe));

	intel_crtc->eld_vld = false;
	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
		struct intel_digital_port *intel_dig_port =
			enc_to_dig_port(encoder);

		intel_dp->DP = intel_dig_port->port_reversal |
			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
		switch (intel_dp->lane_count) {
		case 1:
			intel_dp->DP |= DDI_PORT_WIDTH_X1;
			break;
		case 2:
			intel_dp->DP |= DDI_PORT_WIDTH_X2;
			break;
		case 4:
			intel_dp->DP |= DDI_PORT_WIDTH_X4;
			break;
		default:
			intel_dp->DP |= DDI_PORT_WIDTH_X4;
			WARN(1, "Unexpected DP lane count %d\n",
			     intel_dp->lane_count);
			break;
		}

		if (intel_dp->has_audio) {
			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
					 pipe_name(intel_crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("DP audio: write eld information\n");
			intel_write_eld(encoder, adjusted_mode);
		}

		intel_dp_init_link_config(intel_dp);

	} else if (type == INTEL_OUTPUT_HDMI) {
		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);

		if (intel_hdmi->has_audio) {
			/* Proper support for digital audio needs a new logic
			 * and a new set of registers, so we leave it for future
			 * patch bombing.
			 */
			DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
					 pipe_name(intel_crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
			intel_write_eld(encoder, adjusted_mode);
		}

		intel_hdmi->set_infoframes(encoder, adjusted_mode);
	}
}