Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright © 2018-2020 Intel Corporation
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 /* Conversion (yuv->rgb) matrix from myriadx */
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 /* Graphics layer (layers 2 & 3) formats, only packed formats  are supported */
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 /* Video layer ( 0 & 1) formats, packed and planar formats are supported */
0052 static const u32 kmb_formats_v[] = {
0053     /* packed formats */
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     /*planar formats */
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     /* Due to HW limitations, changing pixel format after initial
0081      * plane configuration is not supported.
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     /* Due to HW limitations, changing plane height or width after
0125      * initial plane configuration is not supported.
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         /* planar formats */
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         /* packed formats */
0203         /* looks hw requires B & G to be swapped when RGB */
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     /* YUV to RGB conversion using the fixed matrix csc_coef_lcd */
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     /* Program Cb/Cr for planar formats */
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         /* check if Cb/Cr is swapped*/
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             /* check if Cb/Cr is swapped*/
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         /* Enable CSC if input is planar and output is RGB */
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     /* Configure LCD_CONTROL */
0475     ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
0476 
0477     /* Set layer blending config */
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     /* LCD is connected to MIPI on kmb
0503      * Therefore this bit is required for DSI Tx
0504      */
0505     ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
0506 
0507     kmb_write_lcd(kmb, LCD_CONTROL, ctrl);
0508 
0509     /* Enable pipeline AXI read transactions for the DMA
0510      * after setting graphics layers. This must be done
0511      * in a separate write cycle.
0512      */
0513     kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
0514 
0515     /* FIXME no doc on how to set output format, these values are taken
0516      * from the Myriadx tests
0517      */
0518     out_format |= LCD_OUTF_FORMAT_RGB888;
0519 
0520     /* Leave RGB order,conversion mode and clip mode to default */
0521     /* do not interleave RGB channels for mipi Tx compatibility */
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     /* Enable DMA */
0529     kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
0530 
0531     /* Save initial display config */
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     /* Disable pipeline AXI read transactions for the DMA
0636      * prior to setting graphics layers
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 }