Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 MediaTek Inc.
0004  * Author: CK Hu <ck.hu@mediatek.com>
0005  */
0006 
0007 #include <drm/drm_atomic.h>
0008 #include <drm/drm_atomic_helper.h>
0009 #include <drm/drm_atomic_uapi.h>
0010 #include <drm/drm_blend.h>
0011 #include <drm/drm_fourcc.h>
0012 #include <drm/drm_framebuffer.h>
0013 #include <drm/drm_gem_atomic_helper.h>
0014 #include <drm/drm_plane_helper.h>
0015 
0016 #include "mtk_drm_crtc.h"
0017 #include "mtk_drm_ddp_comp.h"
0018 #include "mtk_drm_drv.h"
0019 #include "mtk_drm_gem.h"
0020 #include "mtk_drm_plane.h"
0021 
0022 static const u32 formats[] = {
0023     DRM_FORMAT_XRGB8888,
0024     DRM_FORMAT_ARGB8888,
0025     DRM_FORMAT_BGRX8888,
0026     DRM_FORMAT_BGRA8888,
0027     DRM_FORMAT_ABGR8888,
0028     DRM_FORMAT_XBGR8888,
0029     DRM_FORMAT_RGB888,
0030     DRM_FORMAT_BGR888,
0031     DRM_FORMAT_RGB565,
0032     DRM_FORMAT_UYVY,
0033     DRM_FORMAT_YUYV,
0034 };
0035 
0036 static void mtk_plane_reset(struct drm_plane *plane)
0037 {
0038     struct mtk_plane_state *state;
0039 
0040     if (plane->state) {
0041         __drm_atomic_helper_plane_destroy_state(plane->state);
0042 
0043         state = to_mtk_plane_state(plane->state);
0044         memset(state, 0, sizeof(*state));
0045     } else {
0046         state = kzalloc(sizeof(*state), GFP_KERNEL);
0047         if (!state)
0048             return;
0049     }
0050 
0051     __drm_atomic_helper_plane_reset(plane, &state->base);
0052 
0053     state->base.plane = plane;
0054     state->pending.format = DRM_FORMAT_RGB565;
0055 }
0056 
0057 static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
0058 {
0059     struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
0060     struct mtk_plane_state *state;
0061 
0062     state = kmalloc(sizeof(*state), GFP_KERNEL);
0063     if (!state)
0064         return NULL;
0065 
0066     __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
0067 
0068     WARN_ON(state->base.plane != plane);
0069 
0070     state->pending = old_state->pending;
0071 
0072     return &state->base;
0073 }
0074 
0075 static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
0076                     struct drm_plane_state *state)
0077 {
0078     __drm_atomic_helper_plane_destroy_state(state);
0079     kfree(to_mtk_plane_state(state));
0080 }
0081 
0082 static int mtk_plane_atomic_async_check(struct drm_plane *plane,
0083                     struct drm_atomic_state *state)
0084 {
0085     struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0086                                          plane);
0087     struct drm_crtc_state *crtc_state;
0088     int ret;
0089 
0090     if (plane != new_plane_state->crtc->cursor)
0091         return -EINVAL;
0092 
0093     if (!plane->state)
0094         return -EINVAL;
0095 
0096     if (!plane->state->fb)
0097         return -EINVAL;
0098 
0099     ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane,
0100                        to_mtk_plane_state(new_plane_state));
0101     if (ret)
0102         return ret;
0103 
0104     if (state)
0105         crtc_state = drm_atomic_get_existing_crtc_state(state,
0106                                 new_plane_state->crtc);
0107     else /* Special case for asynchronous cursor updates. */
0108         crtc_state = new_plane_state->crtc->state;
0109 
0110     return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
0111                            DRM_PLANE_HELPER_NO_SCALING,
0112                            DRM_PLANE_HELPER_NO_SCALING,
0113                            true, true);
0114 }
0115 
0116 static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
0117                        struct mtk_plane_state *mtk_plane_state)
0118 {
0119     struct drm_framebuffer *fb = new_state->fb;
0120     struct drm_gem_object *gem;
0121     struct mtk_drm_gem_obj *mtk_gem;
0122     unsigned int pitch, format;
0123     dma_addr_t addr;
0124 
0125     gem = fb->obj[0];
0126     mtk_gem = to_mtk_gem_obj(gem);
0127     addr = mtk_gem->dma_addr;
0128     pitch = fb->pitches[0];
0129     format = fb->format->format;
0130 
0131     addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
0132     addr += (new_state->src.y1 >> 16) * pitch;
0133 
0134     mtk_plane_state->pending.enable = true;
0135     mtk_plane_state->pending.pitch = pitch;
0136     mtk_plane_state->pending.format = format;
0137     mtk_plane_state->pending.addr = addr;
0138     mtk_plane_state->pending.x = new_state->dst.x1;
0139     mtk_plane_state->pending.y = new_state->dst.y1;
0140     mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
0141     mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
0142     mtk_plane_state->pending.rotation = new_state->rotation;
0143     mtk_plane_state->pending.color_encoding = new_state->color_encoding;
0144 }
0145 
0146 static void mtk_plane_atomic_async_update(struct drm_plane *plane,
0147                       struct drm_atomic_state *state)
0148 {
0149     struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0150                                        plane);
0151     struct mtk_plane_state *new_plane_state = to_mtk_plane_state(plane->state);
0152 
0153     plane->state->crtc_x = new_state->crtc_x;
0154     plane->state->crtc_y = new_state->crtc_y;
0155     plane->state->crtc_h = new_state->crtc_h;
0156     plane->state->crtc_w = new_state->crtc_w;
0157     plane->state->src_x = new_state->src_x;
0158     plane->state->src_y = new_state->src_y;
0159     plane->state->src_h = new_state->src_h;
0160     plane->state->src_w = new_state->src_w;
0161     swap(plane->state->fb, new_state->fb);
0162 
0163     mtk_plane_update_new_state(new_state, new_plane_state);
0164     wmb(); /* Make sure the above parameters are set before update */
0165     new_plane_state->pending.async_dirty = true;
0166     mtk_drm_crtc_async_update(new_state->crtc, plane, state);
0167 }
0168 
0169 static const struct drm_plane_funcs mtk_plane_funcs = {
0170     .update_plane = drm_atomic_helper_update_plane,
0171     .disable_plane = drm_atomic_helper_disable_plane,
0172     .destroy = drm_plane_cleanup,
0173     .reset = mtk_plane_reset,
0174     .atomic_duplicate_state = mtk_plane_duplicate_state,
0175     .atomic_destroy_state = mtk_drm_plane_destroy_state,
0176 };
0177 
0178 static int mtk_plane_atomic_check(struct drm_plane *plane,
0179                   struct drm_atomic_state *state)
0180 {
0181     struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0182                                          plane);
0183     struct drm_framebuffer *fb = new_plane_state->fb;
0184     struct drm_crtc_state *crtc_state;
0185     int ret;
0186 
0187     if (!fb)
0188         return 0;
0189 
0190     if (WARN_ON(!new_plane_state->crtc))
0191         return 0;
0192 
0193     ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane,
0194                        to_mtk_plane_state(new_plane_state));
0195     if (ret)
0196         return ret;
0197 
0198     crtc_state = drm_atomic_get_crtc_state(state,
0199                            new_plane_state->crtc);
0200     if (IS_ERR(crtc_state))
0201         return PTR_ERR(crtc_state);
0202 
0203     return drm_atomic_helper_check_plane_state(new_plane_state,
0204                            crtc_state,
0205                            DRM_PLANE_HELPER_NO_SCALING,
0206                            DRM_PLANE_HELPER_NO_SCALING,
0207                            true, true);
0208 }
0209 
0210 static void mtk_plane_atomic_disable(struct drm_plane *plane,
0211                      struct drm_atomic_state *state)
0212 {
0213     struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0214                                        plane);
0215     struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
0216     mtk_plane_state->pending.enable = false;
0217     wmb(); /* Make sure the above parameter is set before update */
0218     mtk_plane_state->pending.dirty = true;
0219 }
0220 
0221 static void mtk_plane_atomic_update(struct drm_plane *plane,
0222                     struct drm_atomic_state *state)
0223 {
0224     struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0225                                        plane);
0226     struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
0227 
0228     if (!new_state->crtc || WARN_ON(!new_state->fb))
0229         return;
0230 
0231     if (!new_state->visible) {
0232         mtk_plane_atomic_disable(plane, state);
0233         return;
0234     }
0235 
0236     mtk_plane_update_new_state(new_state, mtk_plane_state);
0237     wmb(); /* Make sure the above parameters are set before update */
0238     mtk_plane_state->pending.dirty = true;
0239 }
0240 
0241 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
0242     .atomic_check = mtk_plane_atomic_check,
0243     .atomic_update = mtk_plane_atomic_update,
0244     .atomic_disable = mtk_plane_atomic_disable,
0245     .atomic_async_update = mtk_plane_atomic_async_update,
0246     .atomic_async_check = mtk_plane_atomic_async_check,
0247 };
0248 
0249 int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
0250            unsigned long possible_crtcs, enum drm_plane_type type,
0251            unsigned int supported_rotations)
0252 {
0253     int err;
0254 
0255     err = drm_universal_plane_init(dev, plane, possible_crtcs,
0256                        &mtk_plane_funcs, formats,
0257                        ARRAY_SIZE(formats), NULL, type, NULL);
0258     if (err) {
0259         DRM_ERROR("failed to initialize plane\n");
0260         return err;
0261     }
0262 
0263     if (supported_rotations & ~DRM_MODE_ROTATE_0) {
0264         err = drm_plane_create_rotation_property(plane,
0265                              DRM_MODE_ROTATE_0,
0266                              supported_rotations);
0267         if (err)
0268             DRM_INFO("Create rotation property failed\n");
0269     }
0270 
0271     drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
0272 
0273     return 0;
0274 }