0001
0002
0003
0004
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
0043
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
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
0167
0168 logicvc_layer_buffer_find_setup(logicvc, layer, new_state,
0169 &setup);
0170
0171
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
0182
0183 regmap_write(logicvc->regmap, LOGICVC_LAYER_HPOSITION_REG(index),
0184 mode->hdisplay - 1 - new_state->crtc_x);
0185
0186
0187 regmap_write(logicvc->regmap, LOGICVC_LAYER_VPOSITION_REG(index),
0188 mode->vdisplay - 1 - new_state->crtc_y);
0189
0190
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
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
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
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
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
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
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
0501 if (logicvc->config.background_layer &&
0502 index == (logicvc->config.layers_count - 1)) {
0503
0504
0505
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 }