Commit ef9621bc authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] v4l: vsp1: Store the display list manager in the WPF

Each WPF can process display lists independently, move the manager to
the WPF to reflect that and prepare for display list support for non-DRM
pipelines.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent c2dd2513
......@@ -48,6 +48,25 @@ struct vsp1_dl_list {
int reg_count;
};
/**
* struct vsp1_dl_manager - Display List manager
* @vsp1: the VSP1 device
* @lock: protects the active, queued and pending lists
* @free: array of all free display lists
* @active: list currently being processed (loaded) by hardware
* @queued: list queued to the hardware (written to the DL registers)
* @pending: list waiting to be queued to the hardware
*/
struct vsp1_dl_manager {
struct vsp1_device *vsp1;
spinlock_t lock;
struct list_head free;
struct vsp1_dl_list *active;
struct vsp1_dl_list *queued;
struct vsp1_dl_list *pending;
};
/* -----------------------------------------------------------------------------
* Display List Transaction Management
*/
......@@ -256,11 +275,16 @@ void vsp1_dlm_reset(struct vsp1_dl_manager *dlm)
dlm->pending = NULL;
}
int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm,
struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
unsigned int prealloc)
{
struct vsp1_dl_manager *dlm;
unsigned int i;
dlm = devm_kzalloc(vsp1->dev, sizeof(*dlm), GFP_KERNEL);
if (!dlm)
return NULL;
dlm->vsp1 = vsp1;
spin_lock_init(&dlm->lock);
......@@ -271,18 +295,21 @@ int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm,
dl = vsp1_dl_list_alloc(dlm);
if (!dl)
return -ENOMEM;
return NULL;
list_add_tail(&dl->list, &dlm->free);
}
return 0;
return dlm;
}
void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm)
void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm)
{
struct vsp1_dl_list *dl, *next;
if (!dlm)
return;
list_for_each_entry_safe(dl, next, &dlm->free, list) {
list_del(&dl->list);
vsp1_dl_list_free(dl);
......
......@@ -17,31 +17,13 @@
struct vsp1_device;
struct vsp1_dl_list;
/**
* struct vsp1_dl_manager - Display List manager
* @vsp1: the VSP1 device
* @lock: protects the active, queued and pending lists
* @free: array of all free display lists
* @active: list currently being processed (loaded) by hardware
* @queued: list queued to the hardware (written to the DL registers)
* @pending: list waiting to be queued to the hardware
*/
struct vsp1_dl_manager {
struct vsp1_device *vsp1;
spinlock_t lock;
struct list_head free;
struct vsp1_dl_list *active;
struct vsp1_dl_list *queued;
struct vsp1_dl_list *pending;
};
struct vsp1_dl_manager;
void vsp1_dlm_setup(struct vsp1_device *vsp1);
int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm,
struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
unsigned int prealloc);
void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm);
void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm);
void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
......
......@@ -31,11 +31,14 @@
* Interrupt Handling
*/
void vsp1_drm_frame_end(struct vsp1_pipeline *pipe)
void vsp1_drm_display_start(struct vsp1_device *vsp1)
{
struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm);
}
vsp1_dlm_irq_frame_end(&vsp1->drm->dlm);
void vsp1_drm_frame_end(struct vsp1_pipeline *pipe)
{
vsp1_dlm_irq_frame_end(pipe->output->dlm);
}
/* -----------------------------------------------------------------------------
......@@ -101,7 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
pipe->num_inputs = 0;
vsp1_dlm_reset(&vsp1->drm->dlm);
vsp1_dlm_reset(pipe->output->dlm);
vsp1_device_put(vsp1);
dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__);
......@@ -228,7 +231,7 @@ void vsp1_du_atomic_begin(struct device *dev)
spin_unlock_irqrestore(&pipe->irqlock, flags);
/* Prepare the display list. */
pipe->dl = vsp1_dl_list_get(&vsp1->drm->dlm);
pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
}
EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
......@@ -555,16 +558,11 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
{
struct vsp1_pipeline *pipe;
unsigned int i;
int ret;
vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL);
if (!vsp1->drm)
return -ENOMEM;
ret = vsp1_dlm_init(vsp1, &vsp1->drm->dlm, 4);
if (ret < 0)
return ret;
pipe = &vsp1->drm->pipe;
vsp1_pipeline_init(pipe);
......@@ -590,5 +588,4 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
void vsp1_drm_cleanup(struct vsp1_device *vsp1)
{
vsp1_dlm_cleanup(&vsp1->drm->dlm);
}
......@@ -13,7 +13,6 @@
#ifndef __VSP1_DRM_H__
#define __VSP1_DRM_H__
#include "vsp1_dl.h"
#include "vsp1_pipe.h"
/**
......@@ -21,22 +20,17 @@
* @pipe: the VSP1 pipeline used for display
* @num_inputs: number of active pipeline inputs at the beginning of an update
* @update: the pipeline configuration has been updated
* @dlm: display list manager used for DRM operation
*/
struct vsp1_drm {
struct vsp1_pipeline pipe;
unsigned int num_inputs;
bool update;
struct vsp1_dl_manager dlm;
};
int vsp1_drm_init(struct vsp1_device *vsp1);
void vsp1_drm_cleanup(struct vsp1_device *vsp1);
int vsp1_drm_create_links(struct vsp1_device *vsp1);
static inline void vsp1_drm_display_start(struct vsp1_device *vsp1)
{
vsp1_dlm_irq_display_start(&vsp1->drm->dlm);
}
void vsp1_drm_display_start(struct vsp1_device *vsp1);
#endif /* __VSP1_DRM_H__ */
......@@ -244,6 +244,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
void vsp1_entity_destroy(struct vsp1_entity *entity)
{
if (entity->destroy)
entity->destroy(entity);
if (entity->subdev.ctrl_handler)
v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
media_entity_cleanup(&entity->subdev.entity);
......
......@@ -56,6 +56,8 @@ struct vsp1_route {
struct vsp1_entity {
struct vsp1_device *vsp1;
void (*destroy)(struct vsp1_entity *);
enum vsp1_entity_type type;
unsigned int index;
const struct vsp1_route *route;
......
......@@ -24,6 +24,7 @@
#define RWPF_PAD_SOURCE 1
struct v4l2_ctrl;
struct vsp1_dl_manager;
struct vsp1_rwpf;
struct vsp1_video;
......@@ -60,6 +61,8 @@ struct vsp1_rwpf {
unsigned int offsets[2];
dma_addr_t buf_addr[3];
struct vsp1_dl_manager *dlm;
};
static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev)
......
......@@ -16,6 +16,7 @@
#include <media/v4l2-subdev.h>
#include "vsp1.h"
#include "vsp1_dl.h"
#include "vsp1_rwpf.h"
#include "vsp1_video.h"
......@@ -218,6 +219,13 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = {
* Initialization and Cleanup
*/
static void vsp1_wpf_destroy(struct vsp1_entity *entity)
{
struct vsp1_rwpf *wpf = container_of(entity, struct vsp1_rwpf, entity);
vsp1_dlm_destroy(wpf->dlm);
}
struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
{
struct v4l2_subdev *subdev;
......@@ -233,6 +241,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
wpf->max_width = WPF_MAX_WIDTH;
wpf->max_height = WPF_MAX_HEIGHT;
wpf->entity.destroy = vsp1_wpf_destroy;
wpf->entity.type = VSP1_ENTITY_WPF;
wpf->entity.index = index;
......@@ -240,6 +249,15 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
if (ret < 0)
return ERR_PTR(ret);
/* Initialize the display list manager if the WPF is used for display */
if ((vsp1->info->features & VSP1_HAS_LIF) && index == 0) {
wpf->dlm = vsp1_dlm_create(vsp1, 4);
if (!wpf->dlm) {
ret = -ENOMEM;
goto error;
}
}
/* Initialize the V4L2 subdev. */
subdev = &wpf->entity.subdev;
v4l2_subdev_init(subdev, &wpf_ops);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment