diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2016-05-26 04:14:22 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2016-06-28 11:42:43 -0400 |
commit | 894dde5c5d1c6d33c4bd3d4384c6cf0aff3f8015 (patch) | |
tree | 7ff18ad4a641508512aefd84f13547cdecac071a | |
parent | d05a331029d31836053a934365056616b0142898 (diff) |
[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>
-rw-r--r-- | drivers/media/platform/vsp1/vsp1.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drv.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_regs.h | 7 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rpf.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rwpf.c | 4 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rwpf.h | 11 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_wpf.c | 145 |
7 files changed, 170 insertions, 17 deletions
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 8713a437076d..06a2ec7e5ad4 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h | |||
@@ -48,6 +48,8 @@ struct vsp1_uds; | |||
48 | #define VSP1_HAS_SRU (1 << 2) | 48 | #define VSP1_HAS_SRU (1 << 2) |
49 | #define VSP1_HAS_BRU (1 << 3) | 49 | #define VSP1_HAS_BRU (1 << 3) |
50 | #define VSP1_HAS_CLU (1 << 4) | 50 | #define VSP1_HAS_CLU (1 << 4) |
51 | #define VSP1_HAS_WPF_VFLIP (1 << 5) | ||
52 | #define VSP1_HAS_WPF_HFLIP (1 << 6) | ||
51 | 53 | ||
52 | struct vsp1_device_info { | 54 | struct vsp1_device_info { |
53 | u32 version; | 55 | u32 version; |
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 769b19edb146..e1377ffe3d68 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
@@ -563,7 +563,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
563 | .version = VI6_IP_VERSION_MODEL_VSPS_H2, | 563 | .version = VI6_IP_VERSION_MODEL_VSPS_H2, |
564 | .gen = 2, | 564 | .gen = 2, |
565 | .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT | 565 | .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT |
566 | | VSP1_HAS_SRU, | 566 | | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP, |
567 | .rpf_count = 5, | 567 | .rpf_count = 5, |
568 | .uds_count = 3, | 568 | .uds_count = 3, |
569 | .wpf_count = 4, | 569 | .wpf_count = 4, |
@@ -572,7 +572,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
572 | }, { | 572 | }, { |
573 | .version = VI6_IP_VERSION_MODEL_VSPR_H2, | 573 | .version = VI6_IP_VERSION_MODEL_VSPR_H2, |
574 | .gen = 2, | 574 | .gen = 2, |
575 | .features = VSP1_HAS_BRU | VSP1_HAS_SRU, | 575 | .features = VSP1_HAS_BRU | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP, |
576 | .rpf_count = 5, | 576 | .rpf_count = 5, |
577 | .uds_count = 3, | 577 | .uds_count = 3, |
578 | .wpf_count = 4, | 578 | .wpf_count = 4, |
@@ -591,7 +591,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
591 | .version = VI6_IP_VERSION_MODEL_VSPS_M2, | 591 | .version = VI6_IP_VERSION_MODEL_VSPS_M2, |
592 | .gen = 2, | 592 | .gen = 2, |
593 | .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT | 593 | .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT |
594 | | VSP1_HAS_SRU, | 594 | | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP, |
595 | .rpf_count = 5, | 595 | .rpf_count = 5, |
596 | .uds_count = 1, | 596 | .uds_count = 1, |
597 | .wpf_count = 4, | 597 | .wpf_count = 4, |
@@ -600,7 +600,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
600 | }, { | 600 | }, { |
601 | .version = VI6_IP_VERSION_MODEL_VSPI_GEN3, | 601 | .version = VI6_IP_VERSION_MODEL_VSPI_GEN3, |
602 | .gen = 3, | 602 | .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, | ||
604 | .rpf_count = 1, | 605 | .rpf_count = 1, |
605 | .uds_count = 1, | 606 | .uds_count = 1, |
606 | .wpf_count = 1, | 607 | .wpf_count = 1, |
@@ -608,7 +609,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
608 | }, { | 609 | }, { |
609 | .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3, | 610 | .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3, |
610 | .gen = 3, | 611 | .gen = 3, |
611 | .features = VSP1_HAS_BRU, | 612 | .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP, |
612 | .rpf_count = 5, | 613 | .rpf_count = 5, |
613 | .wpf_count = 1, | 614 | .wpf_count = 1, |
614 | .num_bru_inputs = 5, | 615 | .num_bru_inputs = 5, |
@@ -616,7 +617,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
616 | }, { | 617 | }, { |
617 | .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3, | 618 | .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3, |
618 | .gen = 3, | 619 | .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, | ||
620 | .rpf_count = 5, | 622 | .rpf_count = 5, |
621 | .wpf_count = 1, | 623 | .wpf_count = 1, |
622 | .num_bru_inputs = 5, | 624 | .num_bru_inputs = 5, |
@@ -624,7 +626,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { | |||
624 | }, { | 626 | }, { |
625 | .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, | 627 | .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, |
626 | .gen = 3, | 628 | .gen = 3, |
627 | .features = VSP1_HAS_BRU | VSP1_HAS_LIF, | 629 | .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP, |
628 | .rpf_count = 5, | 630 | .rpf_count = 5, |
629 | .wpf_count = 2, | 631 | .wpf_count = 2, |
630 | .num_bru_inputs = 5, | 632 | .num_bru_inputs = 5, |
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index dea0bc471108..3b03007ba625 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h | |||
@@ -255,6 +255,8 @@ | |||
255 | #define VI6_WPF_OUTFMT_PDV_MASK (0xff << 24) | 255 | #define VI6_WPF_OUTFMT_PDV_MASK (0xff << 24) |
256 | #define VI6_WPF_OUTFMT_PDV_SHIFT 24 | 256 | #define VI6_WPF_OUTFMT_PDV_SHIFT 24 |
257 | #define VI6_WPF_OUTFMT_PXA (1 << 23) | 257 | #define VI6_WPF_OUTFMT_PXA (1 << 23) |
258 | #define VI6_WPF_OUTFMT_ROT (1 << 18) | ||
259 | #define VI6_WPF_OUTFMT_HFLP (1 << 17) | ||
258 | #define VI6_WPF_OUTFMT_FLP (1 << 16) | 260 | #define VI6_WPF_OUTFMT_FLP (1 << 16) |
259 | #define VI6_WPF_OUTFMT_SPYCS (1 << 15) | 261 | #define VI6_WPF_OUTFMT_SPYCS (1 << 15) |
260 | #define VI6_WPF_OUTFMT_SPUVS (1 << 14) | 262 | #define VI6_WPF_OUTFMT_SPUVS (1 << 14) |
@@ -289,6 +291,11 @@ | |||
289 | #define VI6_WPF_RNDCTRL_CLMD_EXT (2 << 12) | 291 | #define VI6_WPF_RNDCTRL_CLMD_EXT (2 << 12) |
290 | #define VI6_WPF_RNDCTRL_CLMD_MASK (3 << 12) | 292 | #define VI6_WPF_RNDCTRL_CLMD_MASK (3 << 12) |
291 | 293 | ||
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 | |||
292 | #define VI6_WPF_DSTM_STRIDE_Y 0x101c | 299 | #define VI6_WPF_DSTM_STRIDE_Y 0x101c |
293 | #define VI6_WPF_DSTM_STRIDE_C 0x1020 | 300 | #define VI6_WPF_DSTM_STRIDE_C 0x1020 |
294 | #define VI6_WPF_DSTM_ADDR_Y 0x1024 | 301 | #define VI6_WPF_DSTM_ADDR_Y 0x1024 |
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 4258c7208877..388838913205 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
@@ -247,7 +247,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
247 | return ERR_PTR(ret); | 247 | return ERR_PTR(ret); |
248 | 248 | ||
249 | /* Initialize the control handler. */ | 249 | /* Initialize the control handler. */ |
250 | ret = vsp1_rwpf_init_ctrls(rpf); | 250 | ret = vsp1_rwpf_init_ctrls(rpf, 0); |
251 | if (ret < 0) { | 251 | if (ret < 0) { |
252 | dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n", | 252 | dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n", |
253 | index); | 253 | index); |
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index cd3562d1d9cf..8d461b375e91 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c | |||
@@ -241,9 +241,9 @@ static const struct v4l2_ctrl_ops vsp1_rwpf_ctrl_ops = { | |||
241 | .s_ctrl = vsp1_rwpf_s_ctrl, | 241 | .s_ctrl = vsp1_rwpf_s_ctrl, |
242 | }; | 242 | }; |
243 | 243 | ||
244 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf) | 244 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols) |
245 | { | 245 | { |
246 | v4l2_ctrl_handler_init(&rwpf->ctrls, 1); | 246 | v4l2_ctrl_handler_init(&rwpf->ctrls, ncontrols + 1); |
247 | v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops, | 247 | v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops, |
248 | V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); | 248 | V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); |
249 | 249 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 801cacc12e07..cb20484e80da 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
@@ -13,6 +13,8 @@ | |||
13 | #ifndef __VSP1_RWPF_H__ | 13 | #ifndef __VSP1_RWPF_H__ |
14 | #define __VSP1_RWPF_H__ | 14 | #define __VSP1_RWPF_H__ |
15 | 15 | ||
16 | #include <linux/spinlock.h> | ||
17 | |||
16 | #include <media/media-entity.h> | 18 | #include <media/media-entity.h> |
17 | #include <media/v4l2-ctrls.h> | 19 | #include <media/v4l2-ctrls.h> |
18 | #include <media/v4l2-subdev.h> | 20 | #include <media/v4l2-subdev.h> |
@@ -52,6 +54,13 @@ struct vsp1_rwpf { | |||
52 | u32 mult_alpha; | 54 | u32 mult_alpha; |
53 | u32 outfmt; | 55 | u32 outfmt; |
54 | 56 | ||
57 | struct { | ||
58 | spinlock_t lock; | ||
59 | struct v4l2_ctrl *ctrls[2]; | ||
60 | unsigned int pending; | ||
61 | unsigned int active; | ||
62 | } flip; | ||
63 | |||
55 | unsigned int offsets[2]; | 64 | unsigned int offsets[2]; |
56 | struct vsp1_rwpf_memory mem; | 65 | struct vsp1_rwpf_memory mem; |
57 | 66 | ||
@@ -71,7 +80,7 @@ static inline struct vsp1_rwpf *entity_to_rwpf(struct vsp1_entity *entity) | |||
71 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); | 80 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); |
72 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); | 81 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); |
73 | 82 | ||
74 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf); | 83 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols); |
75 | 84 | ||
76 | extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops; | 85 | extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops; |
77 | 86 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 9385bc703dcd..31983169c24a 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
@@ -37,6 +37,97 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, | |||
37 | } | 37 | } |
38 | 38 | ||
39 | /* ----------------------------------------------------------------------------- | 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 | |||
130 | /* ----------------------------------------------------------------------------- | ||
40 | * V4L2 Subdevice Core Operations | 131 | * V4L2 Subdevice Core Operations |
41 | */ | 132 | */ |
42 | 133 | ||
@@ -85,10 +176,32 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) | |||
85 | static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) | 176 | static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) |
86 | { | 177 | { |
87 | struct vsp1_rwpf *wpf = entity_to_rwpf(entity); | 178 | 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 | } | ||
88 | 201 | ||
89 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); | 202 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]); |
90 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); | 203 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]); |
91 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); | 204 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]); |
92 | } | 205 | } |
93 | 206 | ||
94 | static void wpf_configure(struct vsp1_entity *entity, | 207 | static void wpf_configure(struct vsp1_entity *entity, |
@@ -105,8 +218,22 @@ static void wpf_configure(struct vsp1_entity *entity, | |||
105 | u32 srcrpf = 0; | 218 | u32 srcrpf = 0; |
106 | 219 | ||
107 | if (!full) { | 220 | if (!full) { |
108 | vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, wpf->outfmt | | 221 | const unsigned int mask = BIT(WPF_CTRL_VFLIP) |
109 | (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT)); | 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); | ||
110 | return; | 237 | return; |
111 | } | 238 | } |
112 | 239 | ||
@@ -149,6 +276,12 @@ static void wpf_configure(struct vsp1_entity *entity, | |||
149 | format->plane_fmt[1].bytesperline); | 276 | format->plane_fmt[1].bytesperline); |
150 | 277 | ||
151 | vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap); | 278 | 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)); | ||
152 | } | 285 | } |
153 | 286 | ||
154 | if (sink_format->code != source_format->code) | 287 | if (sink_format->code != source_format->code) |
@@ -234,7 +367,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
234 | } | 367 | } |
235 | 368 | ||
236 | /* Initialize the control handler. */ | 369 | /* Initialize the control handler. */ |
237 | ret = vsp1_rwpf_init_ctrls(wpf); | 370 | ret = wpf_init_controls(wpf); |
238 | if (ret < 0) { | 371 | if (ret < 0) { |
239 | dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", | 372 | dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", |
240 | index); | 373 | index); |