int pl111_crtc_helper_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { int ret; struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); struct drm_display_mode *duplicated_mode; DRM_DEBUG_KMS("DRM crtc_helper_mode_set, x=%d y=%d bpp=%d\n", adjusted_mode->hdisplay, adjusted_mode->vdisplay, crtc->fb->bits_per_pixel); duplicated_mode = drm_mode_duplicate(crtc->dev, adjusted_mode); if (!duplicated_mode) return -ENOMEM; pl111_crtc->new_mode = duplicated_mode; ret = show_framebuffer_on_crtc(crtc, crtc->fb, false, NULL); if (ret != 0) { pl111_crtc->new_mode = pl111_crtc->current_mode; drm_mode_destroy(crtc->dev, duplicated_mode); } return ret; }
static int omap_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; struct omap_video_timings timings = {0}; struct drm_device *dev = connector->dev; struct drm_display_mode *new_mode; int ret = MODE_BAD; copy_timings_drm_to_omap(&timings, mode); mode->vrefresh = drm_mode_vrefresh(mode); if (!dssdrv->check_timings(dssdev, &timings)) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); new_mode->clock = timings.pixel_clock; new_mode->vrefresh = 0; if (mode->vrefresh == drm_mode_vrefresh(new_mode)) ret = MODE_OK; drm_mode_destroy(dev, new_mode); } DBG("connector: mode %s: " "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", (ret == MODE_OK) ? "valid" : "invalid", mode->base.id, mode->name, mode->vrefresh, mode->clock, mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); return ret; }
static int intel_dsi_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dsi *intel_dsi = intel_attached_dsi(connector); struct drm_display_mode *mode; struct drm_display_mode *input_mode = NULL; DRM_DEBUG_KMS("\n"); if (!intel_connector->panel.fixed_mode) { DRM_DEBUG_KMS("no fixed mode\n"); return 0; } input_mode = intel_connector->panel.fixed_mode; mode = drm_mode_duplicate(connector->dev, input_mode); if (!mode) { DRM_DEBUG_KMS("drm_mode_duplicate failed\n"); return 0; } drm_mode_probed_add(connector, mode); /*Fill the panel info here*/ intel_dsi->dev.dev_ops->get_info(0, connector); return 1; }
void intel_dsi_set_drrs_state(struct intel_encoder *intel_encoder) { struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; struct drm_display_mode *target_mode = dev_priv->drrs.connector->panel.target_mode; struct intel_mipi_drrs_work *work = dev_priv->drrs.mipi_drrs_work; unsigned int ret; ret = work_busy(&work->work.work); if (ret) { if (work->target_mode) if (work->target_mode->vrefresh == target_mode->vrefresh) { DRM_DEBUG_KMS("Repeated request for %dHz\n", target_mode->vrefresh); return; } DRM_DEBUG_KMS("Cancelling an queued/executing work\n"); atomic_set(&work->abort_wait_loop, 1); cancel_delayed_work_sync(&work->work); atomic_set(&work->abort_wait_loop, 0); if (ret & WORK_BUSY_PENDING) drm_mode_destroy(intel_encoder->base.dev, work->target_mode); } work->intel_encoder = intel_encoder; work->target_rr_type = dev_priv->drrs_state.target_rr_type; work->target_mode = drm_mode_duplicate(intel_encoder->base.dev, target_mode); schedule_delayed_work(&dev_priv->drrs.mipi_drrs_work->work, 0); }
static int meson_connector_get_modes(struct drm_connector *connector) { struct meson_connector *meson_connector = to_meson_connector(connector); struct drm_device *dev = connector->dev; drm_mode_probed_add(connector, drm_mode_duplicate(dev, meson_connector->mode)); return 1; }
static int omap_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; struct videomode vm = {0}; struct drm_device *dev = connector->dev; struct drm_display_mode *new_mode; int r, ret = MODE_BAD; drm_display_mode_to_videomode(mode, &vm); vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE; mode->vrefresh = drm_mode_vrefresh(mode); /* * if the panel driver doesn't have a check_timings, it's most likely * a fixed resolution panel, check if the timings match with the * panel's timings */ if (dssdrv->check_timings) { r = dssdrv->check_timings(dssdev, &vm); } else { struct videomode t = {0}; dssdrv->get_timings(dssdev, &t); if (memcmp(&vm, &t, sizeof(struct videomode))) r = -EINVAL; else r = 0; } if (!r) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); new_mode->clock = vm.pixelclock / 1000; new_mode->vrefresh = 0; if (mode->vrefresh == drm_mode_vrefresh(new_mode)) ret = MODE_OK; drm_mode_destroy(dev, new_mode); } DBG("connector: mode %s: " "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", (ret == MODE_OK) ? "valid" : "invalid", mode->base.id, mode->name, mode->vrefresh, mode->clock, mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); return ret; }
/** * add_established_modes - get est. modes from EDID and add them * @edid: EDID block to scan * * Each EDID block contains a bitmap of the supported "established modes" list * (defined above). Tease them out and add them to the global modes list. */ static int add_established_modes(struct drm_output *output, struct edid *edid) { struct drm_device *dev = output->dev; unsigned long est_bits = edid->established_timings.t1 | (edid->established_timings.t2 << 8) | ((edid->established_timings.mfg_rsvd & 0x80) << 9); int i, modes = 0; for (i = 0; i <= EDID_EST_TIMINGS; i++) if (est_bits & (1<<i)) { struct drm_display_mode *newmode; newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); drm_mode_probed_add(output, newmode); modes++; } return modes; }
static int ch7006_encoder_get_modes(struct drm_encoder *encoder, struct drm_connector *connector) { struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_mode *mode; int n = 0; for (mode = ch7006_modes; mode->mode.clock; mode++) { if (~mode->valid_scales & 1<<priv->scale || ~mode->valid_norms & 1<<priv->norm) continue; drm_mode_probed_add(connector, drm_mode_duplicate(encoder->dev, &mode->mode)); n++; } return n; }
static int intel_dsi_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *mode; DRM_DEBUG_KMS("\n"); if (!intel_connector->panel.fixed_mode) { DRM_DEBUG_KMS("no fixed mode\n"); return 0; } mode = drm_mode_duplicate(connector->dev, intel_connector->panel.fixed_mode); if (!mode) { DRM_DEBUG_KMS("drm_mode_duplicate failed\n"); return 0; } drm_mode_probed_add(connector, mode); return 1; }
static int s6e3ha2_get_modes(struct drm_panel *panel) { struct drm_connector *connector = panel->connector; struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); struct drm_display_mode *mode; mode = drm_mode_duplicate(panel->drm, ctx->desc->mode); if (!mode) { DRM_ERROR("failed to add mode %ux%ux@%u\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, ctx->desc->mode->vrefresh); return -ENOMEM; } drm_mode_set_name(mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); connector->display_info.width_mm = 71; connector->display_info.height_mm = 125; return 1; }
static void intel_mipi_drrs_work_fn(struct work_struct *__work) { struct intel_mipi_drrs_work *work = container_of(to_delayed_work(__work), struct intel_mipi_drrs_work, work); struct intel_encoder *intel_encoder = work->intel_encoder; struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; struct intel_dsi_mnp *intel_dsi_mnp; struct intel_dsi *intel_dsi = NULL; struct intel_crtc *intel_crtc = NULL; struct drm_display_mode *prev_mode = NULL; bool resume_idleness_detection = false, fallback_attempt = false; int ret, retry_cnt = 3; intel_dsi = enc_to_intel_dsi(&intel_encoder->base); intel_crtc = intel_encoder->new_crtc; init: if (work->target_rr_type == DRRS_HIGH_RR) { intel_dsi_mnp = &intel_crtc->config.dsi_mnp; } else if (work->target_rr_type == DRRS_LOW_RR) { intel_dsi_mnp = &intel_crtc->config.dsi_mnp2; } else if (work->target_rr_type == DRRS_MEDIA_RR) { if (intel_calculate_dsi_pll_mnp(intel_dsi, work->target_mode, &intel_crtc->config.dsi_mnp3, 0) < 0) return; intel_dsi_mnp = &intel_crtc->config.dsi_mnp3; } else { DRM_ERROR("Unknown refreshrate_type\n"); return; } if (dev_priv->drrs_state.refresh_rate_type == DRRS_MEDIA_RR && work->target_rr_type == DRRS_HIGH_RR) resume_idleness_detection = true; retry: ret = intel_drrs_configure_dsi_pll(intel_dsi, intel_dsi_mnp); if (ret == 0) { DRM_DEBUG_KMS("cur_rr_type: %d, cur_rr: %d, target_rr_type: %d, target_rr: %d\n", dev_priv->drrs_state.refresh_rate_type, intel_crtc->base.mode.vrefresh, work->target_rr_type, work->target_mode->vrefresh); mutex_lock(&dev_priv->drrs_state.mutex); dev_priv->drrs_state.refresh_rate_type = work->target_rr_type; mutex_unlock(&dev_priv->drrs_state.mutex); DRM_INFO("Refresh Rate set to : %dHz\n", work->target_mode->vrefresh); intel_crtc->base.mode.vrefresh = work->target_mode->vrefresh; intel_crtc->base.mode.clock = work->target_mode->clock; if (resume_idleness_detection) intel_update_drrs(intel_encoder->base.dev); } else if (ret == -ETIMEDOUT && retry_cnt) { retry_cnt--; DRM_DEBUG_KMS("Retry left ... <%d>\n", retry_cnt); goto retry; } else if (ret == -EACCES && !fallback_attempt) { DRM_ERROR("Falling back to the previous DRRS state. %d->%d\n", work->target_rr_type, dev_priv->drrs_state.refresh_rate_type); mutex_lock(&dev_priv->drrs_state.mutex); dev_priv->drrs_state.target_rr_type = dev_priv->drrs_state.refresh_rate_type; mutex_unlock(&dev_priv->drrs_state.mutex); work->target_rr_type = dev_priv->drrs_state.target_rr_type; drm_mode_destroy(intel_encoder->base.dev, work->target_mode); if (work->target_rr_type == DRRS_HIGH_RR) { prev_mode = dev_priv->drrs.connector->panel.fixed_mode; resume_idleness_detection = true; } else if (work->target_rr_type == DRRS_LOW_RR) { prev_mode = dev_priv->drrs.connector->panel.downclock_mode; } else if (work->target_rr_type == DRRS_MEDIA_RR) { prev_mode = dev_priv->drrs.connector->panel.target_mode; } work->target_mode = drm_mode_duplicate(intel_encoder->base.dev, prev_mode); if (!work->target_mode) { DRM_ERROR("target mode creation failed\n"); return; } fallback_attempt = true; goto init; } else { if (fallback_attempt) DRM_ERROR("DRRS State Fallback attempt failed\n"); if (ret == -ETIMEDOUT) DRM_ERROR("TIMEDOUT in all retry attempt\n"); } drm_mode_destroy(intel_encoder->base.dev, work->target_mode); }