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); }
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); } }
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; }
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); }
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)); }
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)); }
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); }
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; }
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; }
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; }
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; }
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)); }
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)); }
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; }
/** * __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; }
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); }
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); }
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); }
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; }
/** * 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); }
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)); } }
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; }
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); }
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; }
/* * 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; }
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; }
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); }
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); } }