drm/komeda: Attach komeda_dev to DRM-KMS
Add komeda_kms abstracton to attach komeda_dev to DRM-KMS CRTC: according to the komeda_pipeline PLANE: according to komeda_layer (layer input pipeline) PRIVATE_OBJS: komeda_pipeline/component all will be treat as private_objs komeda_kms is for connecting DRM-KMS and komeda_dev, like reporting the kms object properties according to the komeda_dev, and pass/convert KMS's requirement to komeda_dev. Changes in v4: - Set drm_atomic_helper_check as mode_config->atomic_check. Changes in v3: - Fixed style problem found by checkpatch.pl --strict. Changes in v2: - Unified abbreviation of "pipeline" to "pipe". Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
This commit is contained in:
Родитель
c46c24bb6b
Коммит
61f1c4a8ab
|
@ -9,7 +9,11 @@ komeda-y := \
|
|||
komeda_dev.o \
|
||||
komeda_format_caps.o \
|
||||
komeda_pipeline.o \
|
||||
komeda_framebuffer.o
|
||||
komeda_framebuffer.o \
|
||||
komeda_kms.o \
|
||||
komeda_crtc.o \
|
||||
komeda_plane.o \
|
||||
komeda_private_obj.o
|
||||
|
||||
komeda-y += \
|
||||
d71/d71_dev.o
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
|
||||
* Author: James.Qian.Wang <james.qian.wang@arm.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
|
||||
struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_crtc_funcs komeda_crtc_funcs = {
|
||||
};
|
||||
|
||||
int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
|
||||
struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_crtc *crtc;
|
||||
struct komeda_pipeline *master;
|
||||
char str[16];
|
||||
int i;
|
||||
|
||||
kms->n_crtcs = 0;
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++) {
|
||||
crtc = &kms->crtcs[kms->n_crtcs];
|
||||
master = mdev->pipelines[i];
|
||||
|
||||
crtc->master = master;
|
||||
crtc->slave = NULL;
|
||||
|
||||
if (crtc->slave)
|
||||
sprintf(str, "pipe-%d", crtc->slave->id);
|
||||
else
|
||||
sprintf(str, "None");
|
||||
|
||||
DRM_INFO("crtc%d: master(pipe-%d) slave(%s) output: %s.\n",
|
||||
kms->n_crtcs, master->id, str,
|
||||
master->of_output_dev ?
|
||||
master->of_output_dev->full_name : "None");
|
||||
|
||||
kms->n_crtcs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_plane *
|
||||
get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
|
||||
{
|
||||
struct komeda_plane *kplane;
|
||||
struct drm_plane *plane;
|
||||
|
||||
drm_for_each_plane(plane, &kms->base) {
|
||||
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
|
||||
continue;
|
||||
|
||||
kplane = to_kplane(plane);
|
||||
/* only master can be primary */
|
||||
if (kplane->layer->base.pipeline == crtc->master)
|
||||
return plane;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int komeda_crtc_add(struct komeda_kms_dev *kms,
|
||||
struct komeda_crtc *kcrtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &kcrtc->base;
|
||||
int err;
|
||||
|
||||
err = drm_crtc_init_with_planes(&kms->base, crtc,
|
||||
get_crtc_primary(kms, kcrtc), NULL,
|
||||
&komeda_crtc_funcs, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
|
||||
drm_crtc_vblank_reset(crtc);
|
||||
|
||||
crtc->port = kcrtc->master->of_output_port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < kms->n_crtcs; i++) {
|
||||
err = komeda_crtc_add(kms, &kms->crtcs[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -10,9 +10,11 @@
|
|||
#include <linux/component.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
|
||||
struct komeda_drv {
|
||||
struct komeda_dev *mdev;
|
||||
struct komeda_kms_dev *kms;
|
||||
};
|
||||
|
||||
static void komeda_unbind(struct device *dev)
|
||||
|
@ -22,6 +24,7 @@ static void komeda_unbind(struct device *dev)
|
|||
if (!mdrv)
|
||||
return;
|
||||
|
||||
komeda_kms_detach(mdrv->kms);
|
||||
komeda_dev_destroy(mdrv->mdev);
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
@ -43,10 +46,19 @@ static int komeda_bind(struct device *dev)
|
|||
goto free_mdrv;
|
||||
}
|
||||
|
||||
mdrv->kms = komeda_kms_attach(mdrv->mdev);
|
||||
if (IS_ERR(mdrv->kms)) {
|
||||
err = PTR_ERR(mdrv->kms);
|
||||
goto destroy_mdev;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, mdrv);
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_mdev:
|
||||
komeda_dev_destroy(mdrv->mdev);
|
||||
|
||||
free_mdrv:
|
||||
devm_kfree(dev, mdrv);
|
||||
return err;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
|
||||
* Author: James.Qian.Wang <james.qian.wang@arm.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/component.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
#include "komeda_framebuffer.h"
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops);
|
||||
|
||||
static int komeda_gem_cma_dumb_create(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
u32 alignment = 16; /* TODO get alignment from dev */
|
||||
|
||||
args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8),
|
||||
alignment);
|
||||
|
||||
return drm_gem_cma_dumb_create_internal(file, dev, args);
|
||||
}
|
||||
|
||||
static struct drm_driver komeda_kms_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
|
||||
DRIVER_PRIME,
|
||||
.lastclose = drm_fb_helper_lastclose,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = komeda_gem_cma_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = drm_gem_prime_export,
|
||||
.gem_prime_import = drm_gem_prime_import,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
.fops = &komeda_cma_fops,
|
||||
.name = "komeda",
|
||||
.desc = "Arm Komeda Display Processor driver",
|
||||
.date = "20181101",
|
||||
.major = 0,
|
||||
.minor = 1,
|
||||
};
|
||||
|
||||
static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = old_state->dev;
|
||||
|
||||
drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, old_state, 0);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_wait_for_flip_done(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_helper_funcs komeda_mode_config_helpers = {
|
||||
.atomic_commit_tail = komeda_kms_commit_tail,
|
||||
};
|
||||
|
||||
static const struct drm_mode_config_funcs komeda_mode_config_funcs = {
|
||||
.fb_create = komeda_fb_create,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
static void komeda_kms_mode_config_init(struct komeda_kms_dev *kms,
|
||||
struct komeda_dev *mdev)
|
||||
{
|
||||
struct drm_mode_config *config = &kms->base.mode_config;
|
||||
|
||||
drm_mode_config_init(&kms->base);
|
||||
|
||||
komeda_kms_setup_crtcs(kms, mdev);
|
||||
|
||||
/* Get value from dev */
|
||||
config->min_width = 0;
|
||||
config->min_height = 0;
|
||||
config->max_width = 4096;
|
||||
config->max_height = 4096;
|
||||
config->allow_fb_modifiers = false;
|
||||
|
||||
config->funcs = &komeda_mode_config_funcs;
|
||||
config->helper_private = &komeda_mode_config_helpers;
|
||||
}
|
||||
|
||||
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_kms_dev *kms = kzalloc(sizeof(*kms), GFP_KERNEL);
|
||||
struct drm_device *drm;
|
||||
int err;
|
||||
|
||||
if (!kms)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
drm = &kms->base;
|
||||
err = drm_dev_init(drm, &komeda_kms_driver, mdev->dev);
|
||||
if (err)
|
||||
goto free_kms;
|
||||
|
||||
drm->dev_private = mdev;
|
||||
|
||||
komeda_kms_mode_config_init(kms, mdev);
|
||||
|
||||
err = komeda_kms_add_private_objs(kms, mdev);
|
||||
if (err)
|
||||
goto cleanup_mode_config;
|
||||
|
||||
err = komeda_kms_add_planes(kms, mdev);
|
||||
if (err)
|
||||
goto cleanup_mode_config;
|
||||
|
||||
err = drm_vblank_init(drm, kms->n_crtcs);
|
||||
if (err)
|
||||
goto cleanup_mode_config;
|
||||
|
||||
err = komeda_kms_add_crtcs(kms, mdev);
|
||||
if (err)
|
||||
goto cleanup_mode_config;
|
||||
|
||||
err = component_bind_all(mdev->dev, kms);
|
||||
if (err)
|
||||
goto cleanup_mode_config;
|
||||
|
||||
drm_mode_config_reset(drm);
|
||||
|
||||
err = drm_dev_register(drm, 0);
|
||||
if (err)
|
||||
goto uninstall_irq;
|
||||
|
||||
return kms;
|
||||
|
||||
uninstall_irq:
|
||||
drm_irq_uninstall(drm);
|
||||
cleanup_mode_config:
|
||||
drm_mode_config_cleanup(drm);
|
||||
free_kms:
|
||||
kfree(kms);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
void komeda_kms_detach(struct komeda_kms_dev *kms)
|
||||
{
|
||||
struct drm_device *drm = &kms->base;
|
||||
struct komeda_dev *mdev = drm->dev_private;
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
component_unbind_all(mdev->dev, drm);
|
||||
komeda_kms_cleanup_private_objs(mdev);
|
||||
drm_mode_config_cleanup(drm);
|
||||
drm->dev_private = NULL;
|
||||
drm_dev_put(drm);
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
|
||||
* Author: James.Qian.Wang <james.qian.wang@arm.com>
|
||||
*
|
||||
*/
|
||||
#ifndef _KOMEDA_KMS_H_
|
||||
#define _KOMEDA_KMS_H_
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
/** struct komeda_plane - komeda instance of drm_plane */
|
||||
struct komeda_plane {
|
||||
/** @base: &drm_plane */
|
||||
struct drm_plane base;
|
||||
/**
|
||||
* @layer:
|
||||
*
|
||||
* represents available layer input pipelines for this plane.
|
||||
*
|
||||
* NOTE:
|
||||
* the layer is not for a specific Layer, but indicate a group of
|
||||
* Layers with same capabilities.
|
||||
*/
|
||||
struct komeda_layer *layer;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct komeda_plane_state
|
||||
*
|
||||
* The plane_state can be split into two data flow (left/right) and handled
|
||||
* by two layers &komeda_plane.layer and &komeda_plane.layer.right
|
||||
*/
|
||||
struct komeda_plane_state {
|
||||
/** @base: &drm_plane_state */
|
||||
struct drm_plane_state base;
|
||||
|
||||
/* private properties */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct komeda_wb_connector
|
||||
*/
|
||||
struct komeda_wb_connector {
|
||||
/** @base: &drm_writeback_connector */
|
||||
struct drm_writeback_connector base;
|
||||
|
||||
/** @wb_layer: represents associated writeback pipeline of komeda */
|
||||
struct komeda_layer *wb_layer;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct komeda_crtc
|
||||
*/
|
||||
struct komeda_crtc {
|
||||
/** @base: &drm_crtc */
|
||||
struct drm_crtc base;
|
||||
/** @master: only master has display output */
|
||||
struct komeda_pipeline *master;
|
||||
/**
|
||||
* @slave: optional
|
||||
*
|
||||
* Doesn't have its own display output, the handled data flow will
|
||||
* merge into the master.
|
||||
*/
|
||||
struct komeda_pipeline *slave;
|
||||
};
|
||||
|
||||
/** struct komeda_crtc_state */
|
||||
struct komeda_crtc_state {
|
||||
/** @base: &drm_crtc_state */
|
||||
struct drm_crtc_state base;
|
||||
|
||||
/* private properties */
|
||||
|
||||
/* computed state which are used by validate/check */
|
||||
u32 affected_pipes;
|
||||
u32 active_pipes;
|
||||
};
|
||||
|
||||
/** struct komeda_kms_dev - for gather KMS related things */
|
||||
struct komeda_kms_dev {
|
||||
/** @base: &drm_device */
|
||||
struct drm_device base;
|
||||
|
||||
/** @n_crtcs: valid numbers of crtcs in &komeda_kms_dev.crtcs */
|
||||
int n_crtcs;
|
||||
/** @crtcs: crtcs list */
|
||||
struct komeda_crtc crtcs[KOMEDA_MAX_PIPELINES];
|
||||
};
|
||||
|
||||
#define to_kplane(p) container_of(p, struct komeda_plane, base)
|
||||
#define to_kplane_st(p) container_of(p, struct komeda_plane_state, base)
|
||||
#define to_kconn(p) container_of(p, struct komeda_wb_connector, base)
|
||||
#define to_kcrtc(p) container_of(p, struct komeda_crtc, base)
|
||||
#define to_kcrtc_st(p) container_of(p, struct komeda_crtc_state, base)
|
||||
#define to_kdev(p) container_of(p, struct komeda_kms_dev, base)
|
||||
|
||||
int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
|
||||
|
||||
int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
|
||||
int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
|
||||
int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
|
||||
struct komeda_dev *mdev);
|
||||
void komeda_kms_cleanup_private_objs(struct komeda_dev *mdev);
|
||||
|
||||
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
|
||||
void komeda_kms_detach(struct komeda_kms_dev *kms);
|
||||
|
||||
#endif /*_KOMEDA_KMS_H_*/
|
|
@ -331,6 +331,9 @@ struct komeda_pipeline_state {
|
|||
#define to_improc_st(c) container_of(c, struct komeda_improc_state, base)
|
||||
#define to_ctrlr_st(c) container_of(c, struct komeda_timing_ctrlr_state, base)
|
||||
|
||||
#define priv_to_comp_st(o) container_of(o, struct komeda_component_state, obj)
|
||||
#define priv_to_pipe_st(o) container_of(o, struct komeda_pipeline_state, obj)
|
||||
|
||||
/* pipeline APIs */
|
||||
struct komeda_pipeline *
|
||||
komeda_pipeline_add(struct komeda_dev *mdev, size_t size,
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
|
||||
* Author: James.Qian.Wang <james.qian.wang@arm.com>
|
||||
*
|
||||
*/
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
|
||||
static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {
|
||||
};
|
||||
|
||||
static void komeda_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
drm_plane_cleanup(plane);
|
||||
|
||||
kfree(to_kplane(plane));
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs komeda_plane_funcs = {
|
||||
};
|
||||
|
||||
/* for komeda, which is pipeline can be share between crtcs */
|
||||
static u32 get_possible_crtcs(struct komeda_kms_dev *kms,
|
||||
struct komeda_pipeline *pipe)
|
||||
{
|
||||
struct komeda_crtc *crtc;
|
||||
u32 possible_crtcs = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kms->n_crtcs; i++) {
|
||||
crtc = &kms->crtcs[i];
|
||||
|
||||
if ((pipe == crtc->master) || (pipe == crtc->slave))
|
||||
possible_crtcs |= BIT(i);
|
||||
}
|
||||
|
||||
return possible_crtcs;
|
||||
}
|
||||
|
||||
/* use Layer0 as primary */
|
||||
static u32 get_plane_type(struct komeda_kms_dev *kms,
|
||||
struct komeda_component *c)
|
||||
{
|
||||
bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0);
|
||||
|
||||
return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
|
||||
}
|
||||
|
||||
static int komeda_plane_add(struct komeda_kms_dev *kms,
|
||||
struct komeda_layer *layer)
|
||||
{
|
||||
struct komeda_dev *mdev = kms->base.dev_private;
|
||||
struct komeda_component *c = &layer->base;
|
||||
struct komeda_plane *kplane;
|
||||
struct drm_plane *plane;
|
||||
u32 *formats, n_formats = 0;
|
||||
int err;
|
||||
|
||||
kplane = kzalloc(sizeof(*kplane), GFP_KERNEL);
|
||||
if (!kplane)
|
||||
return -ENOMEM;
|
||||
|
||||
plane = &kplane->base;
|
||||
kplane->layer = layer;
|
||||
|
||||
formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
|
||||
layer->layer_type, &n_formats);
|
||||
|
||||
err = drm_universal_plane_init(&kms->base, plane,
|
||||
get_possible_crtcs(kms, c->pipeline),
|
||||
&komeda_plane_funcs,
|
||||
formats, n_formats, NULL,
|
||||
get_plane_type(kms, c),
|
||||
"%s", c->name);
|
||||
|
||||
komeda_put_fourcc_list(formats);
|
||||
|
||||
if (err)
|
||||
goto cleanup;
|
||||
|
||||
drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
komeda_plane_destroy(plane);
|
||||
return err;
|
||||
}
|
||||
|
||||
int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_pipeline *pipe;
|
||||
int i, j, err;
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++) {
|
||||
pipe = mdev->pipelines[i];
|
||||
|
||||
for (j = 0; j < pipe->n_layers; j++) {
|
||||
err = komeda_plane_add(kms, pipe->layers[j]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
|
||||
* Author: James.Qian.Wang <james.qian.wang@arm.com>
|
||||
*
|
||||
*/
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
|
||||
static struct drm_private_state *
|
||||
komeda_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
|
||||
{
|
||||
struct komeda_pipeline_state *st;
|
||||
|
||||
st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->active_comps = 0;
|
||||
|
||||
__drm_atomic_helper_private_obj_duplicate_state(obj, &st->obj);
|
||||
|
||||
return &st->obj;
|
||||
}
|
||||
|
||||
static void
|
||||
komeda_pipeline_atomic_destroy_state(struct drm_private_obj *obj,
|
||||
struct drm_private_state *state)
|
||||
{
|
||||
kfree(priv_to_pipe_st(state));
|
||||
}
|
||||
|
||||
static const struct drm_private_state_funcs komeda_pipeline_obj_funcs = {
|
||||
.atomic_duplicate_state = komeda_pipeline_atomic_duplicate_state,
|
||||
.atomic_destroy_state = komeda_pipeline_atomic_destroy_state,
|
||||
};
|
||||
|
||||
static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms,
|
||||
struct komeda_pipeline *pipe)
|
||||
{
|
||||
struct komeda_pipeline_state *st;
|
||||
|
||||
st = kzalloc(sizeof(*st), GFP_KERNEL);
|
||||
if (!st)
|
||||
return -ENOMEM;
|
||||
|
||||
st->pipe = pipe;
|
||||
drm_atomic_private_obj_init(&pipe->obj, &st->obj,
|
||||
&komeda_pipeline_obj_funcs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
|
||||
struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_pipeline *pipe;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++) {
|
||||
pipe = mdev->pipelines[i];
|
||||
|
||||
err = komeda_pipeline_obj_add(kms, pipe);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Add component */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void komeda_kms_cleanup_private_objs(struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_pipeline *pipe;
|
||||
struct komeda_component *c;
|
||||
int i, id;
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++) {
|
||||
pipe = mdev->pipelines[i];
|
||||
dp_for_each_set_bit(id, pipe->avail_comps) {
|
||||
c = komeda_pipeline_get_component(pipe, id);
|
||||
|
||||
drm_atomic_private_obj_fini(&c->obj);
|
||||
}
|
||||
drm_atomic_private_obj_fini(&pipe->obj);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче