mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
drm/imx: add FB modifier support
This adds FB modifier support for the Vivante single buffer tiled formats, when the PRG/PRE engines are present. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
This commit is contained in:
parent
a2ceec52d9
commit
9222f768f7
2 changed files with 60 additions and 6 deletions
|
@ -272,6 +272,7 @@ static int imx_drm_bind(struct device *dev)
|
||||||
drm->mode_config.max_height = 4096;
|
drm->mode_config.max_height = 4096;
|
||||||
drm->mode_config.funcs = &imx_drm_mode_config_funcs;
|
drm->mode_config.funcs = &imx_drm_mode_config_funcs;
|
||||||
drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
|
drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
|
||||||
|
drm->mode_config.allow_fb_modifiers = true;
|
||||||
|
|
||||||
drm_mode_config_init(drm);
|
drm_mode_config_init(drm);
|
||||||
|
|
||||||
|
|
|
@ -551,7 +551,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
|
||||||
drm_rect_width(&state->src) >> 16,
|
drm_rect_width(&state->src) >> 16,
|
||||||
drm_rect_height(&state->src) >> 16,
|
drm_rect_height(&state->src) >> 16,
|
||||||
fb->pitches[0], fb->format->format,
|
fb->pitches[0], fb->format->format,
|
||||||
0, &eba);
|
fb->modifier, &eba);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
|
if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
|
||||||
|
@ -700,18 +700,71 @@ static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
|
||||||
int ipu_planes_assign_pre(struct drm_device *dev,
|
int ipu_planes_assign_pre(struct drm_device *dev,
|
||||||
struct drm_atomic_state *state)
|
struct drm_atomic_state *state)
|
||||||
{
|
{
|
||||||
|
struct drm_crtc_state *old_crtc_state, *crtc_state;
|
||||||
struct drm_plane_state *plane_state;
|
struct drm_plane_state *plane_state;
|
||||||
|
struct ipu_plane_state *ipu_state;
|
||||||
|
struct ipu_plane *ipu_plane;
|
||||||
struct drm_plane *plane;
|
struct drm_plane *plane;
|
||||||
|
struct drm_crtc *crtc;
|
||||||
int available_pres = ipu_prg_max_active_channels();
|
int available_pres = ipu_prg_max_active_channels();
|
||||||
int i;
|
int ret, i;
|
||||||
|
|
||||||
|
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
|
||||||
|
ret = drm_atomic_add_affected_planes(state, crtc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are going over the planes in 2 passes: first we assign PREs to
|
||||||
|
* planes with a tiling modifier, which need the PREs to resolve into
|
||||||
|
* linear. Any failure to assign a PRE there is fatal. In the second
|
||||||
|
* pass we try to assign PREs to linear FBs, to improve memory access
|
||||||
|
* patterns for them. Failure at this point is non-fatal, as we can
|
||||||
|
* scan out linear FBs without a PRE.
|
||||||
|
*/
|
||||||
|
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
||||||
|
ipu_state = to_ipu_plane_state(plane_state);
|
||||||
|
ipu_plane = to_ipu_plane(plane);
|
||||||
|
|
||||||
|
if (!plane_state->fb) {
|
||||||
|
ipu_state->use_pre = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) ||
|
||||||
|
plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ipu_prg_present(ipu_plane->ipu) || !available_pres)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!ipu_prg_format_supported(ipu_plane->ipu,
|
||||||
|
plane_state->fb->format->format,
|
||||||
|
plane_state->fb->modifier))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ipu_state->use_pre = true;
|
||||||
|
available_pres--;
|
||||||
|
}
|
||||||
|
|
||||||
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
||||||
struct ipu_plane_state *ipu_state =
|
ipu_state = to_ipu_plane_state(plane_state);
|
||||||
to_ipu_plane_state(plane_state);
|
ipu_plane = to_ipu_plane(plane);
|
||||||
struct ipu_plane *ipu_plane = to_ipu_plane(plane);
|
|
||||||
|
if (!plane_state->fb) {
|
||||||
|
ipu_state->use_pre = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) &&
|
||||||
|
plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* make sure that modifier is initialized */
|
||||||
|
plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR;
|
||||||
|
|
||||||
if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
|
if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
|
||||||
plane_state->fb &&
|
|
||||||
ipu_prg_format_supported(ipu_plane->ipu,
|
ipu_prg_format_supported(ipu_plane->ipu,
|
||||||
plane_state->fb->format->format,
|
plane_state->fb->format->format,
|
||||||
plane_state->fb->modifier)) {
|
plane_state->fb->modifier)) {
|
||||||
|
|
Loading…
Reference in a new issue