diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-07-10 17:03:46 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-04-23 09:20:15 -0400 |
commit | 629bb6d4b38fe62d36ab52ad22c3ab726f6ce6e8 (patch) | |
tree | f826d26c1ecabf02fd1a3d8be8408e1d637e8ae7 | |
parent | d9b45ed3d8b75e8cf38c8cd1563c29217eecba27 (diff) |
[media] v4l: vsp1: Add BRU support
The Blend ROP Unit performs blending and ROP operations for up to four
sources.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/platform/vsp1/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_bru.c | 395 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_bru.h | 39 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drv.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_entity.c | 3 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_entity.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_regs.h | 98 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rpf.c | 6 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rwpf.h | 4 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.c | 19 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_wpf.c | 12 |
13 files changed, 586 insertions, 5 deletions
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 151cecd0ea25..6a93f928dfde 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o | 1 | vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o |
2 | vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o | 2 | vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o |
3 | vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o | 3 | vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o |
4 | vsp1-y += vsp1_sru.o vsp1_uds.o | 4 | vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o | 6 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o |
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 8626e9b956c2..6ca2cf20d545 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h | |||
@@ -28,6 +28,7 @@ struct clk; | |||
28 | struct device; | 28 | struct device; |
29 | 29 | ||
30 | struct vsp1_platform_data; | 30 | struct vsp1_platform_data; |
31 | struct vsp1_bru; | ||
31 | struct vsp1_hsit; | 32 | struct vsp1_hsit; |
32 | struct vsp1_lif; | 33 | struct vsp1_lif; |
33 | struct vsp1_lut; | 34 | struct vsp1_lut; |
@@ -49,6 +50,7 @@ struct vsp1_device { | |||
49 | struct mutex lock; | 50 | struct mutex lock; |
50 | int ref_count; | 51 | int ref_count; |
51 | 52 | ||
53 | struct vsp1_bru *bru; | ||
52 | struct vsp1_hsit *hsi; | 54 | struct vsp1_hsit *hsi; |
53 | struct vsp1_hsit *hst; | 55 | struct vsp1_hsit *hst; |
54 | struct vsp1_lif *lif; | 56 | struct vsp1_lif *lif; |
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c new file mode 100644 index 000000000000..f80695480060 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_bru.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * vsp1_bru.c -- R-Car VSP1 Blend ROP Unit | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/gfp.h> | ||
16 | |||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1.h" | ||
20 | #include "vsp1_bru.h" | ||
21 | |||
22 | #define BRU_MIN_SIZE 4U | ||
23 | #define BRU_MAX_SIZE 8190U | ||
24 | |||
25 | /* ----------------------------------------------------------------------------- | ||
26 | * Device Access | ||
27 | */ | ||
28 | |||
29 | static inline u32 vsp1_bru_read(struct vsp1_bru *bru, u32 reg) | ||
30 | { | ||
31 | return vsp1_read(bru->entity.vsp1, reg); | ||
32 | } | ||
33 | |||
34 | static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) | ||
35 | { | ||
36 | vsp1_write(bru->entity.vsp1, reg, data); | ||
37 | } | ||
38 | |||
39 | /* ----------------------------------------------------------------------------- | ||
40 | * V4L2 Subdevice Core Operations | ||
41 | */ | ||
42 | |||
43 | static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input) | ||
44 | { | ||
45 | return media_entity_remote_pad(&bru->entity.pads[input]) != NULL; | ||
46 | } | ||
47 | |||
48 | static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | ||
49 | { | ||
50 | struct vsp1_bru *bru = to_bru(subdev); | ||
51 | struct v4l2_mbus_framefmt *format; | ||
52 | unsigned int i; | ||
53 | |||
54 | if (!enable) | ||
55 | return 0; | ||
56 | |||
57 | format = &bru->entity.formats[BRU_PAD_SOURCE]; | ||
58 | |||
59 | /* The hardware is extremely flexible but we have no userspace API to | ||
60 | * expose all the parameters, nor is it clear whether we would have use | ||
61 | * cases for all the supported modes. Let's just harcode the parameters | ||
62 | * to sane default values for now. | ||
63 | */ | ||
64 | |||
65 | /* Disable both color data normalization and dithering. */ | ||
66 | vsp1_bru_write(bru, VI6_BRU_INCTRL, 0); | ||
67 | |||
68 | /* Set the background position to cover the whole output image and | ||
69 | * set its color to opaque black. | ||
70 | */ | ||
71 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, | ||
72 | (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | | ||
73 | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); | ||
74 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); | ||
75 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, | ||
76 | 0xff << VI6_BRU_VIRRPF_COL_A_SHIFT); | ||
77 | |||
78 | /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP | ||
79 | * unit with a NOP operation to make BRU input 1 available as the | ||
80 | * Blend/ROP unit B SRC input. | ||
81 | */ | ||
82 | vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | | ||
83 | VI6_BRU_ROP_CROP(VI6_ROP_NOP) | | ||
84 | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); | ||
85 | |||
86 | for (i = 0; i < 4; ++i) { | ||
87 | u32 ctrl = 0; | ||
88 | |||
89 | /* Configure all Blend/ROP units corresponding to an enabled BRU | ||
90 | * input for alpha blending. Blend/ROP units corresponding to | ||
91 | * disabled BRU inputs are used in ROP NOP mode to ignore the | ||
92 | * SRC input. | ||
93 | */ | ||
94 | if (bru_is_input_enabled(bru, i)) | ||
95 | ctrl |= VI6_BRU_CTRL_RBC; | ||
96 | else | ||
97 | ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) | ||
98 | | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); | ||
99 | |||
100 | /* Select the virtual RPF as the Blend/ROP unit A DST input to | ||
101 | * serve as a background color. | ||
102 | */ | ||
103 | if (i == 0) | ||
104 | ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF; | ||
105 | |||
106 | /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to | ||
107 | * D in that order. The Blend/ROP unit B SRC is hardwired to the | ||
108 | * ROP unit output, the corresponding register bits must be set | ||
109 | * to 0. | ||
110 | */ | ||
111 | if (i != 1) | ||
112 | ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); | ||
113 | |||
114 | vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl); | ||
115 | |||
116 | /* Harcode the blending formula to | ||
117 | * | ||
118 | * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa | ||
119 | * DSTa = DSTa * (1 - SRCa) + SRCa | ||
120 | */ | ||
121 | vsp1_bru_write(bru, VI6_BRU_BLD(i), | ||
122 | VI6_BRU_BLD_CCMDX_255_SRC_A | | ||
123 | VI6_BRU_BLD_CCMDY_SRC_A | | ||
124 | VI6_BRU_BLD_ACMDX_255_SRC_A | | ||
125 | VI6_BRU_BLD_ACMDY_COEFY | | ||
126 | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | /* ----------------------------------------------------------------------------- | ||
133 | * V4L2 Subdevice Pad Operations | ||
134 | */ | ||
135 | |||
136 | /* | ||
137 | * The BRU can't perform format conversion, all sink and source formats must be | ||
138 | * identical. We pick the format on the first sink pad (pad 0) and propagate it | ||
139 | * to all other pads. | ||
140 | */ | ||
141 | |||
142 | static int bru_enum_mbus_code(struct v4l2_subdev *subdev, | ||
143 | struct v4l2_subdev_fh *fh, | ||
144 | struct v4l2_subdev_mbus_code_enum *code) | ||
145 | { | ||
146 | static const unsigned int codes[] = { | ||
147 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
148 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
149 | }; | ||
150 | struct v4l2_mbus_framefmt *format; | ||
151 | |||
152 | if (code->pad == BRU_PAD_SINK(0)) { | ||
153 | if (code->index >= ARRAY_SIZE(codes)) | ||
154 | return -EINVAL; | ||
155 | |||
156 | code->code = codes[code->index]; | ||
157 | } else { | ||
158 | if (code->index) | ||
159 | return -EINVAL; | ||
160 | |||
161 | format = v4l2_subdev_get_try_format(fh, BRU_PAD_SINK(0)); | ||
162 | code->code = format->code; | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int bru_enum_frame_size(struct v4l2_subdev *subdev, | ||
169 | struct v4l2_subdev_fh *fh, | ||
170 | struct v4l2_subdev_frame_size_enum *fse) | ||
171 | { | ||
172 | if (fse->index) | ||
173 | return -EINVAL; | ||
174 | |||
175 | if (fse->code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
176 | fse->code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
177 | return -EINVAL; | ||
178 | |||
179 | fse->min_width = BRU_MIN_SIZE; | ||
180 | fse->max_width = BRU_MAX_SIZE; | ||
181 | fse->min_height = BRU_MIN_SIZE; | ||
182 | fse->max_height = BRU_MAX_SIZE; | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, | ||
188 | struct v4l2_subdev_fh *fh, | ||
189 | unsigned int pad, u32 which) | ||
190 | { | ||
191 | switch (which) { | ||
192 | case V4L2_SUBDEV_FORMAT_TRY: | ||
193 | return v4l2_subdev_get_try_crop(fh, pad); | ||
194 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
195 | return &bru->compose[pad]; | ||
196 | default: | ||
197 | return NULL; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
202 | struct v4l2_subdev_format *fmt) | ||
203 | { | ||
204 | struct vsp1_bru *bru = to_bru(subdev); | ||
205 | |||
206 | fmt->format = *vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad, | ||
207 | fmt->which); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_fh *fh, | ||
213 | unsigned int pad, struct v4l2_mbus_framefmt *fmt, | ||
214 | enum v4l2_subdev_format_whence which) | ||
215 | { | ||
216 | struct v4l2_mbus_framefmt *format; | ||
217 | |||
218 | switch (pad) { | ||
219 | case BRU_PAD_SINK(0): | ||
220 | /* Default to YUV if the requested format is not supported. */ | ||
221 | if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
222 | fmt->code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
223 | fmt->code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
224 | break; | ||
225 | |||
226 | default: | ||
227 | /* The BRU can't perform format conversion. */ | ||
228 | format = vsp1_entity_get_pad_format(&bru->entity, fh, | ||
229 | BRU_PAD_SINK(0), which); | ||
230 | fmt->code = format->code; | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE); | ||
235 | fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE); | ||
236 | fmt->field = V4L2_FIELD_NONE; | ||
237 | fmt->colorspace = V4L2_COLORSPACE_SRGB; | ||
238 | } | ||
239 | |||
240 | static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
241 | struct v4l2_subdev_format *fmt) | ||
242 | { | ||
243 | struct vsp1_bru *bru = to_bru(subdev); | ||
244 | struct v4l2_mbus_framefmt *format; | ||
245 | |||
246 | bru_try_format(bru, fh, fmt->pad, &fmt->format, fmt->which); | ||
247 | |||
248 | format = vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad, | ||
249 | fmt->which); | ||
250 | *format = fmt->format; | ||
251 | |||
252 | /* Reset the compose rectangle */ | ||
253 | if (fmt->pad != BRU_PAD_SOURCE) { | ||
254 | struct v4l2_rect *compose; | ||
255 | |||
256 | compose = bru_get_compose(bru, fh, fmt->pad, fmt->which); | ||
257 | compose->left = 0; | ||
258 | compose->top = 0; | ||
259 | compose->width = format->width; | ||
260 | compose->height = format->height; | ||
261 | } | ||
262 | |||
263 | /* Propagate the format code to all pads */ | ||
264 | if (fmt->pad == BRU_PAD_SINK(0)) { | ||
265 | unsigned int i; | ||
266 | |||
267 | for (i = 0; i <= BRU_PAD_SOURCE; ++i) { | ||
268 | format = vsp1_entity_get_pad_format(&bru->entity, fh, | ||
269 | i, fmt->which); | ||
270 | format->code = fmt->format.code; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int bru_get_selection(struct v4l2_subdev *subdev, | ||
278 | struct v4l2_subdev_fh *fh, | ||
279 | struct v4l2_subdev_selection *sel) | ||
280 | { | ||
281 | struct vsp1_bru *bru = to_bru(subdev); | ||
282 | |||
283 | if (sel->pad == BRU_PAD_SOURCE) | ||
284 | return -EINVAL; | ||
285 | |||
286 | switch (sel->target) { | ||
287 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
288 | sel->r.left = 0; | ||
289 | sel->r.top = 0; | ||
290 | sel->r.width = BRU_MAX_SIZE; | ||
291 | sel->r.height = BRU_MAX_SIZE; | ||
292 | return 0; | ||
293 | |||
294 | case V4L2_SEL_TGT_COMPOSE: | ||
295 | sel->r = *bru_get_compose(bru, fh, sel->pad, sel->which); | ||
296 | return 0; | ||
297 | |||
298 | default: | ||
299 | return -EINVAL; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | static int bru_set_selection(struct v4l2_subdev *subdev, | ||
304 | struct v4l2_subdev_fh *fh, | ||
305 | struct v4l2_subdev_selection *sel) | ||
306 | { | ||
307 | struct vsp1_bru *bru = to_bru(subdev); | ||
308 | struct v4l2_mbus_framefmt *format; | ||
309 | struct v4l2_rect *compose; | ||
310 | |||
311 | if (sel->pad == BRU_PAD_SOURCE) | ||
312 | return -EINVAL; | ||
313 | |||
314 | if (sel->target != V4L2_SEL_TGT_COMPOSE) | ||
315 | return -EINVAL; | ||
316 | |||
317 | /* The compose rectangle top left corner must be inside the output | ||
318 | * frame. | ||
319 | */ | ||
320 | format = vsp1_entity_get_pad_format(&bru->entity, fh, BRU_PAD_SOURCE, | ||
321 | sel->which); | ||
322 | sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); | ||
323 | sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); | ||
324 | |||
325 | /* Scaling isn't supported, the compose rectangle size must be identical | ||
326 | * to the sink format size. | ||
327 | */ | ||
328 | format = vsp1_entity_get_pad_format(&bru->entity, fh, sel->pad, | ||
329 | sel->which); | ||
330 | sel->r.width = format->width; | ||
331 | sel->r.height = format->height; | ||
332 | |||
333 | compose = bru_get_compose(bru, fh, sel->pad, sel->which); | ||
334 | *compose = sel->r; | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | /* ----------------------------------------------------------------------------- | ||
340 | * V4L2 Subdevice Operations | ||
341 | */ | ||
342 | |||
343 | static struct v4l2_subdev_video_ops bru_video_ops = { | ||
344 | .s_stream = bru_s_stream, | ||
345 | }; | ||
346 | |||
347 | static struct v4l2_subdev_pad_ops bru_pad_ops = { | ||
348 | .enum_mbus_code = bru_enum_mbus_code, | ||
349 | .enum_frame_size = bru_enum_frame_size, | ||
350 | .get_fmt = bru_get_format, | ||
351 | .set_fmt = bru_set_format, | ||
352 | .get_selection = bru_get_selection, | ||
353 | .set_selection = bru_set_selection, | ||
354 | }; | ||
355 | |||
356 | static struct v4l2_subdev_ops bru_ops = { | ||
357 | .video = &bru_video_ops, | ||
358 | .pad = &bru_pad_ops, | ||
359 | }; | ||
360 | |||
361 | /* ----------------------------------------------------------------------------- | ||
362 | * Initialization and Cleanup | ||
363 | */ | ||
364 | |||
365 | struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) | ||
366 | { | ||
367 | struct v4l2_subdev *subdev; | ||
368 | struct vsp1_bru *bru; | ||
369 | int ret; | ||
370 | |||
371 | bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL); | ||
372 | if (bru == NULL) | ||
373 | return ERR_PTR(-ENOMEM); | ||
374 | |||
375 | bru->entity.type = VSP1_ENTITY_BRU; | ||
376 | |||
377 | ret = vsp1_entity_init(vsp1, &bru->entity, 5); | ||
378 | if (ret < 0) | ||
379 | return ERR_PTR(ret); | ||
380 | |||
381 | /* Initialize the V4L2 subdev. */ | ||
382 | subdev = &bru->entity.subdev; | ||
383 | v4l2_subdev_init(subdev, &bru_ops); | ||
384 | |||
385 | subdev->entity.ops = &vsp1_media_ops; | ||
386 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
387 | snprintf(subdev->name, sizeof(subdev->name), "%s bru", | ||
388 | dev_name(vsp1->dev)); | ||
389 | v4l2_set_subdevdata(subdev, bru); | ||
390 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
391 | |||
392 | vsp1_entity_init_formats(subdev, NULL); | ||
393 | |||
394 | return bru; | ||
395 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h new file mode 100644 index 000000000000..37062704dbf6 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_bru.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * vsp1_bru.h -- R-Car VSP1 Blend ROP Unit | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_BRU_H__ | ||
14 | #define __VSP1_BRU_H__ | ||
15 | |||
16 | #include <media/media-entity.h> | ||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1_entity.h" | ||
20 | |||
21 | struct vsp1_device; | ||
22 | |||
23 | #define BRU_PAD_SINK(n) (n) | ||
24 | #define BRU_PAD_SOURCE 4 | ||
25 | |||
26 | struct vsp1_bru { | ||
27 | struct vsp1_entity entity; | ||
28 | |||
29 | struct v4l2_rect compose[4]; | ||
30 | }; | ||
31 | |||
32 | static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) | ||
33 | { | ||
34 | return container_of(subdev, struct vsp1_bru, entity.subdev); | ||
35 | } | ||
36 | |||
37 | struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1); | ||
38 | |||
39 | #endif /* __VSP1_BRU_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 3cd2df5af90e..28e1de3270e0 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/videodev2.h> | 20 | #include <linux/videodev2.h> |
21 | 21 | ||
22 | #include "vsp1.h" | 22 | #include "vsp1.h" |
23 | #include "vsp1_bru.h" | ||
23 | #include "vsp1_hsit.h" | 24 | #include "vsp1_hsit.h" |
24 | #include "vsp1_lif.h" | 25 | #include "vsp1_lif.h" |
25 | #include "vsp1_lut.h" | 26 | #include "vsp1_lut.h" |
@@ -155,6 +156,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) | |||
155 | } | 156 | } |
156 | 157 | ||
157 | /* Instantiate all the entities. */ | 158 | /* Instantiate all the entities. */ |
159 | vsp1->bru = vsp1_bru_create(vsp1); | ||
160 | if (IS_ERR(vsp1->bru)) { | ||
161 | ret = PTR_ERR(vsp1->bru); | ||
162 | goto done; | ||
163 | } | ||
164 | |||
165 | list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities); | ||
166 | |||
158 | vsp1->hsi = vsp1_hsit_create(vsp1, true); | 167 | vsp1->hsi = vsp1_hsit_create(vsp1, true); |
159 | if (IS_ERR(vsp1->hsi)) { | 168 | if (IS_ERR(vsp1->hsi)) { |
160 | ret = PTR_ERR(vsp1->hsi); | 169 | ret = PTR_ERR(vsp1->hsi); |
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index a9022f858aa5..44167834285d 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c | |||
@@ -119,6 +119,9 @@ const struct media_entity_operations vsp1_media_ops = { | |||
119 | */ | 119 | */ |
120 | 120 | ||
121 | static const struct vsp1_route vsp1_routes[] = { | 121 | static const struct vsp1_route vsp1_routes[] = { |
122 | { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE, | ||
123 | { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1), | ||
124 | VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), } }, | ||
122 | { VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } }, | 125 | { VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } }, |
123 | { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } }, | 126 | { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } }, |
124 | { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } }, | 127 | { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } }, |
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 3c6a5c831bcf..7afbd8a7ba66 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h | |||
@@ -20,6 +20,7 @@ | |||
20 | struct vsp1_device; | 20 | struct vsp1_device; |
21 | 21 | ||
22 | enum vsp1_entity_type { | 22 | enum vsp1_entity_type { |
23 | VSP1_ENTITY_BRU, | ||
23 | VSP1_ENTITY_HSI, | 24 | VSP1_ENTITY_HSI, |
24 | VSP1_ENTITY_HST, | 25 | VSP1_ENTITY_HST, |
25 | VSP1_ENTITY_LIF, | 26 | VSP1_ENTITY_LIF, |
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 28650806c20f..3e74b44286f6 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h | |||
@@ -451,13 +451,111 @@ | |||
451 | * BRU Control Registers | 451 | * BRU Control Registers |
452 | */ | 452 | */ |
453 | 453 | ||
454 | #define VI6_ROP_NOP 0 | ||
455 | #define VI6_ROP_AND 1 | ||
456 | #define VI6_ROP_AND_REV 2 | ||
457 | #define VI6_ROP_COPY 3 | ||
458 | #define VI6_ROP_AND_INV 4 | ||
459 | #define VI6_ROP_CLEAR 5 | ||
460 | #define VI6_ROP_XOR 6 | ||
461 | #define VI6_ROP_OR 7 | ||
462 | #define VI6_ROP_NOR 8 | ||
463 | #define VI6_ROP_EQUIV 9 | ||
464 | #define VI6_ROP_INVERT 10 | ||
465 | #define VI6_ROP_OR_REV 11 | ||
466 | #define VI6_ROP_COPY_INV 12 | ||
467 | #define VI6_ROP_OR_INV 13 | ||
468 | #define VI6_ROP_NAND 14 | ||
469 | #define VI6_ROP_SET 15 | ||
470 | |||
454 | #define VI6_BRU_INCTRL 0x2c00 | 471 | #define VI6_BRU_INCTRL 0x2c00 |
472 | #define VI6_BRU_INCTRL_NRM (1 << 28) | ||
473 | #define VI6_BRU_INCTRL_DnON (1 << (16 + (n))) | ||
474 | #define VI6_BRU_INCTRL_DITHn_OFF (0 << ((n) * 4)) | ||
475 | #define VI6_BRU_INCTRL_DITHn_18BPP (1 << ((n) * 4)) | ||
476 | #define VI6_BRU_INCTRL_DITHn_16BPP (2 << ((n) * 4)) | ||
477 | #define VI6_BRU_INCTRL_DITHn_15BPP (3 << ((n) * 4)) | ||
478 | #define VI6_BRU_INCTRL_DITHn_12BPP (4 << ((n) * 4)) | ||
479 | #define VI6_BRU_INCTRL_DITHn_8BPP (5 << ((n) * 4)) | ||
480 | #define VI6_BRU_INCTRL_DITHn_MASK (7 << ((n) * 4)) | ||
481 | #define VI6_BRU_INCTRL_DITHn_SHIFT ((n) * 4) | ||
482 | |||
455 | #define VI6_BRU_VIRRPF_SIZE 0x2c04 | 483 | #define VI6_BRU_VIRRPF_SIZE 0x2c04 |
484 | #define VI6_BRU_VIRRPF_SIZE_HSIZE_MASK (0x1fff << 16) | ||
485 | #define VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT 16 | ||
486 | #define VI6_BRU_VIRRPF_SIZE_VSIZE_MASK (0x1fff << 0) | ||
487 | #define VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT 0 | ||
488 | |||
456 | #define VI6_BRU_VIRRPF_LOC 0x2c08 | 489 | #define VI6_BRU_VIRRPF_LOC 0x2c08 |
490 | #define VI6_BRU_VIRRPF_LOC_HCOORD_MASK (0x1fff << 16) | ||
491 | #define VI6_BRU_VIRRPF_LOC_HCOORD_SHIFT 16 | ||
492 | #define VI6_BRU_VIRRPF_LOC_VCOORD_MASK (0x1fff << 0) | ||
493 | #define VI6_BRU_VIRRPF_LOC_VCOORD_SHIFT 0 | ||
494 | |||
457 | #define VI6_BRU_VIRRPF_COL 0x2c0c | 495 | #define VI6_BRU_VIRRPF_COL 0x2c0c |
496 | #define VI6_BRU_VIRRPF_COL_A_MASK (0xff << 24) | ||
497 | #define VI6_BRU_VIRRPF_COL_A_SHIFT 24 | ||
498 | #define VI6_BRU_VIRRPF_COL_RCR_MASK (0xff << 16) | ||
499 | #define VI6_BRU_VIRRPF_COL_RCR_SHIFT 16 | ||
500 | #define VI6_BRU_VIRRPF_COL_GY_MASK (0xff << 8) | ||
501 | #define VI6_BRU_VIRRPF_COL_GY_SHIFT 8 | ||
502 | #define VI6_BRU_VIRRPF_COL_BCB_MASK (0xff << 0) | ||
503 | #define VI6_BRU_VIRRPF_COL_BCB_SHIFT 0 | ||
504 | |||
458 | #define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8) | 505 | #define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8) |
506 | #define VI6_BRU_CTRL_RBC (1 << 31) | ||
507 | #define VI6_BRU_CTRL_DSTSEL_BRUIN(n) ((n) << 20) | ||
508 | #define VI6_BRU_CTRL_DSTSEL_VRPF (4 << 20) | ||
509 | #define VI6_BRU_CTRL_DSTSEL_MASK (7 << 20) | ||
510 | #define VI6_BRU_CTRL_SRCSEL_BRUIN(n) ((n) << 16) | ||
511 | #define VI6_BRU_CTRL_SRCSEL_VRPF (4 << 16) | ||
512 | #define VI6_BRU_CTRL_SRCSEL_MASK (7 << 16) | ||
513 | #define VI6_BRU_CTRL_CROP(rop) ((rop) << 4) | ||
514 | #define VI6_BRU_CTRL_CROP_MASK (0xf << 4) | ||
515 | #define VI6_BRU_CTRL_AROP(rop) ((rop) << 0) | ||
516 | #define VI6_BRU_CTRL_AROP_MASK (0xf << 0) | ||
517 | |||
459 | #define VI6_BRU_BLD(n) (0x2c14 + (n) * 8) | 518 | #define VI6_BRU_BLD(n) (0x2c14 + (n) * 8) |
519 | #define VI6_BRU_BLD_CBES (1 << 31) | ||
520 | #define VI6_BRU_BLD_CCMDX_DST_A (0 << 28) | ||
521 | #define VI6_BRU_BLD_CCMDX_255_DST_A (1 << 28) | ||
522 | #define VI6_BRU_BLD_CCMDX_SRC_A (2 << 28) | ||
523 | #define VI6_BRU_BLD_CCMDX_255_SRC_A (3 << 28) | ||
524 | #define VI6_BRU_BLD_CCMDX_COEFX (4 << 28) | ||
525 | #define VI6_BRU_BLD_CCMDX_MASK (7 << 28) | ||
526 | #define VI6_BRU_BLD_CCMDY_DST_A (0 << 24) | ||
527 | #define VI6_BRU_BLD_CCMDY_255_DST_A (1 << 24) | ||
528 | #define VI6_BRU_BLD_CCMDY_SRC_A (2 << 24) | ||
529 | #define VI6_BRU_BLD_CCMDY_255_SRC_A (3 << 24) | ||
530 | #define VI6_BRU_BLD_CCMDY_COEFY (4 << 24) | ||
531 | #define VI6_BRU_BLD_CCMDY_MASK (7 << 24) | ||
532 | #define VI6_BRU_BLD_CCMDY_SHIFT 24 | ||
533 | #define VI6_BRU_BLD_ABES (1 << 23) | ||
534 | #define VI6_BRU_BLD_ACMDX_DST_A (0 << 20) | ||
535 | #define VI6_BRU_BLD_ACMDX_255_DST_A (1 << 20) | ||
536 | #define VI6_BRU_BLD_ACMDX_SRC_A (2 << 20) | ||
537 | #define VI6_BRU_BLD_ACMDX_255_SRC_A (3 << 20) | ||
538 | #define VI6_BRU_BLD_ACMDX_COEFX (4 << 20) | ||
539 | #define VI6_BRU_BLD_ACMDX_MASK (7 << 20) | ||
540 | #define VI6_BRU_BLD_ACMDY_DST_A (0 << 16) | ||
541 | #define VI6_BRU_BLD_ACMDY_255_DST_A (1 << 16) | ||
542 | #define VI6_BRU_BLD_ACMDY_SRC_A (2 << 16) | ||
543 | #define VI6_BRU_BLD_ACMDY_255_SRC_A (3 << 16) | ||
544 | #define VI6_BRU_BLD_ACMDY_COEFY (4 << 16) | ||
545 | #define VI6_BRU_BLD_ACMDY_MASK (7 << 16) | ||
546 | #define VI6_BRU_BLD_COEFX_MASK (0xff << 8) | ||
547 | #define VI6_BRU_BLD_COEFX_SHIFT 8 | ||
548 | #define VI6_BRU_BLD_COEFY_MASK (0xff << 0) | ||
549 | #define VI6_BRU_BLD_COEFY_SHIFT 0 | ||
550 | |||
460 | #define VI6_BRU_ROP 0x2c30 | 551 | #define VI6_BRU_ROP 0x2c30 |
552 | #define VI6_BRU_ROP_DSTSEL_BRUIN(n) ((n) << 20) | ||
553 | #define VI6_BRU_ROP_DSTSEL_VRPF (4 << 20) | ||
554 | #define VI6_BRU_ROP_DSTSEL_MASK (7 << 20) | ||
555 | #define VI6_BRU_ROP_CROP(rop) ((rop) << 4) | ||
556 | #define VI6_BRU_ROP_CROP_MASK (0xf << 4) | ||
557 | #define VI6_BRU_ROP_AROP(rop) ((rop) << 0) | ||
558 | #define VI6_BRU_ROP_AROP_MASK (0xf << 0) | ||
461 | 559 | ||
462 | /* ----------------------------------------------------------------------------- | 560 | /* ----------------------------------------------------------------------------- |
463 | * HGO Control Registers | 561 | * HGO Control Registers |
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 42444568b9fd..c3d98642a4aa 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
@@ -96,8 +96,10 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
96 | vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); | 96 | vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); |
97 | vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); | 97 | vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); |
98 | 98 | ||
99 | /* Output location. Composing isn't supported yet. */ | 99 | /* Output location */ |
100 | vsp1_rpf_write(rpf, VI6_RPF_LOC, 0); | 100 | vsp1_rpf_write(rpf, VI6_RPF_LOC, |
101 | (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | | ||
102 | (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); | ||
101 | 103 | ||
102 | /* Disable alpha, mask and color key. Set the alpha channel to a fixed | 104 | /* Disable alpha, mask and color key. Set the alpha channel to a fixed |
103 | * value of 255. | 105 | * value of 255. |
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 5c5ee81bbeae..b4fb65e58770 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
@@ -30,6 +30,10 @@ struct vsp1_rwpf { | |||
30 | unsigned int max_width; | 30 | unsigned int max_width; |
31 | unsigned int max_height; | 31 | unsigned int max_height; |
32 | 32 | ||
33 | struct { | ||
34 | unsigned int left; | ||
35 | unsigned int top; | ||
36 | } location; | ||
33 | struct v4l2_rect crop; | 37 | struct v4l2_rect crop; |
34 | 38 | ||
35 | unsigned int offsets[2]; | 39 | unsigned int offsets[2]; |
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 1ef875d521da..8a1253e51f04 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <media/videobuf2-dma-contig.h> | 28 | #include <media/videobuf2-dma-contig.h> |
29 | 29 | ||
30 | #include "vsp1.h" | 30 | #include "vsp1.h" |
31 | #include "vsp1_bru.h" | ||
31 | #include "vsp1_entity.h" | 32 | #include "vsp1_entity.h" |
32 | #include "vsp1_rwpf.h" | 33 | #include "vsp1_rwpf.h" |
33 | #include "vsp1_video.h" | 34 | #include "vsp1_video.h" |
@@ -280,6 +281,9 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | |||
280 | struct media_pad *pad; | 281 | struct media_pad *pad; |
281 | bool uds_found = false; | 282 | bool uds_found = false; |
282 | 283 | ||
284 | input->location.left = 0; | ||
285 | input->location.top = 0; | ||
286 | |||
283 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); | 287 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); |
284 | 288 | ||
285 | while (1) { | 289 | while (1) { |
@@ -292,6 +296,17 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | |||
292 | 296 | ||
293 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | 297 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); |
294 | 298 | ||
299 | /* A BRU is present in the pipeline, store the compose rectangle | ||
300 | * location in the input RPF for use when configuring the RPF. | ||
301 | */ | ||
302 | if (entity->type == VSP1_ENTITY_BRU) { | ||
303 | struct vsp1_bru *bru = to_bru(&entity->subdev); | ||
304 | struct v4l2_rect *rect = &bru->compose[pad->index]; | ||
305 | |||
306 | input->location.left = rect->left; | ||
307 | input->location.top = rect->top; | ||
308 | } | ||
309 | |||
295 | /* We've reached the WPF, we're done. */ | 310 | /* We've reached the WPF, we're done. */ |
296 | if (entity->type == VSP1_ENTITY_WPF) | 311 | if (entity->type == VSP1_ENTITY_WPF) |
297 | break; | 312 | break; |
@@ -363,6 +378,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
363 | rwpf->video.pipe_index = 0; | 378 | rwpf->video.pipe_index = 0; |
364 | } else if (e->type == VSP1_ENTITY_LIF) { | 379 | } else if (e->type == VSP1_ENTITY_LIF) { |
365 | pipe->lif = e; | 380 | pipe->lif = e; |
381 | } else if (e->type == VSP1_ENTITY_BRU) { | ||
382 | pipe->bru = e; | ||
366 | } | 383 | } |
367 | } | 384 | } |
368 | 385 | ||
@@ -392,6 +409,7 @@ error: | |||
392 | pipe->num_video = 0; | 409 | pipe->num_video = 0; |
393 | pipe->num_inputs = 0; | 410 | pipe->num_inputs = 0; |
394 | pipe->output = NULL; | 411 | pipe->output = NULL; |
412 | pipe->bru = NULL; | ||
395 | pipe->lif = NULL; | 413 | pipe->lif = NULL; |
396 | return ret; | 414 | return ret; |
397 | } | 415 | } |
@@ -430,6 +448,7 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | |||
430 | pipe->num_video = 0; | 448 | pipe->num_video = 0; |
431 | pipe->num_inputs = 0; | 449 | pipe->num_inputs = 0; |
432 | pipe->output = NULL; | 450 | pipe->output = NULL; |
451 | pipe->bru = NULL; | ||
433 | pipe->lif = NULL; | 452 | pipe->lif = NULL; |
434 | } | 453 | } |
435 | 454 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 53e4b3745940..c04d48fa2999 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h | |||
@@ -75,6 +75,7 @@ struct vsp1_pipeline { | |||
75 | unsigned int num_inputs; | 75 | unsigned int num_inputs; |
76 | struct vsp1_rwpf *inputs[VPS1_MAX_RPF]; | 76 | struct vsp1_rwpf *inputs[VPS1_MAX_RPF]; |
77 | struct vsp1_rwpf *output; | 77 | struct vsp1_rwpf *output; |
78 | struct vsp1_entity *bru; | ||
78 | struct vsp1_entity *lif; | 79 | struct vsp1_entity *lif; |
79 | 80 | ||
80 | struct list_head entities; | 81 | struct list_head entities; |
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index ef9f88ead319..1294340dcb36 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
@@ -58,13 +58,21 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Sources */ | 61 | /* Sources. If the pipeline has a single input configure it as the |
62 | * master layer. Otherwise configure all inputs as sub-layers and | ||
63 | * select the virtual RPF as the master layer. | ||
64 | */ | ||
62 | for (i = 0; i < pipe->num_inputs; ++i) { | 65 | for (i = 0; i < pipe->num_inputs; ++i) { |
63 | struct vsp1_rwpf *input = pipe->inputs[i]; | 66 | struct vsp1_rwpf *input = pipe->inputs[i]; |
64 | 67 | ||
65 | srcrpf |= VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index); | 68 | srcrpf |= pipe->num_inputs == 1 |
69 | ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) | ||
70 | : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); | ||
66 | } | 71 | } |
67 | 72 | ||
73 | if (pipe->num_inputs > 1) | ||
74 | srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; | ||
75 | |||
68 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); | 76 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); |
69 | 77 | ||
70 | /* Destination stride. */ | 78 | /* Destination stride. */ |