Path: blob/master/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
26519 views
// SPDX-License-Identifier: GPL-2.01/*2* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.3* Author: James.Qian.Wang <[email protected]>4*5*/6#include <drm/drm_atomic.h>7#include <drm/drm_atomic_helper.h>8#include <drm/drm_blend.h>9#include <drm/drm_print.h>10#include "komeda_dev.h"11#include "komeda_kms.h"12#include "komeda_framebuffer.h"1314static int15komeda_plane_init_data_flow(struct drm_plane_state *st,16struct komeda_crtc_state *kcrtc_st,17struct komeda_data_flow_cfg *dflow)18{19struct komeda_plane *kplane = to_kplane(st->plane);20struct drm_framebuffer *fb = st->fb;21const struct komeda_format_caps *caps = to_kfb(fb)->format_caps;22struct komeda_pipeline *pipe = kplane->layer->base.pipeline;2324memset(dflow, 0, sizeof(*dflow));2526dflow->blending_zorder = st->normalized_zpos;27if (pipe == to_kcrtc(st->crtc)->master)28dflow->blending_zorder -= kcrtc_st->max_slave_zorder;29if (dflow->blending_zorder < 0) {30DRM_DEBUG_ATOMIC("%s zorder:%d < max_slave_zorder: %d.\n",31st->plane->name, st->normalized_zpos,32kcrtc_st->max_slave_zorder);33return -EINVAL;34}3536dflow->pixel_blend_mode = st->pixel_blend_mode;37dflow->layer_alpha = st->alpha >> 8;3839dflow->out_x = st->crtc_x;40dflow->out_y = st->crtc_y;41dflow->out_w = st->crtc_w;42dflow->out_h = st->crtc_h;4344dflow->in_x = st->src_x >> 16;45dflow->in_y = st->src_y >> 16;46dflow->in_w = st->src_w >> 16;47dflow->in_h = st->src_h >> 16;4849dflow->rot = drm_rotation_simplify(st->rotation, caps->supported_rots);50if (!has_bits(dflow->rot, caps->supported_rots)) {51DRM_DEBUG_ATOMIC("rotation(0x%x) isn't supported by %p4cc with modifier: 0x%llx.\n",52dflow->rot, &caps->fourcc, fb->modifier);53return -EINVAL;54}5556komeda_complete_data_flow_cfg(kplane->layer, dflow, fb);5758return 0;59}6061/**62* komeda_plane_atomic_check - build input data flow63* @plane: DRM plane64* @state: the plane state object65*66* RETURNS:67* Zero for success or -errno68*/69static int70komeda_plane_atomic_check(struct drm_plane *plane,71struct drm_atomic_state *state)72{73struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,74plane);75struct komeda_plane *kplane = to_kplane(plane);76struct komeda_plane_state *kplane_st = to_kplane_st(new_plane_state);77struct komeda_layer *layer = kplane->layer;78struct drm_crtc_state *crtc_st;79struct komeda_crtc_state *kcrtc_st;80struct komeda_data_flow_cfg dflow;81int err;8283if (!new_plane_state->crtc || !new_plane_state->fb)84return 0;8586crtc_st = drm_atomic_get_crtc_state(state,87new_plane_state->crtc);88if (IS_ERR(crtc_st) || !crtc_st->enable) {89DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n");90return -EINVAL;91}9293/* crtc is inactive, skip the resource assignment */94if (!crtc_st->active)95return 0;9697kcrtc_st = to_kcrtc_st(crtc_st);9899err = komeda_plane_init_data_flow(new_plane_state, kcrtc_st, &dflow);100if (err)101return err;102103if (dflow.en_split)104err = komeda_build_layer_split_data_flow(layer,105kplane_st, kcrtc_st, &dflow);106else107err = komeda_build_layer_data_flow(layer,108kplane_st, kcrtc_st, &dflow);109110return err;111}112113/* plane doesn't represent a real HW, so there is no HW update for plane.114* komeda handles all the HW update in crtc->atomic_flush115*/116static void117komeda_plane_atomic_update(struct drm_plane *plane,118struct drm_atomic_state *state)119{120}121122static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {123.atomic_check = komeda_plane_atomic_check,124.atomic_update = komeda_plane_atomic_update,125};126127static void komeda_plane_destroy(struct drm_plane *plane)128{129drm_plane_cleanup(plane);130131kfree(to_kplane(plane));132}133134static void komeda_plane_reset(struct drm_plane *plane)135{136struct komeda_plane_state *state;137138if (plane->state)139__drm_atomic_helper_plane_destroy_state(plane->state);140141kfree(plane->state);142plane->state = NULL;143144state = kzalloc(sizeof(*state), GFP_KERNEL);145if (state)146__drm_atomic_helper_plane_reset(plane, &state->base);147}148149static struct drm_plane_state *150komeda_plane_atomic_duplicate_state(struct drm_plane *plane)151{152struct komeda_plane_state *new;153154if (WARN_ON(!plane->state))155return NULL;156157new = kzalloc(sizeof(*new), GFP_KERNEL);158if (!new)159return NULL;160161__drm_atomic_helper_plane_duplicate_state(plane, &new->base);162163return &new->base;164}165166static void167komeda_plane_atomic_destroy_state(struct drm_plane *plane,168struct drm_plane_state *state)169{170__drm_atomic_helper_plane_destroy_state(state);171kfree(to_kplane_st(state));172}173174static bool175komeda_plane_format_mod_supported(struct drm_plane *plane,176u32 format, u64 modifier)177{178struct komeda_dev *mdev = plane->dev->dev_private;179struct komeda_plane *kplane = to_kplane(plane);180u32 layer_type = kplane->layer->layer_type;181182return komeda_format_mod_supported(&mdev->fmt_tbl, layer_type,183format, modifier, 0);184}185186static const struct drm_plane_funcs komeda_plane_funcs = {187.update_plane = drm_atomic_helper_update_plane,188.disable_plane = drm_atomic_helper_disable_plane,189.destroy = komeda_plane_destroy,190.reset = komeda_plane_reset,191.atomic_duplicate_state = komeda_plane_atomic_duplicate_state,192.atomic_destroy_state = komeda_plane_atomic_destroy_state,193.format_mod_supported = komeda_plane_format_mod_supported,194};195196/* for komeda, which is pipeline can be share between crtcs */197static u32 get_possible_crtcs(struct komeda_kms_dev *kms,198struct komeda_pipeline *pipe)199{200struct komeda_crtc *crtc;201u32 possible_crtcs = 0;202int i;203204for (i = 0; i < kms->n_crtcs; i++) {205crtc = &kms->crtcs[i];206207if ((pipe == crtc->master) || (pipe == crtc->slave))208possible_crtcs |= BIT(i);209}210211return possible_crtcs;212}213214static void215komeda_set_crtc_plane_mask(struct komeda_kms_dev *kms,216struct komeda_pipeline *pipe,217struct drm_plane *plane)218{219struct komeda_crtc *kcrtc;220int i;221222for (i = 0; i < kms->n_crtcs; i++) {223kcrtc = &kms->crtcs[i];224225if (pipe == kcrtc->slave)226kcrtc->slave_planes |= BIT(drm_plane_index(plane));227}228}229230/* use Layer0 as primary */231static u32 get_plane_type(struct komeda_kms_dev *kms,232struct komeda_component *c)233{234bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0);235236return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;237}238239static int komeda_plane_add(struct komeda_kms_dev *kms,240struct komeda_layer *layer)241{242struct komeda_dev *mdev = kms->base.dev_private;243struct komeda_component *c = &layer->base;244struct komeda_plane *kplane;245struct drm_plane *plane;246u32 *formats, n_formats = 0;247int err;248249kplane = kzalloc(sizeof(*kplane), GFP_KERNEL);250if (!kplane)251return -ENOMEM;252253plane = &kplane->base;254kplane->layer = layer;255256formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,257layer->layer_type, &n_formats);258if (!formats) {259kfree(kplane);260return -ENOMEM;261}262263err = drm_universal_plane_init(&kms->base, plane,264get_possible_crtcs(kms, c->pipeline),265&komeda_plane_funcs,266formats, n_formats, komeda_supported_modifiers,267get_plane_type(kms, c),268"%s", c->name);269270komeda_put_fourcc_list(formats);271272if (err) {273kfree(kplane);274return err;275}276277drm_plane_helper_add(plane, &komeda_plane_helper_funcs);278279err = drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,280layer->supported_rots);281if (err)282goto cleanup;283284err = drm_plane_create_alpha_property(plane);285if (err)286goto cleanup;287288err = drm_plane_create_blend_mode_property(plane,289BIT(DRM_MODE_BLEND_PIXEL_NONE) |290BIT(DRM_MODE_BLEND_PREMULTI) |291BIT(DRM_MODE_BLEND_COVERAGE));292if (err)293goto cleanup;294295err = drm_plane_create_color_properties(plane,296BIT(DRM_COLOR_YCBCR_BT601) |297BIT(DRM_COLOR_YCBCR_BT709) |298BIT(DRM_COLOR_YCBCR_BT2020),299BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |300BIT(DRM_COLOR_YCBCR_FULL_RANGE),301DRM_COLOR_YCBCR_BT601,302DRM_COLOR_YCBCR_LIMITED_RANGE);303if (err)304goto cleanup;305306err = drm_plane_create_zpos_property(plane, layer->base.id, 0, 8);307if (err)308goto cleanup;309310komeda_set_crtc_plane_mask(kms, c->pipeline, plane);311312return 0;313cleanup:314komeda_plane_destroy(plane);315return err;316}317318int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev)319{320struct komeda_pipeline *pipe;321int i, j, err;322323for (i = 0; i < mdev->n_pipelines; i++) {324pipe = mdev->pipelines[i];325326for (j = 0; j < pipe->n_layers; j++) {327err = komeda_plane_add(kms, pipe->layers[j]);328if (err)329return err;330}331}332333return 0;334}335336337