static int rcar_lvds_connector_atomic_check(struct drm_connector *connector, struct drm_connector_state *state) { struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); const struct drm_display_mode *panel_mode; struct drm_crtc_state *crtc_state; if (list_empty(&connector->modes)) { dev_dbg(lvds->dev, "connector: empty modes list\n"); return -EINVAL; } panel_mode = list_first_entry(&connector->modes, struct drm_display_mode, head); /* We're not allowed to modify the resolution. */ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); if (crtc_state->mode.hdisplay != panel_mode->hdisplay || crtc_state->mode.vdisplay != panel_mode->vdisplay) return -EINVAL; /* The flat panel mode is fixed, just copy it to the adjusted mode. */ drm_mode_copy(&crtc_state->adjusted_mode, panel_mode); return 0; }
static int mtk_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; struct drm_crtc_state *crtc_state; struct drm_rect clip = { 0, }; if (!fb) return 0; if (!mtk_fb_get_gem_obj(fb)) { DRM_DEBUG_KMS("buffer is null\n"); return -EFAULT; } if (!state->crtc) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); clip.x2 = crtc_state->mode.hdisplay; clip.y2 = crtc_state->mode.vdisplay; return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, true, true); }
static int vkms_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_crtc_state *crtc_state; bool can_position = false; int ret; if (!state->fb | !state->crtc) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) can_position = true; ret = drm_atomic_helper_check_plane_state(state, crtc_state, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, can_position, true); if (ret != 0) return ret; /* for now primary plane must be visible and full screen */ if (!state->visible && !can_position) return -EINVAL; return 0; }
/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for * * This function returns the plane state for the given plane, allocating it if * needed. It will also grab the relevant plane lock to make sure that the state * is consistent. * * Returns: * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. */ struct drm_plane_state * drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane) { int ret, index = drm_plane_index(plane); struct drm_plane_state *plane_state; WARN_ON(!state->acquire_ctx); /* the legacy pointers should never be set */ WARN_ON(plane->fb); WARN_ON(plane->old_fb); WARN_ON(plane->crtc); plane_state = drm_atomic_get_existing_plane_state(state, plane); if (plane_state) return plane_state; ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx); if (ret) return ERR_PTR(ret); plane_state = plane->funcs->atomic_duplicate_state(plane); if (!plane_state) return ERR_PTR(-ENOMEM); state->planes[index].state = plane_state; state->planes[index].ptr = plane; state->planes[index].old_state = plane->state; state->planes[index].new_state = plane_state; plane_state->state = state; DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n", plane->base.id, plane->name, plane_state, state); if (plane_state->crtc) { struct drm_crtc_state *crtc_state; crtc_state = drm_atomic_get_crtc_state(state, plane_state->crtc); if (IS_ERR(crtc_state)) return ERR_CAST(crtc_state); } return plane_state; }
static int ade_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; struct drm_crtc *crtc = state->crtc; struct drm_crtc_state *crtc_state; u32 src_x = state->src_x >> 16; u32 src_y = state->src_y >> 16; u32 src_w = state->src_w >> 16; u32 src_h = state->src_h >> 16; int crtc_x = state->crtc_x; int crtc_y = state->crtc_y; u32 crtc_w = state->crtc_w; u32 crtc_h = state->crtc_h; u32 fmt; if (!crtc || !fb) return 0; fmt = ade_get_format(fb->pixel_format); if (fmt == ADE_FORMAT_UNSUPPORT) return -EINVAL; crtc_state = drm_atomic_get_crtc_state(state->state, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); if (src_w != crtc_w || src_h != crtc_h) { DRM_ERROR("Scale not support!!!\n"); return -EINVAL; } if (src_x + src_w > fb->width || src_y + src_h > fb->height) return -EINVAL; if (crtc_x < 0 || crtc_y < 0) return -EINVAL; if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay || crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay) return -EINVAL; return 0; }
/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for * * This function returns the plane state for the given plane, allocating it if * needed. It will also grab the relevant plane lock to make sure that the state * is consistent. * * Returns: * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. */ struct drm_plane_state * drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane) { int ret, index; struct drm_plane_state *plane_state; index = drm_plane_index(plane); if (state->plane_states[index]) return state->plane_states[index]; ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx); if (ret) return ERR_PTR(ret); plane_state = plane->funcs->atomic_duplicate_state(plane); if (!plane_state) return ERR_PTR(-ENOMEM); state->plane_states[index] = plane_state; state->planes[index] = plane; plane_state->state = state; DRM_DEBUG_ATOMIC("Added [PLANE:%d] %p state to %p\n", plane->base.id, plane_state, state); if (plane_state->crtc) { struct drm_crtc_state *crtc_state; crtc_state = drm_atomic_get_crtc_state(state, plane_state->crtc); if (IS_ERR(crtc_state)) return ERR_CAST(crtc_state); } return plane_state; }
static int mdp5_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct drm_plane_state *old_state = plane->state; DBG("%s: check (%d -> %d)", mdp5_plane->name, plane_enabled(old_state), plane_enabled(state)); if (plane_enabled(state) && plane_enabled(old_state)) { /* we cannot change SMP block configuration during scanout: */ bool full_modeset = false; if (state->fb->pixel_format != old_state->fb->pixel_format) { DBG("%s: pixel_format change!", mdp5_plane->name); full_modeset = true; } if (state->src_w != old_state->src_w) { DBG("%s: src_w change!", mdp5_plane->name); full_modeset = true; } if (to_mdp5_plane_state(old_state)->pending) { DBG("%s: still pending!", mdp5_plane->name); full_modeset = true; } if (full_modeset) { struct drm_crtc_state *crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); crtc_state->mode_changed = true; to_mdp5_plane_state(state)->mode_changed = true; } } else { to_mdp5_plane_state(state)->mode_changed = true; } return 0; }
static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, struct drm_plane_state *state) { struct sti_plane *plane = to_sti_plane(drm_plane); struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane); struct drm_crtc *crtc = state->crtc; struct drm_framebuffer *fb = state->fb; bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false; struct drm_crtc_state *crtc_state; struct drm_display_mode *mode; int dst_x, dst_y, dst_w, dst_h; int src_x, src_y, src_w, src_h; /* no need for further checks if the plane is being disabled */ if (!crtc || !fb) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, crtc); mode = &crtc_state->mode; dst_x = state->crtc_x; dst_y = state->crtc_y; dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x); dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y); /* src_x are in 16.16 format */ src_x = state->src_x >> 16; src_y = state->src_y >> 16; src_w = state->src_w >> 16; src_h = state->src_h >> 16; if (!sti_hqvdp_check_hw_scaling(hqvdp, mode, src_w, src_h, dst_w, dst_h)) { DRM_ERROR("Scaling beyond HW capabilities\n"); return -EINVAL; } if (!drm_fb_cma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } /* * Input / output size * Align to upper even value */ dst_w = ALIGN(dst_w, 2); dst_h = ALIGN(dst_h, 2); if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) || (src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) || (dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) || (dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) { DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n", src_w, src_h, dst_w, dst_h); return -EINVAL; } if (first_prepare) { /* Start HQVDP XP70 coprocessor */ sti_hqvdp_start_xp70(hqvdp); /* Prevent VTG shutdown */ if (clk_prepare_enable(hqvdp->clk_pix_main)) { DRM_ERROR("Failed to prepare/enable pix main clk\n"); return -EINVAL; } /* Register VTG Vsync callback to handle bottom fields */ if (sti_vtg_register_client(hqvdp->vtg, &hqvdp->vtg_nb, crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); return -EINVAL; } } DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)), drm_plane->base.id, sti_plane_to_str(plane)); DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", sti_plane_to_str(plane), dst_w, dst_h, dst_x, dst_y, src_w, src_h, src_x, src_y); return 0; }