161f1c4a8Sjames qian wang (Arm Technology China) // SPDX-License-Identifier: GPL-2.0 261f1c4a8Sjames qian wang (Arm Technology China) /* 361f1c4a8Sjames qian wang (Arm Technology China) * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. 461f1c4a8Sjames qian wang (Arm Technology China) * Author: James.Qian.Wang <james.qian.wang@arm.com> 561f1c4a8Sjames qian wang (Arm Technology China) * 661f1c4a8Sjames qian wang (Arm Technology China) */ 761f1c4a8Sjames qian wang (Arm Technology China) #include <drm/drm_atomic.h> 861f1c4a8Sjames qian wang (Arm Technology China) #include <drm/drm_atomic_helper.h> 961f1c4a8Sjames qian wang (Arm Technology China) #include <drm/drm_plane_helper.h> 109e560309Sjames qian wang (Arm Technology China) #include <drm/drm_print.h> 1161f1c4a8Sjames qian wang (Arm Technology China) #include "komeda_dev.h" 1261f1c4a8Sjames qian wang (Arm Technology China) #include "komeda_kms.h" 1361f1c4a8Sjames qian wang (Arm Technology China) 149e560309Sjames qian wang (Arm Technology China) static int 159e560309Sjames qian wang (Arm Technology China) komeda_plane_init_data_flow(struct drm_plane_state *st, 169e560309Sjames qian wang (Arm Technology China) struct komeda_data_flow_cfg *dflow) 179e560309Sjames qian wang (Arm Technology China) { 189e560309Sjames qian wang (Arm Technology China) struct drm_framebuffer *fb = st->fb; 199e560309Sjames qian wang (Arm Technology China) 209e560309Sjames qian wang (Arm Technology China) memset(dflow, 0, sizeof(*dflow)); 219e560309Sjames qian wang (Arm Technology China) 229e560309Sjames qian wang (Arm Technology China) dflow->blending_zorder = st->zpos; 239e560309Sjames qian wang (Arm Technology China) 249e560309Sjames qian wang (Arm Technology China) /* if format doesn't have alpha, fix blend mode to PIXEL_NONE */ 259e560309Sjames qian wang (Arm Technology China) dflow->pixel_blend_mode = fb->format->has_alpha ? 269e560309Sjames qian wang (Arm Technology China) st->pixel_blend_mode : DRM_MODE_BLEND_PIXEL_NONE; 279e560309Sjames qian wang (Arm Technology China) dflow->layer_alpha = st->alpha >> 8; 289e560309Sjames qian wang (Arm Technology China) 299e560309Sjames qian wang (Arm Technology China) dflow->out_x = st->crtc_x; 309e560309Sjames qian wang (Arm Technology China) dflow->out_y = st->crtc_y; 319e560309Sjames qian wang (Arm Technology China) dflow->out_w = st->crtc_w; 329e560309Sjames qian wang (Arm Technology China) dflow->out_h = st->crtc_h; 339e560309Sjames qian wang (Arm Technology China) 349e560309Sjames qian wang (Arm Technology China) dflow->in_x = st->src_x >> 16; 359e560309Sjames qian wang (Arm Technology China) dflow->in_y = st->src_y >> 16; 369e560309Sjames qian wang (Arm Technology China) dflow->in_w = st->src_w >> 16; 379e560309Sjames qian wang (Arm Technology China) dflow->in_h = st->src_h >> 16; 389e560309Sjames qian wang (Arm Technology China) 39d92b66b8Sjames qian wang (Arm Technology China) komeda_complete_data_flow_cfg(dflow); 40502932a0Sjames qian wang (Arm Technology China) 419e560309Sjames qian wang (Arm Technology China) return 0; 429e560309Sjames qian wang (Arm Technology China) } 439e560309Sjames qian wang (Arm Technology China) 448c919745Sjames qian wang (Arm Technology China) /** 458c919745Sjames qian wang (Arm Technology China) * komeda_plane_atomic_check - build input data flow 468c919745Sjames qian wang (Arm Technology China) * @plane: DRM plane 478c919745Sjames qian wang (Arm Technology China) * @state: the plane state object 488c919745Sjames qian wang (Arm Technology China) * 498c919745Sjames qian wang (Arm Technology China) * RETURNS: 508c919745Sjames qian wang (Arm Technology China) * Zero for success or -errno 518c919745Sjames qian wang (Arm Technology China) */ 5215e9122dSjames qian wang (Arm Technology China) static int 5315e9122dSjames qian wang (Arm Technology China) komeda_plane_atomic_check(struct drm_plane *plane, 549e560309Sjames qian wang (Arm Technology China) struct drm_plane_state *state) 559e560309Sjames qian wang (Arm Technology China) { 569e560309Sjames qian wang (Arm Technology China) struct komeda_plane *kplane = to_kplane(plane); 579e560309Sjames qian wang (Arm Technology China) struct komeda_plane_state *kplane_st = to_kplane_st(state); 589e560309Sjames qian wang (Arm Technology China) struct komeda_layer *layer = kplane->layer; 599e560309Sjames qian wang (Arm Technology China) struct drm_crtc_state *crtc_st; 609e560309Sjames qian wang (Arm Technology China) struct komeda_crtc_state *kcrtc_st; 619e560309Sjames qian wang (Arm Technology China) struct komeda_data_flow_cfg dflow; 629e560309Sjames qian wang (Arm Technology China) int err; 639e560309Sjames qian wang (Arm Technology China) 649e560309Sjames qian wang (Arm Technology China) if (!state->crtc || !state->fb) 659e560309Sjames qian wang (Arm Technology China) return 0; 669e560309Sjames qian wang (Arm Technology China) 679e560309Sjames qian wang (Arm Technology China) crtc_st = drm_atomic_get_crtc_state(state->state, state->crtc); 686d10dc61SDan Carpenter if (IS_ERR(crtc_st) || !crtc_st->enable) { 699e560309Sjames qian wang (Arm Technology China) DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n"); 709e560309Sjames qian wang (Arm Technology China) return -EINVAL; 719e560309Sjames qian wang (Arm Technology China) } 729e560309Sjames qian wang (Arm Technology China) 739e560309Sjames qian wang (Arm Technology China) /* crtc is inactive, skip the resource assignment */ 749e560309Sjames qian wang (Arm Technology China) if (!crtc_st->active) 759e560309Sjames qian wang (Arm Technology China) return 0; 769e560309Sjames qian wang (Arm Technology China) 779e560309Sjames qian wang (Arm Technology China) kcrtc_st = to_kcrtc_st(crtc_st); 789e560309Sjames qian wang (Arm Technology China) 799e560309Sjames qian wang (Arm Technology China) err = komeda_plane_init_data_flow(state, &dflow); 809e560309Sjames qian wang (Arm Technology China) if (err) 819e560309Sjames qian wang (Arm Technology China) return err; 829e560309Sjames qian wang (Arm Technology China) 839e560309Sjames qian wang (Arm Technology China) err = komeda_build_layer_data_flow(layer, kplane_st, kcrtc_st, &dflow); 849e560309Sjames qian wang (Arm Technology China) 859e560309Sjames qian wang (Arm Technology China) return err; 869e560309Sjames qian wang (Arm Technology China) } 879e560309Sjames qian wang (Arm Technology China) 889e560309Sjames qian wang (Arm Technology China) /* plane doesn't represent a real HW, so there is no HW update for plane. 899e560309Sjames qian wang (Arm Technology China) * komeda handles all the HW update in crtc->atomic_flush 909e560309Sjames qian wang (Arm Technology China) */ 9115e9122dSjames qian wang (Arm Technology China) static void 9215e9122dSjames qian wang (Arm Technology China) komeda_plane_atomic_update(struct drm_plane *plane, 939e560309Sjames qian wang (Arm Technology China) struct drm_plane_state *old_state) 949e560309Sjames qian wang (Arm Technology China) { 959e560309Sjames qian wang (Arm Technology China) } 969e560309Sjames qian wang (Arm Technology China) 9761f1c4a8Sjames qian wang (Arm Technology China) static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = { 989e560309Sjames qian wang (Arm Technology China) .atomic_check = komeda_plane_atomic_check, 999e560309Sjames qian wang (Arm Technology China) .atomic_update = komeda_plane_atomic_update, 10061f1c4a8Sjames qian wang (Arm Technology China) }; 10161f1c4a8Sjames qian wang (Arm Technology China) 10261f1c4a8Sjames qian wang (Arm Technology China) static void komeda_plane_destroy(struct drm_plane *plane) 10361f1c4a8Sjames qian wang (Arm Technology China) { 10461f1c4a8Sjames qian wang (Arm Technology China) drm_plane_cleanup(plane); 10561f1c4a8Sjames qian wang (Arm Technology China) 10661f1c4a8Sjames qian wang (Arm Technology China) kfree(to_kplane(plane)); 10761f1c4a8Sjames qian wang (Arm Technology China) } 10861f1c4a8Sjames qian wang (Arm Technology China) 1099e560309Sjames qian wang (Arm Technology China) static void komeda_plane_reset(struct drm_plane *plane) 1109e560309Sjames qian wang (Arm Technology China) { 1119e560309Sjames qian wang (Arm Technology China) struct komeda_plane_state *state; 1129e560309Sjames qian wang (Arm Technology China) struct komeda_plane *kplane = to_kplane(plane); 1139e560309Sjames qian wang (Arm Technology China) 1149e560309Sjames qian wang (Arm Technology China) if (plane->state) 1159e560309Sjames qian wang (Arm Technology China) __drm_atomic_helper_plane_destroy_state(plane->state); 1169e560309Sjames qian wang (Arm Technology China) 1179e560309Sjames qian wang (Arm Technology China) kfree(plane->state); 1189e560309Sjames qian wang (Arm Technology China) plane->state = NULL; 1199e560309Sjames qian wang (Arm Technology China) 1209e560309Sjames qian wang (Arm Technology China) state = kzalloc(sizeof(*state), GFP_KERNEL); 1219e560309Sjames qian wang (Arm Technology China) if (state) { 1229e560309Sjames qian wang (Arm Technology China) state->base.rotation = DRM_MODE_ROTATE_0; 1239e560309Sjames qian wang (Arm Technology China) state->base.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; 1249e560309Sjames qian wang (Arm Technology China) state->base.alpha = DRM_BLEND_ALPHA_OPAQUE; 1259e560309Sjames qian wang (Arm Technology China) state->base.zpos = kplane->layer->base.id; 1269e560309Sjames qian wang (Arm Technology China) plane->state = &state->base; 1279e560309Sjames qian wang (Arm Technology China) plane->state->plane = plane; 1289e560309Sjames qian wang (Arm Technology China) } 1299e560309Sjames qian wang (Arm Technology China) } 1309e560309Sjames qian wang (Arm Technology China) 1319e560309Sjames qian wang (Arm Technology China) static struct drm_plane_state * 1329e560309Sjames qian wang (Arm Technology China) komeda_plane_atomic_duplicate_state(struct drm_plane *plane) 1339e560309Sjames qian wang (Arm Technology China) { 1349e560309Sjames qian wang (Arm Technology China) struct komeda_plane_state *new; 1359e560309Sjames qian wang (Arm Technology China) 1369e560309Sjames qian wang (Arm Technology China) if (WARN_ON(!plane->state)) 1379e560309Sjames qian wang (Arm Technology China) return NULL; 1389e560309Sjames qian wang (Arm Technology China) 1399e560309Sjames qian wang (Arm Technology China) new = kzalloc(sizeof(*new), GFP_KERNEL); 1409e560309Sjames qian wang (Arm Technology China) if (!new) 1419e560309Sjames qian wang (Arm Technology China) return NULL; 1429e560309Sjames qian wang (Arm Technology China) 1439e560309Sjames qian wang (Arm Technology China) __drm_atomic_helper_plane_duplicate_state(plane, &new->base); 1449e560309Sjames qian wang (Arm Technology China) 1459e560309Sjames qian wang (Arm Technology China) return &new->base; 1469e560309Sjames qian wang (Arm Technology China) } 1479e560309Sjames qian wang (Arm Technology China) 1489e560309Sjames qian wang (Arm Technology China) static void 1499e560309Sjames qian wang (Arm Technology China) komeda_plane_atomic_destroy_state(struct drm_plane *plane, 1509e560309Sjames qian wang (Arm Technology China) struct drm_plane_state *state) 1519e560309Sjames qian wang (Arm Technology China) { 1529e560309Sjames qian wang (Arm Technology China) __drm_atomic_helper_plane_destroy_state(state); 1539e560309Sjames qian wang (Arm Technology China) kfree(to_kplane_st(state)); 1549e560309Sjames qian wang (Arm Technology China) } 1559e560309Sjames qian wang (Arm Technology China) 15665ad2392Sjames qian wang (Arm Technology China) static bool 15765ad2392Sjames qian wang (Arm Technology China) komeda_plane_format_mod_supported(struct drm_plane *plane, 15865ad2392Sjames qian wang (Arm Technology China) u32 format, u64 modifier) 15965ad2392Sjames qian wang (Arm Technology China) { 16065ad2392Sjames qian wang (Arm Technology China) struct komeda_dev *mdev = plane->dev->dev_private; 16165ad2392Sjames qian wang (Arm Technology China) struct komeda_plane *kplane = to_kplane(plane); 16265ad2392Sjames qian wang (Arm Technology China) u32 layer_type = kplane->layer->layer_type; 16365ad2392Sjames qian wang (Arm Technology China) 16465ad2392Sjames qian wang (Arm Technology China) return komeda_format_mod_supported(&mdev->fmt_tbl, layer_type, 16565ad2392Sjames qian wang (Arm Technology China) format, modifier); 16665ad2392Sjames qian wang (Arm Technology China) } 16765ad2392Sjames qian wang (Arm Technology China) 16861f1c4a8Sjames qian wang (Arm Technology China) static const struct drm_plane_funcs komeda_plane_funcs = { 1699e560309Sjames qian wang (Arm Technology China) .update_plane = drm_atomic_helper_update_plane, 1709e560309Sjames qian wang (Arm Technology China) .disable_plane = drm_atomic_helper_disable_plane, 1719e560309Sjames qian wang (Arm Technology China) .destroy = komeda_plane_destroy, 1729e560309Sjames qian wang (Arm Technology China) .reset = komeda_plane_reset, 1739e560309Sjames qian wang (Arm Technology China) .atomic_duplicate_state = komeda_plane_atomic_duplicate_state, 1749e560309Sjames qian wang (Arm Technology China) .atomic_destroy_state = komeda_plane_atomic_destroy_state, 17565ad2392Sjames qian wang (Arm Technology China) .format_mod_supported = komeda_plane_format_mod_supported, 17661f1c4a8Sjames qian wang (Arm Technology China) }; 17761f1c4a8Sjames qian wang (Arm Technology China) 17861f1c4a8Sjames qian wang (Arm Technology China) /* for komeda, which is pipeline can be share between crtcs */ 17961f1c4a8Sjames qian wang (Arm Technology China) static u32 get_possible_crtcs(struct komeda_kms_dev *kms, 18061f1c4a8Sjames qian wang (Arm Technology China) struct komeda_pipeline *pipe) 18161f1c4a8Sjames qian wang (Arm Technology China) { 18261f1c4a8Sjames qian wang (Arm Technology China) struct komeda_crtc *crtc; 18361f1c4a8Sjames qian wang (Arm Technology China) u32 possible_crtcs = 0; 18461f1c4a8Sjames qian wang (Arm Technology China) int i; 18561f1c4a8Sjames qian wang (Arm Technology China) 18661f1c4a8Sjames qian wang (Arm Technology China) for (i = 0; i < kms->n_crtcs; i++) { 18761f1c4a8Sjames qian wang (Arm Technology China) crtc = &kms->crtcs[i]; 18861f1c4a8Sjames qian wang (Arm Technology China) 18961f1c4a8Sjames qian wang (Arm Technology China) if ((pipe == crtc->master) || (pipe == crtc->slave)) 19061f1c4a8Sjames qian wang (Arm Technology China) possible_crtcs |= BIT(i); 19161f1c4a8Sjames qian wang (Arm Technology China) } 19261f1c4a8Sjames qian wang (Arm Technology China) 19361f1c4a8Sjames qian wang (Arm Technology China) return possible_crtcs; 19461f1c4a8Sjames qian wang (Arm Technology China) } 19561f1c4a8Sjames qian wang (Arm Technology China) 19661f1c4a8Sjames qian wang (Arm Technology China) /* use Layer0 as primary */ 19761f1c4a8Sjames qian wang (Arm Technology China) static u32 get_plane_type(struct komeda_kms_dev *kms, 19861f1c4a8Sjames qian wang (Arm Technology China) struct komeda_component *c) 19961f1c4a8Sjames qian wang (Arm Technology China) { 20061f1c4a8Sjames qian wang (Arm Technology China) bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0); 20161f1c4a8Sjames qian wang (Arm Technology China) 20261f1c4a8Sjames qian wang (Arm Technology China) return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; 20361f1c4a8Sjames qian wang (Arm Technology China) } 20461f1c4a8Sjames qian wang (Arm Technology China) 20561f1c4a8Sjames qian wang (Arm Technology China) static int komeda_plane_add(struct komeda_kms_dev *kms, 20661f1c4a8Sjames qian wang (Arm Technology China) struct komeda_layer *layer) 20761f1c4a8Sjames qian wang (Arm Technology China) { 20861f1c4a8Sjames qian wang (Arm Technology China) struct komeda_dev *mdev = kms->base.dev_private; 20961f1c4a8Sjames qian wang (Arm Technology China) struct komeda_component *c = &layer->base; 21061f1c4a8Sjames qian wang (Arm Technology China) struct komeda_plane *kplane; 21161f1c4a8Sjames qian wang (Arm Technology China) struct drm_plane *plane; 21261f1c4a8Sjames qian wang (Arm Technology China) u32 *formats, n_formats = 0; 21361f1c4a8Sjames qian wang (Arm Technology China) int err; 21461f1c4a8Sjames qian wang (Arm Technology China) 21561f1c4a8Sjames qian wang (Arm Technology China) kplane = kzalloc(sizeof(*kplane), GFP_KERNEL); 21661f1c4a8Sjames qian wang (Arm Technology China) if (!kplane) 21761f1c4a8Sjames qian wang (Arm Technology China) return -ENOMEM; 21861f1c4a8Sjames qian wang (Arm Technology China) 21961f1c4a8Sjames qian wang (Arm Technology China) plane = &kplane->base; 22061f1c4a8Sjames qian wang (Arm Technology China) kplane->layer = layer; 22161f1c4a8Sjames qian wang (Arm Technology China) 22261f1c4a8Sjames qian wang (Arm Technology China) formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl, 22361f1c4a8Sjames qian wang (Arm Technology China) layer->layer_type, &n_formats); 22461f1c4a8Sjames qian wang (Arm Technology China) 22561f1c4a8Sjames qian wang (Arm Technology China) err = drm_universal_plane_init(&kms->base, plane, 22661f1c4a8Sjames qian wang (Arm Technology China) get_possible_crtcs(kms, c->pipeline), 22761f1c4a8Sjames qian wang (Arm Technology China) &komeda_plane_funcs, 22865ad2392Sjames qian wang (Arm Technology China) formats, n_formats, komeda_supported_modifiers, 22961f1c4a8Sjames qian wang (Arm Technology China) get_plane_type(kms, c), 23061f1c4a8Sjames qian wang (Arm Technology China) "%s", c->name); 23161f1c4a8Sjames qian wang (Arm Technology China) 23261f1c4a8Sjames qian wang (Arm Technology China) komeda_put_fourcc_list(formats); 23361f1c4a8Sjames qian wang (Arm Technology China) 23461f1c4a8Sjames qian wang (Arm Technology China) if (err) 23561f1c4a8Sjames qian wang (Arm Technology China) goto cleanup; 23661f1c4a8Sjames qian wang (Arm Technology China) 23761f1c4a8Sjames qian wang (Arm Technology China) drm_plane_helper_add(plane, &komeda_plane_helper_funcs); 23861f1c4a8Sjames qian wang (Arm Technology China) 23961f1c4a8Sjames qian wang (Arm Technology China) return 0; 24061f1c4a8Sjames qian wang (Arm Technology China) cleanup: 24161f1c4a8Sjames qian wang (Arm Technology China) komeda_plane_destroy(plane); 24261f1c4a8Sjames qian wang (Arm Technology China) return err; 24361f1c4a8Sjames qian wang (Arm Technology China) } 24461f1c4a8Sjames qian wang (Arm Technology China) 24561f1c4a8Sjames qian wang (Arm Technology China) int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev) 24661f1c4a8Sjames qian wang (Arm Technology China) { 24761f1c4a8Sjames qian wang (Arm Technology China) struct komeda_pipeline *pipe; 24861f1c4a8Sjames qian wang (Arm Technology China) int i, j, err; 24961f1c4a8Sjames qian wang (Arm Technology China) 25061f1c4a8Sjames qian wang (Arm Technology China) for (i = 0; i < mdev->n_pipelines; i++) { 25161f1c4a8Sjames qian wang (Arm Technology China) pipe = mdev->pipelines[i]; 25261f1c4a8Sjames qian wang (Arm Technology China) 25361f1c4a8Sjames qian wang (Arm Technology China) for (j = 0; j < pipe->n_layers; j++) { 25461f1c4a8Sjames qian wang (Arm Technology China) err = komeda_plane_add(kms, pipe->layers[j]); 25561f1c4a8Sjames qian wang (Arm Technology China) if (err) 25661f1c4a8Sjames qian wang (Arm Technology China) return err; 25761f1c4a8Sjames qian wang (Arm Technology China) } 25861f1c4a8Sjames qian wang (Arm Technology China) } 25961f1c4a8Sjames qian wang (Arm Technology China) 26061f1c4a8Sjames qian wang (Arm Technology China) return 0; 26161f1c4a8Sjames qian wang (Arm Technology China) } 262