17f7b96a8SAnitha Chrisanthus // SPDX-License-Identifier: GPL-2.0-only
27f7b96a8SAnitha Chrisanthus /*
37f7b96a8SAnitha Chrisanthus * Copyright © 2018-2020 Intel Corporation
47f7b96a8SAnitha Chrisanthus */
57f7b96a8SAnitha Chrisanthus
67f7b96a8SAnitha Chrisanthus #include <drm/drm_atomic.h>
77f7b96a8SAnitha Chrisanthus #include <drm/drm_atomic_helper.h>
890bb087fSVille Syrjälä #include <drm/drm_blend.h>
97f7b96a8SAnitha Chrisanthus #include <drm/drm_crtc.h>
106bcfe8eaSDanilo Krummrich #include <drm/drm_fb_dma_helper.h>
117f7b96a8SAnitha Chrisanthus #include <drm/drm_fourcc.h>
12720cf96dSVille Syrjälä #include <drm/drm_framebuffer.h>
13*4a83c26aSDanilo Krummrich #include <drm/drm_gem_dma_helper.h>
147f7b96a8SAnitha Chrisanthus #include <drm/drm_managed.h>
157f7b96a8SAnitha Chrisanthus
167f7b96a8SAnitha Chrisanthus #include "kmb_drv.h"
177f7b96a8SAnitha Chrisanthus #include "kmb_plane.h"
187f7b96a8SAnitha Chrisanthus #include "kmb_regs.h"
197f7b96a8SAnitha Chrisanthus
207f7b96a8SAnitha Chrisanthus const u32 layer_irqs[] = {
217f7b96a8SAnitha Chrisanthus LCD_INT_VL0,
227f7b96a8SAnitha Chrisanthus LCD_INT_VL1,
237f7b96a8SAnitha Chrisanthus LCD_INT_GL0,
247f7b96a8SAnitha Chrisanthus LCD_INT_GL1
257f7b96a8SAnitha Chrisanthus };
267f7b96a8SAnitha Chrisanthus
277f7b96a8SAnitha Chrisanthus /* Conversion (yuv->rgb) matrix from myriadx */
287f7b96a8SAnitha Chrisanthus static const u32 csc_coef_lcd[] = {
297f7b96a8SAnitha Chrisanthus 1024, 0, 1436,
307f7b96a8SAnitha Chrisanthus 1024, -352, -731,
317f7b96a8SAnitha Chrisanthus 1024, 1814, 0,
327f7b96a8SAnitha Chrisanthus -179, 125, -226
337f7b96a8SAnitha Chrisanthus };
347f7b96a8SAnitha Chrisanthus
357cb397e7SAnitha Chrisanthus /* Graphics layer (layers 2 & 3) formats, only packed formats are supported */
367cb397e7SAnitha Chrisanthus static const u32 kmb_formats_g[] = {
377cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB332,
387cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
397cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
407cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
417cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
427cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
437cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
447cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
457cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
467cb397e7SAnitha Chrisanthus };
477cb397e7SAnitha Chrisanthus
487cb397e7SAnitha Chrisanthus /* Video layer ( 0 & 1) formats, packed and planar formats are supported */
497cb397e7SAnitha Chrisanthus static const u32 kmb_formats_v[] = {
507cb397e7SAnitha Chrisanthus /* packed formats */
517cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB332,
527cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
537cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
547cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
557cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
567cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
577cb397e7SAnitha Chrisanthus DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
587cb397e7SAnitha Chrisanthus DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
597cb397e7SAnitha Chrisanthus DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
607cb397e7SAnitha Chrisanthus /*planar formats */
617cb397e7SAnitha Chrisanthus DRM_FORMAT_YUV420, DRM_FORMAT_YVU420,
627cb397e7SAnitha Chrisanthus DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
637cb397e7SAnitha Chrisanthus DRM_FORMAT_YUV444, DRM_FORMAT_YVU444,
647cb397e7SAnitha Chrisanthus DRM_FORMAT_NV12, DRM_FORMAT_NV21,
657cb397e7SAnitha Chrisanthus };
667cb397e7SAnitha Chrisanthus
check_pixel_format(struct drm_plane * plane,u32 format)677f7b96a8SAnitha Chrisanthus static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
687f7b96a8SAnitha Chrisanthus {
69982f8ad6SEdmund Dea struct kmb_drm_private *kmb;
70982f8ad6SEdmund Dea struct kmb_plane *kmb_plane = to_kmb_plane(plane);
717f7b96a8SAnitha Chrisanthus int i;
72982f8ad6SEdmund Dea int plane_id = kmb_plane->id;
73982f8ad6SEdmund Dea struct disp_cfg init_disp_cfg;
747f7b96a8SAnitha Chrisanthus
75982f8ad6SEdmund Dea kmb = to_kmb(plane->dev);
76982f8ad6SEdmund Dea init_disp_cfg = kmb->init_disp_cfg[plane_id];
77982f8ad6SEdmund Dea /* Due to HW limitations, changing pixel format after initial
78982f8ad6SEdmund Dea * plane configuration is not supported.
79982f8ad6SEdmund Dea */
80982f8ad6SEdmund Dea if (init_disp_cfg.format && init_disp_cfg.format != format) {
81982f8ad6SEdmund Dea drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
82982f8ad6SEdmund Dea return -EINVAL;
83982f8ad6SEdmund Dea }
847f7b96a8SAnitha Chrisanthus for (i = 0; i < plane->format_count; i++) {
857f7b96a8SAnitha Chrisanthus if (plane->format_types[i] == format)
867f7b96a8SAnitha Chrisanthus return 0;
877f7b96a8SAnitha Chrisanthus }
887f7b96a8SAnitha Chrisanthus return -EINVAL;
897f7b96a8SAnitha Chrisanthus }
907f7b96a8SAnitha Chrisanthus
kmb_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)917f7b96a8SAnitha Chrisanthus static int kmb_plane_atomic_check(struct drm_plane *plane,
927c11b99aSMaxime Ripard struct drm_atomic_state *state)
937f7b96a8SAnitha Chrisanthus {
947c11b99aSMaxime Ripard struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
957c11b99aSMaxime Ripard plane);
96982f8ad6SEdmund Dea struct kmb_drm_private *kmb;
97982f8ad6SEdmund Dea struct kmb_plane *kmb_plane = to_kmb_plane(plane);
98982f8ad6SEdmund Dea int plane_id = kmb_plane->id;
99982f8ad6SEdmund Dea struct disp_cfg init_disp_cfg;
1007f7b96a8SAnitha Chrisanthus struct drm_framebuffer *fb;
1017f7b96a8SAnitha Chrisanthus int ret;
1027f7b96a8SAnitha Chrisanthus struct drm_crtc_state *crtc_state;
1037f7b96a8SAnitha Chrisanthus bool can_position;
1047f7b96a8SAnitha Chrisanthus
105982f8ad6SEdmund Dea kmb = to_kmb(plane->dev);
106982f8ad6SEdmund Dea init_disp_cfg = kmb->init_disp_cfg[plane_id];
107ba5c1649SMaxime Ripard fb = new_plane_state->fb;
108ba5c1649SMaxime Ripard if (!fb || !new_plane_state->crtc)
1097f7b96a8SAnitha Chrisanthus return 0;
1107f7b96a8SAnitha Chrisanthus
1117f7b96a8SAnitha Chrisanthus ret = check_pixel_format(plane, fb->format->format);
1127f7b96a8SAnitha Chrisanthus if (ret)
1137f7b96a8SAnitha Chrisanthus return ret;
1147f7b96a8SAnitha Chrisanthus
115c026565fSEdmund Dea if (new_plane_state->crtc_w > KMB_FB_MAX_WIDTH ||
116c026565fSEdmund Dea new_plane_state->crtc_h > KMB_FB_MAX_HEIGHT ||
117c026565fSEdmund Dea new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
118c026565fSEdmund Dea new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
1197f7b96a8SAnitha Chrisanthus return -EINVAL;
120982f8ad6SEdmund Dea
121982f8ad6SEdmund Dea /* Due to HW limitations, changing plane height or width after
122982f8ad6SEdmund Dea * initial plane configuration is not supported.
123982f8ad6SEdmund Dea */
124982f8ad6SEdmund Dea if ((init_disp_cfg.width && init_disp_cfg.height) &&
125982f8ad6SEdmund Dea (init_disp_cfg.width != fb->width ||
126982f8ad6SEdmund Dea init_disp_cfg.height != fb->height)) {
127982f8ad6SEdmund Dea drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
128982f8ad6SEdmund Dea return -EINVAL;
129982f8ad6SEdmund Dea }
1307f7b96a8SAnitha Chrisanthus can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
1317f7b96a8SAnitha Chrisanthus crtc_state =
132dec92020SMaxime Ripard drm_atomic_get_existing_crtc_state(state,
133ba5c1649SMaxime Ripard new_plane_state->crtc);
134ba5c1649SMaxime Ripard return drm_atomic_helper_check_plane_state(new_plane_state,
135ba5c1649SMaxime Ripard crtc_state,
136cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING,
137cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING,
1387f7b96a8SAnitha Chrisanthus can_position, true);
1397f7b96a8SAnitha Chrisanthus }
1407f7b96a8SAnitha Chrisanthus
kmb_plane_atomic_disable(struct drm_plane * plane,struct drm_atomic_state * state)1417f7b96a8SAnitha Chrisanthus static void kmb_plane_atomic_disable(struct drm_plane *plane,
142977697e2SMaxime Ripard struct drm_atomic_state *state)
1437f7b96a8SAnitha Chrisanthus {
1447f7b96a8SAnitha Chrisanthus struct kmb_plane *kmb_plane = to_kmb_plane(plane);
1457f7b96a8SAnitha Chrisanthus int plane_id = kmb_plane->id;
1467f7b96a8SAnitha Chrisanthus struct kmb_drm_private *kmb;
1477f7b96a8SAnitha Chrisanthus
1487f7b96a8SAnitha Chrisanthus kmb = to_kmb(plane->dev);
1497f7b96a8SAnitha Chrisanthus
15098fdd004SArnd Bergmann if (WARN_ON(plane_id >= KMB_MAX_PLANES))
15198fdd004SArnd Bergmann return;
15298fdd004SArnd Bergmann
1537f7b96a8SAnitha Chrisanthus switch (plane_id) {
1547f7b96a8SAnitha Chrisanthus case LAYER_0:
1557f7b96a8SAnitha Chrisanthus kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
1567f7b96a8SAnitha Chrisanthus break;
1577f7b96a8SAnitha Chrisanthus case LAYER_1:
1587f7b96a8SAnitha Chrisanthus kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE;
1597f7b96a8SAnitha Chrisanthus break;
1607f7b96a8SAnitha Chrisanthus }
1617f7b96a8SAnitha Chrisanthus
1627f7b96a8SAnitha Chrisanthus kmb->plane_status[plane_id].disable = true;
1637f7b96a8SAnitha Chrisanthus }
1647f7b96a8SAnitha Chrisanthus
get_pixel_format(u32 format)1657f7b96a8SAnitha Chrisanthus static unsigned int get_pixel_format(u32 format)
1667f7b96a8SAnitha Chrisanthus {
1677f7b96a8SAnitha Chrisanthus unsigned int val = 0;
1687f7b96a8SAnitha Chrisanthus
1697f7b96a8SAnitha Chrisanthus switch (format) {
1707f7b96a8SAnitha Chrisanthus /* planar formats */
1717f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YUV444:
1727f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
1737f7b96a8SAnitha Chrisanthus break;
1747f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YVU444:
1757f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
1767f7b96a8SAnitha Chrisanthus | LCD_LAYER_CRCB_ORDER;
1777f7b96a8SAnitha Chrisanthus break;
1787f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YUV422:
1797f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
1807f7b96a8SAnitha Chrisanthus break;
1817f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YVU422:
1827f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
1837f7b96a8SAnitha Chrisanthus | LCD_LAYER_CRCB_ORDER;
1847f7b96a8SAnitha Chrisanthus break;
1857f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YUV420:
1867f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
1877f7b96a8SAnitha Chrisanthus break;
1887f7b96a8SAnitha Chrisanthus case DRM_FORMAT_YVU420:
1897f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
1907f7b96a8SAnitha Chrisanthus | LCD_LAYER_CRCB_ORDER;
1917f7b96a8SAnitha Chrisanthus break;
1927f7b96a8SAnitha Chrisanthus case DRM_FORMAT_NV12:
1937f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
1947f7b96a8SAnitha Chrisanthus break;
1957f7b96a8SAnitha Chrisanthus case DRM_FORMAT_NV21:
1967f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
1977f7b96a8SAnitha Chrisanthus | LCD_LAYER_CRCB_ORDER;
1987f7b96a8SAnitha Chrisanthus break;
1997f7b96a8SAnitha Chrisanthus /* packed formats */
2007f7b96a8SAnitha Chrisanthus /* looks hw requires B & G to be swapped when RGB */
2017f7b96a8SAnitha Chrisanthus case DRM_FORMAT_RGB332:
2027f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
2037f7b96a8SAnitha Chrisanthus break;
2047f7b96a8SAnitha Chrisanthus case DRM_FORMAT_XBGR4444:
2057f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBX4444;
2067f7b96a8SAnitha Chrisanthus break;
2077f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ARGB4444:
2087f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA4444 | LCD_LAYER_BGR_ORDER;
2097f7b96a8SAnitha Chrisanthus break;
2107f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ABGR4444:
2117f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA4444;
2127f7b96a8SAnitha Chrisanthus break;
2137f7b96a8SAnitha Chrisanthus case DRM_FORMAT_XRGB1555:
2147f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
2157f7b96a8SAnitha Chrisanthus break;
2167f7b96a8SAnitha Chrisanthus case DRM_FORMAT_XBGR1555:
2177f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_XRGB1555;
2187f7b96a8SAnitha Chrisanthus break;
2197f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ARGB1555:
2207f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
2217f7b96a8SAnitha Chrisanthus break;
2227f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ABGR1555:
2237f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA1555;
2247f7b96a8SAnitha Chrisanthus break;
2257f7b96a8SAnitha Chrisanthus case DRM_FORMAT_RGB565:
2267f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
2277f7b96a8SAnitha Chrisanthus break;
2287f7b96a8SAnitha Chrisanthus case DRM_FORMAT_BGR565:
2297f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGB565;
2307f7b96a8SAnitha Chrisanthus break;
2317f7b96a8SAnitha Chrisanthus case DRM_FORMAT_RGB888:
2327f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
2337f7b96a8SAnitha Chrisanthus break;
2347f7b96a8SAnitha Chrisanthus case DRM_FORMAT_BGR888:
2357f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGB888;
2367f7b96a8SAnitha Chrisanthus break;
2377f7b96a8SAnitha Chrisanthus case DRM_FORMAT_XRGB8888:
2387f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBX8888 | LCD_LAYER_BGR_ORDER;
2397f7b96a8SAnitha Chrisanthus break;
2407f7b96a8SAnitha Chrisanthus case DRM_FORMAT_XBGR8888:
2417f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBX8888;
2427f7b96a8SAnitha Chrisanthus break;
2437f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ARGB8888:
2447f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA8888 | LCD_LAYER_BGR_ORDER;
2457f7b96a8SAnitha Chrisanthus break;
2467f7b96a8SAnitha Chrisanthus case DRM_FORMAT_ABGR8888:
2477f7b96a8SAnitha Chrisanthus val = LCD_LAYER_FORMAT_RGBA8888;
2487f7b96a8SAnitha Chrisanthus break;
2497f7b96a8SAnitha Chrisanthus }
2507f7b96a8SAnitha Chrisanthus DRM_INFO_ONCE("%s : %d format=0x%x val=0x%x\n",
2517f7b96a8SAnitha Chrisanthus __func__, __LINE__, format, val);
2527f7b96a8SAnitha Chrisanthus return val;
2537f7b96a8SAnitha Chrisanthus }
2547f7b96a8SAnitha Chrisanthus
get_bits_per_pixel(const struct drm_format_info * format)2557f7b96a8SAnitha Chrisanthus static unsigned int get_bits_per_pixel(const struct drm_format_info *format)
2567f7b96a8SAnitha Chrisanthus {
2577f7b96a8SAnitha Chrisanthus u32 bpp = 0;
2587f7b96a8SAnitha Chrisanthus unsigned int val = 0;
2597f7b96a8SAnitha Chrisanthus
2607f7b96a8SAnitha Chrisanthus if (format->num_planes > 1) {
2617f7b96a8SAnitha Chrisanthus val = LCD_LAYER_8BPP;
2627f7b96a8SAnitha Chrisanthus return val;
2637f7b96a8SAnitha Chrisanthus }
2647f7b96a8SAnitha Chrisanthus
2657f7b96a8SAnitha Chrisanthus bpp += 8 * format->cpp[0];
2667f7b96a8SAnitha Chrisanthus
2677f7b96a8SAnitha Chrisanthus switch (bpp) {
2687f7b96a8SAnitha Chrisanthus case 8:
2697f7b96a8SAnitha Chrisanthus val = LCD_LAYER_8BPP;
2707f7b96a8SAnitha Chrisanthus break;
2717f7b96a8SAnitha Chrisanthus case 16:
2727f7b96a8SAnitha Chrisanthus val = LCD_LAYER_16BPP;
2737f7b96a8SAnitha Chrisanthus break;
2747f7b96a8SAnitha Chrisanthus case 24:
2757f7b96a8SAnitha Chrisanthus val = LCD_LAYER_24BPP;
2767f7b96a8SAnitha Chrisanthus break;
2777f7b96a8SAnitha Chrisanthus case 32:
2787f7b96a8SAnitha Chrisanthus val = LCD_LAYER_32BPP;
2797f7b96a8SAnitha Chrisanthus break;
2807f7b96a8SAnitha Chrisanthus }
2817f7b96a8SAnitha Chrisanthus
2827f7b96a8SAnitha Chrisanthus DRM_DEBUG("bpp=%d val=0x%x\n", bpp, val);
2837f7b96a8SAnitha Chrisanthus return val;
2847f7b96a8SAnitha Chrisanthus }
2857f7b96a8SAnitha Chrisanthus
config_csc(struct kmb_drm_private * kmb,int plane_id)2867f7b96a8SAnitha Chrisanthus static void config_csc(struct kmb_drm_private *kmb, int plane_id)
2877f7b96a8SAnitha Chrisanthus {
2887f7b96a8SAnitha Chrisanthus /* YUV to RGB conversion using the fixed matrix csc_coef_lcd */
2897f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);
2907f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);
2917f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);
2927f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);
2937f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);
2947f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);
2957f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);
2967f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);
2977f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);
2987f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
2997f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
3007f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
3017f7b96a8SAnitha Chrisanthus }
3027f7b96a8SAnitha Chrisanthus
kmb_plane_set_alpha(struct kmb_drm_private * kmb,const struct drm_plane_state * state,unsigned char plane_id,unsigned int * val)303c026565fSEdmund Dea static void kmb_plane_set_alpha(struct kmb_drm_private *kmb,
304c026565fSEdmund Dea const struct drm_plane_state *state,
305c026565fSEdmund Dea unsigned char plane_id,
306c026565fSEdmund Dea unsigned int *val)
307c026565fSEdmund Dea {
308c026565fSEdmund Dea u16 plane_alpha = state->alpha;
309c026565fSEdmund Dea u16 pixel_blend_mode = state->pixel_blend_mode;
310c026565fSEdmund Dea int has_alpha = state->fb->format->has_alpha;
311c026565fSEdmund Dea
312c026565fSEdmund Dea if (plane_alpha != DRM_BLEND_ALPHA_OPAQUE)
313c026565fSEdmund Dea *val |= LCD_LAYER_ALPHA_STATIC;
314c026565fSEdmund Dea
315c026565fSEdmund Dea if (has_alpha) {
316c026565fSEdmund Dea switch (pixel_blend_mode) {
317c026565fSEdmund Dea case DRM_MODE_BLEND_PIXEL_NONE:
318c026565fSEdmund Dea break;
319c026565fSEdmund Dea case DRM_MODE_BLEND_PREMULTI:
320c026565fSEdmund Dea *val |= LCD_LAYER_ALPHA_EMBED | LCD_LAYER_ALPHA_PREMULT;
321c026565fSEdmund Dea break;
322c026565fSEdmund Dea case DRM_MODE_BLEND_COVERAGE:
323c026565fSEdmund Dea *val |= LCD_LAYER_ALPHA_EMBED;
324c026565fSEdmund Dea break;
325c026565fSEdmund Dea default:
326c026565fSEdmund Dea DRM_DEBUG("Missing pixel blend mode case (%s == %ld)\n",
327c026565fSEdmund Dea __stringify(pixel_blend_mode),
328c026565fSEdmund Dea (long)pixel_blend_mode);
329c026565fSEdmund Dea break;
330c026565fSEdmund Dea }
331c026565fSEdmund Dea }
332c026565fSEdmund Dea
333c026565fSEdmund Dea if (plane_alpha == DRM_BLEND_ALPHA_OPAQUE && !has_alpha) {
334c026565fSEdmund Dea *val &= LCD_LAYER_ALPHA_DISABLED;
335c026565fSEdmund Dea return;
336c026565fSEdmund Dea }
337c026565fSEdmund Dea
338c026565fSEdmund Dea kmb_write_lcd(kmb, LCD_LAYERn_ALPHA(plane_id), plane_alpha);
339c026565fSEdmund Dea }
340c026565fSEdmund Dea
kmb_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)3417f7b96a8SAnitha Chrisanthus static void kmb_plane_atomic_update(struct drm_plane *plane,
342977697e2SMaxime Ripard struct drm_atomic_state *state)
3437f7b96a8SAnitha Chrisanthus {
344977697e2SMaxime Ripard struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state,
345977697e2SMaxime Ripard plane);
34637418bf1SMaxime Ripard struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
34737418bf1SMaxime Ripard plane);
3487f7b96a8SAnitha Chrisanthus struct drm_framebuffer *fb;
3497f7b96a8SAnitha Chrisanthus struct kmb_drm_private *kmb;
3507f7b96a8SAnitha Chrisanthus unsigned int width;
3517f7b96a8SAnitha Chrisanthus unsigned int height;
3527f7b96a8SAnitha Chrisanthus unsigned int dma_len;
3537f7b96a8SAnitha Chrisanthus struct kmb_plane *kmb_plane;
3547f7b96a8SAnitha Chrisanthus unsigned int dma_cfg;
3557f7b96a8SAnitha Chrisanthus unsigned int ctrl = 0, val = 0, out_format = 0;
3567f7b96a8SAnitha Chrisanthus unsigned int src_w, src_h, crtc_x, crtc_y;
3577f7b96a8SAnitha Chrisanthus unsigned char plane_id;
3587f7b96a8SAnitha Chrisanthus int num_planes;
3597f7b96a8SAnitha Chrisanthus static dma_addr_t addr[MAX_SUB_PLANES];
360982f8ad6SEdmund Dea struct disp_cfg *init_disp_cfg;
3617f7b96a8SAnitha Chrisanthus
362977697e2SMaxime Ripard if (!plane || !new_plane_state || !old_plane_state)
3637f7b96a8SAnitha Chrisanthus return;
3647f7b96a8SAnitha Chrisanthus
365e05162c0SMaxime Ripard fb = new_plane_state->fb;
3667f7b96a8SAnitha Chrisanthus if (!fb)
3677f7b96a8SAnitha Chrisanthus return;
368c026565fSEdmund Dea
3697f7b96a8SAnitha Chrisanthus num_planes = fb->format->num_planes;
3707f7b96a8SAnitha Chrisanthus kmb_plane = to_kmb_plane(plane);
3717f7b96a8SAnitha Chrisanthus
3727f7b96a8SAnitha Chrisanthus kmb = to_kmb(plane->dev);
373c026565fSEdmund Dea plane_id = kmb_plane->id;
3747f7b96a8SAnitha Chrisanthus
3757f7b96a8SAnitha Chrisanthus spin_lock_irq(&kmb->irq_lock);
3767f7b96a8SAnitha Chrisanthus if (kmb->kmb_under_flow || kmb->kmb_flush_done) {
3777f7b96a8SAnitha Chrisanthus spin_unlock_irq(&kmb->irq_lock);
3787f7b96a8SAnitha Chrisanthus drm_dbg(&kmb->drm, "plane_update:underflow!!!! returning");
3797f7b96a8SAnitha Chrisanthus return;
3807f7b96a8SAnitha Chrisanthus }
3817f7b96a8SAnitha Chrisanthus spin_unlock_irq(&kmb->irq_lock);
3827f7b96a8SAnitha Chrisanthus
383982f8ad6SEdmund Dea init_disp_cfg = &kmb->init_disp_cfg[plane_id];
384982f8ad6SEdmund Dea src_w = new_plane_state->src_w >> 16;
385e05162c0SMaxime Ripard src_h = new_plane_state->src_h >> 16;
386e05162c0SMaxime Ripard crtc_x = new_plane_state->crtc_x;
387e05162c0SMaxime Ripard crtc_y = new_plane_state->crtc_y;
3887f7b96a8SAnitha Chrisanthus
3897f7b96a8SAnitha Chrisanthus drm_dbg(&kmb->drm,
3907f7b96a8SAnitha Chrisanthus "src_w=%d src_h=%d, fb->format->format=0x%x fb->flags=0x%x\n",
3917f7b96a8SAnitha Chrisanthus src_w, src_h, fb->format->format, fb->flags);
3927f7b96a8SAnitha Chrisanthus
3937f7b96a8SAnitha Chrisanthus width = fb->width;
3947f7b96a8SAnitha Chrisanthus height = fb->height;
3957f7b96a8SAnitha Chrisanthus dma_len = (width * height * fb->format->cpp[0]);
3967f7b96a8SAnitha Chrisanthus drm_dbg(&kmb->drm, "dma_len=%d ", dma_len);
3977f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
3987f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
3997f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
4007f7b96a8SAnitha Chrisanthus fb->pitches[0]);
4017f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
4027f7b96a8SAnitha Chrisanthus (width * fb->format->cpp[0]));
4037f7b96a8SAnitha Chrisanthus
4046bcfe8eaSDanilo Krummrich addr[Y_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
4057f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),
4067f7b96a8SAnitha Chrisanthus addr[Y_PLANE] + fb->offsets[0]);
4077f7b96a8SAnitha Chrisanthus val = get_pixel_format(fb->format->format);
4087f7b96a8SAnitha Chrisanthus val |= get_bits_per_pixel(fb->format);
4097f7b96a8SAnitha Chrisanthus /* Program Cb/Cr for planar formats */
4107f7b96a8SAnitha Chrisanthus if (num_planes > 1) {
4117f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
4127f7b96a8SAnitha Chrisanthus width * fb->format->cpp[0]);
4137f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
4147f7b96a8SAnitha Chrisanthus (width * fb->format->cpp[0]));
4157f7b96a8SAnitha Chrisanthus
4166bcfe8eaSDanilo Krummrich addr[U_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state,
4177f7b96a8SAnitha Chrisanthus U_PLANE);
4187f7b96a8SAnitha Chrisanthus /* check if Cb/Cr is swapped*/
4197f7b96a8SAnitha Chrisanthus if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
4207f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4217f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_START_CR_ADR(plane_id),
4227f7b96a8SAnitha Chrisanthus addr[U_PLANE]);
4237f7b96a8SAnitha Chrisanthus else
4247f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4257f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_START_CB_ADR(plane_id),
4267f7b96a8SAnitha Chrisanthus addr[U_PLANE]);
4277f7b96a8SAnitha Chrisanthus
4287f7b96a8SAnitha Chrisanthus if (num_planes == 3) {
4297f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4307f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
4317f7b96a8SAnitha Chrisanthus ((width) * fb->format->cpp[0]));
4327f7b96a8SAnitha Chrisanthus
4337f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4347f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
4357f7b96a8SAnitha Chrisanthus ((width) * fb->format->cpp[0]));
4367f7b96a8SAnitha Chrisanthus
4376bcfe8eaSDanilo Krummrich addr[V_PLANE] = drm_fb_dma_get_gem_addr(fb,
438e05162c0SMaxime Ripard new_plane_state,
4397f7b96a8SAnitha Chrisanthus V_PLANE);
4407f7b96a8SAnitha Chrisanthus
4417f7b96a8SAnitha Chrisanthus /* check if Cb/Cr is swapped*/
4427f7b96a8SAnitha Chrisanthus if (val & LCD_LAYER_CRCB_ORDER)
4437f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4447f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_START_CB_ADR(plane_id),
4457f7b96a8SAnitha Chrisanthus addr[V_PLANE]);
4467f7b96a8SAnitha Chrisanthus else
4477f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb,
4487f7b96a8SAnitha Chrisanthus LCD_LAYERn_DMA_START_CR_ADR(plane_id),
4497f7b96a8SAnitha Chrisanthus addr[V_PLANE]);
4507f7b96a8SAnitha Chrisanthus }
4517f7b96a8SAnitha Chrisanthus }
4527f7b96a8SAnitha Chrisanthus
4537f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
4547f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
4557f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_COL_START(plane_id), crtc_x);
4567f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_ROW_START(plane_id), crtc_y);
4577f7b96a8SAnitha Chrisanthus
4587f7b96a8SAnitha Chrisanthus val |= LCD_LAYER_FIFO_100;
4597f7b96a8SAnitha Chrisanthus
4607f7b96a8SAnitha Chrisanthus if (val & LCD_LAYER_PLANAR_STORAGE) {
4617f7b96a8SAnitha Chrisanthus val |= LCD_LAYER_CSC_EN;
4627f7b96a8SAnitha Chrisanthus
4637f7b96a8SAnitha Chrisanthus /* Enable CSC if input is planar and output is RGB */
4647f7b96a8SAnitha Chrisanthus config_csc(kmb, plane_id);
4657f7b96a8SAnitha Chrisanthus }
4667f7b96a8SAnitha Chrisanthus
467c026565fSEdmund Dea kmb_plane_set_alpha(kmb, plane->state, plane_id, &val);
468c026565fSEdmund Dea
4697f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);
4707f7b96a8SAnitha Chrisanthus
471c026565fSEdmund Dea /* Configure LCD_CONTROL */
472c026565fSEdmund Dea ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
473c026565fSEdmund Dea
474c026565fSEdmund Dea /* Set layer blending config */
475c026565fSEdmund Dea ctrl &= ~LCD_CTRL_ALPHA_ALL;
476c026565fSEdmund Dea ctrl |= LCD_CTRL_ALPHA_BOTTOM_VL1 |
477c026565fSEdmund Dea LCD_CTRL_ALPHA_BLEND_VL2;
478c026565fSEdmund Dea
479c026565fSEdmund Dea ctrl &= ~LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE;
480c026565fSEdmund Dea
4817f7b96a8SAnitha Chrisanthus switch (plane_id) {
4827f7b96a8SAnitha Chrisanthus case LAYER_0:
483c026565fSEdmund Dea ctrl |= LCD_CTRL_VL1_ENABLE;
4847f7b96a8SAnitha Chrisanthus break;
4857f7b96a8SAnitha Chrisanthus case LAYER_1:
486c026565fSEdmund Dea ctrl |= LCD_CTRL_VL2_ENABLE;
4877f7b96a8SAnitha Chrisanthus break;
4887f7b96a8SAnitha Chrisanthus case LAYER_2:
489c026565fSEdmund Dea ctrl |= LCD_CTRL_GL1_ENABLE;
4907f7b96a8SAnitha Chrisanthus break;
4917f7b96a8SAnitha Chrisanthus case LAYER_3:
492c026565fSEdmund Dea ctrl |= LCD_CTRL_GL2_ENABLE;
4937f7b96a8SAnitha Chrisanthus break;
4947f7b96a8SAnitha Chrisanthus }
4957f7b96a8SAnitha Chrisanthus
4967f7b96a8SAnitha Chrisanthus ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
4977f7b96a8SAnitha Chrisanthus | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
4987f7b96a8SAnitha Chrisanthus
4997f7b96a8SAnitha Chrisanthus /* LCD is connected to MIPI on kmb
5007f7b96a8SAnitha Chrisanthus * Therefore this bit is required for DSI Tx
5017f7b96a8SAnitha Chrisanthus */
5027f7b96a8SAnitha Chrisanthus ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
5037f7b96a8SAnitha Chrisanthus
504c026565fSEdmund Dea kmb_write_lcd(kmb, LCD_CONTROL, ctrl);
5057f7b96a8SAnitha Chrisanthus
5060aab5dceSEdmund Dea /* Enable pipeline AXI read transactions for the DMA
5070aab5dceSEdmund Dea * after setting graphics layers. This must be done
5080aab5dceSEdmund Dea * in a separate write cycle.
5090aab5dceSEdmund Dea */
5100aab5dceSEdmund Dea kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
5110aab5dceSEdmund Dea
5120aab5dceSEdmund Dea /* FIXME no doc on how to set output format, these values are taken
5130aab5dceSEdmund Dea * from the Myriadx tests
5147f7b96a8SAnitha Chrisanthus */
5157f7b96a8SAnitha Chrisanthus out_format |= LCD_OUTF_FORMAT_RGB888;
5167f7b96a8SAnitha Chrisanthus
5177f7b96a8SAnitha Chrisanthus /* Leave RGB order,conversion mode and clip mode to default */
5187f7b96a8SAnitha Chrisanthus /* do not interleave RGB channels for mipi Tx compatibility */
5197f7b96a8SAnitha Chrisanthus out_format |= LCD_OUTF_MIPI_RGB_MODE;
5207f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_OUT_FORMAT_CFG, out_format);
5217f7b96a8SAnitha Chrisanthus
5227f7b96a8SAnitha Chrisanthus dma_cfg = LCD_DMA_LAYER_ENABLE | LCD_DMA_LAYER_VSTRIDE_EN |
5237f7b96a8SAnitha Chrisanthus LCD_DMA_LAYER_CONT_UPDATE | LCD_DMA_LAYER_AXI_BURST_16;
5247f7b96a8SAnitha Chrisanthus
5257f7b96a8SAnitha Chrisanthus /* Enable DMA */
5267f7b96a8SAnitha Chrisanthus kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
527982f8ad6SEdmund Dea
528982f8ad6SEdmund Dea /* Save initial display config */
529982f8ad6SEdmund Dea if (!init_disp_cfg->width ||
530982f8ad6SEdmund Dea !init_disp_cfg->height ||
531982f8ad6SEdmund Dea !init_disp_cfg->format) {
532982f8ad6SEdmund Dea init_disp_cfg->width = width;
533982f8ad6SEdmund Dea init_disp_cfg->height = height;
534982f8ad6SEdmund Dea init_disp_cfg->format = fb->format->format;
535982f8ad6SEdmund Dea }
536982f8ad6SEdmund Dea
5377f7b96a8SAnitha Chrisanthus drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
5387f7b96a8SAnitha Chrisanthus kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));
5397f7b96a8SAnitha Chrisanthus
5407f7b96a8SAnitha Chrisanthus kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR, LCD_INT_EOF |
5417f7b96a8SAnitha Chrisanthus LCD_INT_DMA_ERR);
5427f7b96a8SAnitha Chrisanthus kmb_set_bitmask_lcd(kmb, LCD_INT_ENABLE, LCD_INT_EOF |
5437f7b96a8SAnitha Chrisanthus LCD_INT_DMA_ERR);
5447f7b96a8SAnitha Chrisanthus }
5457f7b96a8SAnitha Chrisanthus
5467f7b96a8SAnitha Chrisanthus static const struct drm_plane_helper_funcs kmb_plane_helper_funcs = {
5477f7b96a8SAnitha Chrisanthus .atomic_check = kmb_plane_atomic_check,
5487f7b96a8SAnitha Chrisanthus .atomic_update = kmb_plane_atomic_update,
5497f7b96a8SAnitha Chrisanthus .atomic_disable = kmb_plane_atomic_disable
5507f7b96a8SAnitha Chrisanthus };
5517f7b96a8SAnitha Chrisanthus
kmb_plane_destroy(struct drm_plane * plane)5527f7b96a8SAnitha Chrisanthus void kmb_plane_destroy(struct drm_plane *plane)
5537f7b96a8SAnitha Chrisanthus {
5547f7b96a8SAnitha Chrisanthus struct kmb_plane *kmb_plane = to_kmb_plane(plane);
5557f7b96a8SAnitha Chrisanthus
5567f7b96a8SAnitha Chrisanthus drm_plane_cleanup(plane);
5577f7b96a8SAnitha Chrisanthus kfree(kmb_plane);
5587f7b96a8SAnitha Chrisanthus }
5597f7b96a8SAnitha Chrisanthus
5607f7b96a8SAnitha Chrisanthus static const struct drm_plane_funcs kmb_plane_funcs = {
5617f7b96a8SAnitha Chrisanthus .update_plane = drm_atomic_helper_update_plane,
5627f7b96a8SAnitha Chrisanthus .disable_plane = drm_atomic_helper_disable_plane,
5637f7b96a8SAnitha Chrisanthus .destroy = kmb_plane_destroy,
5647f7b96a8SAnitha Chrisanthus .reset = drm_atomic_helper_plane_reset,
5657f7b96a8SAnitha Chrisanthus .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
5667f7b96a8SAnitha Chrisanthus .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
5677f7b96a8SAnitha Chrisanthus };
5687f7b96a8SAnitha Chrisanthus
kmb_plane_init(struct drm_device * drm)5697f7b96a8SAnitha Chrisanthus struct kmb_plane *kmb_plane_init(struct drm_device *drm)
5707f7b96a8SAnitha Chrisanthus {
5717f7b96a8SAnitha Chrisanthus struct kmb_drm_private *kmb = to_kmb(drm);
5727f7b96a8SAnitha Chrisanthus struct kmb_plane *plane = NULL;
5737f7b96a8SAnitha Chrisanthus struct kmb_plane *primary = NULL;
5747f7b96a8SAnitha Chrisanthus int i = 0;
5757f7b96a8SAnitha Chrisanthus int ret = 0;
5767f7b96a8SAnitha Chrisanthus enum drm_plane_type plane_type;
5777f7b96a8SAnitha Chrisanthus const u32 *plane_formats;
5787f7b96a8SAnitha Chrisanthus int num_plane_formats;
579c026565fSEdmund Dea unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
580c026565fSEdmund Dea BIT(DRM_MODE_BLEND_PREMULTI) |
581c026565fSEdmund Dea BIT(DRM_MODE_BLEND_COVERAGE);
5827f7b96a8SAnitha Chrisanthus
5837f7b96a8SAnitha Chrisanthus for (i = 0; i < KMB_MAX_PLANES; i++) {
5847f7b96a8SAnitha Chrisanthus plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL);
5857f7b96a8SAnitha Chrisanthus
5867f7b96a8SAnitha Chrisanthus if (!plane) {
5877f7b96a8SAnitha Chrisanthus drm_err(drm, "Failed to allocate plane\n");
5887f7b96a8SAnitha Chrisanthus return ERR_PTR(-ENOMEM);
5897f7b96a8SAnitha Chrisanthus }
5907f7b96a8SAnitha Chrisanthus
5917f7b96a8SAnitha Chrisanthus plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
5927f7b96a8SAnitha Chrisanthus DRM_PLANE_TYPE_OVERLAY;
5937f7b96a8SAnitha Chrisanthus if (i < 2) {
5947f7b96a8SAnitha Chrisanthus plane_formats = kmb_formats_v;
5957f7b96a8SAnitha Chrisanthus num_plane_formats = ARRAY_SIZE(kmb_formats_v);
5967f7b96a8SAnitha Chrisanthus } else {
5977f7b96a8SAnitha Chrisanthus plane_formats = kmb_formats_g;
5987f7b96a8SAnitha Chrisanthus num_plane_formats = ARRAY_SIZE(kmb_formats_g);
5997f7b96a8SAnitha Chrisanthus }
6007f7b96a8SAnitha Chrisanthus
6017f7b96a8SAnitha Chrisanthus ret = drm_universal_plane_init(drm, &plane->base_plane,
6027f7b96a8SAnitha Chrisanthus POSSIBLE_CRTCS, &kmb_plane_funcs,
6037f7b96a8SAnitha Chrisanthus plane_formats, num_plane_formats,
6047f7b96a8SAnitha Chrisanthus NULL, plane_type, "plane %d", i);
6057f7b96a8SAnitha Chrisanthus if (ret < 0) {
6067f7b96a8SAnitha Chrisanthus drm_err(drm, "drm_universal_plane_init failed (ret=%d)",
6077f7b96a8SAnitha Chrisanthus ret);
6087f7b96a8SAnitha Chrisanthus goto cleanup;
6097f7b96a8SAnitha Chrisanthus }
6107f7b96a8SAnitha Chrisanthus drm_dbg(drm, "%s : %d i=%d type=%d",
6117f7b96a8SAnitha Chrisanthus __func__, __LINE__,
6127f7b96a8SAnitha Chrisanthus i, plane_type);
613c026565fSEdmund Dea drm_plane_create_alpha_property(&plane->base_plane);
614c026565fSEdmund Dea
615c026565fSEdmund Dea drm_plane_create_blend_mode_property(&plane->base_plane,
616c026565fSEdmund Dea blend_caps);
617c026565fSEdmund Dea
618c026565fSEdmund Dea drm_plane_create_zpos_immutable_property(&plane->base_plane, i);
619c026565fSEdmund Dea
6207f7b96a8SAnitha Chrisanthus drm_plane_helper_add(&plane->base_plane,
6217f7b96a8SAnitha Chrisanthus &kmb_plane_helper_funcs);
622c026565fSEdmund Dea
6237f7b96a8SAnitha Chrisanthus if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
6247f7b96a8SAnitha Chrisanthus primary = plane;
6257f7b96a8SAnitha Chrisanthus kmb->plane = plane;
6267f7b96a8SAnitha Chrisanthus }
6277f7b96a8SAnitha Chrisanthus drm_dbg(drm, "%s : %d primary=%p\n", __func__, __LINE__,
6287f7b96a8SAnitha Chrisanthus &primary->base_plane);
6297f7b96a8SAnitha Chrisanthus plane->id = i;
6307f7b96a8SAnitha Chrisanthus }
6317f7b96a8SAnitha Chrisanthus
6320aab5dceSEdmund Dea /* Disable pipeline AXI read transactions for the DMA
6330aab5dceSEdmund Dea * prior to setting graphics layers
6340aab5dceSEdmund Dea */
6350aab5dceSEdmund Dea kmb_clr_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
6360aab5dceSEdmund Dea
6377f7b96a8SAnitha Chrisanthus return primary;
6387f7b96a8SAnitha Chrisanthus cleanup:
6397f7b96a8SAnitha Chrisanthus drmm_kfree(drm, plane);
6407f7b96a8SAnitha Chrisanthus return ERR_PTR(ret);
6417f7b96a8SAnitha Chrisanthus }
642