Merge tag 'drm-next-2018-12-27' of git://anongit.freedesktop.org/drm/drm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Dec 2018 03:57:29 +0000 (19:57 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Dec 2018 03:57:29 +0000 (19:57 -0800)
Pull more drm updates from Dave Airlie:
 "Daniel collected a couple of pulls after I want on holidays, back for
  a couple of days, so may as well send them out.

  This has exynos and etnaviv work for 4.21.

  exynos:
   - plane alpha and blending configurability

  etnaviv:
   - mostly cleanups in prep for new features"

* tag 'drm-next-2018-12-27' of git://anongit.freedesktop.org/drm/drm:
  drm/etnaviv: remove lastctx member from gpu struct
  drm/etnaviv: replace header include with forward declaration
  drm/etnaviv: remove unnecessary local irq disable
  drm/exynos: fimd: Make pixel blend mode configurable
  drm/exynos: fimd: Make plane alpha configurable
  drm/etnaviv: Replace drm_dev_unref with drm_dev_put
  drm/etnaviv: consolidate hardware fence handling in etnaviv_gpu
  drm/etnaviv: kill active fence tracking

drivers/gpu/drm/etnaviv/etnaviv_buffer.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/etnaviv/etnaviv_drv.h
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
include/video/samsung_fimd.h

index 7fea74861a87fdff9a30c3a313a06360093aba80..160ce3c060a5666b40c542372436f1ebb0ff4b5e 100644 (file)
@@ -439,6 +439,4 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
 
        if (drm_debug & DRM_UT_DRIVER)
                etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
-
-       gpu->lastctx = cmdbuf->ctx;
 }
index 52802e6049e0adab5045b57cc09bd265708ae34d..96efc84396bf73e7abe6dfe3cac90384099f9db2 100644 (file)
@@ -72,14 +72,8 @@ static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file)
        for (i = 0; i < ETNA_MAX_PIPES; i++) {
                struct etnaviv_gpu *gpu = priv->gpu[i];
 
-               if (gpu) {
-                       mutex_lock(&gpu->lock);
-                       if (gpu->lastctx == ctx)
-                               gpu->lastctx = NULL;
-                       mutex_unlock(&gpu->lock);
-
+               if (gpu)
                        drm_sched_entity_destroy(&ctx->sched_entity[i]);
-               }
        }
 
        kfree(ctx);
@@ -523,7 +517,7 @@ static int etnaviv_bind(struct device *dev)
        if (!priv) {
                dev_err(dev, "failed to allocate private data\n");
                ret = -ENOMEM;
-               goto out_unref;
+               goto out_put;
        }
        drm->dev_private = priv;
 
@@ -549,7 +543,7 @@ out_register:
        component_unbind_all(dev, drm);
 out_bind:
        kfree(priv);
-out_unref:
+out_put:
        drm_dev_put(drm);
 
        return ret;
index 8d02d1b7dcf5a54b5bc1623b847f73dad1b493d0..4bf698de599696f0462ee50af4f7b5ff59fc199b 100644 (file)
@@ -107,17 +107,6 @@ static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base)
        return base + nelem * elem_size;
 }
 
-/* returns true if fence a comes after fence b */
-static inline bool fence_after(u32 a, u32 b)
-{
-       return (s32)(a - b) > 0;
-}
-
-static inline bool fence_after_eq(u32 a, u32 b)
-{
-       return (s32)(a - b) >= 0;
-}
-
 /*
  * Etnaviv timeouts are specified wrt CLOCK_MONOTONIC, not jiffies.
  * We need to calculate the timeout in terms of number of jiffies
index f225fbc6edd2d94c7b82a37b56c401a66966fd95..6904535475de1828efc6a273612e4da7ad3284b6 100644 (file)
@@ -3,10 +3,12 @@
  * Copyright (C) 2015-2018 Etnaviv Project
  */
 
+#include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/dma-fence.h>
 #include <linux/moduleparam.h>
 #include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/thermal.h>
 
 #include "etnaviv_cmdbuf.h"
@@ -976,7 +978,6 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
 
 void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
 {
-       unsigned long flags;
        unsigned int i = 0;
 
        dev_err(gpu->dev, "recover hung GPU!\n");
@@ -989,15 +990,13 @@ void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
        etnaviv_hw_reset(gpu);
 
        /* complete all events, the GPU won't do it after the reset */
-       spin_lock_irqsave(&gpu->event_spinlock, flags);
+       spin_lock(&gpu->event_spinlock);
        for_each_set_bit_from(i, gpu->event_bitmap, ETNA_NR_EVENTS)
                complete(&gpu->event_free);
        bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS);
-       spin_unlock_irqrestore(&gpu->event_spinlock, flags);
-       gpu->completed_fence = gpu->active_fence;
+       spin_unlock(&gpu->event_spinlock);
 
        etnaviv_gpu_hw_init(gpu);
-       gpu->lastctx = NULL;
        gpu->exec_state = -1;
 
        mutex_unlock(&gpu->lock);
@@ -1032,7 +1031,7 @@ static bool etnaviv_fence_signaled(struct dma_fence *fence)
 {
        struct etnaviv_fence *f = to_etnaviv_fence(fence);
 
-       return fence_completed(f->gpu, f->base.seqno);
+       return (s32)(f->gpu->completed_fence - f->base.seqno) >= 0;
 }
 
 static void etnaviv_fence_release(struct dma_fence *fence)
@@ -1071,6 +1070,12 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
        return &f->base;
 }
 
+/* returns true if fence a comes after fence b */
+static inline bool fence_after(u32 a, u32 b)
+{
+       return (s32)(a - b) > 0;
+}
+
 /*
  * event management:
  */
@@ -1078,7 +1083,7 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
 static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
        unsigned int *events)
 {
-       unsigned long flags, timeout = msecs_to_jiffies(10 * 10000);
+       unsigned long timeout = msecs_to_jiffies(10 * 10000);
        unsigned i, acquired = 0;
 
        for (i = 0; i < nr_events; i++) {
@@ -1095,7 +1100,7 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
                timeout = ret;
        }
 
-       spin_lock_irqsave(&gpu->event_spinlock, flags);
+       spin_lock(&gpu->event_spinlock);
 
        for (i = 0; i < nr_events; i++) {
                int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS);
@@ -1105,7 +1110,7 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
                set_bit(event, gpu->event_bitmap);
        }
 
-       spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+       spin_unlock(&gpu->event_spinlock);
 
        return 0;
 
@@ -1118,18 +1123,11 @@ out:
 
 static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&gpu->event_spinlock, flags);
-
        if (!test_bit(event, gpu->event_bitmap)) {
                dev_warn(gpu->dev, "event %u is already marked as free",
                         event);
-               spin_unlock_irqrestore(&gpu->event_spinlock, flags);
        } else {
                clear_bit(event, gpu->event_bitmap);
-               spin_unlock_irqrestore(&gpu->event_spinlock, flags);
-
                complete(&gpu->event_free);
        }
 }
@@ -1306,8 +1304,6 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit)
                goto out_unlock;
        }
 
-       gpu->active_fence = gpu_fence->seqno;
-
        if (submit->nr_pmrs) {
                gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre;
                kref_get(&submit->refcount);
@@ -1549,7 +1545,6 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
        etnaviv_gpu_update_clock(gpu);
        etnaviv_gpu_hw_init(gpu);
 
-       gpu->lastctx = NULL;
        gpu->exec_state = -1;
 
        mutex_unlock(&gpu->lock);
@@ -1806,8 +1801,8 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev)
        struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
        u32 idle, mask;
 
-       /* If we have outstanding fences, we're not idle */
-       if (gpu->completed_fence != gpu->active_fence)
+       /* If there are any jobs in the HW queue, we're not idle */
+       if (atomic_read(&gpu->sched.hw_rq_count))
                return -EBUSY;
 
        /* Check whether the hardware (except FE) is idle */
index 9a75a6937268eebff62e04a13b3669fb3d5934b1..9bcf151f706bb7d1da8d518a92d2b446134fbad9 100644 (file)
@@ -6,9 +6,6 @@
 #ifndef __ETNAVIV_GPU_H__
 #define __ETNAVIV_GPU_H__
 
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-
 #include "etnaviv_cmdbuf.h"
 #include "etnaviv_drv.h"
 
@@ -88,6 +85,8 @@ struct etnaviv_event {
 
 struct etnaviv_cmdbuf_suballoc;
 struct etnaviv_cmdbuf;
+struct regulator;
+struct clk;
 
 #define ETNA_NR_EVENTS 30
 
@@ -98,7 +97,6 @@ struct etnaviv_gpu {
        struct mutex lock;
        struct etnaviv_chip_identity identity;
        enum etnaviv_sec_mode sec_mode;
-       struct etnaviv_file_private *lastctx;
        struct workqueue_struct *wq;
        struct drm_gpu_scheduler sched;
 
@@ -121,7 +119,6 @@ struct etnaviv_gpu {
        struct mutex fence_lock;
        struct idr fence_idr;
        u32 next_fence;
-       u32 active_fence;
        u32 completed_fence;
        wait_queue_head_t fence_event;
        u64 fence_context;
@@ -161,11 +158,6 @@ static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
        return readl(gpu->mmio + reg);
 }
 
-static inline bool fence_completed(struct etnaviv_gpu *gpu, u32 fence)
-{
-       return fence_after_eq(gpu->completed_fence, fence);
-}
-
 int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value);
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
index e3d6a8584715a7966b2d87bfa546bdddf0f90605..786a8ee6f10fbc483d40ad59fbc7877767a8fb7f 100644 (file)
@@ -228,6 +228,21 @@ static const uint32_t fimd_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
+static const unsigned int capabilities[WINDOWS_NR] = {
+       0,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+};
+
+static inline void fimd_set_bits(struct fimd_context *ctx, u32 reg, u32 mask,
+                                u32 val)
+{
+       val = (val & mask) | (readl(ctx->regs + reg) & ~mask);
+       writel(val, ctx->regs + reg);
+}
+
 static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
 {
        struct fimd_context *ctx = crtc->ctx;
@@ -551,13 +566,88 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
        writel(val, ctx->regs + VIDCON0);
 }
 
+static void fimd_win_set_bldeq(struct fimd_context *ctx, unsigned int win,
+                              unsigned int alpha, unsigned int pixel_alpha)
+{
+       u32 mask = BLENDEQ_A_FUNC_F(0xf) | BLENDEQ_B_FUNC_F(0xf);
+       u32 val = 0;
+
+       switch (pixel_alpha) {
+       case DRM_MODE_BLEND_PIXEL_NONE:
+       case DRM_MODE_BLEND_COVERAGE:
+               val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA_A);
+               val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
+               break;
+       case DRM_MODE_BLEND_PREMULTI:
+       default:
+               if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+                       val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA0);
+                       val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
+               } else {
+                       val |= BLENDEQ_A_FUNC_F(BLENDEQ_ONE);
+                       val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
+               }
+               break;
+       }
+       fimd_set_bits(ctx, BLENDEQx(win), mask, val);
+}
 
-static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
-                               uint32_t pixel_format, int width)
+static void fimd_win_set_bldmod(struct fimd_context *ctx, unsigned int win,
+                               unsigned int alpha, unsigned int pixel_alpha)
 {
-       unsigned long val;
+       u32 win_alpha_l = (alpha >> 8) & 0xf;
+       u32 win_alpha_h = alpha >> 12;
+       u32 val = 0;
 
-       val = WINCONx_ENWIN;
+       switch (pixel_alpha) {
+       case DRM_MODE_BLEND_PIXEL_NONE:
+               break;
+       case DRM_MODE_BLEND_COVERAGE:
+       case DRM_MODE_BLEND_PREMULTI:
+       default:
+               val |= WINCON1_ALPHA_SEL;
+               val |= WINCON1_BLD_PIX;
+               val |= WINCON1_ALPHA_MUL;
+               break;
+       }
+       fimd_set_bits(ctx, WINCON(win), WINCONx_BLEND_MODE_MASK, val);
+
+       /* OSD alpha */
+       val = VIDISD14C_ALPHA0_R(win_alpha_h) |
+               VIDISD14C_ALPHA0_G(win_alpha_h) |
+               VIDISD14C_ALPHA0_B(win_alpha_h) |
+               VIDISD14C_ALPHA1_R(0x0) |
+               VIDISD14C_ALPHA1_G(0x0) |
+               VIDISD14C_ALPHA1_B(0x0);
+       writel(val, ctx->regs + VIDOSD_C(win));
+
+       val = VIDW_ALPHA_R(win_alpha_l) | VIDW_ALPHA_G(win_alpha_l) |
+               VIDW_ALPHA_B(win_alpha_l);
+       writel(val, ctx->regs + VIDWnALPHA0(win));
+
+       val = VIDW_ALPHA_R(0x0) | VIDW_ALPHA_G(0x0) |
+               VIDW_ALPHA_B(0x0);
+       writel(val, ctx->regs + VIDWnALPHA1(win));
+
+       fimd_set_bits(ctx, BLENDCON, BLENDCON_NEW_MASK,
+                       BLENDCON_NEW_8BIT_ALPHA_VALUE);
+}
+
+static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
+                               struct drm_framebuffer *fb, int width)
+{
+       struct exynos_drm_plane plane = ctx->planes[win];
+       struct exynos_drm_plane_state *state =
+               to_exynos_plane_state(plane.base.state);
+       uint32_t pixel_format = fb->format->format;
+       unsigned int alpha = state->base.alpha;
+       u32 val = WINCONx_ENWIN;
+       unsigned int pixel_alpha;
+
+       if (fb->format->has_alpha)
+               pixel_alpha = state->base.pixel_blend_mode;
+       else
+               pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
 
        /*
         * In case of s3c64xx, window 0 doesn't support alpha channel.
@@ -591,8 +681,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
                break;
        case DRM_FORMAT_ARGB8888:
        default:
-               val |= WINCON1_BPPMODE_25BPP_A1888
-                       | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
+               val |= WINCON1_BPPMODE_25BPP_A1888;
                val |= WINCONx_WSWP;
                val |= WINCONx_BURSTLEN_16WORD;
                break;
@@ -610,25 +699,12 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
                val &= ~WINCONx_BURSTLEN_MASK;
                val |= WINCONx_BURSTLEN_4WORD;
        }
-
-       writel(val, ctx->regs + WINCON(win));
+       fimd_set_bits(ctx, WINCON(win), ~WINCONx_BLEND_MODE_MASK, val);
 
        /* hardware window 0 doesn't support alpha channel. */
        if (win != 0) {
-               /* OSD alpha */
-               val = VIDISD14C_ALPHA0_R(0xf) |
-                       VIDISD14C_ALPHA0_G(0xf) |
-                       VIDISD14C_ALPHA0_B(0xf) |
-                       VIDISD14C_ALPHA1_R(0xf) |
-                       VIDISD14C_ALPHA1_G(0xf) |
-                       VIDISD14C_ALPHA1_B(0xf);
-
-               writel(val, ctx->regs + VIDOSD_C(win));
-
-               val = VIDW_ALPHA_R(0xf) | VIDW_ALPHA_G(0xf) |
-                       VIDW_ALPHA_G(0xf);
-               writel(val, ctx->regs + VIDWnALPHA0(win));
-               writel(val, ctx->regs + VIDWnALPHA1(win));
+               fimd_win_set_bldmod(ctx, win, alpha, pixel_alpha);
+               fimd_win_set_bldeq(ctx, win, alpha, pixel_alpha);
        }
 }
 
@@ -785,7 +861,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
        }
 
-       fimd_win_set_pixfmt(ctx, win, fb->format->format, state->src.w);
+       fimd_win_set_pixfmt(ctx, win, fb, state->src.w);
 
        /* hardware window 0 doesn't support color key. */
        if (win != 0)
@@ -987,6 +1063,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
                ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
                ctx->configs[i].zpos = i;
                ctx->configs[i].type = fimd_win_types[i];
+               ctx->configs[i].capabilities = capabilities[i];
                ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
                                        &ctx->configs[i]);
                if (ret)
index d8fc96ed11e9d29ecde7654419d1554aaeb7ab16..4ba5efe8d086a876285399b68051df0ce87fc368 100644 (file)
 #define WINCONx_BURSTLEN_8WORD                 (0x1 << 9)
 #define WINCONx_BURSTLEN_4WORD                 (0x2 << 9)
 #define WINCONx_ENWIN                          (1 << 0)
+#define WINCONx_BLEND_MODE_MASK                        (0xc2)
 
 #define WINCON0_BPPMODE_MASK                   (0xf << 2)
 #define WINCON0_BPPMODE_SHIFT                  2
 #define WINCON0_BPPMODE_24BPP_888              (0xb << 2)
 
 #define WINCON1_LOCALSEL_CAMIF                 (1 << 23)
+#define WINCON1_ALPHA_MUL                      (1 << 7)
 #define WINCON1_BLD_PIX                                (1 << 6)
 #define WINCON1_BPPMODE_MASK                   (0xf << 2)
 #define WINCON1_BPPMODE_SHIFT                  2
 #define WPALCON_W0PAL_16BPP_565                        (0x6 << 0)
 
 /* Blending equation control */
+#define BLENDEQx(_win)                         (0x244 + ((_win - 1) * 4))
+#define BLENDEQ_ZERO                           0x0
+#define BLENDEQ_ONE                            0x1
+#define BLENDEQ_ALPHA_A                                0x2
+#define BLENDEQ_ONE_MINUS_ALPHA_A              0x3
+#define BLENDEQ_ALPHA0                         0x6
+#define BLENDEQ_B_FUNC_F(_x)                   (_x << 6)
+#define BLENDEQ_A_FUNC_F(_x)                   (_x << 0)
 #define BLENDCON                               0x260
 #define BLENDCON_NEW_MASK                      (1 << 0)
 #define BLENDCON_NEW_8BIT_ALPHA_VALUE          (1 << 0)