linux/drivers/gpu/drm/mediatek/mtk_drm_plane.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015 MediaTek Inc.
   3 * Author: CK Hu <ck.hu@mediatek.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 */
  14
  15#include <drm/drmP.h>
  16#include <drm/drm_atomic.h>
  17#include <drm/drm_atomic_helper.h>
  18#include <drm/drm_plane_helper.h>
  19
  20#include "mtk_drm_crtc.h"
  21#include "mtk_drm_ddp_comp.h"
  22#include "mtk_drm_drv.h"
  23#include "mtk_drm_fb.h"
  24#include "mtk_drm_gem.h"
  25#include "mtk_drm_plane.h"
  26
  27static const u32 formats[] = {
  28        DRM_FORMAT_XRGB8888,
  29        DRM_FORMAT_ARGB8888,
  30        DRM_FORMAT_RGB565,
  31        DRM_FORMAT_UYVY,
  32        DRM_FORMAT_YUYV,
  33};
  34
  35static void mtk_plane_reset(struct drm_plane *plane)
  36{
  37        struct mtk_plane_state *state;
  38
  39        if (plane->state) {
  40                __drm_atomic_helper_plane_destroy_state(plane->state);
  41
  42                state = to_mtk_plane_state(plane->state);
  43                memset(state, 0, sizeof(*state));
  44        } else {
  45                state = kzalloc(sizeof(*state), GFP_KERNEL);
  46                if (!state)
  47                        return;
  48                plane->state = &state->base;
  49        }
  50
  51        state->base.plane = plane;
  52        state->pending.format = DRM_FORMAT_RGB565;
  53}
  54
  55static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
  56{
  57        struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
  58        struct mtk_plane_state *state;
  59
  60        state = kzalloc(sizeof(*state), GFP_KERNEL);
  61        if (!state)
  62                return NULL;
  63
  64        __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
  65
  66        WARN_ON(state->base.plane != plane);
  67
  68        state->pending = old_state->pending;
  69
  70        return &state->base;
  71}
  72
  73static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
  74                                        struct drm_plane_state *state)
  75{
  76        __drm_atomic_helper_plane_destroy_state(state);
  77        kfree(to_mtk_plane_state(state));
  78}
  79
  80static const struct drm_plane_funcs mtk_plane_funcs = {
  81        .update_plane = drm_atomic_helper_update_plane,
  82        .disable_plane = drm_atomic_helper_disable_plane,
  83        .destroy = drm_plane_cleanup,
  84        .reset = mtk_plane_reset,
  85        .atomic_duplicate_state = mtk_plane_duplicate_state,
  86        .atomic_destroy_state = mtk_drm_plane_destroy_state,
  87};
  88
  89static int mtk_plane_atomic_check(struct drm_plane *plane,
  90                                  struct drm_plane_state *state)
  91{
  92        struct drm_framebuffer *fb = state->fb;
  93        struct drm_crtc_state *crtc_state;
  94
  95        if (!fb)
  96                return 0;
  97
  98        if (!mtk_fb_get_gem_obj(fb)) {
  99                DRM_DEBUG_KMS("buffer is null\n");
 100                return -EFAULT;
 101        }
 102
 103        if (!state->crtc)
 104                return 0;
 105
 106        crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
 107        if (IS_ERR(crtc_state))
 108                return PTR_ERR(crtc_state);
 109
 110        return drm_atomic_helper_check_plane_state(state, crtc_state,
 111                                                   DRM_PLANE_HELPER_NO_SCALING,
 112                                                   DRM_PLANE_HELPER_NO_SCALING,
 113                                                   true, true);
 114}
 115
 116static void mtk_plane_atomic_update(struct drm_plane *plane,
 117                                    struct drm_plane_state *old_state)
 118{
 119        struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
 120        struct drm_crtc *crtc = plane->state->crtc;
 121        struct drm_framebuffer *fb = plane->state->fb;
 122        struct drm_gem_object *gem;
 123        struct mtk_drm_gem_obj *mtk_gem;
 124        unsigned int pitch, format;
 125        dma_addr_t addr;
 126
 127        if (!crtc || WARN_ON(!fb))
 128                return;
 129
 130        gem = mtk_fb_get_gem_obj(fb);
 131        mtk_gem = to_mtk_gem_obj(gem);
 132        addr = mtk_gem->dma_addr;
 133        pitch = fb->pitches[0];
 134        format = fb->format->format;
 135
 136        addr += (plane->state->src.x1 >> 16) * fb->format->cpp[0];
 137        addr += (plane->state->src.y1 >> 16) * pitch;
 138
 139        state->pending.enable = true;
 140        state->pending.pitch = pitch;
 141        state->pending.format = format;
 142        state->pending.addr = addr;
 143        state->pending.x = plane->state->dst.x1;
 144        state->pending.y = plane->state->dst.y1;
 145        state->pending.width = drm_rect_width(&plane->state->dst);
 146        state->pending.height = drm_rect_height(&plane->state->dst);
 147        wmb(); /* Make sure the above parameters are set before update */
 148        state->pending.dirty = true;
 149}
 150
 151static void mtk_plane_atomic_disable(struct drm_plane *plane,
 152                                     struct drm_plane_state *old_state)
 153{
 154        struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
 155
 156        state->pending.enable = false;
 157        wmb(); /* Make sure the above parameter is set before update */
 158        state->pending.dirty = true;
 159}
 160
 161static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
 162        .atomic_check = mtk_plane_atomic_check,
 163        .atomic_update = mtk_plane_atomic_update,
 164        .atomic_disable = mtk_plane_atomic_disable,
 165};
 166
 167int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 168                   unsigned long possible_crtcs, enum drm_plane_type type)
 169{
 170        int err;
 171
 172        err = drm_universal_plane_init(dev, plane, possible_crtcs,
 173                                       &mtk_plane_funcs, formats,
 174                                       ARRAY_SIZE(formats), NULL, type, NULL);
 175        if (err) {
 176                DRM_ERROR("failed to initialize plane\n");
 177                return err;
 178        }
 179
 180        drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
 181
 182        return 0;
 183}
 184