v4l2-mem2mem.h 6.8 KB
Newer Older
1 2 3 4 5 6 7
/*
 * Memory-to-memory device framework for Video for Linux 2.
 *
 * Helper functions for devices that use memory buffers for both source
 * and destination.
 *
 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
8
 * Pawel Osciak, <pawel@osciak.com>
9 10 11 12 13 14 15 16 17 18 19
 * Marek Szyprowski, <m.szyprowski@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version
 */

#ifndef _MEDIA_V4L2_MEM2MEM_H
#define _MEDIA_V4L2_MEM2MEM_H

20
#include <media/videobuf2-core.h>
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

/**
 * struct v4l2_m2m_ops - mem-to-mem device driver callbacks
 * @device_run:	required. Begin the actual job (transaction) inside this
 *		callback.
 *		The job does NOT have to end before this callback returns
 *		(and it will be the usual case). When the job finishes,
 *		v4l2_m2m_job_finish() has to be called.
 * @job_ready:	optional. Should return 0 if the driver does not have a job
 *		fully prepared to run yet (i.e. it will not be able to finish a
 *		transaction without sleeping). If not provided, it will be
 *		assumed that one source and one destination buffer are all
 *		that is required for the driver to perform one full transaction.
 *		This method may not sleep.
 * @job_abort:	required. Informs the driver that it has to abort the currently
 *		running transaction as soon as possible (i.e. as soon as it can
 *		stop the device safely; e.g. in the next interrupt handler),
 *		even if the transaction would not have been finished by then.
 *		After the driver performs the necessary steps, it has to call
 *		v4l2_m2m_job_finish() (as if the transaction ended normally).
 *		This function does not have to (and will usually not) wait
 *		until the device enters a state when it can be stopped.
 */
struct v4l2_m2m_ops {
	void (*device_run)(void *priv);
	int (*job_ready)(void *priv);
	void (*job_abort)(void *priv);
48 49
	void (*lock)(void *priv);
	void (*unlock)(void *priv);
50 51 52 53 54 55
};

struct v4l2_m2m_dev;

struct v4l2_m2m_queue_ctx {
/* private: internal use only */
56
	struct vb2_queue	q;
57 58 59 60

	/* Queue for buffers ready to be processed as soon as this
	 * instance receives access to the device */
	struct list_head	rdy_queue;
61
	spinlock_t		rdy_spinlock;
62
	u8			num_rdy;
63
	bool			buffered;
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
};

struct v4l2_m2m_ctx {
/* private: internal use only */
	struct v4l2_m2m_dev		*m2m_dev;

	/* Capture (output to memory) queue context */
	struct v4l2_m2m_queue_ctx	cap_q_ctx;

	/* Output (input from memory) queue context */
	struct v4l2_m2m_queue_ctx	out_q_ctx;

	/* For device job queue */
	struct list_head		queue;
	unsigned long			job_flags;
79
	wait_queue_head_t		finished;
80 81 82 83 84

	/* Instance private data */
	void				*priv;
};

85 86 87 88 89
struct v4l2_m2m_buffer {
	struct vb2_buffer	vb;
	struct list_head	list;
};

90 91
void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev);

92
struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
93 94 95 96 97
				       enum v4l2_buf_type type);

void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
			 struct v4l2_m2m_ctx *m2m_ctx);

98 99 100 101 102 103
static inline void
v4l2_m2m_buf_done(struct vb2_buffer *buf, enum vb2_buffer_state state)
{
	vb2_buffer_done(buf, state);
}

104 105 106 107 108 109 110 111 112 113
int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		     struct v4l2_requestbuffers *reqbufs);

int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		      struct v4l2_buffer *buf);

int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		  struct v4l2_buffer *buf);
int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		   struct v4l2_buffer *buf);
114 115
int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
			 struct v4l2_create_buffers *create);
116

117 118 119
int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		   struct v4l2_exportbuffer *eb);

120 121 122 123 124 125 126 127 128 129 130
int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		      enum v4l2_buf_type type);
int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		       enum v4l2_buf_type type);

unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
			   struct poll_table_struct *wait);

int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
		  struct vm_area_struct *vma);

131
struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops);
132 133
void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);

134 135 136 137
struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
		void *drv_priv,
		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq));

138 139 140 141 142 143 144 145 146 147 148 149
static inline void v4l2_m2m_set_src_buffered(struct v4l2_m2m_ctx *m2m_ctx,
					     bool buffered)
{
	m2m_ctx->out_q_ctx.buffered = buffered;
}

static inline void v4l2_m2m_set_dst_buffered(struct v4l2_m2m_ctx *m2m_ctx,
					     bool buffered)
{
	m2m_ctx->cap_q_ctx.buffered = buffered;
}

150 151
void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx);

152
void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb);
153 154 155 156 157 158 159 160

/**
 * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for
 * use
 */
static inline
unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
{
161
	return m2m_ctx->out_q_ctx.num_rdy;
162 163 164 165 166 167 168 169 170
}

/**
 * v4l2_m2m_num_src_bufs_ready() - return the number of destination buffers
 * ready for use
 */
static inline
unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
{
171
	return m2m_ctx->cap_q_ctx.num_rdy;
172 173
}

174
void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx);
175 176 177 178 179 180 181

/**
 * v4l2_m2m_next_src_buf() - return next source buffer from the list of ready
 * buffers
 */
static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx)
{
182
	return v4l2_m2m_next_buf(&m2m_ctx->out_q_ctx);
183 184 185 186 187 188 189 190
}

/**
 * v4l2_m2m_next_dst_buf() - return next destination buffer from the list of
 * ready buffers
 */
static inline void *v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx)
{
191
	return v4l2_m2m_next_buf(&m2m_ctx->cap_q_ctx);
192 193 194
}

/**
195
 * v4l2_m2m_get_src_vq() - return vb2_queue for source buffers
196 197
 */
static inline
198
struct vb2_queue *v4l2_m2m_get_src_vq(struct v4l2_m2m_ctx *m2m_ctx)
199
{
200
	return &m2m_ctx->out_q_ctx.q;
201 202 203
}

/**
204
 * v4l2_m2m_get_dst_vq() - return vb2_queue for destination buffers
205 206
 */
static inline
207
struct vb2_queue *v4l2_m2m_get_dst_vq(struct v4l2_m2m_ctx *m2m_ctx)
208
{
209
	return &m2m_ctx->cap_q_ctx.q;
210 211
}

212
void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx);
213 214 215 216 217 218 219

/**
 * v4l2_m2m_src_buf_remove() - take off a source buffer from the list of ready
 * buffers and return it
 */
static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
{
220
	return v4l2_m2m_buf_remove(&m2m_ctx->out_q_ctx);
221 222 223 224 225 226 227 228
}

/**
 * v4l2_m2m_dst_buf_remove() - take off a destination buffer from the list of
 * ready buffers and return it
 */
static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
{
229
	return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx);
230 231 232 233
}

#endif /* _MEDIA_V4L2_MEM2MEM_H */