1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. 4 * Author: James.Qian.Wang <james.qian.wang@arm.com> 5 * 6 */ 7 #include <drm/drm_atomic.h> 8 #include <drm/drm_atomic_helper.h> 9 #include <drm/drm_plane_helper.h> 10 #include <drm/drm_print.h> 11 #include "komeda_dev.h" 12 #include "komeda_kms.h" 13 14 static int 15 komeda_plane_init_data_flow(struct drm_plane_state *st, 16 struct komeda_data_flow_cfg *dflow) 17 { 18 struct drm_framebuffer *fb = st->fb; 19 20 memset(dflow, 0, sizeof(*dflow)); 21 22 dflow->blending_zorder = st->zpos; 23 24 /* if format doesn't have alpha, fix blend mode to PIXEL_NONE */ 25 dflow->pixel_blend_mode = fb->format->has_alpha ? 26 st->pixel_blend_mode : DRM_MODE_BLEND_PIXEL_NONE; 27 dflow->layer_alpha = st->alpha >> 8; 28 29 dflow->out_x = st->crtc_x; 30 dflow->out_y = st->crtc_y; 31 dflow->out_w = st->crtc_w; 32 dflow->out_h = st->crtc_h; 33 34 dflow->in_x = st->src_x >> 16; 35 dflow->in_y = st->src_y >> 16; 36 dflow->in_w = st->src_w >> 16; 37 dflow->in_h = st->src_h >> 16; 38 39 return 0; 40 } 41 42 /** 43 * komeda_plane_atomic_check - build input data flow 44 * @plane: DRM plane 45 * @state: the plane state object 46 * 47 * RETURNS: 48 * Zero for success or -errno 49 */ 50 static int 51 komeda_plane_atomic_check(struct drm_plane *plane, 52 struct drm_plane_state *state) 53 { 54 struct komeda_plane *kplane = to_kplane(plane); 55 struct komeda_plane_state *kplane_st = to_kplane_st(state); 56 struct komeda_layer *layer = kplane->layer; 57 struct drm_crtc_state *crtc_st; 58 struct komeda_crtc_state *kcrtc_st; 59 struct komeda_data_flow_cfg dflow; 60 int err; 61 62 if (!state->crtc || !state->fb) 63 return 0; 64 65 crtc_st = drm_atomic_get_crtc_state(state->state, state->crtc); 66 if (IS_ERR(crtc_st) || !crtc_st->enable) { 67 DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n"); 68 return -EINVAL; 69 } 70 71 /* crtc is inactive, skip the resource assignment */ 72 if (!crtc_st->active) 73 return 0; 74 75 kcrtc_st = to_kcrtc_st(crtc_st); 76 77 err = komeda_plane_init_data_flow(state, &dflow); 78 if (err) 79 return err; 80 81 err = komeda_build_layer_data_flow(layer, kplane_st, kcrtc_st, &dflow); 82 83 return err; 84 } 85 86 /* plane doesn't represent a real HW, so there is no HW update for plane. 87 * komeda handles all the HW update in crtc->atomic_flush 88 */ 89 static void 90 komeda_plane_atomic_update(struct drm_plane *plane, 91 struct drm_plane_state *old_state) 92 { 93 } 94 95 static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = { 96 .atomic_check = komeda_plane_atomic_check, 97 .atomic_update = komeda_plane_atomic_update, 98 }; 99 100 static void komeda_plane_destroy(struct drm_plane *plane) 101 { 102 drm_plane_cleanup(plane); 103 104 kfree(to_kplane(plane)); 105 } 106 107 static void komeda_plane_reset(struct drm_plane *plane) 108 { 109 struct komeda_plane_state *state; 110 struct komeda_plane *kplane = to_kplane(plane); 111 112 if (plane->state) 113 __drm_atomic_helper_plane_destroy_state(plane->state); 114 115 kfree(plane->state); 116 plane->state = NULL; 117 118 state = kzalloc(sizeof(*state), GFP_KERNEL); 119 if (state) { 120 state->base.rotation = DRM_MODE_ROTATE_0; 121 state->base.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; 122 state->base.alpha = DRM_BLEND_ALPHA_OPAQUE; 123 state->base.zpos = kplane->layer->base.id; 124 plane->state = &state->base; 125 plane->state->plane = plane; 126 } 127 } 128 129 static struct drm_plane_state * 130 komeda_plane_atomic_duplicate_state(struct drm_plane *plane) 131 { 132 struct komeda_plane_state *new; 133 134 if (WARN_ON(!plane->state)) 135 return NULL; 136 137 new = kzalloc(sizeof(*new), GFP_KERNEL); 138 if (!new) 139 return NULL; 140 141 __drm_atomic_helper_plane_duplicate_state(plane, &new->base); 142 143 return &new->base; 144 } 145 146 static void 147 komeda_plane_atomic_destroy_state(struct drm_plane *plane, 148 struct drm_plane_state *state) 149 { 150 __drm_atomic_helper_plane_destroy_state(state); 151 kfree(to_kplane_st(state)); 152 } 153 154 static const struct drm_plane_funcs komeda_plane_funcs = { 155 .update_plane = drm_atomic_helper_update_plane, 156 .disable_plane = drm_atomic_helper_disable_plane, 157 .destroy = komeda_plane_destroy, 158 .reset = komeda_plane_reset, 159 .atomic_duplicate_state = komeda_plane_atomic_duplicate_state, 160 .atomic_destroy_state = komeda_plane_atomic_destroy_state, 161 }; 162 163 /* for komeda, which is pipeline can be share between crtcs */ 164 static u32 get_possible_crtcs(struct komeda_kms_dev *kms, 165 struct komeda_pipeline *pipe) 166 { 167 struct komeda_crtc *crtc; 168 u32 possible_crtcs = 0; 169 int i; 170 171 for (i = 0; i < kms->n_crtcs; i++) { 172 crtc = &kms->crtcs[i]; 173 174 if ((pipe == crtc->master) || (pipe == crtc->slave)) 175 possible_crtcs |= BIT(i); 176 } 177 178 return possible_crtcs; 179 } 180 181 /* use Layer0 as primary */ 182 static u32 get_plane_type(struct komeda_kms_dev *kms, 183 struct komeda_component *c) 184 { 185 bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0); 186 187 return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; 188 } 189 190 static int komeda_plane_add(struct komeda_kms_dev *kms, 191 struct komeda_layer *layer) 192 { 193 struct komeda_dev *mdev = kms->base.dev_private; 194 struct komeda_component *c = &layer->base; 195 struct komeda_plane *kplane; 196 struct drm_plane *plane; 197 u32 *formats, n_formats = 0; 198 int err; 199 200 kplane = kzalloc(sizeof(*kplane), GFP_KERNEL); 201 if (!kplane) 202 return -ENOMEM; 203 204 plane = &kplane->base; 205 kplane->layer = layer; 206 207 formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl, 208 layer->layer_type, &n_formats); 209 210 err = drm_universal_plane_init(&kms->base, plane, 211 get_possible_crtcs(kms, c->pipeline), 212 &komeda_plane_funcs, 213 formats, n_formats, NULL, 214 get_plane_type(kms, c), 215 "%s", c->name); 216 217 komeda_put_fourcc_list(formats); 218 219 if (err) 220 goto cleanup; 221 222 drm_plane_helper_add(plane, &komeda_plane_helper_funcs); 223 224 return 0; 225 cleanup: 226 komeda_plane_destroy(plane); 227 return err; 228 } 229 230 int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev) 231 { 232 struct komeda_pipeline *pipe; 233 int i, j, err; 234 235 for (i = 0; i < mdev->n_pipelines; i++) { 236 pipe = mdev->pipelines[i]; 237 238 for (j = 0; j < pipe->n_layers; j++) { 239 err = komeda_plane_add(kms, pipe->layers[j]); 240 if (err) 241 return err; 242 } 243 } 244 245 return 0; 246 } 247