From: Philipp Zabel <p.zabel@pengutronix.de>
To: dri-devel@lists.freedesktop.org
Cc: Mark Rutland <mark.rutland@arm.com>,
devicetree@vger.kernel.org, patchwork-lst@pengutronix.de,
Rob Herring <robh+dt@kernel.org>,
kernel@pengutronix.de
Subject: [PATCH v3 9/9] drm/imx: use PRG/PRE when possible
Date: Tue, 14 Mar 2017 11:38:48 +0100 [thread overview]
Message-ID: <1489487928-26083-9-git-send-email-p.zabel@pengutronix.de> (raw)
In-Reply-To: <1489487928-26083-1-git-send-email-p.zabel@pengutronix.de>
From: Lucas Stach <l.stach@pengutronix.de>
Allow the planes to use the PRG/PRE units as linear prefetchers when
possible. This improves DRAM efficiency a bit and reduces the chance
for display underflow when the memory subsystem is under load.
This does not yet support scanning out tiled buffers directly, as this
needs more work, but it already wires up the basic interaction between
imx-drm, the IPUv3 driver and the PRG and PRE drivers.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
v3: Fix modular build (export ipu_planes_assign_pre symbol)
---
drivers/gpu/drm/imx/imx-drm-core.c | 5 ++
drivers/gpu/drm/imx/imx-drm.h | 3 +
drivers/gpu/drm/imx/ipuv3-plane.c | 124 ++++++++++++++++++++++++++++++++++++-
3 files changed, 129 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index a8f09d38bddb4..9e7310e09d020 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -110,6 +110,11 @@ static int imx_drm_atomic_check(struct drm_device *dev,
if (ret)
return ret;
+ /* Assign PRG/PRE channels and check if all constrains are satisfied. */
+ ret = ipu_planes_assign_pre(dev, state);
+ if (ret)
+ return ret;
+
return ret;
}
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index cc003334505dc..295434b199db9 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -39,4 +39,7 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
void imx_drm_connector_destroy(struct drm_connector *connector);
void imx_drm_encoder_destroy(struct drm_encoder *encoder);
+int ipu_planes_assign_pre(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
#endif /* _IMX_DRM_H_ */
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index cecb8eba5c320..d63e853a03006 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -23,6 +23,17 @@
#include "video/imx-ipu-v3.h"
#include "ipuv3-plane.h"
+struct ipu_plane_state {
+ struct drm_plane_state base;
+ bool use_pre;
+};
+
+static inline struct ipu_plane_state *
+to_ipu_plane_state(struct drm_plane_state *p)
+{
+ return container_of(p, struct ipu_plane_state, base);
+}
+
static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
{
return container_of(p, struct ipu_plane, base);
@@ -223,6 +234,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
ipu_dmfc_disable_channel(ipu_plane->dmfc);
if (ipu_plane->dp)
ipu_dp_disable(ipu_plane->ipu);
+ if (ipu_prg_present(ipu_plane->ipu))
+ ipu_prg_channel_disable(ipu_plane->ipu_ch);
}
void ipu_plane_disable_deferred(struct drm_plane *plane)
@@ -246,13 +259,56 @@ static void ipu_plane_destroy(struct drm_plane *plane)
kfree(ipu_plane);
}
+void ipu_plane_state_reset(struct drm_plane *plane)
+{
+ struct ipu_plane_state *ipu_state;
+
+ if (plane->state) {
+ ipu_state = to_ipu_plane_state(plane->state);
+ __drm_atomic_helper_plane_destroy_state(plane->state);
+ kfree(ipu_state);
+ }
+
+ ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
+
+ if (ipu_state) {
+ ipu_state->base.plane = plane;
+ ipu_state->base.rotation = DRM_ROTATE_0;
+ }
+
+ plane->state = &ipu_state->base;
+}
+
+struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct ipu_plane_state *state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
+ if (state)
+ __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
+
+ return &state->base;
+}
+
+void ipu_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
+
+ __drm_atomic_helper_plane_destroy_state(state);
+ kfree(ipu_state);
+}
+
static const struct drm_plane_funcs ipu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = ipu_plane_destroy,
- .reset = drm_atomic_helper_plane_reset,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+ .reset = ipu_plane_state_reset,
+ .atomic_duplicate_state = ipu_plane_duplicate_state,
+ .atomic_destroy_state = ipu_plane_destroy_state,
};
static int ipu_plane_atomic_check(struct drm_plane *plane,
@@ -426,17 +482,33 @@ static void ipu_plane_atomic_disable(struct drm_plane *plane,
ipu_plane->disabling = true;
}
+static int ipu_chan_assign_axi_id(int ipu_chan)
+{
+ switch (ipu_chan) {
+ case IPUV3_CHANNEL_MEM_BG_SYNC:
+ return 1;
+ case IPUV3_CHANNEL_MEM_FG_SYNC:
+ return 2;
+ case IPUV3_CHANNEL_MEM_DC_SYNC:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
static void ipu_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct ipu_plane *ipu_plane = to_ipu_plane(plane);
struct drm_plane_state *state = plane->state;
+ struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
struct drm_crtc_state *crtc_state = state->crtc->state;
struct drm_framebuffer *fb = state->fb;
struct drm_rect *dst = &state->dst;
unsigned long eba, ubo, vbo;
unsigned long alpha_eba = 0;
enum ipu_color_space ics;
+ unsigned int axi_id = 0;
int active;
if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
@@ -444,7 +516,23 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
eba = drm_plane_state_to_eba(state, 0);
+ /*
+ * Configure PRG channel and attached PRE, this changes the EBA to an
+ * internal SRAM location.
+ */
+ if (ipu_state->use_pre) {
+ axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
+ ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
+ drm_rect_width(&state->src) >> 16,
+ drm_rect_height(&state->src) >> 16,
+ state->fb->pitches[0],
+ state->fb->format->format, &eba);
+ }
+
if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
+ /* nothing to do if PRE is used */
+ if (ipu_state->use_pre)
+ return;
active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
@@ -503,6 +591,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
+ ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
switch (fb->format->format) {
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
@@ -578,6 +667,35 @@ static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
.atomic_update = ipu_plane_atomic_update,
};
+int ipu_planes_assign_pre(struct drm_device *dev,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *plane_state;
+ struct drm_plane *plane;
+ int available_pres = ipu_prg_max_active_channels();
+ int i;
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct ipu_plane_state *ipu_state =
+ to_ipu_plane_state(plane_state);
+ struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+ if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
+ plane_state->fb &&
+ ipu_prg_format_supported(ipu_plane->ipu,
+ plane_state->fb->format->format,
+ plane_state->fb->modifier)) {
+ ipu_state->use_pre = true;
+ available_pres--;
+ } else {
+ ipu_state->use_pre = false;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
+
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs,
enum drm_plane_type type)
--
2.11.0
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
prev parent reply other threads:[~2017-03-14 10:38 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-14 10:38 [PATCH v3 1/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Philipp Zabel
[not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-03-14 10:38 ` [PATCH v3 2/9] gpu: ipu-v3: add driver for " Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 3/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 4/9] gpu: ipu-v3: add driver for " Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus Philipp Zabel
2017-03-20 22:12 ` Rob Herring
2017-03-14 10:38 ` [PATCH v3 7/9] gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 6/9] gpu: ipu-v3: hook up PRG unit Philipp Zabel
2017-03-14 10:38 ` Philipp Zabel [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1489487928-26083-9-git-send-email-p.zabel@pengutronix.de \
--to=p.zabel@pengutronix.de \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=kernel@pengutronix.de \
--cc=mark.rutland@arm.com \
--cc=patchwork-lst@pengutronix.de \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).