Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2019-2022 Bootlin
0004  * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
0005  */
0006 
0007 #include <linux/of.h>
0008 #include <linux/types.h>
0009 
0010 #include <drm/drm_atomic.h>
0011 #include <drm/drm_atomic_helper.h>
0012 #include <drm/drm_blend.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_plane.h>
0017 #include <drm/drm_plane_helper.h>
0018 #include <drm/drm_print.h>
0019 
0020 #include "logicvc_crtc.h"
0021 #include "logicvc_drm.h"
0022 #include "logicvc_layer.h"
0023 #include "logicvc_of.h"
0024 #include "logicvc_regs.h"
0025 
0026 #define logicvc_layer(p) \
0027     container_of(p, struct logicvc_layer, drm_plane)
0028 
0029 static uint32_t logicvc_layer_formats_rgb16[] = {
0030     DRM_FORMAT_RGB565,
0031     DRM_FORMAT_BGR565,
0032     DRM_FORMAT_INVALID,
0033 };
0034 
0035 static uint32_t logicvc_layer_formats_rgb24[] = {
0036     DRM_FORMAT_XRGB8888,
0037     DRM_FORMAT_XBGR8888,
0038     DRM_FORMAT_INVALID,
0039 };
0040 
0041 /*
0042  * What we call depth in this driver only counts color components, not alpha.
0043  * This allows us to stay compatible with the LogiCVC bistream definitions.
0044  */
0045 static uint32_t logicvc_layer_formats_rgb24_alpha[] = {
0046     DRM_FORMAT_ARGB8888,
0047     DRM_FORMAT_ABGR8888,
0048     DRM_FORMAT_INVALID,
0049 };
0050 
0051 static struct logicvc_layer_formats logicvc_layer_formats[] = {
0052     {
0053         .colorspace = LOGICVC_LAYER_COLORSPACE_RGB,
0054         .depth      = 16,
0055         .formats    = logicvc_layer_formats_rgb16,
0056     },
0057     {
0058         .colorspace = LOGICVC_LAYER_COLORSPACE_RGB,
0059         .depth      = 24,
0060         .formats    = logicvc_layer_formats_rgb24,
0061     },
0062     {
0063         .colorspace = LOGICVC_LAYER_COLORSPACE_RGB,
0064         .depth      = 24,
0065         .alpha      = true,
0066         .formats    = logicvc_layer_formats_rgb24_alpha,
0067     },
0068     { }
0069 };
0070 
0071 static bool logicvc_layer_format_inverted(uint32_t format)
0072 {
0073     switch (format) {
0074     case DRM_FORMAT_BGR565:
0075     case DRM_FORMAT_BGR888:
0076     case DRM_FORMAT_XBGR8888:
0077     case DRM_FORMAT_ABGR8888:
0078         return true;
0079     default:
0080         return false;
0081     }
0082 }
0083 
0084 static int logicvc_plane_atomic_check(struct drm_plane *drm_plane,
0085                       struct drm_atomic_state *state)
0086 {
0087     struct drm_device *drm_dev = drm_plane->dev;
0088     struct logicvc_layer *layer = logicvc_layer(drm_plane);
0089     struct logicvc_drm *logicvc = logicvc_drm(drm_dev);
0090     struct drm_plane_state *new_state =
0091         drm_atomic_get_new_plane_state(state, drm_plane);
0092     struct drm_crtc_state *crtc_state;
0093     int min_scale, max_scale;
0094     bool can_position;
0095     int ret;
0096 
0097     if (!new_state->crtc)
0098         return 0;
0099 
0100     crtc_state = drm_atomic_get_existing_crtc_state(new_state->state,
0101                             new_state->crtc);
0102     if (WARN_ON(!crtc_state))
0103         return -EINVAL;
0104 
0105     if (new_state->crtc_x < 0 || new_state->crtc_y < 0) {
0106         drm_err(drm_dev,
0107             "Negative on-CRTC positions are not supported.\n");
0108         return -EINVAL;
0109     }
0110 
0111     if (!logicvc->caps->layer_address) {
0112         ret = logicvc_layer_buffer_find_setup(logicvc, layer, new_state,
0113                               NULL);
0114         if (ret) {
0115             drm_err(drm_dev, "No viable setup for buffer found.\n");
0116             return ret;
0117         }
0118     }
0119 
0120     min_scale = DRM_PLANE_HELPER_NO_SCALING;
0121     max_scale = DRM_PLANE_HELPER_NO_SCALING;
0122 
0123     can_position = (drm_plane->type == DRM_PLANE_TYPE_OVERLAY &&
0124             layer->index != (logicvc->config.layers_count - 1) &&
0125             logicvc->config.layers_configurable);
0126 
0127     ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
0128                           min_scale, max_scale,
0129                           can_position, true);
0130     if (ret) {
0131         drm_err(drm_dev, "Invalid plane state\n\n");
0132         return ret;
0133     }
0134 
0135     return 0;
0136 }
0137 
0138 static void logicvc_plane_atomic_update(struct drm_plane *drm_plane,
0139                     struct drm_atomic_state *state)
0140 {
0141     struct logicvc_layer *layer = logicvc_layer(drm_plane);
0142     struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
0143     struct drm_device *drm_dev = &logicvc->drm_dev;
0144     struct drm_plane_state *new_state =
0145         drm_atomic_get_new_plane_state(state, drm_plane);
0146     struct drm_crtc *drm_crtc = &logicvc->crtc->drm_crtc;
0147     struct drm_display_mode *mode = &drm_crtc->state->adjusted_mode;
0148     struct drm_framebuffer *fb = new_state->fb;
0149     struct logicvc_layer_buffer_setup setup = {};
0150     u32 index = layer->index;
0151     u32 reg;
0152 
0153     /* Layer dimensions */
0154 
0155     regmap_write(logicvc->regmap, LOGICVC_LAYER_WIDTH_REG(index),
0156              new_state->crtc_w - 1);
0157     regmap_write(logicvc->regmap, LOGICVC_LAYER_HEIGHT_REG(index),
0158              new_state->crtc_h - 1);
0159 
0160     if (logicvc->caps->layer_address) {
0161         phys_addr_t fb_addr = drm_fb_cma_get_gem_addr(fb, new_state, 0);
0162 
0163         regmap_write(logicvc->regmap, LOGICVC_LAYER_ADDRESS_REG(index),
0164                  fb_addr);
0165     } else {
0166         /* Rely on offsets to configure the address. */
0167 
0168         logicvc_layer_buffer_find_setup(logicvc, layer, new_state,
0169                         &setup);
0170 
0171         /* Layer memory offsets */
0172 
0173         regmap_write(logicvc->regmap, LOGICVC_BUFFER_SEL_REG,
0174                  LOGICVC_BUFFER_SEL_VALUE(index, setup.buffer_sel));
0175         regmap_write(logicvc->regmap, LOGICVC_LAYER_HOFFSET_REG(index),
0176                  setup.hoffset);
0177         regmap_write(logicvc->regmap, LOGICVC_LAYER_VOFFSET_REG(index),
0178                  setup.voffset);
0179     }
0180 
0181     /* Layer position */
0182 
0183     regmap_write(logicvc->regmap, LOGICVC_LAYER_HPOSITION_REG(index),
0184              mode->hdisplay - 1 - new_state->crtc_x);
0185 
0186     /* Vertical position must be set last to sync layer register changes. */
0187     regmap_write(logicvc->regmap, LOGICVC_LAYER_VPOSITION_REG(index),
0188              mode->vdisplay - 1 - new_state->crtc_y);
0189 
0190     /* Layer alpha */
0191 
0192     if (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_LAYER) {
0193         u32 alpha_bits;
0194         u32 alpha_max;
0195         u32 alpha;
0196 
0197         switch (layer->config.depth) {
0198         case 8:
0199             alpha_bits = 3;
0200             break;
0201         case 16:
0202             if (layer->config.colorspace ==
0203                 LOGICVC_LAYER_COLORSPACE_YUV)
0204                 alpha_bits = 8;
0205             else
0206                 alpha_bits = 6;
0207             break;
0208         default:
0209             alpha_bits = 8;
0210             break;
0211         }
0212 
0213         alpha_max = BIT(alpha_bits) - 1;
0214         alpha = new_state->alpha * alpha_max / DRM_BLEND_ALPHA_OPAQUE;
0215 
0216         drm_dbg_kms(drm_dev, "Setting layer %d alpha to %d/%d\n", index,
0217                 alpha, alpha_max);
0218 
0219         regmap_write(logicvc->regmap, LOGICVC_LAYER_ALPHA_REG(index),
0220                  alpha);
0221     }
0222 
0223     /* Layer control */
0224 
0225     reg = LOGICVC_LAYER_CTRL_ENABLE;
0226 
0227     if (logicvc_layer_format_inverted(fb->format->format))
0228         reg |= LOGICVC_LAYER_CTRL_PIXEL_FORMAT_INVERT;
0229 
0230     reg |= LOGICVC_LAYER_CTRL_COLOR_KEY_DISABLE;
0231 
0232     regmap_write(logicvc->regmap, LOGICVC_LAYER_CTRL_REG(index), reg);
0233 }
0234 
0235 static void logicvc_plane_atomic_disable(struct drm_plane *drm_plane,
0236                      struct drm_atomic_state *state)
0237 {
0238     struct logicvc_layer *layer = logicvc_layer(drm_plane);
0239     struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
0240     u32 index = layer->index;
0241 
0242     regmap_write(logicvc->regmap, LOGICVC_LAYER_CTRL_REG(index), 0);
0243 }
0244 
0245 static struct drm_plane_helper_funcs logicvc_plane_helper_funcs = {
0246     .atomic_check       = logicvc_plane_atomic_check,
0247     .atomic_update      = logicvc_plane_atomic_update,
0248     .atomic_disable     = logicvc_plane_atomic_disable,
0249 };
0250 
0251 static const struct drm_plane_funcs logicvc_plane_funcs = {
0252     .update_plane       = drm_atomic_helper_update_plane,
0253     .disable_plane      = drm_atomic_helper_disable_plane,
0254     .destroy        = drm_plane_cleanup,
0255     .reset          = drm_atomic_helper_plane_reset,
0256     .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
0257     .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
0258 };
0259 
0260 int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc,
0261                     struct logicvc_layer *layer,
0262                     struct drm_plane_state *state,
0263                     struct logicvc_layer_buffer_setup *setup)
0264 {
0265     struct drm_device *drm_dev = &logicvc->drm_dev;
0266     struct drm_framebuffer *fb = state->fb;
0267     /* All the supported formats have a single data plane. */
0268     u32 layer_bytespp = fb->format->cpp[0];
0269     u32 layer_stride = layer_bytespp * logicvc->config.row_stride;
0270     u32 base_offset = layer->config.base_offset * layer_stride;
0271     u32 buffer_offset = layer->config.buffer_offset * layer_stride;
0272     u8 buffer_sel = 0;
0273     u16 voffset = 0;
0274     u16 hoffset = 0;
0275     phys_addr_t fb_addr;
0276     u32 fb_offset;
0277     u32 gap;
0278 
0279     if (!logicvc->reserved_mem_base) {
0280         drm_err(drm_dev, "No reserved memory base was registered!\n");
0281         return -ENOMEM;
0282     }
0283 
0284     fb_addr = drm_fb_cma_get_gem_addr(fb, state, 0);
0285     if (fb_addr < logicvc->reserved_mem_base) {
0286         drm_err(drm_dev,
0287             "Framebuffer memory below reserved memory base!\n");
0288         return -EINVAL;
0289     }
0290 
0291     fb_offset = (u32) (fb_addr - logicvc->reserved_mem_base);
0292 
0293     if (fb_offset < base_offset) {
0294         drm_err(drm_dev,
0295             "Framebuffer offset below layer base offset!\n");
0296         return -EINVAL;
0297     }
0298 
0299     gap = fb_offset - base_offset;
0300 
0301     /* Use the possible video buffers selection. */
0302     if (gap && buffer_offset) {
0303         buffer_sel = gap / buffer_offset;
0304         if (buffer_sel > LOGICVC_BUFFER_SEL_MAX)
0305             buffer_sel = LOGICVC_BUFFER_SEL_MAX;
0306 
0307         gap -= buffer_sel * buffer_offset;
0308     }
0309 
0310     /* Use the vertical offset. */
0311     if (gap && layer_stride && logicvc->config.layers_configurable) {
0312         voffset = gap / layer_stride;
0313         if (voffset > LOGICVC_LAYER_VOFFSET_MAX)
0314             voffset = LOGICVC_LAYER_VOFFSET_MAX;
0315 
0316         gap -= voffset * layer_stride;
0317     }
0318 
0319     /* Use the horizontal offset. */
0320     if (gap && layer_bytespp && logicvc->config.layers_configurable) {
0321         hoffset = gap / layer_bytespp;
0322         if (hoffset > LOGICVC_DIMENSIONS_MAX)
0323             hoffset = LOGICVC_DIMENSIONS_MAX;
0324 
0325         gap -= hoffset * layer_bytespp;
0326     }
0327 
0328     if (gap) {
0329         drm_err(drm_dev,
0330             "Unable to find layer %d buffer setup for 0x%x byte gap\n",
0331             layer->index, fb_offset - base_offset);
0332         return -EINVAL;
0333     }
0334 
0335     drm_dbg_kms(drm_dev, "Found layer %d buffer setup for 0x%x byte gap:\n",
0336             layer->index, fb_offset - base_offset);
0337 
0338     drm_dbg_kms(drm_dev, "- buffer_sel = 0x%x chunks of 0x%x bytes\n",
0339             buffer_sel, buffer_offset);
0340     drm_dbg_kms(drm_dev, "- voffset = 0x%x chunks of 0x%x bytes\n", voffset,
0341             layer_stride);
0342     drm_dbg_kms(drm_dev, "- hoffset = 0x%x chunks of 0x%x bytes\n", hoffset,
0343             layer_bytespp);
0344 
0345     if (setup) {
0346         setup->buffer_sel = buffer_sel;
0347         setup->voffset = voffset;
0348         setup->hoffset = hoffset;
0349     }
0350 
0351     return 0;
0352 }
0353 
0354 static struct logicvc_layer_formats *logicvc_layer_formats_lookup(struct logicvc_layer *layer)
0355 {
0356     bool alpha;
0357     unsigned int i = 0;
0358 
0359     alpha = (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_PIXEL);
0360 
0361     while (logicvc_layer_formats[i].formats) {
0362         if (logicvc_layer_formats[i].colorspace == layer->config.colorspace &&
0363             logicvc_layer_formats[i].depth == layer->config.depth &&
0364             logicvc_layer_formats[i].alpha == alpha)
0365             return &logicvc_layer_formats[i];
0366 
0367         i++;
0368     }
0369 
0370     return NULL;
0371 }
0372 
0373 static unsigned int logicvc_layer_formats_count(struct logicvc_layer_formats *formats)
0374 {
0375     unsigned int count = 0;
0376 
0377     while (formats->formats[count] != DRM_FORMAT_INVALID)
0378         count++;
0379 
0380     return count;
0381 }
0382 
0383 static int logicvc_layer_config_parse(struct logicvc_drm *logicvc,
0384                       struct logicvc_layer *layer)
0385 {
0386     struct device_node *of_node = layer->of_node;
0387     struct logicvc_layer_config *config = &layer->config;
0388     int ret;
0389 
0390     logicvc_of_property_parse_bool(of_node,
0391                        LOGICVC_OF_PROPERTY_LAYER_PRIMARY,
0392                        &config->primary);
0393 
0394     ret = logicvc_of_property_parse_u32(of_node,
0395                         LOGICVC_OF_PROPERTY_LAYER_COLORSPACE,
0396                         &config->colorspace);
0397     if (ret)
0398         return ret;
0399 
0400     ret = logicvc_of_property_parse_u32(of_node,
0401                         LOGICVC_OF_PROPERTY_LAYER_DEPTH,
0402                         &config->depth);
0403     if (ret)
0404         return ret;
0405 
0406     ret = logicvc_of_property_parse_u32(of_node,
0407                         LOGICVC_OF_PROPERTY_LAYER_ALPHA_MODE,
0408                         &config->alpha_mode);
0409     if (ret)
0410         return ret;
0411 
0412     /*
0413      * Memory offset is only relevant without layer address configuration.
0414      */
0415     if (logicvc->caps->layer_address)
0416         return 0;
0417 
0418     ret = logicvc_of_property_parse_u32(of_node,
0419                         LOGICVC_OF_PROPERTY_LAYER_BASE_OFFSET,
0420                         &config->base_offset);
0421     if (ret)
0422         return ret;
0423 
0424     ret = logicvc_of_property_parse_u32(of_node,
0425                         LOGICVC_OF_PROPERTY_LAYER_BUFFER_OFFSET,
0426                         &config->buffer_offset);
0427     if (ret)
0428         return ret;
0429 
0430     return 0;
0431 }
0432 
0433 struct logicvc_layer *logicvc_layer_get_from_index(struct logicvc_drm *logicvc,
0434                            u32 index)
0435 {
0436     struct logicvc_layer *layer;
0437 
0438     list_for_each_entry(layer, &logicvc->layers_list, list)
0439         if (layer->index == index)
0440             return layer;
0441 
0442     return NULL;
0443 }
0444 
0445 struct logicvc_layer *logicvc_layer_get_from_type(struct logicvc_drm *logicvc,
0446                           enum drm_plane_type type)
0447 {
0448     struct logicvc_layer *layer;
0449 
0450     list_for_each_entry(layer, &logicvc->layers_list, list)
0451         if (layer->drm_plane.type == type)
0452             return layer;
0453 
0454     return NULL;
0455 }
0456 
0457 struct logicvc_layer *logicvc_layer_get_primary(struct logicvc_drm *logicvc)
0458 {
0459     return logicvc_layer_get_from_type(logicvc, DRM_PLANE_TYPE_PRIMARY);
0460 }
0461 
0462 static int logicvc_layer_init(struct logicvc_drm *logicvc,
0463                   struct device_node *of_node, u32 index)
0464 {
0465     struct drm_device *drm_dev = &logicvc->drm_dev;
0466     struct device *dev = drm_dev->dev;
0467     struct logicvc_layer *layer = NULL;
0468     struct logicvc_layer_formats *formats;
0469     unsigned int formats_count;
0470     enum drm_plane_type type;
0471     unsigned int zpos;
0472     int ret;
0473 
0474     layer = devm_kzalloc(dev, sizeof(*layer), GFP_KERNEL);
0475     if (!layer) {
0476         ret = -ENOMEM;
0477         goto error;
0478     }
0479 
0480     layer->of_node = of_node;
0481     layer->index = index;
0482 
0483     ret = logicvc_layer_config_parse(logicvc, layer);
0484     if (ret) {
0485         drm_err(drm_dev, "Failed to parse config for layer #%d\n",
0486             index);
0487         goto error;
0488     }
0489 
0490     formats = logicvc_layer_formats_lookup(layer);
0491     if (!formats) {
0492         drm_err(drm_dev, "Failed to lookup formats for layer #%d\n",
0493             index);
0494         ret = -EINVAL;
0495         goto error;
0496     }
0497 
0498     formats_count = logicvc_layer_formats_count(formats);
0499 
0500     /* The final layer can be configured as a background layer. */
0501     if (logicvc->config.background_layer &&
0502         index == (logicvc->config.layers_count - 1)) {
0503         /*
0504          * A zero value for black is only valid for RGB, not for YUV,
0505          * so this will need to take the format in account for YUV.
0506          */
0507         u32 background = 0;
0508 
0509         drm_dbg_kms(drm_dev, "Using layer #%d as background layer\n",
0510                 index);
0511 
0512         regmap_write(logicvc->regmap, LOGICVC_BACKGROUND_COLOR_REG,
0513                  background);
0514 
0515         devm_kfree(dev, layer);
0516 
0517         return 0;
0518     }
0519 
0520     if (layer->config.primary)
0521         type = DRM_PLANE_TYPE_PRIMARY;
0522     else
0523         type = DRM_PLANE_TYPE_OVERLAY;
0524 
0525     ret = drm_universal_plane_init(drm_dev, &layer->drm_plane, 0,
0526                        &logicvc_plane_funcs, formats->formats,
0527                        formats_count, NULL, type, NULL);
0528     if (ret) {
0529         drm_err(drm_dev, "Failed to initialize layer plane\n");
0530         return ret;
0531     }
0532 
0533     drm_plane_helper_add(&layer->drm_plane, &logicvc_plane_helper_funcs);
0534 
0535     zpos = logicvc->config.layers_count - index - 1;
0536     drm_dbg_kms(drm_dev, "Giving layer #%d zpos %d\n", index, zpos);
0537 
0538     if (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_LAYER)
0539         drm_plane_create_alpha_property(&layer->drm_plane);
0540 
0541     drm_plane_create_zpos_immutable_property(&layer->drm_plane, zpos);
0542 
0543     drm_dbg_kms(drm_dev, "Registering layer #%d\n", index);
0544 
0545     layer->formats = formats;
0546 
0547     list_add_tail(&layer->list, &logicvc->layers_list);
0548 
0549     return 0;
0550 
0551 error:
0552     if (layer)
0553         devm_kfree(dev, layer);
0554 
0555     return ret;
0556 }
0557 
0558 static void logicvc_layer_fini(struct logicvc_drm *logicvc,
0559                    struct logicvc_layer *layer)
0560 {
0561     struct device *dev = logicvc->drm_dev.dev;
0562 
0563     list_del(&layer->list);
0564     devm_kfree(dev, layer);
0565 }
0566 
0567 void logicvc_layers_attach_crtc(struct logicvc_drm *logicvc)
0568 {
0569     uint32_t possible_crtcs = drm_crtc_mask(&logicvc->crtc->drm_crtc);
0570     struct logicvc_layer *layer;
0571 
0572     list_for_each_entry(layer, &logicvc->layers_list, list) {
0573         if (layer->drm_plane.type != DRM_PLANE_TYPE_OVERLAY)
0574             continue;
0575 
0576         layer->drm_plane.possible_crtcs = possible_crtcs;
0577     }
0578 }
0579 
0580 int logicvc_layers_init(struct logicvc_drm *logicvc)
0581 {
0582     struct drm_device *drm_dev = &logicvc->drm_dev;
0583     struct device *dev = drm_dev->dev;
0584     struct device_node *of_node = dev->of_node;
0585     struct device_node *layer_node = NULL;
0586     struct device_node *layers_node;
0587     struct logicvc_layer *layer;
0588     struct logicvc_layer *next;
0589     int ret = 0;
0590 
0591     layers_node = of_get_child_by_name(of_node, "layers");
0592     if (!layers_node) {
0593         drm_err(drm_dev, "No layers node found in the description\n");
0594         ret = -ENODEV;
0595         goto error;
0596     }
0597 
0598     for_each_child_of_node(layers_node, layer_node) {
0599         u32 index = 0;
0600 
0601         if (!logicvc_of_node_is_layer(layer_node))
0602             continue;
0603 
0604         ret = of_property_read_u32(layer_node, "reg", &index);
0605         if (ret)
0606             continue;
0607 
0608         layer = logicvc_layer_get_from_index(logicvc, index);
0609         if (layer) {
0610             drm_err(drm_dev, "Duplicated entry for layer #%d\n",
0611                 index);
0612             continue;
0613         }
0614 
0615         ret = logicvc_layer_init(logicvc, layer_node, index);
0616         if (ret) {
0617             of_node_put(layers_node);
0618             goto error;
0619         }
0620     }
0621 
0622     of_node_put(layers_node);
0623 
0624     return 0;
0625 
0626 error:
0627     list_for_each_entry_safe(layer, next, &logicvc->layers_list, list)
0628         logicvc_layer_fini(logicvc, layer);
0629 
0630     return ret;
0631 }