aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/platform/s5p-fimc/fimc-lite.h
blob: 7085761f8c4b11d427a7db4a45a17ade57454f6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
 *
 * 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.
 */

#ifndef FIMC_LITE_H_
#define FIMC_LITE_H_

#include <linux/sizes.h>
#include <linux/io.h>
#include <linux/irqreturn.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/videodev2.h>

#include <media/media-entity.h>
#include <media/videobuf2-core.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
#include <media/s5p_fimc.h>

#include "fimc-core.h"

#define FIMC_LITE_DRV_NAME	"exynos-fimc-lite"
#define FLITE_CLK_NAME		"flite"
#define FIMC_LITE_MAX_DEVS	2
#define FLITE_REQ_BUFS_MIN	2

/* Bit index definitions for struct fimc_lite::state */
enum {
	ST_FLITE_LPM,
	ST_FLITE_PENDING,
	ST_FLITE_RUN,
	ST_FLITE_STREAM,
	ST_FLITE_SUSPENDED,
	ST_FLITE_OFF,
	ST_FLITE_IN_USE,
	ST_FLITE_CONFIG,
	ST_SENSOR_STREAM,
};

#define FLITE_SD_PAD_SINK	0
#define FLITE_SD_PAD_SOURCE_DMA	1
#define FLITE_SD_PAD_SOURCE_ISP	2
#define FLITE_SD_PADS_NUM	3

struct flite_variant {
	unsigned short max_width;
	unsigned short max_height;
	unsigned short out_width_align;
	unsigned short win_hor_offs_align;
	unsigned short out_hor_offs_align;
};

struct flite_drvdata {
	struct flite_variant *variant[FIMC_LITE_MAX_DEVS];
};

#define fimc_lite_get_drvdata(_pdev) \
	((struct flite_drvdata *) platform_get_device_id(_pdev)->driver_data)

struct fimc_lite_events {
	unsigned int data_overflow;
};

#define FLITE_MAX_PLANES	1

/**
 * struct flite_frame - source/target frame properties
 * @f_width: full pixel width
 * @f_height: full pixel height
 * @rect: crop/composition rectangle
 */
struct flite_frame {
	u16 f_width;
	u16 f_height;
	struct v4l2_rect rect;
};

/**
 * struct flite_buffer - video buffer structure
 * @vb:    vb2 buffer
 * @list:  list head for the buffers queue
 * @paddr: precalculated physical address
 */
struct flite_buffer {
	struct vb2_buffer vb;
	struct list_head list;
	dma_addr_t paddr;
};

/**
 * struct fimc_lite - fimc lite structure
 * @pdev: pointer to FIMC-LITE platform device
 * @variant: variant information for this IP
 * @v4l2_dev: pointer to top the level v4l2_device
 * @vfd: video device node
 * @fh: v4l2 file handle
 * @alloc_ctx: videobuf2 memory allocator context
 * @subdev: FIMC-LITE subdev
 * @vd_pad: media (sink) pad for the capture video node
 * @subdev_pads: the subdev media pads
 * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS
 * @ctrl_handler: v4l2 control handler
 * @test_pattern: test pattern controls
 * @index: FIMC-LITE platform device index
 * @pipeline: video capture pipeline data structure
 * @pipeline_ops: media pipeline ops for the video node driver
 * @slock: spinlock protecting this data structure and the hw registers
 * @lock: mutex serializing video device and the subdev operations
 * @clock: FIMC-LITE gate clock
 * @regs: memory mapped io registers
 * @irq_queue: interrupt handler waitqueue
 * @fmt: pointer to color format description structure
 * @payload: image size in bytes (w x h x bpp)
 * @inp_frame: camera input frame structure
 * @out_frame: DMA output frame structure
 * @out_path: output data path (DMA or FIFO)
 * @source_subdev_grp_id: source subdev group id
 * @state: driver state flags
 * @pending_buf_q: pending buffers queue head
 * @active_buf_q: the queue head of buffers scheduled in hardware
 * @vb_queue: vb2 buffers queue
 * @active_buf_count: number of video buffers scheduled in hardware
 * @frame_count: the captured frames counter
 * @reqbufs_count: the number of buffers requested with REQBUFS ioctl
 * @ref_count: driver's private reference counter
 */
struct fimc_lite {
	struct platform_device	*pdev;
	struct flite_variant	*variant;
	struct v4l2_device	*v4l2_dev;
	struct video_device	vfd;
	struct v4l2_fh		fh;
	struct vb2_alloc_ctx	*alloc_ctx;
	struct v4l2_subdev	subdev;
	struct media_pad	vd_pad;
	struct media_pad	subdev_pads[FLITE_SD_PADS_NUM];
	struct v4l2_subdev	*sensor;
	struct v4l2_ctrl_handler ctrl_handler;
	struct v4l2_ctrl	*test_pattern;
	u32			index;
	struct fimc_pipeline	pipeline;
	const struct fimc_pipeline_ops *pipeline_ops;

	struct mutex		lock;
	spinlock_t		slock;

	struct clk		*clock;
	void __iomem		*regs;
	wait_queue_head_t	irq_queue;

	const struct fimc_fmt	*fmt;
	unsigned long		payload[FLITE_MAX_PLANES];
	struct flite_frame	inp_frame;
	struct flite_frame	out_frame;
	atomic_t		out_path;
	unsigned int		source_subdev_grp_id;

	unsigned long		state;
	struct list_head	pending_buf_q;
	struct list_head	active_buf_q;
	struct vb2_queue	vb_queue;
	unsigned int		frame_count;
	unsigned int		reqbufs_count;
	int			ref_count;

	struct fimc_lite_events	events;
};

static inline bool fimc_lite_active(struct fimc_lite *fimc)
{
	unsigned long flags;
	bool ret;

	spin_lock_irqsave(&fimc->slock, flags);
	ret = fimc->state & (1 << ST_FLITE_RUN) ||
		fimc->state & (1 << ST_FLITE_PENDING);
	spin_unlock_irqrestore(&fimc->slock, flags);
	return ret;
}

static inline void fimc_lite_active_queue_add(struct fimc_lite *dev,
					 struct flite_buffer *buf)
{
	list_add_tail(&buf->list, &dev->active_buf_q);
}

static inline struct flite_buffer *fimc_lite_active_queue_pop(
					struct fimc_lite *dev)
{
	struct flite_buffer *buf = list_entry(dev->active_buf_q.next,
					      struct flite_buffer, list);
	list_del(&buf->list);
	return buf;
}

static inline void fimc_lite_pending_queue_add(struct fimc_lite *dev,
					struct flite_buffer *buf)
{
	list_add_tail(&buf->list, &dev->pending_buf_q);
}

static inline struct flite_buffer *fimc_lite_pending_queue_pop(
					struct fimc_lite *dev)
{
	struct flite_buffer *buf = list_entry(dev->pending_buf_q.next,
					      struct flite_buffer, list);
	list_del(&buf->list);
	return buf;
}

#endif /* FIMC_LITE_H_ */