Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2015 Freescale Semiconductor, Inc.
0004  *
0005  * Freescale DCU drm device driver
0006  */
0007 
0008 #include <linux/regmap.h>
0009 
0010 #include <drm/drm_atomic.h>
0011 #include <drm/drm_atomic_helper.h>
0012 #include <drm/drm_crtc.h>
0013 #include <drm/drm_fb_cma_helper.h>
0014 #include <drm/drm_fourcc.h>
0015 #include <drm/drm_framebuffer.h>
0016 #include <drm/drm_gem_cma_helper.h>
0017 #include <drm/drm_plane_helper.h>
0018 #include <drm/drm_probe_helper.h>
0019 
0020 #include "fsl_dcu_drm_drv.h"
0021 #include "fsl_dcu_drm_plane.h"
0022 
0023 static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
0024 {
0025     struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
0026     unsigned int total_layer = fsl_dev->soc->total_layer;
0027     unsigned int index;
0028 
0029     index = drm_plane_index(plane);
0030     if (index < total_layer)
0031         return total_layer - index - 1;
0032 
0033     dev_err(fsl_dev->dev, "No more layer left\n");
0034     return -EINVAL;
0035 }
0036 
0037 static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
0038                       struct drm_atomic_state *state)
0039 {
0040     struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0041                                          plane);
0042     struct drm_framebuffer *fb = new_plane_state->fb;
0043 
0044     if (!new_plane_state->fb || !new_plane_state->crtc)
0045         return 0;
0046 
0047     switch (fb->format->format) {
0048     case DRM_FORMAT_RGB565:
0049     case DRM_FORMAT_RGB888:
0050     case DRM_FORMAT_XRGB8888:
0051     case DRM_FORMAT_ARGB8888:
0052     case DRM_FORMAT_XRGB4444:
0053     case DRM_FORMAT_ARGB4444:
0054     case DRM_FORMAT_XRGB1555:
0055     case DRM_FORMAT_ARGB1555:
0056     case DRM_FORMAT_YUV422:
0057         return 0;
0058     default:
0059         return -EINVAL;
0060     }
0061 }
0062 
0063 static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
0064                          struct drm_atomic_state *state)
0065 {
0066     struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
0067     unsigned int value;
0068     int index;
0069 
0070     index = fsl_dcu_drm_plane_index(plane);
0071     if (index < 0)
0072         return;
0073 
0074     regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
0075     value &= ~DCU_LAYER_EN;
0076     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
0077 }
0078 
0079 static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
0080                         struct drm_atomic_state *state)
0081 
0082 {
0083     struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
0084     struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0085                                        plane);
0086     struct drm_framebuffer *fb = plane->state->fb;
0087     struct drm_gem_cma_object *gem;
0088     unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
0089     int index;
0090 
0091     if (!fb)
0092         return;
0093 
0094     index = fsl_dcu_drm_plane_index(plane);
0095     if (index < 0)
0096         return;
0097 
0098     gem = drm_fb_cma_get_gem_obj(fb, 0);
0099 
0100     switch (fb->format->format) {
0101     case DRM_FORMAT_RGB565:
0102         bpp = FSL_DCU_RGB565;
0103         break;
0104     case DRM_FORMAT_RGB888:
0105         bpp = FSL_DCU_RGB888;
0106         break;
0107     case DRM_FORMAT_ARGB8888:
0108         alpha = DCU_LAYER_AB_WHOLE_FRAME;
0109         fallthrough;
0110     case DRM_FORMAT_XRGB8888:
0111         bpp = FSL_DCU_ARGB8888;
0112         break;
0113     case DRM_FORMAT_ARGB4444:
0114         alpha = DCU_LAYER_AB_WHOLE_FRAME;
0115         fallthrough;
0116     case DRM_FORMAT_XRGB4444:
0117         bpp = FSL_DCU_ARGB4444;
0118         break;
0119     case DRM_FORMAT_ARGB1555:
0120         alpha = DCU_LAYER_AB_WHOLE_FRAME;
0121         fallthrough;
0122     case DRM_FORMAT_XRGB1555:
0123         bpp = FSL_DCU_ARGB1555;
0124         break;
0125     case DRM_FORMAT_YUV422:
0126         bpp = FSL_DCU_YUV422;
0127         break;
0128     default:
0129         return;
0130     }
0131 
0132     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
0133              DCU_LAYER_HEIGHT(new_state->crtc_h) |
0134              DCU_LAYER_WIDTH(new_state->crtc_w));
0135     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
0136              DCU_LAYER_POSY(new_state->crtc_y) |
0137              DCU_LAYER_POSX(new_state->crtc_x));
0138     regmap_write(fsl_dev->regmap,
0139              DCU_CTRLDESCLN(index, 3), gem->paddr);
0140     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
0141              DCU_LAYER_EN |
0142              DCU_LAYER_TRANS(0xff) |
0143              DCU_LAYER_BPP(bpp) |
0144              alpha);
0145     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
0146              DCU_LAYER_CKMAX_R(0xFF) |
0147              DCU_LAYER_CKMAX_G(0xFF) |
0148              DCU_LAYER_CKMAX_B(0xFF));
0149     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
0150              DCU_LAYER_CKMIN_R(0) |
0151              DCU_LAYER_CKMIN_G(0) |
0152              DCU_LAYER_CKMIN_B(0));
0153     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
0154     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
0155              DCU_LAYER_FG_FCOLOR(0));
0156     regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
0157              DCU_LAYER_BG_BCOLOR(0));
0158 
0159     if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
0160         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
0161                  DCU_LAYER_POST_SKIP(0) |
0162                  DCU_LAYER_PRE_SKIP(0));
0163     }
0164 
0165     return;
0166 }
0167 
0168 static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
0169     .atomic_check = fsl_dcu_drm_plane_atomic_check,
0170     .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
0171     .atomic_update = fsl_dcu_drm_plane_atomic_update,
0172 };
0173 
0174 static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
0175 {
0176     drm_plane_cleanup(plane);
0177     kfree(plane);
0178 }
0179 
0180 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
0181     .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
0182     .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
0183     .destroy = fsl_dcu_drm_plane_destroy,
0184     .disable_plane = drm_atomic_helper_disable_plane,
0185     .reset = drm_atomic_helper_plane_reset,
0186     .update_plane = drm_atomic_helper_update_plane,
0187 };
0188 
0189 static const u32 fsl_dcu_drm_plane_formats[] = {
0190     DRM_FORMAT_RGB565,
0191     DRM_FORMAT_RGB888,
0192     DRM_FORMAT_XRGB8888,
0193     DRM_FORMAT_ARGB8888,
0194     DRM_FORMAT_XRGB4444,
0195     DRM_FORMAT_ARGB4444,
0196     DRM_FORMAT_XRGB1555,
0197     DRM_FORMAT_ARGB1555,
0198     DRM_FORMAT_YUV422,
0199 };
0200 
0201 void fsl_dcu_drm_init_planes(struct drm_device *dev)
0202 {
0203     struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
0204     int i, j;
0205 
0206     for (i = 0; i < fsl_dev->soc->total_layer; i++) {
0207         for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
0208             regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
0209     }
0210 }
0211 
0212 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
0213 {
0214     struct drm_plane *primary;
0215     int ret;
0216 
0217     primary = kzalloc(sizeof(*primary), GFP_KERNEL);
0218     if (!primary) {
0219         DRM_DEBUG_KMS("Failed to allocate primary plane\n");
0220         return NULL;
0221     }
0222 
0223     /* possible_crtc's will be filled in later by crtc_init */
0224     ret = drm_universal_plane_init(dev, primary, 0,
0225                        &fsl_dcu_drm_plane_funcs,
0226                        fsl_dcu_drm_plane_formats,
0227                        ARRAY_SIZE(fsl_dcu_drm_plane_formats),
0228                        NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
0229     if (ret) {
0230         kfree(primary);
0231         primary = NULL;
0232     }
0233     drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
0234 
0235     return primary;
0236 }