static void intel_psr_write_vsc(struct intel_dp *intel_dp, struct edp_vsc_psr *vsc_psr) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config.cpu_transcoder); u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config.cpu_transcoder); uint32_t *data = (uint32_t *) vsc_psr; unsigned int i; /* As per BSPec (Pipe Video Data Island Packet), we need to disable the video DIP being updated before program video DIP data buffer registers for DIP being updated. */ I915_WRITE(ctl_reg, 0); POSTING_READ(ctl_reg); for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) { if (i < sizeof(struct edp_vsc_psr)) I915_WRITE(data_reg + i, *data++); else I915_WRITE(data_reg + i, 0); } I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW); POSTING_READ(ctl_reg); }
static void ibx_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); u32 port; assert_hdmi_port_disabled(intel_hdmi); /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; if (!intel_hdmi->has_hdmi_sink) { if (!(val & VIDEO_DIP_ENABLE)) return; val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); POSTING_READ(reg); return; } switch (intel_dig_port->port) { case PORT_B: port = VIDEO_DIP_PORT_B; break; case PORT_C: port = VIDEO_DIP_PORT_C; break; case PORT_D: port = VIDEO_DIP_PORT_D; break; default: BUG(); return; } if (port != (val & VIDEO_DIP_PORT_MASK)) { if (val & VIDEO_DIP_ENABLE) { val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); POSTING_READ(reg); } val &= ~VIDEO_DIP_PORT_MASK; val |= port; } val |= VIDEO_DIP_ENABLE; val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); }
int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, u8 *buf, int buflen) { struct drm_encoder *encoder = &intel_dsi->base.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); enum pipe pipe = intel_crtc->pipe; u32 mask; int ret; /* * XXX: should issue multiple read requests and reads if request is * longer than MIPI_MAX_RETURN_PKT_SIZE */ I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL); ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd); if (ret) return ret; mask = GEN_READ_DATA_AVAIL; if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for read data.\n"); ret = dsi_read_data_return(intel_dsi, buf, buflen); if (ret < 0) return ret; if (ret != buflen) return -EIO; return 0; }
static void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); int pipe = intel_crtc->pipe; u32 val; DRM_DEBUG_KMS("\n"); mutex_lock(&dev_priv->dpio_lock); /* program rcomp for compliance, reduce from 50 ohms to 45 ohms * needed everytime after power gate */ vlv_flisdsi_write(dev_priv, 0x04, 0x0004); mutex_unlock(&dev_priv->dpio_lock); /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(dev_priv); I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); usleep_range(2500, 3000); val = I915_READ(MIPI_PORT_CTRL(pipe)); I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD); usleep_range(1000, 1500); I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); usleep_range(2500, 3000); I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); usleep_range(2500, 3000); }
static void intel_psr_write_vsc(struct intel_dp *intel_dp, const struct edp_vsc_psr *vsc_psr) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); uint32_t *data = (uint32_t *) vsc_psr; unsigned int i; /* As per BSPec (Pipe Video Data Island Packet), we need to disable the video DIP being updated before program video DIP data buffer registers for DIP being updated. */ I915_WRITE(ctl_reg, 0); POSTING_READ(ctl_reg); for (i = 0; i < sizeof(*vsc_psr); i += 4) { I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i >> 2), *data); data++; } for (; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i >> 2), 0); I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW); POSTING_READ(ctl_reg); }
int intel_configure_dsi_pll(struct intel_dsi *intel_dsi, struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private; struct drm_encoder *encoder = &(intel_dsi->base.base); struct intel_connector *intel_connector = intel_dsi->attached_connector; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_crtc_config *config = &intel_crtc->config; int ret; DRM_DEBUG_KMS("\n"); ret = intel_calculate_dsi_pll_mnp(intel_dsi, mode, &config->dsi_mnp, intel_dsi->dsi_clock_freq); if (ret < 0) return ret; /* In case of DRRS, Calculating the divider values for downclock_mode */ if (intel_connector->panel.downclock_avail && dev_priv->drrs_state.type >= SEAMLESS_DRRS_SUPPORT) { ret = intel_calculate_dsi_pll_mnp(intel_dsi, intel_connector->panel.downclock_mode, &config->dsi_mnp2, 0); if (ret < 0) return ret; } intel_configure_dsi_pll_reg(dev_priv, &config->dsi_mnp, intel_dsi, false); return 0; }
static void intel_dsi_pre_enable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; DRM_DEBUG_KMS("\n"); intel_enable_dsi_pll(intel_dsi); if (is_cmd_mode(intel_dsi)) { /* XXX: Implement me */ I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); } else { intel_dsi->hs = 0; dpi_send_cmd(intel_dsi, TURN_ON); usleep_range(1000, 1500); if (intel_dsi->dev.dev_ops->enable) intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); intel_dsi_port_enable(encoder); } }
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct dip_infoframe avi_if = { .type = DIP_TYPE_AVI, .ver = DIP_VERSION_AVI, .len = DIP_LEN_AVI, }; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2; if (intel_hdmi->rgb_quant_range_selectable) { if (intel_crtc->config.limited_color_range) avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED; else avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL; } avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode); intel_set_infoframe(encoder, &avi_if); }
/* * send a video mode command * * XXX: commands with data in MIPI_DPI_DATA? */ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs) { struct drm_encoder *encoder = &intel_dsi->base.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); enum pipe pipe = intel_crtc->pipe; u32 mask; /* XXX: pipe, hs */ if (hs) cmd &= ~DPI_LP_MODE; else cmd |= DPI_LP_MODE; /* clear bit */ I915_WRITE(MIPI_INTR_STAT(pipe), SPL_PKT_SENT_INTERRUPT); /* XXX: old code skips write if control unchanged */ if (cmd == I915_READ(MIPI_DPI_CONTROL(pipe))) DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); I915_WRITE(MIPI_DPI_CONTROL(pipe), cmd); mask = SPL_PKT_SENT_INTERRUPT; if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 100)) DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd); return 0; }
static void hsw_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); assert_hdmi_port_disabled(intel_hdmi); if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); POSTING_READ(reg); return; } val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); I915_WRITE(reg, val); POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); }
static void intel_dsi_disable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; u32 temp; DRM_DEBUG_KMS("\n"); if (is_vid_mode(intel_dsi)) { dpi_send_cmd(intel_dsi, SHUTDOWN); msleep(10); /* de-assert ip_tg_enable signal */ temp = I915_READ(MIPI_PORT_CTRL(pipe)); I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE); POSTING_READ(MIPI_PORT_CTRL(pipe)); msleep(2); } /* if disable packets are sent before sending shutdown packet then in * some next enable sequence send turn on packet error is observed */ if (intel_dsi->dev.dev_ops->disable) intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); }
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); int pipe = intel_crtc->pipe; u32 val; DRM_DEBUG_KMS("\n"); I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); usleep_range(2000, 2500); I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); usleep_range(2000, 2500); I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); usleep_range(2000, 2500); val = I915_READ(MIPI_PORT_CTRL(pipe)); I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD); usleep_range(1000, 1500); if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT) == 0x00000), 30)) DRM_ERROR("DSI LP not going Low\n"); I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); usleep_range(2000, 2500); vlv_disable_dsi_pll(encoder); }
static void vlv_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); assert_hdmi_port_disabled(intel_hdmi); /* See the big comment in g4x_set_infoframes() */ val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; if (!intel_hdmi->has_hdmi_sink) { if (!(val & VIDEO_DIP_ENABLE)) return; val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); POSTING_READ(reg); return; } val |= VIDEO_DIP_ENABLE; val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); I915_WRITE(reg, val); POSTING_READ(reg); intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); }
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 drm_crtc *crtc = encoder->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_output *intel_output = enc_to_intel_output(encoder); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; u32 sdvox; sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE | SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; if (hdmi_priv->has_hdmi_sink) sdvox |= SDVO_AUDIO_ENABLE; if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; I915_WRITE(hdmi_priv->sdvox_reg, sdvox); POSTING_READ(hdmi_priv->sdvox_reg); }
static void hsw_write_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) { uint32_t *data = (uint32_t *)frame; 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); u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->pipe); unsigned int i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(ctl_reg); if (data_reg == 0) return; val &= ~hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } /* Write every possible data byte to force correct ECC calculation. */ for (; i < VIDEO_DIP_DATA_SIZE; i += 4) I915_WRITE(data_reg + i, 0); mmiowb(); val |= hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); POSTING_READ(ctl_reg); }
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); union hdmi_infoframe frame; int ret; ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, adjusted_mode); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return; } if (intel_hdmi->rgb_quant_range_selectable) { if (intel_crtc->config.limited_color_range) frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; else frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; } intel_write_infoframe(encoder, &frame); }
static void hsw_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) { uint32_t *data = (uint32_t *)frame; 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); u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); u32 data_reg; int i; u32 val = I915_READ(ctl_reg); data_reg = hsw_infoframe_data_reg(type, intel_crtc->config.cpu_transcoder); if (data_reg == 0) return; val &= ~hsw_infoframe_enable(type); I915_WRITE(ctl_reg, val); mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } /* Write every possible data byte to force correct ECC calculation. */ for (; i < VIDEO_DIP_DATA_SIZE; i += 4) I915_WRITE(data_reg + i, 0); mmiowb(); val |= hsw_infoframe_enable(type); I915_WRITE(ctl_reg, val); POSTING_READ(ctl_reg); }
static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; if (!IS_VALLEYVIEW(dev)) return; /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), 0x00002000); vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), DPIO_TX_OCALINIT_EN); mutex_unlock(&dev_priv->dpio_lock); }
static void intel_dsi_enable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; u32 temp; DRM_DEBUG_KMS("\n"); if (is_cmd_mode(intel_dsi)) I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); else { msleep(20); /* XXX */ dpi_send_cmd(intel_dsi, TURN_ON); msleep(100); /* assert ip_tg_enable signal */ temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK; temp = temp | intel_dsi->port_bits; I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); POSTING_READ(MIPI_PORT_CTRL(pipe)); } if (intel_dsi->dev.dev_ops->enable) intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); }
static int dsi_read_data_return(struct intel_dsi *intel_dsi, u8 *buf, int buflen) { struct drm_encoder *encoder = &intel_dsi->base.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); enum pipe pipe = intel_crtc->pipe; int i, len = 0; u32 data_reg, val; if (intel_dsi->hs) { data_reg = MIPI_HS_GEN_DATA(pipe); } else { data_reg = MIPI_LP_GEN_DATA(pipe); } while (len < buflen) { val = I915_READ(data_reg); for (i = 0; i < 4 && len < buflen; i++, len++) buf[len] = val >> 8 * i; } return len; }
void intel_dsi_port_enable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; u32 val, port_control = 0; if (intel_dsi->dual_link) { port_control = (intel_dsi->dual_link - 1) << DUAL_LINK_MODE_SHIFT; if (pipe == PIPE_A) port_control |= LANE_CONFIGURATION_DUAL_LINK_A; else port_control |= LANE_CONFIGURATION_DUAL_LINK_B; /*Pixel overlap count; only for VLV CO stepping */ if (IS_VALLEYVIEW_C0(dev) && (intel_dsi->dual_link & MIPI_DUAL_LINK_FRONT_BACK)) { val = I915_READ(VLV_CHICKEN_3); val &= ~PIXEL_OVERLAP_CNT_MASK | intel_dsi->pixel_overlap << PIXEL_OVERLAP_CNT_SHIFT; I915_WRITE(VLV_CHICKEN_3, val); } /* Port A */ val = I915_READ(MIPI_PORT_CTRL(0)); val = val | port_control; I915_WRITE(MIPI_PORT_CTRL(0), val | DPI_ENABLE); if (!IS_VALLEYVIEW_C0(dev)) { /* for stepping before C0; we need to enable * PORTC explicitly. From C0 onwards enable PORT A * also enabled PORT C for dual link */ val = I915_READ(MIPI_PORT_CTRL(1)); I915_WRITE(MIPI_PORT_CTRL(1), val | DPI_ENABLE); } else { if (intel_crtc->config.dither) { val = I915_READ(MIPI_PORT_CTRL(0)); val = val | DITHERING_ENABLE; I915_WRITE(MIPI_PORT_CTRL(0), val); val = I915_READ(MIPI_PORT_CTRL(1)); val = val | DITHERING_ENABLE; I915_WRITE(MIPI_PORT_CTRL(1), val); } } usleep_range(2000, 2500); } else { val = I915_READ(MIPI_PORT_CTRL(pipe)); val = val | port_control; if (intel_crtc->config.dither && IS_VALLEYVIEW_C0(dev)) val |= DITHERING_ENABLE; I915_WRITE(MIPI_PORT_CTRL(pipe), val | DPI_ENABLE); usleep_range(2000, 2500); } }
void intel_disable_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); trace_intel_disable_plane(&plane->base, crtc); plane->disable_plane(plane, crtc_state); }
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum intel_display_power_domain power_domain; enum intel_pipe_crc_source source; u32 val = 0; /* shut up gcc */ int ret = 0; if (display_crc_ctl_parse_source(source_name, &source) < 0) { DRM_DEBUG_DRIVER("unknown source %s\n", source_name); return -EINVAL; } power_domain = POWER_DOMAIN_PIPE(crtc->index); 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, crtc->index, &source, &val); if (ret != 0) goto out; if (source) { /* * 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(intel_crtc); } I915_WRITE(PIPE_CRC_CTL(crtc->index), val); POSTING_READ(PIPE_CRC_CTL(crtc->index)); if (!source) { if (IS_G4X(dev_priv)) g4x_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_HASWELL(dev_priv) && crtc->index == PIPE_A) hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); hsw_enable_ips(intel_crtc); } pipe_crc->skipped = 0; *values_cnt = 5; out: intel_display_power_put(dev_priv, power_domain); return ret; }
static void set_dsi_timings(struct drm_encoder *encoder, const struct drm_display_mode *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_dsi *intel_dsi = enc_to_intel_dsi(encoder); int pipe = intel_crtc->pipe; unsigned int bpp = intel_crtc->config.pipe_bpp; unsigned int lane_count = intel_dsi->lane_count; u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp; hactive = mode->hdisplay; hfp = mode->hsync_start - mode->hdisplay; hsync = mode->hsync_end - mode->hsync_start; hbp = mode->htotal - mode->hsync_end; vfp = mode->vsync_start - mode->vdisplay; vsync = mode->vsync_end - mode->vsync_start; vbp = mode->vtotal - mode->vsync_end; /* horizontal values are in terms of high speed byte clock */ hactive = txbyteclkhs(hactive, bpp, lane_count); hfp = txbyteclkhs(hfp, bpp, lane_count); hsync = txbyteclkhs(hsync, bpp, lane_count); hbp = txbyteclkhs(hbp, bpp, lane_count); /* FIXME: Find better way to do this */ /* For 7x10 panel we need to have BLLP added to active */ /* Trying to find optimal BLLP Multiplier */ /* 2.875 - Original multiplier, Works with flicker */ /* 2.000 - works but still some flicker */ /* 1.500 - Works, No Flicker */ /* 1.250 - Works, No Flicker */ /* 1.100 - Doesn't work */ /* FIXME: Acer Mango spec requires to run the DSI clock at 500 to * 560Mbps. Recomendation is to run at 513 Mbps. The addition dsi * clock is to be filled with NULL packets. Refer to acer panel * spec for more details. */ if (dev_priv->mipi_panel_id == MIPI_DSI_AUO_B080XAT_PANEL_ID) hactive = (hactive * 10) / 8; I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); /* meaningful for video mode non-burst sync pulse mode only, can be zero * for non-burst sync events and burst modes */ I915_WRITE(MIPI_HSYNC_PADDING_COUNT(pipe), hsync); I915_WRITE(MIPI_HBP_COUNT(pipe), hbp); /* vertical values are in terms of lines */ I915_WRITE(MIPI_VFP_COUNT(pipe), vfp); I915_WRITE(MIPI_VSYNC_PADDING_COUNT(pipe), vsync); I915_WRITE(MIPI_VBP_COUNT(pipe), vbp); }
void intel_update_slave(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); trace_intel_update_plane(&plane->base, crtc); plane->update_slave(plane, crtc_state, plane_state); }
static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *state) { struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; struct intel_crtc *crtc = to_intel_crtc(state->crtc); return &intel_dp->mst_encoders[crtc->pipe]->base.base; }
/** Sets the color ramps on behalf of RandR */ static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); intel_crtc->lut_r[regno] = red >> 8; intel_crtc->lut_g[regno] = green >> 8; intel_crtc->lut_b[regno] = blue >> 8; }
static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); *red = intel_crtc->lut_r[regno] << 8; *green = intel_crtc->lut_g[regno] << 8; *blue = intel_crtc->lut_b[regno] << 8; }
int intel_drrs_configure_dsi_pll(struct intel_dsi *intel_dsi, struct intel_dsi_mnp *intel_dsi_mnp) { struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(intel_dsi->base.base.crtc); struct intel_mipi_drrs_work *work = dev_priv->drrs.mipi_drrs_work; u32 dsi_pll_ctrl, vactive; u32 dsl_offset = PIPEDSL(intel_crtc->pipe), dsl; unsigned long timeout; intel_configure_dsi_pll_reg(dev_priv, intel_dsi_mnp, intel_dsi, true); dsi_pll_ctrl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); dsi_pll_ctrl &= (~DSI_PLL_VCO_EN); vactive = (I915_READ(VTOTAL(intel_crtc->pipe)) & VERTICAL_ACTIVE_DISPLAY_MASK) + 1; timeout = jiffies + msecs_to_jiffies(50); do { if (atomic_read(&work->abort_wait_loop) == 1) { DRM_DEBUG_KMS("Aborting the pll update\n"); return -EPERM; } dsl = (I915_READ(dsl_offset) & DSL_LINEMASK_GEN3); if (jiffies >= timeout) { DRM_ERROR("Timeout at waiting for Vblank\n"); return -ETIMEDOUT; } } while (dsl <= vactive); mutex_lock(&dev_priv->dpio_lock); /* Toggle the VCO_EN to bring in the new dividers values */ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_pll_ctrl); dsi_pll_ctrl |= DSI_PLL_VCO_EN; vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_pll_ctrl); mutex_unlock(&dev_priv->dpio_lock); DRM_DEBUG_KMS("PLL Changed between DSL: %d, %d\n", dsl, I915_READ(dsl_offset) & DSL_LINEMASK_GEN3); if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) { DRM_ERROR("DSI PLL lock failed\n"); return -EACCES; } return 0; }
void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; u32 val; DRM_DEBUG_KMS("\n"); I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER | DEVICE_READY, ULPS_STATE_MASK | DEVICE_READY); usleep_range(2000, 2500); I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT | DEVICE_READY, ULPS_STATE_MASK | DEVICE_READY); usleep_range(2000, 2500); I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER | DEVICE_READY, ULPS_STATE_MASK | DEVICE_READY); usleep_range(2000, 2500); if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & 0x20000) == 0x00000), 30)) DRM_ERROR("DSI LP not going Low\n"); I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), 0, LP_OUTPUT_HOLD); usleep_range(1000, 1500); I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00, DEVICE_READY); usleep_range(2000, 2500); intel_disable_dsi_pll(intel_dsi); val = I915_READ(DSPCLK_GATE_D); val &= ~VSUNIT_CLOCK_GATE_DISABLE; I915_WRITE(DSPCLK_GATE_D, val); if (intel_dsi->dev.dev_ops->disable_panel_power) intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev); #ifdef CONFIG_CRYSTAL_COVE if (BYT_CR_CONFIG) { /* Disable Panel */ vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PCONF0, 0x2000CC00); vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PAD, 0x00000004); udelay(500); } else intel_mid_pmic_writeb(PMIC_PANEL_EN, 0x00); #else /* need to code for BYT-CR for example where things have changed */ DRM_ERROR("PANEL Disable to supported yet\n"); #endif msleep(intel_dsi->panel_off_delay); msleep(intel_dsi->panel_pwr_cycle_delay); }