0001
0002
0003
0004
0005
0006 #include <drm/drm_atomic.h>
0007 #include <drm/drm_atomic_helper.h>
0008 #include <drm/drm_blend.h>
0009 #include <drm/drm_crtc.h>
0010 #include <drm/drm_crtc_helper.h>
0011 #include <drm/drm_fb_cma_helper.h>
0012 #include <drm/drm_fb_helper.h>
0013 #include <drm/drm_fourcc.h>
0014 #include <drm/drm_framebuffer.h>
0015 #include <drm/drm_gem_cma_helper.h>
0016 #include <drm/drm_managed.h>
0017 #include <drm/drm_plane_helper.h>
0018
0019 #include "kmb_drv.h"
0020 #include "kmb_plane.h"
0021 #include "kmb_regs.h"
0022
0023 const u32 layer_irqs[] = {
0024 LCD_INT_VL0,
0025 LCD_INT_VL1,
0026 LCD_INT_GL0,
0027 LCD_INT_GL1
0028 };
0029
0030
0031 static const u32 csc_coef_lcd[] = {
0032 1024, 0, 1436,
0033 1024, -352, -731,
0034 1024, 1814, 0,
0035 -179, 125, -226
0036 };
0037
0038
0039 static const u32 kmb_formats_g[] = {
0040 DRM_FORMAT_RGB332,
0041 DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
0042 DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
0043 DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
0044 DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
0045 DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
0046 DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
0047 DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
0048 DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
0049 };
0050
0051
0052 static const u32 kmb_formats_v[] = {
0053
0054 DRM_FORMAT_RGB332,
0055 DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
0056 DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
0057 DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
0058 DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
0059 DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
0060 DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
0061 DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
0062 DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
0063
0064 DRM_FORMAT_YUV420, DRM_FORMAT_YVU420,
0065 DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
0066 DRM_FORMAT_YUV444, DRM_FORMAT_YVU444,
0067 DRM_FORMAT_NV12, DRM_FORMAT_NV21,
0068 };
0069
0070 static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
0071 {
0072 struct kmb_drm_private *kmb;
0073 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
0074 int i;
0075 int plane_id = kmb_plane->id;
0076 struct disp_cfg init_disp_cfg;
0077
0078 kmb = to_kmb(plane->dev);
0079 init_disp_cfg = kmb->init_disp_cfg[plane_id];
0080
0081
0082
0083 if (init_disp_cfg.format && init_disp_cfg.format != format) {
0084 drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
0085 return -EINVAL;
0086 }
0087 for (i = 0; i < plane->format_count; i++) {
0088 if (plane->format_types[i] == format)
0089 return 0;
0090 }
0091 return -EINVAL;
0092 }
0093
0094 static int kmb_plane_atomic_check(struct drm_plane *plane,
0095 struct drm_atomic_state *state)
0096 {
0097 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0098 plane);
0099 struct kmb_drm_private *kmb;
0100 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
0101 int plane_id = kmb_plane->id;
0102 struct disp_cfg init_disp_cfg;
0103 struct drm_framebuffer *fb;
0104 int ret;
0105 struct drm_crtc_state *crtc_state;
0106 bool can_position;
0107
0108 kmb = to_kmb(plane->dev);
0109 init_disp_cfg = kmb->init_disp_cfg[plane_id];
0110 fb = new_plane_state->fb;
0111 if (!fb || !new_plane_state->crtc)
0112 return 0;
0113
0114 ret = check_pixel_format(plane, fb->format->format);
0115 if (ret)
0116 return ret;
0117
0118 if (new_plane_state->crtc_w > KMB_FB_MAX_WIDTH ||
0119 new_plane_state->crtc_h > KMB_FB_MAX_HEIGHT ||
0120 new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
0121 new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
0122 return -EINVAL;
0123
0124
0125
0126
0127 if ((init_disp_cfg.width && init_disp_cfg.height) &&
0128 (init_disp_cfg.width != fb->width ||
0129 init_disp_cfg.height != fb->height)) {
0130 drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
0131 return -EINVAL;
0132 }
0133 can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
0134 crtc_state =
0135 drm_atomic_get_existing_crtc_state(state,
0136 new_plane_state->crtc);
0137 return drm_atomic_helper_check_plane_state(new_plane_state,
0138 crtc_state,
0139 DRM_PLANE_HELPER_NO_SCALING,
0140 DRM_PLANE_HELPER_NO_SCALING,
0141 can_position, true);
0142 }
0143
0144 static void kmb_plane_atomic_disable(struct drm_plane *plane,
0145 struct drm_atomic_state *state)
0146 {
0147 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
0148 int plane_id = kmb_plane->id;
0149 struct kmb_drm_private *kmb;
0150
0151 kmb = to_kmb(plane->dev);
0152
0153 if (WARN_ON(plane_id >= KMB_MAX_PLANES))
0154 return;
0155
0156 switch (plane_id) {
0157 case LAYER_0:
0158 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
0159 break;
0160 case LAYER_1:
0161 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE;
0162 break;
0163 }
0164
0165 kmb->plane_status[plane_id].disable = true;
0166 }
0167
0168 static unsigned int get_pixel_format(u32 format)
0169 {
0170 unsigned int val = 0;
0171
0172 switch (format) {
0173
0174 case DRM_FORMAT_YUV444:
0175 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
0176 break;
0177 case DRM_FORMAT_YVU444:
0178 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
0179 | LCD_LAYER_CRCB_ORDER;
0180 break;
0181 case DRM_FORMAT_YUV422:
0182 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
0183 break;
0184 case DRM_FORMAT_YVU422:
0185 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
0186 | LCD_LAYER_CRCB_ORDER;
0187 break;
0188 case DRM_FORMAT_YUV420:
0189 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
0190 break;
0191 case DRM_FORMAT_YVU420:
0192 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
0193 | LCD_LAYER_CRCB_ORDER;
0194 break;
0195 case DRM_FORMAT_NV12:
0196 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
0197 break;
0198 case DRM_FORMAT_NV21:
0199 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
0200 | LCD_LAYER_CRCB_ORDER;
0201 break;
0202
0203
0204 case DRM_FORMAT_RGB332:
0205 val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
0206 break;
0207 case DRM_FORMAT_XBGR4444:
0208 val = LCD_LAYER_FORMAT_RGBX4444;
0209 break;
0210 case DRM_FORMAT_ARGB4444:
0211 val = LCD_LAYER_FORMAT_RGBA4444 | LCD_LAYER_BGR_ORDER;
0212 break;
0213 case DRM_FORMAT_ABGR4444:
0214 val = LCD_LAYER_FORMAT_RGBA4444;
0215 break;
0216 case DRM_FORMAT_XRGB1555:
0217 val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
0218 break;
0219 case DRM_FORMAT_XBGR1555:
0220 val = LCD_LAYER_FORMAT_XRGB1555;
0221 break;
0222 case DRM_FORMAT_ARGB1555:
0223 val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
0224 break;
0225 case DRM_FORMAT_ABGR1555:
0226 val = LCD_LAYER_FORMAT_RGBA1555;
0227 break;
0228 case DRM_FORMAT_RGB565:
0229 val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
0230 break;
0231 case DRM_FORMAT_BGR565:
0232 val = LCD_LAYER_FORMAT_RGB565;
0233 break;
0234 case DRM_FORMAT_RGB888:
0235 val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
0236 break;
0237 case DRM_FORMAT_BGR888:
0238 val = LCD_LAYER_FORMAT_RGB888;
0239 break;
0240 case DRM_FORMAT_XRGB8888:
0241 val = LCD_LAYER_FORMAT_RGBX8888 | LCD_LAYER_BGR_ORDER;
0242 break;
0243 case DRM_FORMAT_XBGR8888:
0244 val = LCD_LAYER_FORMAT_RGBX8888;
0245 break;
0246 case DRM_FORMAT_ARGB8888:
0247 val = LCD_LAYER_FORMAT_RGBA8888 | LCD_LAYER_BGR_ORDER;
0248 break;
0249 case DRM_FORMAT_ABGR8888:
0250 val = LCD_LAYER_FORMAT_RGBA8888;
0251 break;
0252 }
0253 DRM_INFO_ONCE("%s : %d format=0x%x val=0x%x\n",
0254 __func__, __LINE__, format, val);
0255 return val;
0256 }
0257
0258 static unsigned int get_bits_per_pixel(const struct drm_format_info *format)
0259 {
0260 u32 bpp = 0;
0261 unsigned int val = 0;
0262
0263 if (format->num_planes > 1) {
0264 val = LCD_LAYER_8BPP;
0265 return val;
0266 }
0267
0268 bpp += 8 * format->cpp[0];
0269
0270 switch (bpp) {
0271 case 8:
0272 val = LCD_LAYER_8BPP;
0273 break;
0274 case 16:
0275 val = LCD_LAYER_16BPP;
0276 break;
0277 case 24:
0278 val = LCD_LAYER_24BPP;
0279 break;
0280 case 32:
0281 val = LCD_LAYER_32BPP;
0282 break;
0283 }
0284
0285 DRM_DEBUG("bpp=%d val=0x%x\n", bpp, val);
0286 return val;
0287 }
0288
0289 static void config_csc(struct kmb_drm_private *kmb, int plane_id)
0290 {
0291
0292 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);
0293 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);
0294 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);
0295 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);
0296 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);
0297 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);
0298 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);
0299 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);
0300 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);
0301 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
0302 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
0303 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
0304 }
0305
0306 static void kmb_plane_set_alpha(struct kmb_drm_private *kmb,
0307 const struct drm_plane_state *state,
0308 unsigned char plane_id,
0309 unsigned int *val)
0310 {
0311 u16 plane_alpha = state->alpha;
0312 u16 pixel_blend_mode = state->pixel_blend_mode;
0313 int has_alpha = state->fb->format->has_alpha;
0314
0315 if (plane_alpha != DRM_BLEND_ALPHA_OPAQUE)
0316 *val |= LCD_LAYER_ALPHA_STATIC;
0317
0318 if (has_alpha) {
0319 switch (pixel_blend_mode) {
0320 case DRM_MODE_BLEND_PIXEL_NONE:
0321 break;
0322 case DRM_MODE_BLEND_PREMULTI:
0323 *val |= LCD_LAYER_ALPHA_EMBED | LCD_LAYER_ALPHA_PREMULT;
0324 break;
0325 case DRM_MODE_BLEND_COVERAGE:
0326 *val |= LCD_LAYER_ALPHA_EMBED;
0327 break;
0328 default:
0329 DRM_DEBUG("Missing pixel blend mode case (%s == %ld)\n",
0330 __stringify(pixel_blend_mode),
0331 (long)pixel_blend_mode);
0332 break;
0333 }
0334 }
0335
0336 if (plane_alpha == DRM_BLEND_ALPHA_OPAQUE && !has_alpha) {
0337 *val &= LCD_LAYER_ALPHA_DISABLED;
0338 return;
0339 }
0340
0341 kmb_write_lcd(kmb, LCD_LAYERn_ALPHA(plane_id), plane_alpha);
0342 }
0343
0344 static void kmb_plane_atomic_update(struct drm_plane *plane,
0345 struct drm_atomic_state *state)
0346 {
0347 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state,
0348 plane);
0349 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0350 plane);
0351 struct drm_framebuffer *fb;
0352 struct kmb_drm_private *kmb;
0353 unsigned int width;
0354 unsigned int height;
0355 unsigned int dma_len;
0356 struct kmb_plane *kmb_plane;
0357 unsigned int dma_cfg;
0358 unsigned int ctrl = 0, val = 0, out_format = 0;
0359 unsigned int src_w, src_h, crtc_x, crtc_y;
0360 unsigned char plane_id;
0361 int num_planes;
0362 static dma_addr_t addr[MAX_SUB_PLANES];
0363 struct disp_cfg *init_disp_cfg;
0364
0365 if (!plane || !new_plane_state || !old_plane_state)
0366 return;
0367
0368 fb = new_plane_state->fb;
0369 if (!fb)
0370 return;
0371
0372 num_planes = fb->format->num_planes;
0373 kmb_plane = to_kmb_plane(plane);
0374
0375 kmb = to_kmb(plane->dev);
0376 plane_id = kmb_plane->id;
0377
0378 spin_lock_irq(&kmb->irq_lock);
0379 if (kmb->kmb_under_flow || kmb->kmb_flush_done) {
0380 spin_unlock_irq(&kmb->irq_lock);
0381 drm_dbg(&kmb->drm, "plane_update:underflow!!!! returning");
0382 return;
0383 }
0384 spin_unlock_irq(&kmb->irq_lock);
0385
0386 init_disp_cfg = &kmb->init_disp_cfg[plane_id];
0387 src_w = new_plane_state->src_w >> 16;
0388 src_h = new_plane_state->src_h >> 16;
0389 crtc_x = new_plane_state->crtc_x;
0390 crtc_y = new_plane_state->crtc_y;
0391
0392 drm_dbg(&kmb->drm,
0393 "src_w=%d src_h=%d, fb->format->format=0x%x fb->flags=0x%x\n",
0394 src_w, src_h, fb->format->format, fb->flags);
0395
0396 width = fb->width;
0397 height = fb->height;
0398 dma_len = (width * height * fb->format->cpp[0]);
0399 drm_dbg(&kmb->drm, "dma_len=%d ", dma_len);
0400 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
0401 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
0402 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
0403 fb->pitches[0]);
0404 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
0405 (width * fb->format->cpp[0]));
0406
0407 addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
0408 kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),
0409 addr[Y_PLANE] + fb->offsets[0]);
0410 val = get_pixel_format(fb->format->format);
0411 val |= get_bits_per_pixel(fb->format);
0412
0413 if (num_planes > 1) {
0414 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
0415 width * fb->format->cpp[0]);
0416 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
0417 (width * fb->format->cpp[0]));
0418
0419 addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state,
0420 U_PLANE);
0421
0422 if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
0423 kmb_write_lcd(kmb,
0424 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
0425 addr[U_PLANE]);
0426 else
0427 kmb_write_lcd(kmb,
0428 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
0429 addr[U_PLANE]);
0430
0431 if (num_planes == 3) {
0432 kmb_write_lcd(kmb,
0433 LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
0434 ((width) * fb->format->cpp[0]));
0435
0436 kmb_write_lcd(kmb,
0437 LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
0438 ((width) * fb->format->cpp[0]));
0439
0440 addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
0441 new_plane_state,
0442 V_PLANE);
0443
0444
0445 if (val & LCD_LAYER_CRCB_ORDER)
0446 kmb_write_lcd(kmb,
0447 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
0448 addr[V_PLANE]);
0449 else
0450 kmb_write_lcd(kmb,
0451 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
0452 addr[V_PLANE]);
0453 }
0454 }
0455
0456 kmb_write_lcd(kmb, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
0457 kmb_write_lcd(kmb, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
0458 kmb_write_lcd(kmb, LCD_LAYERn_COL_START(plane_id), crtc_x);
0459 kmb_write_lcd(kmb, LCD_LAYERn_ROW_START(plane_id), crtc_y);
0460
0461 val |= LCD_LAYER_FIFO_100;
0462
0463 if (val & LCD_LAYER_PLANAR_STORAGE) {
0464 val |= LCD_LAYER_CSC_EN;
0465
0466
0467 config_csc(kmb, plane_id);
0468 }
0469
0470 kmb_plane_set_alpha(kmb, plane->state, plane_id, &val);
0471
0472 kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);
0473
0474
0475 ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
0476
0477
0478 ctrl &= ~LCD_CTRL_ALPHA_ALL;
0479 ctrl |= LCD_CTRL_ALPHA_BOTTOM_VL1 |
0480 LCD_CTRL_ALPHA_BLEND_VL2;
0481
0482 ctrl &= ~LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE;
0483
0484 switch (plane_id) {
0485 case LAYER_0:
0486 ctrl |= LCD_CTRL_VL1_ENABLE;
0487 break;
0488 case LAYER_1:
0489 ctrl |= LCD_CTRL_VL2_ENABLE;
0490 break;
0491 case LAYER_2:
0492 ctrl |= LCD_CTRL_GL1_ENABLE;
0493 break;
0494 case LAYER_3:
0495 ctrl |= LCD_CTRL_GL2_ENABLE;
0496 break;
0497 }
0498
0499 ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
0500 | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
0501
0502
0503
0504
0505 ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
0506
0507 kmb_write_lcd(kmb, LCD_CONTROL, ctrl);
0508
0509
0510
0511
0512
0513 kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
0514
0515
0516
0517
0518 out_format |= LCD_OUTF_FORMAT_RGB888;
0519
0520
0521
0522 out_format |= LCD_OUTF_MIPI_RGB_MODE;
0523 kmb_write_lcd(kmb, LCD_OUT_FORMAT_CFG, out_format);
0524
0525 dma_cfg = LCD_DMA_LAYER_ENABLE | LCD_DMA_LAYER_VSTRIDE_EN |
0526 LCD_DMA_LAYER_CONT_UPDATE | LCD_DMA_LAYER_AXI_BURST_16;
0527
0528
0529 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
0530
0531
0532 if (!init_disp_cfg->width ||
0533 !init_disp_cfg->height ||
0534 !init_disp_cfg->format) {
0535 init_disp_cfg->width = width;
0536 init_disp_cfg->height = height;
0537 init_disp_cfg->format = fb->format->format;
0538 }
0539
0540 drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
0541 kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));
0542
0543 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR, LCD_INT_EOF |
0544 LCD_INT_DMA_ERR);
0545 kmb_set_bitmask_lcd(kmb, LCD_INT_ENABLE, LCD_INT_EOF |
0546 LCD_INT_DMA_ERR);
0547 }
0548
0549 static const struct drm_plane_helper_funcs kmb_plane_helper_funcs = {
0550 .atomic_check = kmb_plane_atomic_check,
0551 .atomic_update = kmb_plane_atomic_update,
0552 .atomic_disable = kmb_plane_atomic_disable
0553 };
0554
0555 void kmb_plane_destroy(struct drm_plane *plane)
0556 {
0557 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
0558
0559 drm_plane_cleanup(plane);
0560 kfree(kmb_plane);
0561 }
0562
0563 static const struct drm_plane_funcs kmb_plane_funcs = {
0564 .update_plane = drm_atomic_helper_update_plane,
0565 .disable_plane = drm_atomic_helper_disable_plane,
0566 .destroy = kmb_plane_destroy,
0567 .reset = drm_atomic_helper_plane_reset,
0568 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
0569 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
0570 };
0571
0572 struct kmb_plane *kmb_plane_init(struct drm_device *drm)
0573 {
0574 struct kmb_drm_private *kmb = to_kmb(drm);
0575 struct kmb_plane *plane = NULL;
0576 struct kmb_plane *primary = NULL;
0577 int i = 0;
0578 int ret = 0;
0579 enum drm_plane_type plane_type;
0580 const u32 *plane_formats;
0581 int num_plane_formats;
0582 unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
0583 BIT(DRM_MODE_BLEND_PREMULTI) |
0584 BIT(DRM_MODE_BLEND_COVERAGE);
0585
0586 for (i = 0; i < KMB_MAX_PLANES; i++) {
0587 plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL);
0588
0589 if (!plane) {
0590 drm_err(drm, "Failed to allocate plane\n");
0591 return ERR_PTR(-ENOMEM);
0592 }
0593
0594 plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
0595 DRM_PLANE_TYPE_OVERLAY;
0596 if (i < 2) {
0597 plane_formats = kmb_formats_v;
0598 num_plane_formats = ARRAY_SIZE(kmb_formats_v);
0599 } else {
0600 plane_formats = kmb_formats_g;
0601 num_plane_formats = ARRAY_SIZE(kmb_formats_g);
0602 }
0603
0604 ret = drm_universal_plane_init(drm, &plane->base_plane,
0605 POSSIBLE_CRTCS, &kmb_plane_funcs,
0606 plane_formats, num_plane_formats,
0607 NULL, plane_type, "plane %d", i);
0608 if (ret < 0) {
0609 drm_err(drm, "drm_universal_plane_init failed (ret=%d)",
0610 ret);
0611 goto cleanup;
0612 }
0613 drm_dbg(drm, "%s : %d i=%d type=%d",
0614 __func__, __LINE__,
0615 i, plane_type);
0616 drm_plane_create_alpha_property(&plane->base_plane);
0617
0618 drm_plane_create_blend_mode_property(&plane->base_plane,
0619 blend_caps);
0620
0621 drm_plane_create_zpos_immutable_property(&plane->base_plane, i);
0622
0623 drm_plane_helper_add(&plane->base_plane,
0624 &kmb_plane_helper_funcs);
0625
0626 if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
0627 primary = plane;
0628 kmb->plane = plane;
0629 }
0630 drm_dbg(drm, "%s : %d primary=%p\n", __func__, __LINE__,
0631 &primary->base_plane);
0632 plane->id = i;
0633 }
0634
0635
0636
0637
0638 kmb_clr_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
0639
0640 return primary;
0641 cleanup:
0642 drmm_kfree(drm, plane);
0643 return ERR_PTR(ret);
0644 }