Skip to content

Commit 501802e

Browse files
Michael RieschHans Verkuil
authored andcommitted
media: rockchip: rkcif: add abstraction for dma blocks
Add an abstraction for the DMA parts and the ping-pong scheme (a double-buffering mechanism) of the different CIF variants. Each stream is represented as V4L2 device whose corresponding media entity has one sink pad. This sink pad is connected to an instance of the INTERFACE/CROP abstraction. Tested-by: Gerald Loacker <gerald.loacker@wolfvision.net> Reviewed-by: Gerald Loacker <gerald.loacker@wolfvision.net> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com> Signed-off-by: Michael Riesch <michael.riesch@collabora.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> [hverkuil: dropped deprecated vb2_ops_wait_prepare/finish callbacks]
1 parent 85411d1 commit 501802e

5 files changed

Lines changed: 773 additions & 0 deletions

File tree

drivers/media/platform/rockchip/rkcif/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_CIF) += rockchip-cif.o
33

44
rockchip-cif-objs += rkcif-dev.o
55
rockchip-cif-objs += rkcif-interface.o
6+
rockchip-cif-objs += rkcif-stream.o

drivers/media/platform/rockchip/rkcif/rkcif-common.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ enum rkcif_format_type {
3333
RKCIF_FMT_TYPE_RAW,
3434
};
3535

36+
enum rkcif_id_index {
37+
RKCIF_ID0,
38+
RKCIF_ID1,
39+
RKCIF_ID2,
40+
RKCIF_ID3,
41+
RKCIF_ID_MAX
42+
};
43+
3644
enum rkcif_interface_index {
3745
RKCIF_DVP,
3846
RKCIF_MIPI_BASE,
@@ -63,13 +71,32 @@ enum rkcif_interface_type {
6371
RKCIF_IF_MIPI,
6472
};
6573

74+
struct rkcif_buffer {
75+
struct vb2_v4l2_buffer vb;
76+
struct list_head queue;
77+
dma_addr_t buff_addr[VIDEO_MAX_PLANES];
78+
bool is_dummy;
79+
};
80+
81+
struct rkcif_dummy_buffer {
82+
struct rkcif_buffer buffer;
83+
void *vaddr;
84+
u32 size;
85+
};
86+
6687
struct rkcif_input_fmt {
6788
u32 mbus_code;
6889

6990
enum rkcif_format_type fmt_type;
7091
enum v4l2_field field;
7192
};
7293

94+
struct rkcif_output_fmt {
95+
u32 fourcc;
96+
u32 mbus_code;
97+
u8 cplanes;
98+
};
99+
73100
struct rkcif_interface;
74101

75102
struct rkcif_remote {
@@ -79,6 +106,42 @@ struct rkcif_remote {
79106
struct rkcif_interface *interface;
80107
};
81108

109+
struct rkcif_stream {
110+
enum rkcif_id_index id;
111+
struct rkcif_device *rkcif;
112+
struct rkcif_interface *interface;
113+
const struct rkcif_output_fmt *out_fmts;
114+
unsigned int out_fmts_num;
115+
116+
/* in ping-pong mode, two buffers can be provided to the HW */
117+
struct rkcif_buffer *buffers[2];
118+
int frame_idx;
119+
int frame_phase;
120+
121+
/* in case of no available buffer, HW can write to the dummy buffer */
122+
struct rkcif_dummy_buffer dummy;
123+
124+
bool stopping;
125+
wait_queue_head_t wq_stopped;
126+
127+
/* queue of available buffers plus spinlock that protects it */
128+
spinlock_t driver_queue_lock;
129+
struct list_head driver_queue;
130+
131+
/* lock used by the V4L2 core */
132+
struct mutex vlock;
133+
134+
struct media_pad pad;
135+
struct media_pipeline pipeline;
136+
struct v4l2_pix_format_mplane pix;
137+
struct vb2_queue buf_queue;
138+
struct video_device vdev;
139+
140+
void (*queue_buffer)(struct rkcif_stream *stream, unsigned int index);
141+
int (*start_streaming)(struct rkcif_stream *stream);
142+
void (*stop_streaming)(struct rkcif_stream *stream);
143+
};
144+
82145
struct rkcif_dvp {
83146
u32 dvp_clk_delay;
84147
};
@@ -89,6 +152,8 @@ struct rkcif_interface {
89152
enum rkcif_interface_index index;
90153
struct rkcif_device *rkcif;
91154
struct rkcif_remote *remote;
155+
struct rkcif_stream streams[RKCIF_ID_MAX];
156+
unsigned int streams_num;
92157
const struct rkcif_input_fmt *in_fmts;
93158
unsigned int in_fmts_num;
94159

@@ -99,6 +164,8 @@ struct rkcif_interface {
99164
union {
100165
struct rkcif_dvp dvp;
101166
};
167+
168+
void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
102169
};
103170

104171
struct rkcif_match_data {

drivers/media/platform/rockchip/rkcif/rkcif-interface.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,41 @@ static int rkcif_interface_set_routing(struct v4l2_subdev *sd,
157157
if (ret)
158158
return ret;
159159

160+
for (unsigned int i = 0; i < routing->num_routes; i++) {
161+
const struct v4l2_subdev_route *route = &routing->routes[i];
162+
163+
if (route->source_stream >= RKCIF_ID_MAX)
164+
return -EINVAL;
165+
}
166+
160167
ret = v4l2_subdev_set_routing(sd, state, routing);
161168

162169
return ret;
163170
}
164171

172+
static int rkcif_interface_apply_crop(struct rkcif_stream *stream,
173+
struct v4l2_subdev_state *state)
174+
{
175+
struct rkcif_interface *interface = stream->interface;
176+
struct v4l2_rect *crop;
177+
178+
crop = v4l2_subdev_state_get_crop(state, RKCIF_IF_PAD_SRC, stream->id);
179+
if (!crop)
180+
return -EINVAL;
181+
182+
if (interface->set_crop)
183+
interface->set_crop(stream, crop->left, crop->top);
184+
185+
return 0;
186+
}
187+
165188
static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
166189
struct v4l2_subdev_state *state,
167190
u32 pad, u64 streams_mask)
168191
{
192+
struct rkcif_interface *interface = to_rkcif_interface(sd);
193+
struct rkcif_stream *stream;
194+
struct v4l2_subdev_route *route;
169195
struct v4l2_subdev *remote_sd;
170196
struct media_pad *remote_pad;
171197
u64 mask;
@@ -174,6 +200,17 @@ static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
174200
media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]);
175201
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
176202

203+
/* DVP has one crop setting for all IDs */
204+
if (interface->type == RKCIF_IF_DVP) {
205+
stream = &interface->streams[RKCIF_ID0];
206+
rkcif_interface_apply_crop(stream, state);
207+
} else {
208+
for_each_active_route(&state->routing, route) {
209+
stream = &interface->streams[route->sink_stream];
210+
rkcif_interface_apply_crop(stream, state);
211+
}
212+
}
213+
177214
mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
178215
RKCIF_IF_PAD_SRC, &streams_mask);
179216

0 commit comments

Comments
 (0)