| /* |
| * include/media/m2m1shot2.h |
| * |
| * Copyright (C) 2015 Samsung Electronics Co., Ltd. |
| * |
| * Contact: Cho KyongHo <pullip.cho@samsung.com> |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| */ |
| |
| #ifndef _M2M1SHOT2_H_ |
| #define _M2M1SHOT2_H_ |
| |
| #include <linux/kernel.h> |
| #include <linux/videodev2.h> |
| #include <linux/list.h> |
| #include <linux/miscdevice.h> |
| #include <linux/dma-direction.h> |
| #include <linux/kref.h> |
| #include <linux/completion.h> |
| #include <linux/dma-buf.h> |
| |
| #include <uapi/linux/m2m1shot2.h> |
| |
| #include "../../drivers/staging/android/sw_sync.h" |
| |
| struct m2m1shot2_device; |
| struct m2m1shot2_context; |
| |
| /** |
| * struct m2m1shot2_dma_buffer - buffer description of a plane of an image |
| * |
| * @payload : length of the effective data |
| * @offset : the offset where the effective dta is stored from the start |
| * of the buffer if the buffer type is dmabuf. |
| * @dmabuf : the pointer to dmabuf structure if the buffer type is dmabuf |
| * @attachment : the pointer to attachment structure if the buffer type is |
| * @length : length of the buffer if the buffer type is userptr |
| * @addr : userptr address if the memory type is userptr |
| * @vma : copy of the head vma of the list of vm_area_struct that |
| * describes the user area [@addr, @addr + @length) |
| * @sgt : scatterlist table if the buffer type is dmabuf |
| * @dma_addr : DMA address for the client device |
| * @priv : for the private use of the client device driver |
| */ |
| struct m2m1shot2_dma_buffer { |
| u32 payload; |
| union { |
| struct { |
| u32 offset; |
| struct dma_buf *dmabuf; |
| struct dma_buf_attachment *attachment; |
| } dmabuf; |
| struct { |
| u32 length; |
| unsigned long addr; |
| struct vm_area_struct *vma; |
| } userptr; |
| }; |
| struct sg_table *sgt; |
| dma_addr_t dma_addr; |
| void *priv; |
| }; |
| |
| /** |
| * struct m2m1shot2_context_format - image format description of an image |
| * |
| * @fmt : the image format information given by the userspace |
| * @priv : the client drivers' private data that can be initialized in |
| * m2m1shot2_devops.prepare_format(). It must be static data so |
| * hat the resources related to the data don't need to be |
| * released. The framework does not provide a chance to release |
| * any resouce related to @priv. |
| */ |
| struct m2m1shot2_context_format { |
| struct m2m1shot2_format fmt; |
| void *priv; |
| u32 colorspace; |
| }; |
| |
| /** |
| * struct m2m1shot2_context_image |
| * - description for both of source and target images |
| * |
| * @index : index of the current image in m2m1shot2_context.source array |
| * @flags : flags about the image configured in the userspace. |
| * See include/uapi/linux/m2m1shot2.h |
| * @fmt : image format information given by the userspace |
| * @memory : memory type of all buffers in @plane |
| * @plane : buffer information of all planes of the image |
| * @fence_waiter: waiter object of @fence of the image to support for |
| * asynchronous fence waiter |
| * @fence : acquire fence of the image. The image processing deos not |
| * start until @fence is signaled. |
| */ |
| struct m2m1shot2_context_image { |
| unsigned int index; |
| u32 flags; |
| struct m2m1shot2_context_format fmt; |
| |
| u32 memory; |
| unsigned int num_planes; |
| struct m2m1shot2_dma_buffer plane[M2M1SHOT2_MAX_PLANES]; |
| |
| struct sync_fence_waiter waiter; |
| struct sync_fence *fence; |
| }; |
| |
| /** |
| * struct m2m1shot2_source_image - source image description |
| * |
| * @img : image description |
| * @ext : extra image processing description. |
| * See include/uapi/linux/m2m1shot2.h |
| */ |
| struct m2m1shot2_source_image { |
| struct m2m1shot2_context_image img; |
| struct m2m1shot2_extra ext; |
| }; |
| |
| /** |
| * struct m2m1shot2_devops |
| * |
| * @init_context : [MANDATORY] |
| * called on creation of a context. The given parameter |
| * is initialized by the caller. The callee can register |
| * its private data to m2m1shot2_context.priv. A context |
| * is created when a userspace opens the device node. |
| * @free_context : [MANDATORY] |
| * called on destruction of a context. The given context |
| * has complete information until its return. The callee |
| * should cleaning up all the relevant data in this |
| * function. |
| * @prepare_format : [MANDATORY] |
| * called when userspace pushes a work to the device |
| * through m2m1shot2. m2m1shot2 calls this function for |
| * every image provided from the userspace and the callee |
| * should initializes @payload and @num_planes on return |
| * according to the format. @num_planes should not be |
| * greater than M2M1SHOT2_MAX_PLANES and @num_planes |
| * number of elements in @payload should be initialized |
| * by the callee. |
| * @prepare_source : [OPTIONAL] |
| * called when userspace pushes a task to the device |
| * through m2m1shot2 and the driver verified that the |
| * image format and the buffer do not have a problem. |
| * The callee then should identify and confirm the rest |
| * of attributes specified in m2m1shot2_source_image. |
| * @device_run : [MANDATORY] |
| * called when work is ready to be processed by H/W. |
| */ |
| |
| struct m2m1shot2_devops { |
| int (*init_context)(struct m2m1shot2_context *ctx); |
| int (*free_context)(struct m2m1shot2_context *ctx); |
| int (*prepare_format)(struct m2m1shot2_context_format *fmt, |
| unsigned int index, |
| enum dma_data_direction dir, |
| size_t payload[], |
| unsigned int *num_planes); |
| int (*prepare_source)(struct m2m1shot2_context *ctx, |
| unsigned int index, |
| struct m2m1shot2_source_image *img); |
| int (*prepare_target)(struct m2m1shot2_context *ctx, |
| struct m2m1shot2_context_image *img); |
| int (*prepare_perf)(struct m2m1shot2_context *ctx, |
| struct m2m1shot2_performance_data *data); |
| int (*device_run)(struct m2m1shot2_context *ctx); |
| int (*custom_ioctl)(struct m2m1shot2_context *ctx, |
| unsigned int cmd, |
| unsigned int arg); |
| }; |
| |
| /* m2m1shot2_context.state flags */ |
| |
| /* H/W is working on the context or it is waiting for H/W time */ |
| #define M2M1S2_CTXSTATE_PROCESSING 0 |
| /* The context is waiting for H/W time */ |
| #define M2M1S2_CTXSTATE_PENDING 1 |
| /* A process is waiting for a context to finish*/ |
| #define M2M1S2_CTXSTATE_WAITING 2 |
| /* The context is finished but userspace does not yet subscribe */ |
| #define M2M1S2_CTXSTATE_PROCESSED 8 |
| /* A error is occurred during processing the context */ |
| #define M2M1S2_CTXSTATE_ERROR 9 |
| |
| /* force clean all the caches before DMA for better performance */ |
| #define M2M1S2_CTXSTATE_CACHECLEANALL 16 |
| /* force invalidate all the caches after DMA for better performance */ |
| #define M2M1S2_CTXSTATE_CACHEINVALALL 17 |
| |
| #define M2M1S2_CTXSTATE_CACHEFLUSH 18 |
| #define M2M1S2_CTXSTATE_CACHEFLUSHALL 19 |
| |
| #define M2M1S2_CTXSTATE_IDLE(ctx) (((ctx)->state & 0xFF) == 0) |
| /* PROCESSIG | PENDING */ |
| #define M2M1S2_CTXSTATE_BUSY(ctx) (((ctx)->state & 0x3) != 0) |
| |
| #define BTS_PEAK_FPS_RATIO 1667 |
| |
| #define M2M1S2_TIMEOUT_INTERVAL 1000 |
| /** |
| * struct m2m1shot2_context - context of tasks |
| * |
| * @node : node entry to m2m1shot2_device.contexts |
| * @state : state of the context |
| * @starter : counter of acquire fences to wait. |
| * @m21dev : the singleton device instance that the context is born |
| * @priv : private data that is allowed to store client drivers' private |
| * @mutex : serialization of user's requests |
| * @complete : sync point between the waiter and the driver |
| * @work : work to schedule the context that is scheduled by a fence |
| * because asynchronous waiter of an Android fence is invoked |
| * with IRQ disabled. |
| * @dwork : work to schedule the destruction of the context because it |
| * is required to wait until a pending context to be finished. |
| * @flags : flags specified in m2m1shot2.flags. |
| * @num_sources : the number of effective elements in @source |
| * @source : source image information |
| * @target : destination image information |
| * @timeline : monotonic timeline of Android sync that signals the release |
| * fences |
| * @timeline_max: the timestamp of the most recent release fence |
| * @ctx_private : the framework' private use |
| * @work_delay_in_nsec : delay in processing (nsec) |
| * @timer : timeout that the acquire fence can't receive the signal |
| * for some time. |
| * @release_fence : release fence of ctx. It is only used for debugging. |
| */ |
| struct m2m1shot2_context { |
| struct list_head node; |
| unsigned long state; |
| struct kref starter; |
| struct m2m1shot2_device *m21dev; |
| void *priv; |
| struct mutex mutex; |
| struct completion complete; |
| struct work_struct work; |
| struct work_struct dwork; |
| |
| unsigned int flags; |
| unsigned int num_sources; |
| struct m2m1shot2_source_image source[M2M1SHOT2_MAX_IMAGES]; |
| struct m2m1shot2_context_image target; |
| |
| struct sw_sync_timeline *timeline; |
| enum m2m1shot2_priority priority; |
| u32 timeline_max; |
| u32 ctx_private; |
| u32 ctx_private2; |
| u64 work_delay_in_nsec; |
| struct timer_list timer; |
| struct sync_fence *release_fence; |
| spinlock_t fence_timeout_lock; |
| }; |
| |
| #define M2M1SHOT2_DEVATTR_COHERENT (1 << 0) |
| /** |
| * struct m2m1shot2_device |
| * |
| * @misc : misc device desciptor for user-kernel interface |
| * @attr : attribute flags that describes the characteristics of the |
| * client device. |
| * @dev : the client device desciptor |
| * @contexts : list of instances of m2m1shot2_context that are not currently |
| * under processing request. |
| * - a node added in m2m1shot2_open() and |
| * __m2m1shot2_finish_context() |
| * - a node removed in m2m1shot2_start_context() and |
| * m2m1shot2_cancel_context(). |
| * @active_contexts: the list of the contexts that is waiting to be serviced |
| * - a node added in m2m1shot2_start_context(). |
| * - a node removed in m2m1shot2_schedule() and |
| * m2m1shot2_cancel_context(). |
| * @current_task: indicate the context that is currently being processed |
| * - a value set in m2m1shot2_schedule() |
| * - NULL is set in __m2m1shot2_finish_context(). |
| * @lock_ctx : lock to protect the consistency of @contexts, @active_contexts |
| * and @current_task. |
| * @ops : callback functions that the client device driver must |
| * implement according to the events. |
| * @schedule_workqueue: queue of work to schedule a image processing task. |
| * An workqueue is needed to run m2m1shot2_schedule() in a |
| * process context when the task need to wait for a fence because |
| * the callback of the fence waiter is in IRQ disabled context. |
| * |
| * LIFECYCLE of m2m1shot2_context: |
| * - added to @contexts on creation |
| * - moved from @contexts to @active_contexts on process request |
| * - moved from @active_contexts to @current_task on processing |
| * - moved from @current_task to @contexts on completion |
| * - removed from @contexts on destruction |
| */ |
| struct m2m1shot2_device { |
| struct miscdevice misc; |
| unsigned long attr; |
| struct device *dev; |
| struct list_head contexts; |
| struct list_head active_contexts; |
| struct m2m1shot2_context *current_ctx; |
| spinlock_t lock_ctx; |
| spinlock_t lock_priority; |
| const struct m2m1shot2_devops *ops; |
| struct workqueue_struct *schedule_workqueue; |
| struct workqueue_struct *destroy_workqueue; |
| unsigned char prior_stats[M2M1SHOT2_PRIORITY_END]; |
| struct mutex lock_qos; |
| struct list_head qos_contexts; |
| }; |
| |
| #ifdef CONFIG_MEDIA_M2M1SHOT2 |
| struct m2m1shot2_context *m2m1shot2_current_context( |
| const struct m2m1shot2_device *m21dev); |
| struct m2m1shot2_device *m2m1shot2_create_device(struct device *dev, |
| const struct m2m1shot2_devops *ops, |
| const char *nodename, int id, unsigned long attr); |
| void m2m1shot2_destroy_device(struct m2m1shot2_device *m21dev); |
| void m2m1shot2_finish_context(struct m2m1shot2_context *ctx, bool success); |
| void m2m1shot2_schedule(struct m2m1shot2_device *m21dev); |
| |
| static inline u32 m2m1shot2_get_payload(struct m2m1shot2_context *ctx, |
| unsigned int index, unsigned int plane) |
| { |
| BUG_ON(index >= M2M1SHOT2_MAX_IMAGES); |
| BUG_ON(plane >= ctx->source[index].img.num_planes); |
| |
| return ctx->source[index].img.plane[plane].payload; |
| } |
| |
| static inline void m2m1shot2_set_payload(struct m2m1shot2_context *ctx, |
| unsigned int plane, u32 payload) |
| { |
| BUG_ON(plane >= ctx->target.num_planes); |
| BUG_ON((ctx->target.memory == M2M1SHOT2_BUFTYPE_DMABUF) |
| && (payload > ctx->target.plane[plane].dmabuf.dmabuf->size)); |
| BUG_ON((ctx->target.memory == M2M1SHOT2_BUFTYPE_USERPTR) |
| && (payload > ctx->target.plane[plane].userptr.length)); |
| |
| ctx->target.plane[plane].payload = payload; |
| } |
| |
| static inline dma_addr_t m2m1shot2_src_dma_addr(struct m2m1shot2_context *ctx, |
| unsigned int index, unsigned int plane) |
| { |
| BUG_ON(index >= M2M1SHOT2_MAX_IMAGES); |
| BUG_ON(plane >= ctx->source[index].img.num_planes); |
| |
| return ctx->source[index].img.plane[plane].dma_addr; |
| } |
| |
| static inline dma_addr_t m2m1shot2_dst_dma_addr(struct m2m1shot2_context *ctx, |
| unsigned int plane) |
| { |
| BUG_ON(plane >= ctx->target.num_planes); |
| |
| return ctx->target.plane[plane].dma_addr; |
| } |
| |
| static inline struct m2m1shot2_context_format *m2m1shot2_src_format( |
| struct m2m1shot2_context *ctx, unsigned int index) |
| { |
| BUG_ON(index >= M2M1SHOT2_MAX_IMAGES); |
| |
| return &ctx->source[index].img.fmt; |
| } |
| |
| static inline struct m2m1shot2_context_format *m2m1shot2_dst_format( |
| struct m2m1shot2_context *ctx) |
| { |
| return &ctx->target.fmt; |
| } |
| |
| #else /* !CONFIG_MEDIA_M2M1SHOT2 */ |
| static inline struct m2m1shot2_context *m2m1shot2_current_context( |
| const struct m2m1shot2_device *m21dev) |
| { |
| return NULL; |
| } |
| static inline struct m2m1shot2_device *m2m1shot2_create_device( |
| struct device *dev, const struct m2m1shot2_devops *ops, |
| const char *nodename, int id, unsigned long attr) |
| { |
| return NULL; |
| } |
| #define m2m1shot2_destroy_device(m21dev) do { } while (0) |
| #define m2m1shot2_finish_context(ctx, success) do { } while (0) |
| static inline u32 m2m1shot2_get_payload(struct m2m1shot2_context *ctx, |
| unsigned int index, unsigned int plane) |
| { |
| return 0; |
| } |
| |
| #define m2m1shot2_set_payload(ctx, plane, payload) do { } while (0) |
| static inline dma_addr_t m2m1shot2_src_dma_addr(struct m2m1shot2_context *ctx, |
| unsigned int index, unsigned int plane) |
| { |
| return 0; |
| } |
| |
| static inline dma_addr_t m2m1shot2_dst_dma_addr(struct m2m1shot2_context *ctx, |
| unsigned int plane) |
| { |
| return 0; |
| } |
| #endif /* CONFIG_MEDIA_M2M1SHOT2 */ |
| |
| #endif /* _M2M1SHOT2_H_ */ |