Commit | Line | Data |
---|---|---|
26e0ca22 LP |
1 | /* |
2 | * vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter | |
3 | * | |
8a1edc55 | 4 | * Copyright (C) 2013-2014 Renesas Electronics Corporation |
26e0ca22 LP |
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 | ||
16 | #include <media/v4l2-subdev.h> | |
17 | ||
18 | #include "vsp1.h" | |
ef9621bc | 19 | #include "vsp1_dl.h" |
26e0ca22 LP |
20 | #include "vsp1_rwpf.h" |
21 | #include "vsp1_video.h" | |
22 | ||
23 | #define WPF_MAX_WIDTH 2048 | |
24 | #define WPF_MAX_HEIGHT 2048 | |
25 | ||
26 | /* ----------------------------------------------------------------------------- | |
27 | * Device Access | |
28 | */ | |
29 | ||
26e0ca22 LP |
30 | static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) |
31 | { | |
1517b039 TS |
32 | vsp1_mod_write(&wpf->entity, |
33 | reg + wpf->entity.index * VI6_WPF_OFFSET, data); | |
26e0ca22 LP |
34 | } |
35 | ||
36 | /* ----------------------------------------------------------------------------- | |
37 | * V4L2 Subdevice Core Operations | |
38 | */ | |
39 | ||
40 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | |
41 | { | |
5aeb01ad | 42 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); |
26e0ca22 | 43 | struct vsp1_rwpf *wpf = to_rwpf(subdev); |
26e0ca22 | 44 | struct vsp1_device *vsp1 = wpf->entity.vsp1; |
e5ad37b6 | 45 | const struct v4l2_rect *crop = &wpf->crop; |
26e0ca22 LP |
46 | unsigned int i; |
47 | u32 srcrpf = 0; | |
48 | u32 outfmt = 0; | |
7578c204 | 49 | |
26e0ca22 LP |
50 | if (!enable) { |
51 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); | |
1517b039 TS |
52 | vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + |
53 | VI6_WPF_SRCRPF, 0); | |
26e0ca22 LP |
54 | return 0; |
55 | } | |
56 | ||
5d0beeec TH |
57 | /* Sources. If the pipeline has a single input and BRU is not used, |
58 | * configure it as the master layer. Otherwise configure all | |
59 | * inputs as sub-layers and select the virtual RPF as the master | |
60 | * layer. | |
629bb6d4 | 61 | */ |
5aa2eb3c | 62 | for (i = 0; i < vsp1->info->rpf_count; ++i) { |
26e0ca22 LP |
63 | struct vsp1_rwpf *input = pipe->inputs[i]; |
64 | ||
96bfa6a5 LP |
65 | if (!input) |
66 | continue; | |
67 | ||
5d0beeec | 68 | srcrpf |= (!pipe->bru && pipe->num_inputs == 1) |
629bb6d4 LP |
69 | ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) |
70 | : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); | |
26e0ca22 LP |
71 | } |
72 | ||
5d0beeec | 73 | if (pipe->bru || pipe->num_inputs > 1) |
629bb6d4 LP |
74 | srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; |
75 | ||
26e0ca22 LP |
76 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); |
77 | ||
e5ad37b6 | 78 | /* Destination stride. */ |
26e0ca22 | 79 | if (!pipe->lif) { |
86960eec | 80 | struct v4l2_pix_format_mplane *format = &wpf->format; |
26e0ca22 LP |
81 | |
82 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, | |
83 | format->plane_fmt[0].bytesperline); | |
84 | if (format->num_planes > 1) | |
85 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, | |
86 | format->plane_fmt[1].bytesperline); | |
87 | } | |
88 | ||
e5ad37b6 LP |
89 | vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | |
90 | (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) | | |
91 | (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT)); | |
92 | vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | | |
93 | (crop->top << VI6_WPF_SZCLIP_OFST_SHIFT) | | |
94 | (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT)); | |
26e0ca22 LP |
95 | |
96 | /* Format */ | |
97 | if (!pipe->lif) { | |
86960eec | 98 | const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; |
26e0ca22 LP |
99 | |
100 | outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; | |
101 | ||
7a52b6de LP |
102 | if (fmtinfo->alpha) |
103 | outfmt |= VI6_WPF_OUTFMT_PXA; | |
26e0ca22 LP |
104 | if (fmtinfo->swap_yc) |
105 | outfmt |= VI6_WPF_OUTFMT_SPYCS; | |
106 | if (fmtinfo->swap_uv) | |
107 | outfmt |= VI6_WPF_OUTFMT_SPUVS; | |
108 | ||
109 | vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); | |
110 | } | |
111 | ||
112 | if (wpf->entity.formats[RWPF_PAD_SINK].code != | |
113 | wpf->entity.formats[RWPF_PAD_SOURCE].code) | |
114 | outfmt |= VI6_WPF_OUTFMT_CSC; | |
115 | ||
bd2fdd5a | 116 | outfmt |= wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT; |
26e0ca22 LP |
117 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); |
118 | ||
1517b039 TS |
119 | vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index), |
120 | VI6_DPR_WPF_FPORCH_FP_WPFN); | |
26e0ca22 | 121 | |
1517b039 | 122 | vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0); |
26e0ca22 LP |
123 | |
124 | /* Enable interrupts */ | |
125 | vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0); | |
126 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), | |
127 | VI6_WFP_IRQ_ENB_FREE); | |
128 | ||
129 | return 0; | |
130 | } | |
131 | ||
132 | /* ----------------------------------------------------------------------------- | |
133 | * V4L2 Subdevice Operations | |
134 | */ | |
135 | ||
136 | static struct v4l2_subdev_video_ops wpf_video_ops = { | |
137 | .s_stream = wpf_s_stream, | |
138 | }; | |
139 | ||
140 | static struct v4l2_subdev_pad_ops wpf_pad_ops = { | |
0efdf0f5 | 141 | .init_cfg = vsp1_entity_init_cfg, |
26e0ca22 LP |
142 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, |
143 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | |
144 | .get_fmt = vsp1_rwpf_get_format, | |
145 | .set_fmt = vsp1_rwpf_set_format, | |
e5ad37b6 LP |
146 | .get_selection = vsp1_rwpf_get_selection, |
147 | .set_selection = vsp1_rwpf_set_selection, | |
26e0ca22 LP |
148 | }; |
149 | ||
150 | static struct v4l2_subdev_ops wpf_ops = { | |
151 | .video = &wpf_video_ops, | |
152 | .pad = &wpf_pad_ops, | |
153 | }; | |
154 | ||
155 | /* ----------------------------------------------------------------------------- | |
52434534 | 156 | * VSP1 Entity Operations |
26e0ca22 LP |
157 | */ |
158 | ||
52434534 | 159 | static void vsp1_wpf_destroy(struct vsp1_entity *entity) |
26e0ca22 | 160 | { |
52434534 LP |
161 | struct vsp1_rwpf *wpf = entity_to_rwpf(entity); |
162 | ||
163 | vsp1_dlm_destroy(wpf->dlm); | |
164 | } | |
165 | ||
166 | static void wpf_set_memory(struct vsp1_entity *entity) | |
167 | { | |
168 | struct vsp1_rwpf *wpf = entity_to_rwpf(entity); | |
169 | ||
351bbf99 LP |
170 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); |
171 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); | |
172 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); | |
26e0ca22 LP |
173 | } |
174 | ||
52434534 LP |
175 | static const struct vsp1_entity_operations wpf_entity_ops = { |
176 | .destroy = vsp1_wpf_destroy, | |
b58faa95 | 177 | .set_memory = wpf_set_memory, |
26e0ca22 LP |
178 | }; |
179 | ||
180 | /* ----------------------------------------------------------------------------- | |
181 | * Initialization and Cleanup | |
182 | */ | |
183 | ||
184 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |
185 | { | |
26e0ca22 | 186 | struct vsp1_rwpf *wpf; |
823329df | 187 | char name[6]; |
26e0ca22 LP |
188 | int ret; |
189 | ||
190 | wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); | |
191 | if (wpf == NULL) | |
192 | return ERR_PTR(-ENOMEM); | |
193 | ||
194 | wpf->max_width = WPF_MAX_WIDTH; | |
195 | wpf->max_height = WPF_MAX_HEIGHT; | |
196 | ||
52434534 | 197 | wpf->entity.ops = &wpf_entity_ops; |
26e0ca22 LP |
198 | wpf->entity.type = VSP1_ENTITY_WPF; |
199 | wpf->entity.index = index; | |
26e0ca22 | 200 | |
823329df LP |
201 | sprintf(name, "wpf.%u", index); |
202 | ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops); | |
26e0ca22 LP |
203 | if (ret < 0) |
204 | return ERR_PTR(ret); | |
205 | ||
351bbf99 LP |
206 | /* Initialize the display list manager. */ |
207 | wpf->dlm = vsp1_dlm_create(vsp1, index, 4); | |
208 | if (!wpf->dlm) { | |
209 | ret = -ENOMEM; | |
210 | goto error; | |
ef9621bc LP |
211 | } |
212 | ||
7578c204 | 213 | /* Initialize the control handler. */ |
bd2fdd5a LP |
214 | ret = vsp1_rwpf_init_ctrls(wpf); |
215 | if (ret < 0) { | |
7578c204 LP |
216 | dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", |
217 | index); | |
7578c204 LP |
218 | goto error; |
219 | } | |
220 | ||
26e0ca22 LP |
221 | return wpf; |
222 | ||
1499be67 LP |
223 | error: |
224 | vsp1_entity_destroy(&wpf->entity); | |
26e0ca22 LP |
225 | return ERR_PTR(ret); |
226 | } |