Skip to content

Commit 894dde5

Browse files
Laurent Pinchartmchehab
authored andcommitted
[media] v4l: vsp1: wpf: Add flipping support
Vertical flipping is available on both Gen2 and Gen3, while horizontal flipping is only available on Gen3. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
1 parent d05a331 commit 894dde5

File tree

7 files changed

+170
-17
lines changed

7 files changed

+170
-17
lines changed

drivers/media/platform/vsp1/vsp1.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ struct vsp1_uds;
4848
#define VSP1_HAS_SRU (1 << 2)
4949
#define VSP1_HAS_BRU (1 << 3)
5050
#define VSP1_HAS_CLU (1 << 4)
51+
#define VSP1_HAS_WPF_VFLIP (1 << 5)
52+
#define VSP1_HAS_WPF_HFLIP (1 << 6)
5153

5254
struct vsp1_device_info {
5355
u32 version;

drivers/media/platform/vsp1/vsp1_drv.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
563563
.version = VI6_IP_VERSION_MODEL_VSPS_H2,
564564
.gen = 2,
565565
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
566-
| VSP1_HAS_SRU,
566+
| VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
567567
.rpf_count = 5,
568568
.uds_count = 3,
569569
.wpf_count = 4,
@@ -572,7 +572,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
572572
}, {
573573
.version = VI6_IP_VERSION_MODEL_VSPR_H2,
574574
.gen = 2,
575-
.features = VSP1_HAS_BRU | VSP1_HAS_SRU,
575+
.features = VSP1_HAS_BRU | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
576576
.rpf_count = 5,
577577
.uds_count = 3,
578578
.wpf_count = 4,
@@ -591,7 +591,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
591591
.version = VI6_IP_VERSION_MODEL_VSPS_M2,
592592
.gen = 2,
593593
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
594-
| VSP1_HAS_SRU,
594+
| VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
595595
.rpf_count = 5,
596596
.uds_count = 1,
597597
.wpf_count = 4,
@@ -600,31 +600,33 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
600600
}, {
601601
.version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
602602
.gen = 3,
603-
.features = VSP1_HAS_CLU | VSP1_HAS_LUT | VSP1_HAS_SRU,
603+
.features = VSP1_HAS_CLU | VSP1_HAS_LUT | VSP1_HAS_SRU
604+
| VSP1_HAS_WPF_HFLIP | VSP1_HAS_WPF_VFLIP,
604605
.rpf_count = 1,
605606
.uds_count = 1,
606607
.wpf_count = 1,
607608
.uapi = true,
608609
}, {
609610
.version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
610611
.gen = 3,
611-
.features = VSP1_HAS_BRU,
612+
.features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
612613
.rpf_count = 5,
613614
.wpf_count = 1,
614615
.num_bru_inputs = 5,
615616
.uapi = true,
616617
}, {
617618
.version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
618619
.gen = 3,
619-
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT,
620+
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
621+
| VSP1_HAS_WPF_VFLIP,
620622
.rpf_count = 5,
621623
.wpf_count = 1,
622624
.num_bru_inputs = 5,
623625
.uapi = true,
624626
}, {
625627
.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
626628
.gen = 3,
627-
.features = VSP1_HAS_BRU | VSP1_HAS_LIF,
629+
.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP,
628630
.rpf_count = 5,
629631
.wpf_count = 2,
630632
.num_bru_inputs = 5,

drivers/media/platform/vsp1/vsp1_regs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@
255255
#define VI6_WPF_OUTFMT_PDV_MASK (0xff << 24)
256256
#define VI6_WPF_OUTFMT_PDV_SHIFT 24
257257
#define VI6_WPF_OUTFMT_PXA (1 << 23)
258+
#define VI6_WPF_OUTFMT_ROT (1 << 18)
259+
#define VI6_WPF_OUTFMT_HFLP (1 << 17)
258260
#define VI6_WPF_OUTFMT_FLP (1 << 16)
259261
#define VI6_WPF_OUTFMT_SPYCS (1 << 15)
260262
#define VI6_WPF_OUTFMT_SPUVS (1 << 14)
@@ -289,6 +291,11 @@
289291
#define VI6_WPF_RNDCTRL_CLMD_EXT (2 << 12)
290292
#define VI6_WPF_RNDCTRL_CLMD_MASK (3 << 12)
291293

294+
#define VI6_WPF_ROT_CTRL 0x1018
295+
#define VI6_WPF_ROT_CTRL_LN16 (1 << 17)
296+
#define VI6_WPF_ROT_CTRL_LMEM_WD_MASK (0x1fff << 0)
297+
#define VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT 0
298+
292299
#define VI6_WPF_DSTM_STRIDE_Y 0x101c
293300
#define VI6_WPF_DSTM_STRIDE_C 0x1020
294301
#define VI6_WPF_DSTM_ADDR_Y 0x1024

drivers/media/platform/vsp1/vsp1_rpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
247247
return ERR_PTR(ret);
248248

249249
/* Initialize the control handler. */
250-
ret = vsp1_rwpf_init_ctrls(rpf);
250+
ret = vsp1_rwpf_init_ctrls(rpf, 0);
251251
if (ret < 0) {
252252
dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
253253
index);

drivers/media/platform/vsp1/vsp1_rwpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ static const struct v4l2_ctrl_ops vsp1_rwpf_ctrl_ops = {
241241
.s_ctrl = vsp1_rwpf_s_ctrl,
242242
};
243243

244-
int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf)
244+
int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols)
245245
{
246-
v4l2_ctrl_handler_init(&rwpf->ctrls, 1);
246+
v4l2_ctrl_handler_init(&rwpf->ctrls, ncontrols + 1);
247247
v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops,
248248
V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
249249

drivers/media/platform/vsp1/vsp1_rwpf.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef __VSP1_RWPF_H__
1414
#define __VSP1_RWPF_H__
1515

16+
#include <linux/spinlock.h>
17+
1618
#include <media/media-entity.h>
1719
#include <media/v4l2-ctrls.h>
1820
#include <media/v4l2-subdev.h>
@@ -52,6 +54,13 @@ struct vsp1_rwpf {
5254
u32 mult_alpha;
5355
u32 outfmt;
5456

57+
struct {
58+
spinlock_t lock;
59+
struct v4l2_ctrl *ctrls[2];
60+
unsigned int pending;
61+
unsigned int active;
62+
} flip;
63+
5564
unsigned int offsets[2];
5665
struct vsp1_rwpf_memory mem;
5766

@@ -71,7 +80,7 @@ static inline struct vsp1_rwpf *entity_to_rwpf(struct vsp1_entity *entity)
7180
struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index);
7281
struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index);
7382

74-
int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf);
83+
int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols);
7584

7685
extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops;
7786

drivers/media/platform/vsp1/vsp1_wpf.c

Lines changed: 139 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,97 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf,
3636
vsp1_dl_list_write(dl, reg + wpf->entity.index * VI6_WPF_OFFSET, data);
3737
}
3838

39+
/* -----------------------------------------------------------------------------
40+
* Controls
41+
*/
42+
43+
enum wpf_flip_ctrl {
44+
WPF_CTRL_VFLIP = 0,
45+
WPF_CTRL_HFLIP = 1,
46+
WPF_CTRL_MAX,
47+
};
48+
49+
static int vsp1_wpf_s_ctrl(struct v4l2_ctrl *ctrl)
50+
{
51+
struct vsp1_rwpf *wpf =
52+
container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
53+
unsigned int i;
54+
u32 flip = 0;
55+
56+
switch (ctrl->id) {
57+
case V4L2_CID_HFLIP:
58+
case V4L2_CID_VFLIP:
59+
for (i = 0; i < WPF_CTRL_MAX; ++i) {
60+
if (wpf->flip.ctrls[i])
61+
flip |= wpf->flip.ctrls[i]->val ? BIT(i) : 0;
62+
}
63+
64+
spin_lock_irq(&wpf->flip.lock);
65+
wpf->flip.pending = flip;
66+
spin_unlock_irq(&wpf->flip.lock);
67+
break;
68+
69+
default:
70+
return -EINVAL;
71+
}
72+
73+
return 0;
74+
}
75+
76+
static const struct v4l2_ctrl_ops vsp1_wpf_ctrl_ops = {
77+
.s_ctrl = vsp1_wpf_s_ctrl,
78+
};
79+
80+
static int wpf_init_controls(struct vsp1_rwpf *wpf)
81+
{
82+
struct vsp1_device *vsp1 = wpf->entity.vsp1;
83+
unsigned int num_flip_ctrls;
84+
85+
spin_lock_init(&wpf->flip.lock);
86+
87+
if (wpf->entity.index != 0) {
88+
/* Only WPF0 supports flipping. */
89+
num_flip_ctrls = 0;
90+
} else if (vsp1->info->features & VSP1_HAS_WPF_HFLIP) {
91+
/* When horizontal flip is supported the WPF implements two
92+
* controls (horizontal flip and vertical flip).
93+
*/
94+
num_flip_ctrls = 2;
95+
} else if (vsp1->info->features & VSP1_HAS_WPF_VFLIP) {
96+
/* When only vertical flip is supported the WPF implements a
97+
* single control (vertical flip).
98+
*/
99+
num_flip_ctrls = 1;
100+
} else {
101+
/* Otherwise flipping is not supported. */
102+
num_flip_ctrls = 0;
103+
}
104+
105+
vsp1_rwpf_init_ctrls(wpf, num_flip_ctrls);
106+
107+
if (num_flip_ctrls >= 1) {
108+
wpf->flip.ctrls[WPF_CTRL_VFLIP] =
109+
v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
110+
V4L2_CID_VFLIP, 0, 1, 1, 0);
111+
}
112+
113+
if (num_flip_ctrls == 2) {
114+
wpf->flip.ctrls[WPF_CTRL_HFLIP] =
115+
v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
116+
V4L2_CID_HFLIP, 0, 1, 1, 0);
117+
118+
v4l2_ctrl_cluster(2, wpf->flip.ctrls);
119+
}
120+
121+
if (wpf->ctrls.error) {
122+
dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
123+
wpf->entity.index);
124+
return wpf->ctrls.error;
125+
}
126+
127+
return 0;
128+
}
129+
39130
/* -----------------------------------------------------------------------------
40131
* V4L2 Subdevice Core Operations
41132
*/
@@ -85,10 +176,32 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity)
85176
static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
86177
{
87178
struct vsp1_rwpf *wpf = entity_to_rwpf(entity);
179+
const struct v4l2_pix_format_mplane *format = &wpf->format;
180+
struct vsp1_rwpf_memory mem = wpf->mem;
181+
unsigned int flip = wpf->flip.active;
182+
unsigned int offset;
183+
184+
/* Update the memory offsets based on flipping configuration. The
185+
* destination addresses point to the locations where the VSP starts
186+
* writing to memory, which can be different corners of the image
187+
* depending on vertical flipping. Horizontal flipping is handled
188+
* through a line buffer and doesn't modify the start address.
189+
*/
190+
if (flip & BIT(WPF_CTRL_VFLIP)) {
191+
mem.addr[0] += (format->height - 1)
192+
* format->plane_fmt[0].bytesperline;
193+
194+
if (format->num_planes > 1) {
195+
offset = (format->height / wpf->fmtinfo->vsub - 1)
196+
* format->plane_fmt[1].bytesperline;
197+
mem.addr[1] += offset;
198+
mem.addr[2] += offset;
199+
}
200+
}
88201

89-
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]);
90-
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]);
91-
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]);
202+
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
203+
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
204+
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
92205
}
93206

94207
static void wpf_configure(struct vsp1_entity *entity,
@@ -105,8 +218,22 @@ static void wpf_configure(struct vsp1_entity *entity,
105218
u32 srcrpf = 0;
106219

107220
if (!full) {
108-
vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, wpf->outfmt |
109-
(wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT));
221+
const unsigned int mask = BIT(WPF_CTRL_VFLIP)
222+
| BIT(WPF_CTRL_HFLIP);
223+
224+
spin_lock(&wpf->flip.lock);
225+
wpf->flip.active = (wpf->flip.active & ~mask)
226+
| (wpf->flip.pending & mask);
227+
spin_unlock(&wpf->flip.lock);
228+
229+
outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt;
230+
231+
if (wpf->flip.active & BIT(WPF_CTRL_VFLIP))
232+
outfmt |= VI6_WPF_OUTFMT_FLP;
233+
if (wpf->flip.active & BIT(WPF_CTRL_HFLIP))
234+
outfmt |= VI6_WPF_OUTFMT_HFLP;
235+
236+
vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
110237
return;
111238
}
112239

@@ -149,6 +276,12 @@ static void wpf_configure(struct vsp1_entity *entity,
149276
format->plane_fmt[1].bytesperline);
150277

151278
vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap);
279+
280+
if (vsp1->info->features & VSP1_HAS_WPF_HFLIP &&
281+
wpf->entity.index == 0)
282+
vsp1_wpf_write(wpf, dl, VI6_WPF_ROT_CTRL,
283+
VI6_WPF_ROT_CTRL_LN16 |
284+
(256 << VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT));
152285
}
153286

154287
if (sink_format->code != source_format->code)
@@ -234,7 +367,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
234367
}
235368

236369
/* Initialize the control handler. */
237-
ret = vsp1_rwpf_init_ctrls(wpf);
370+
ret = wpf_init_controls(wpf);
238371
if (ret < 0) {
239372
dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
240373
index);

0 commit comments

Comments
 (0)