From: Laurent Pinchart Date: Sun, 15 Nov 2015 00:27:52 +0000 (-0200) Subject: [media] v4l: vsp1: Store the display list manager in the WPF X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=ef9621bcd6640d48834ec9315dae06e9d7cb5283;p=linux-beck.git [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: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 14b2ee3c5fba..e0f4816925d5 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -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, - unsigned int prealloc) +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); diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index caa6a85f6825..46f7ae337374 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -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, - unsigned int prealloc); -void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm); +struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + unsigned int prealloc); +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); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a8cd74335f20..22f67360b750 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -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); } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 5ef32cff9601..e9242f2c870e 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -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__ */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 83689588900a..a94f544dcc77 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -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); diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 311d5b64c9a5..259880e524fe 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -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; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 8e8235682ada..d04df39b2737 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -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) diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index c78d4af50fcf..6afc9c8d9adc 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -16,6 +16,7 @@ #include #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);