linux/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2015 Freescale Semiconductor, Inc.
   4 *
   5 * Freescale DCU drm device driver
   6 */
   7
   8#include <linux/regmap.h>
   9
  10#include <drm/drm_atomic.h>
  11#include <drm/drm_atomic_helper.h>
  12#include <drm/drm_crtc.h>
  13#include <drm/drm_fb_cma_helper.h>
  14#include <drm/drm_fourcc.h>
  15#include <drm/drm_gem_cma_helper.h>
  16#include <drm/drm_plane_helper.h>
  17#include <drm/drm_probe_helper.h>
  18
  19#include "fsl_dcu_drm_drv.h"
  20#include "fsl_dcu_drm_plane.h"
  21
  22static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
  23{
  24        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  25        unsigned int total_layer = fsl_dev->soc->total_layer;
  26        unsigned int index;
  27
  28        index = drm_plane_index(plane);
  29        if (index < total_layer)
  30                return total_layer - index - 1;
  31
  32        dev_err(fsl_dev->dev, "No more layer left\n");
  33        return -EINVAL;
  34}
  35
  36static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
  37                                          struct drm_atomic_state *state)
  38{
  39        struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
  40                                                                                 plane);
  41        struct drm_framebuffer *fb = new_plane_state->fb;
  42
  43        if (!new_plane_state->fb || !new_plane_state->crtc)
  44                return 0;
  45
  46        switch (fb->format->format) {
  47        case DRM_FORMAT_RGB565:
  48        case DRM_FORMAT_RGB888:
  49        case DRM_FORMAT_XRGB8888:
  50        case DRM_FORMAT_ARGB8888:
  51        case DRM_FORMAT_XRGB4444:
  52        case DRM_FORMAT_ARGB4444:
  53        case DRM_FORMAT_XRGB1555:
  54        case DRM_FORMAT_ARGB1555:
  55        case DRM_FORMAT_YUV422:
  56                return 0;
  57        default:
  58                return -EINVAL;
  59        }
  60}
  61
  62static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
  63                                             struct drm_atomic_state *state)
  64{
  65        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  66        unsigned int value;
  67        int index;
  68
  69        index = fsl_dcu_drm_plane_index(plane);
  70        if (index < 0)
  71                return;
  72
  73        regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
  74        value &= ~DCU_LAYER_EN;
  75        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
  76}
  77
  78static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
  79                                            struct drm_atomic_state *state)
  80
  81{
  82        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  83        struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
  84                                                                           plane);
  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->format->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                fallthrough;
 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                fallthrough;
 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                fallthrough;
 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(new_state->crtc_h) |
 133                     DCU_LAYER_WIDTH(new_state->crtc_w));
 134        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
 135                     DCU_LAYER_POSY(new_state->crtc_y) |
 136                     DCU_LAYER_POSX(new_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
 164        return;
 165}
 166
 167static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
 168        .atomic_check = fsl_dcu_drm_plane_atomic_check,
 169        .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
 170        .atomic_update = fsl_dcu_drm_plane_atomic_update,
 171};
 172
 173static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
 174{
 175        drm_plane_cleanup(plane);
 176        kfree(plane);
 177}
 178
 179static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
 180        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 181        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 182        .destroy = fsl_dcu_drm_plane_destroy,
 183        .disable_plane = drm_atomic_helper_disable_plane,
 184        .reset = drm_atomic_helper_plane_reset,
 185        .update_plane = drm_atomic_helper_update_plane,
 186};
 187
 188static const u32 fsl_dcu_drm_plane_formats[] = {
 189        DRM_FORMAT_RGB565,
 190        DRM_FORMAT_RGB888,
 191        DRM_FORMAT_XRGB8888,
 192        DRM_FORMAT_ARGB8888,
 193        DRM_FORMAT_XRGB4444,
 194        DRM_FORMAT_ARGB4444,
 195        DRM_FORMAT_XRGB1555,
 196        DRM_FORMAT_ARGB1555,
 197        DRM_FORMAT_YUV422,
 198};
 199
 200void fsl_dcu_drm_init_planes(struct drm_device *dev)
 201{
 202        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 203        int i, j;
 204
 205        for (i = 0; i < fsl_dev->soc->total_layer; i++) {
 206                for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
 207                        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
 208        }
 209}
 210
 211struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 212{
 213        struct drm_plane *primary;
 214        int ret;
 215
 216        primary = kzalloc(sizeof(*primary), GFP_KERNEL);
 217        if (!primary) {
 218                DRM_DEBUG_KMS("Failed to allocate primary plane\n");
 219                return NULL;
 220        }
 221
 222        /* possible_crtc's will be filled in later by crtc_init */
 223        ret = drm_universal_plane_init(dev, primary, 0,
 224                                       &fsl_dcu_drm_plane_funcs,
 225                                       fsl_dcu_drm_plane_formats,
 226                                       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
 227                                       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 228        if (ret) {
 229                kfree(primary);
 230                primary = NULL;
 231        }
 232        drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
 233
 234        return primary;
 235}
 236