linux/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015 Freescale Semiconductor, Inc.
   3 *
   4 * Freescale DCU drm device driver
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/regmap.h>
  13
  14#include <drm/drmP.h>
  15#include <drm/drm_atomic_helper.h>
  16#include <drm/drm_crtc.h>
  17#include <drm/drm_crtc_helper.h>
  18#include <drm/drm_fb_cma_helper.h>
  19#include <drm/drm_gem_cma_helper.h>
  20#include <drm/drm_plane_helper.h>
  21
  22#include "fsl_dcu_drm_drv.h"
  23#include "fsl_dcu_drm_plane.h"
  24
  25static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
  26{
  27        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  28        unsigned int total_layer = fsl_dev->soc->total_layer;
  29        unsigned int index;
  30
  31        index = drm_plane_index(plane);
  32        if (index < total_layer)
  33                return total_layer - index - 1;
  34
  35        dev_err(fsl_dev->dev, "No more layer left\n");
  36        return -EINVAL;
  37}
  38
  39static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
  40                                          struct drm_plane_state *state)
  41{
  42        struct drm_framebuffer *fb = state->fb;
  43
  44        if (!state->fb || !state->crtc)
  45                return 0;
  46
  47        switch (fb->pixel_format) {
  48        case DRM_FORMAT_RGB565:
  49        case DRM_FORMAT_RGB888:
  50        case DRM_FORMAT_XRGB8888:
  51        case DRM_FORMAT_ARGB8888:
  52        case DRM_FORMAT_XRGB4444:
  53        case DRM_FORMAT_ARGB4444:
  54        case DRM_FORMAT_XRGB1555:
  55        case DRM_FORMAT_ARGB1555:
  56        case DRM_FORMAT_YUV422:
  57                return 0;
  58        default:
  59                return -EINVAL;
  60        }
  61}
  62
  63static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
  64                                             struct drm_plane_state *old_state)
  65{
  66        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  67        unsigned int value;
  68        int index;
  69
  70        index = fsl_dcu_drm_plane_index(plane);
  71        if (index < 0)
  72                return;
  73
  74        regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
  75        value &= ~DCU_LAYER_EN;
  76        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
  77}
  78
  79static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
  80                                            struct drm_plane_state *old_state)
  81
  82{
  83        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  84        struct drm_plane_state *state = plane->state;
  85        struct drm_framebuffer *fb = plane->state->fb;
  86        struct drm_gem_cma_object *gem;
  87        unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
  88        int index;
  89
  90        if (!fb)
  91                return;
  92
  93        index = fsl_dcu_drm_plane_index(plane);
  94        if (index < 0)
  95                return;
  96
  97        gem = drm_fb_cma_get_gem_obj(fb, 0);
  98
  99        switch (fb->pixel_format) {
 100        case DRM_FORMAT_RGB565:
 101                bpp = FSL_DCU_RGB565;
 102                break;
 103        case DRM_FORMAT_RGB888:
 104                bpp = FSL_DCU_RGB888;
 105                break;
 106        case DRM_FORMAT_ARGB8888:
 107                alpha = DCU_LAYER_AB_WHOLE_FRAME;
 108                /* fall-through */
 109        case DRM_FORMAT_XRGB8888:
 110                bpp = FSL_DCU_ARGB8888;
 111                break;
 112        case DRM_FORMAT_ARGB4444:
 113                alpha = DCU_LAYER_AB_WHOLE_FRAME;
 114                /* fall-through */
 115        case DRM_FORMAT_XRGB4444:
 116                bpp = FSL_DCU_ARGB4444;
 117                break;
 118        case DRM_FORMAT_ARGB1555:
 119                alpha = DCU_LAYER_AB_WHOLE_FRAME;
 120                /* fall-through */
 121        case DRM_FORMAT_XRGB1555:
 122                bpp = FSL_DCU_ARGB1555;
 123                break;
 124        case DRM_FORMAT_YUV422:
 125                bpp = FSL_DCU_YUV422;
 126                break;
 127        default:
 128                return;
 129        }
 130
 131        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
 132                     DCU_LAYER_HEIGHT(state->crtc_h) |
 133                     DCU_LAYER_WIDTH(state->crtc_w));
 134        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
 135                     DCU_LAYER_POSY(state->crtc_y) |
 136                     DCU_LAYER_POSX(state->crtc_x));
 137        regmap_write(fsl_dev->regmap,
 138                     DCU_CTRLDESCLN(index, 3), gem->paddr);
 139        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
 140                     DCU_LAYER_EN |
 141                     DCU_LAYER_TRANS(0xff) |
 142                     DCU_LAYER_BPP(bpp) |
 143                     alpha);
 144        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
 145                     DCU_LAYER_CKMAX_R(0xFF) |
 146                     DCU_LAYER_CKMAX_G(0xFF) |
 147                     DCU_LAYER_CKMAX_B(0xFF));
 148        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
 149                     DCU_LAYER_CKMIN_R(0) |
 150                     DCU_LAYER_CKMIN_G(0) |
 151                     DCU_LAYER_CKMIN_B(0));
 152        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
 153        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
 154                     DCU_LAYER_FG_FCOLOR(0));
 155        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
 156                     DCU_LAYER_BG_BCOLOR(0));
 157
 158        if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
 159                regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
 160                             DCU_LAYER_POST_SKIP(0) |
 161                             DCU_LAYER_PRE_SKIP(0));
 162        }
 163        regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
 164                           DCU_MODE_DCU_MODE_MASK,
 165                           DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
 166        regmap_write(fsl_dev->regmap,
 167                     DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
 168
 169        return;
 170}
 171
 172static void
 173fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
 174                             const struct drm_plane_state *new_state)
 175{
 176}
 177
 178static int
 179fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
 180                             const struct drm_plane_state *new_state)
 181{
 182        return 0;
 183}
 184
 185static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
 186        .atomic_check = fsl_dcu_drm_plane_atomic_check,
 187        .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
 188        .atomic_update = fsl_dcu_drm_plane_atomic_update,
 189        .cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
 190        .prepare_fb = fsl_dcu_drm_plane_prepare_fb,
 191};
 192
 193static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
 194{
 195        drm_plane_cleanup(plane);
 196        kfree(plane);
 197}
 198
 199static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
 200        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 201        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 202        .destroy = fsl_dcu_drm_plane_destroy,
 203        .disable_plane = drm_atomic_helper_disable_plane,
 204        .reset = drm_atomic_helper_plane_reset,
 205        .update_plane = drm_atomic_helper_update_plane,
 206};
 207
 208static const u32 fsl_dcu_drm_plane_formats[] = {
 209        DRM_FORMAT_RGB565,
 210        DRM_FORMAT_RGB888,
 211        DRM_FORMAT_XRGB8888,
 212        DRM_FORMAT_ARGB8888,
 213        DRM_FORMAT_XRGB4444,
 214        DRM_FORMAT_ARGB4444,
 215        DRM_FORMAT_XRGB1555,
 216        DRM_FORMAT_ARGB1555,
 217        DRM_FORMAT_YUV422,
 218};
 219
 220struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 221{
 222        struct drm_plane *primary;
 223        int ret;
 224
 225        primary = kzalloc(sizeof(*primary), GFP_KERNEL);
 226        if (!primary) {
 227                DRM_DEBUG_KMS("Failed to allocate primary plane\n");
 228                return NULL;
 229        }
 230
 231        /* possible_crtc's will be filled in later by crtc_init */
 232        ret = drm_universal_plane_init(dev, primary, 0,
 233                                       &fsl_dcu_drm_plane_funcs,
 234                                       fsl_dcu_drm_plane_formats,
 235                                       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
 236                                       DRM_PLANE_TYPE_PRIMARY, NULL);
 237        if (ret) {
 238                kfree(primary);
 239                primary = NULL;
 240        }
 241        drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
 242
 243        return primary;
 244}
 245