diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2017-11-10 11:10:00 -0500 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2017-12-19 06:49:11 -0500 |
commit | 9222f768f7b09fea4f12914b376ec975ef758a60 (patch) | |
tree | 5de428de8b565c4281162e12c574ecab78d78ea6 /drivers | |
parent | a2ceec52d9a48bd046e5496e266dda1c57872f4b (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm-core.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.c | 65 |
2 files changed, 60 insertions, 6 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 17d2f3a1c562..1887a668c55e 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c | |||
@@ -272,6 +272,7 @@ static int imx_drm_bind(struct device *dev) | |||
272 | drm->mode_config.max_height = 4096; | 272 | drm->mode_config.max_height = 4096; |
273 | drm->mode_config.funcs = &imx_drm_mode_config_funcs; | 273 | drm->mode_config.funcs = &imx_drm_mode_config_funcs; |
274 | drm->mode_config.helper_private = &imx_drm_mode_config_helpers; | 274 | drm->mode_config.helper_private = &imx_drm_mode_config_helpers; |
275 | drm->mode_config.allow_fb_modifiers = true; | ||
275 | 276 | ||
276 | drm_mode_config_init(drm); | 277 | drm_mode_config_init(drm); |
277 | 278 | ||
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 091393cb9659..32a6debf7107 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c | |||
@@ -551,7 +551,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
551 | drm_rect_width(&state->src) >> 16, | 551 | drm_rect_width(&state->src) >> 16, |
552 | drm_rect_height(&state->src) >> 16, | 552 | drm_rect_height(&state->src) >> 16, |
553 | fb->pitches[0], fb->format->format, | 553 | fb->pitches[0], fb->format->format, |
554 | 0, &eba); | 554 | fb->modifier, &eba); |
555 | } | 555 | } |
556 | 556 | ||
557 | if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { | 557 | 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 = { | |||
700 | int ipu_planes_assign_pre(struct drm_device *dev, | 700 | int ipu_planes_assign_pre(struct drm_device *dev, |
701 | struct drm_atomic_state *state) | 701 | struct drm_atomic_state *state) |
702 | { | 702 | { |
703 | struct drm_crtc_state *old_crtc_state, *crtc_state; | ||
703 | struct drm_plane_state *plane_state; | 704 | struct drm_plane_state *plane_state; |
705 | struct ipu_plane_state *ipu_state; | ||
706 | struct ipu_plane *ipu_plane; | ||
704 | struct drm_plane *plane; | 707 | struct drm_plane *plane; |
708 | struct drm_crtc *crtc; | ||
705 | int available_pres = ipu_prg_max_active_channels(); | 709 | int available_pres = ipu_prg_max_active_channels(); |
706 | int i; | 710 | int ret, i; |
711 | |||
712 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { | ||
713 | ret = drm_atomic_add_affected_planes(state, crtc); | ||
714 | if (ret) | ||
715 | return ret; | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * We are going over the planes in 2 passes: first we assign PREs to | ||
720 | * planes with a tiling modifier, which need the PREs to resolve into | ||
721 | * linear. Any failure to assign a PRE there is fatal. In the second | ||
722 | * pass we try to assign PREs to linear FBs, to improve memory access | ||
723 | * patterns for them. Failure at this point is non-fatal, as we can | ||
724 | * scan out linear FBs without a PRE. | ||
725 | */ | ||
726 | for_each_new_plane_in_state(state, plane, plane_state, i) { | ||
727 | ipu_state = to_ipu_plane_state(plane_state); | ||
728 | ipu_plane = to_ipu_plane(plane); | ||
729 | |||
730 | if (!plane_state->fb) { | ||
731 | ipu_state->use_pre = false; | ||
732 | continue; | ||
733 | } | ||
734 | |||
735 | if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) || | ||
736 | plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR) | ||
737 | continue; | ||
738 | |||
739 | if (!ipu_prg_present(ipu_plane->ipu) || !available_pres) | ||
740 | return -EINVAL; | ||
741 | |||
742 | if (!ipu_prg_format_supported(ipu_plane->ipu, | ||
743 | plane_state->fb->format->format, | ||
744 | plane_state->fb->modifier)) | ||
745 | return -EINVAL; | ||
746 | |||
747 | ipu_state->use_pre = true; | ||
748 | available_pres--; | ||
749 | } | ||
707 | 750 | ||
708 | for_each_new_plane_in_state(state, plane, plane_state, i) { | 751 | for_each_new_plane_in_state(state, plane, plane_state, i) { |
709 | struct ipu_plane_state *ipu_state = | 752 | ipu_state = to_ipu_plane_state(plane_state); |
710 | to_ipu_plane_state(plane_state); | 753 | ipu_plane = to_ipu_plane(plane); |
711 | struct ipu_plane *ipu_plane = to_ipu_plane(plane); | 754 | |
755 | if (!plane_state->fb) { | ||
756 | ipu_state->use_pre = false; | ||
757 | continue; | ||
758 | } | ||
759 | |||
760 | if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) && | ||
761 | plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR) | ||
762 | continue; | ||
763 | |||
764 | /* make sure that modifier is initialized */ | ||
765 | plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR; | ||
712 | 766 | ||
713 | if (ipu_prg_present(ipu_plane->ipu) && available_pres && | 767 | if (ipu_prg_present(ipu_plane->ipu) && available_pres && |
714 | plane_state->fb && | ||
715 | ipu_prg_format_supported(ipu_plane->ipu, | 768 | ipu_prg_format_supported(ipu_plane->ipu, |
716 | plane_state->fb->format->format, | 769 | plane_state->fb->format->format, |
717 | plane_state->fb->modifier)) { | 770 | plane_state->fb->modifier)) { |