summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tegra/dc.c
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-12-20 09:39:14 +0100
committerThierry Reding <treding@nvidia.com>2017-12-21 14:55:55 +0100
commitebae8d07435ae91314f4a28d69b530d09c625815 (patch)
treefbe41c4c436502a2f073a3c352d3b14a3886cf15 /drivers/gpu/drm/tegra/dc.c
parent4c69ac12e39d3d623686d1c421b05d604e1c6db9 (diff)
drm/tegra: dc: Implement legacy blending
This implements alpha blending on legacy display controllers (Tegra20, Tegra30 and Tegra114). While it's theoretically possible to support the zpos property to enable userspace to specify the Z-order of each plane individually, this is not currently supported and the same fixed Z- order as previously defined is used. Reverts commit 71835caa00e8 ("drm/tegra: fb: Force alpha formats") since the opaque formats are now supported. Reported-by: Dmitry Osipenko <digetx@gmail.com> Fixes: 7772fdaef939 ("drm/tegra: Support ARGB and ABGR formats") Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/dc.c')
-rw-r--r--drivers/gpu/drm/tegra/dc.c81
1 files changed, 68 insertions, 13 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 2a0c1e93f82e..4507063029e0 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -154,30 +154,53 @@ static inline u32 compute_initial_dda(unsigned int in)
static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
{
+ u32 background[3] = {
+ BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
+ BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
+ BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
+ };
+ u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) |
+ BLEND_COLOR_KEY_NONE;
+ u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255);
+ struct tegra_plane_state *state;
+ unsigned int i;
+
+ state = to_tegra_plane_state(plane->base.state);
+
+ /* alpha contribution is 1 minus sum of overlapping windows */
+ for (i = 0; i < 3; i++) {
+ if (state->dependent[i])
+ background[i] |= BLEND_CONTROL_DEPENDENT;
+ }
+
+ /* enable alpha blending if pixel format has an alpha component */
+ if (!state->opaque)
+ foreground |= BLEND_CONTROL_ALPHA;
+
/*
* Disable blending and assume Window A is the bottom-most window,
* Window C is the top-most window and Window B is in the middle.
*/
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY);
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN);
+ tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY);
+ tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN);
switch (plane->index) {
case 0:
- tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X);
- tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y);
- tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY);
+ tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X);
+ tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);
+ tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);
break;
case 1:
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X);
- tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y);
- tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY);
+ tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X);
+ tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);
+ tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);
break;
case 2:
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X);
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y);
- tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY);
+ tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X);
+ tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_Y);
+ tegra_plane_writel(plane, foreground, DC_WIN_BLEND_3WIN_XY);
break;
}
}
@@ -353,6 +376,11 @@ static const u32 tegra20_primary_formats[] = {
DRM_FORMAT_RGBA5551,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_ARGB8888,
+ /* non-native formats */
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_RGBX5551,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB8888,
};
static const u32 tegra114_primary_formats[] = {
@@ -409,18 +437,40 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
struct tegra_bo_tiling *tiling = &plane_state->tiling;
struct tegra_plane *tegra = to_tegra_plane(plane);
struct tegra_dc *dc = to_tegra_dc(state->crtc);
+ unsigned int format;
int err;
/* no need for further checks if the plane is being disabled */
if (!state->crtc)
return 0;
- err = tegra_plane_format(state->fb->format->format,
- &plane_state->format,
+ err = tegra_plane_format(state->fb->format->format, &format,
&plane_state->swap);
if (err < 0)
return err;
+ /*
+ * Tegra20 and Tegra30 are special cases here because they support
+ * only variants of specific formats with an alpha component, but not
+ * the corresponding opaque formats. However, the opaque formats can
+ * be emulated by disabling alpha blending for the plane.
+ */
+ if (!dc->soc->supports_blending) {
+ if (!tegra_plane_format_has_alpha(format)) {
+ err = tegra_plane_format_get_alpha(format, &format);
+ if (err < 0)
+ return err;
+
+ plane_state->opaque = true;
+ } else {
+ plane_state->opaque = false;
+ }
+
+ tegra_plane_check_dependent(tegra, plane_state);
+ }
+
+ plane_state->format = format;
+
err = tegra_fb_get_tiling(state->fb, tiling);
if (err < 0)
return err;
@@ -737,6 +787,11 @@ static const u32 tegra20_overlay_formats[] = {
DRM_FORMAT_RGBA5551,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_ARGB8888,
+ /* non-native formats */
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_RGBX5551,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB8888,
/* planar formats */
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,