[media] v4l: vsp1: Remove unused module read functions
[deliverable/linux.git] / drivers / media / platform / vsp1 / vsp1_rpf.c
1 /*
2 * vsp1_rpf.c -- R-Car VSP1 Read Pixel Formatter
3 *
4 * Copyright (C) 2013-2014 Renesas Electronics 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
16 #include <media/v4l2-subdev.h>
17
18 #include "vsp1.h"
19 #include "vsp1_rwpf.h"
20 #include "vsp1_video.h"
21
22 #define RPF_MAX_WIDTH 8190
23 #define RPF_MAX_HEIGHT 8190
24
25 /* -----------------------------------------------------------------------------
26 * Device Access
27 */
28
29 static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data)
30 {
31 vsp1_write(rpf->entity.vsp1,
32 reg + rpf->entity.index * VI6_RPF_OFFSET, data);
33 }
34
35 /* -----------------------------------------------------------------------------
36 * Controls
37 */
38
39 static int rpf_s_ctrl(struct v4l2_ctrl *ctrl)
40 {
41 struct vsp1_rwpf *rpf =
42 container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
43 struct vsp1_pipeline *pipe;
44
45 if (!vsp1_entity_is_streaming(&rpf->entity))
46 return 0;
47
48 switch (ctrl->id) {
49 case V4L2_CID_ALPHA_COMPONENT:
50 vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
51 ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
52
53 pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity);
54 vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val);
55 break;
56 }
57
58 return 0;
59 }
60
61 static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
62 .s_ctrl = rpf_s_ctrl,
63 };
64
65 /* -----------------------------------------------------------------------------
66 * V4L2 Subdevice Core Operations
67 */
68
69 static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
70 {
71 struct vsp1_rwpf *rpf = to_rwpf(subdev);
72 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
73 const struct v4l2_pix_format_mplane *format = &rpf->format;
74 const struct v4l2_rect *crop = &rpf->crop;
75 u32 pstride;
76 u32 infmt;
77 int ret;
78
79 ret = vsp1_entity_set_streaming(&rpf->entity, enable);
80 if (ret < 0)
81 return ret;
82
83 if (!enable)
84 return 0;
85
86 /* Source size, stride and crop offsets.
87 *
88 * The crop offsets correspond to the location of the crop rectangle top
89 * left corner in the plane buffer. Only two offsets are needed, as
90 * planes 2 and 3 always have identical strides.
91 */
92 vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE,
93 (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
94 (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
95 vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE,
96 (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
97 (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
98
99 rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline
100 + crop->left * fmtinfo->bpp[0] / 8;
101 pstride = format->plane_fmt[0].bytesperline
102 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
103
104 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
105 rpf->buf_addr[0] + rpf->offsets[0]);
106
107 if (format->num_planes > 1) {
108 rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
109 + crop->left * fmtinfo->bpp[1] / 8;
110 pstride |= format->plane_fmt[1].bytesperline
111 << VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
112
113 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
114 rpf->buf_addr[1] + rpf->offsets[1]);
115
116 if (format->num_planes > 2)
117 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
118 rpf->buf_addr[2] + rpf->offsets[1]);
119 }
120
121 vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride);
122
123 /* Format */
124 infmt = VI6_RPF_INFMT_CIPM
125 | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT);
126
127 if (fmtinfo->swap_yc)
128 infmt |= VI6_RPF_INFMT_SPYCS;
129 if (fmtinfo->swap_uv)
130 infmt |= VI6_RPF_INFMT_SPUVS;
131
132 if (rpf->entity.formats[RWPF_PAD_SINK].code !=
133 rpf->entity.formats[RWPF_PAD_SOURCE].code)
134 infmt |= VI6_RPF_INFMT_CSC;
135
136 vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt);
137 vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap);
138
139 /* Output location */
140 vsp1_rpf_write(rpf, VI6_RPF_LOC,
141 (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) |
142 (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT));
143
144 /* Use the alpha channel (extended to 8 bits) when available or an
145 * alpha value set through the V4L2_CID_ALPHA_COMPONENT control
146 * otherwise. Disable color keying.
147 */
148 vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
149 (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
150 : VI6_RPF_ALPH_SEL_ASEL_FIXED));
151 vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);
152 vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0);
153
154 return 0;
155 }
156
157 /* -----------------------------------------------------------------------------
158 * V4L2 Subdevice Operations
159 */
160
161 static struct v4l2_subdev_video_ops rpf_video_ops = {
162 .s_stream = rpf_s_stream,
163 };
164
165 static struct v4l2_subdev_pad_ops rpf_pad_ops = {
166 .enum_mbus_code = vsp1_rwpf_enum_mbus_code,
167 .enum_frame_size = vsp1_rwpf_enum_frame_size,
168 .get_fmt = vsp1_rwpf_get_format,
169 .set_fmt = vsp1_rwpf_set_format,
170 .get_selection = vsp1_rwpf_get_selection,
171 .set_selection = vsp1_rwpf_set_selection,
172 };
173
174 static struct v4l2_subdev_ops rpf_ops = {
175 .video = &rpf_video_ops,
176 .pad = &rpf_pad_ops,
177 };
178
179 /* -----------------------------------------------------------------------------
180 * Video Device Operations
181 */
182
183 static void rpf_set_memory(struct vsp1_rwpf *rpf, struct vsp1_rwpf_memory *mem)
184 {
185 unsigned int i;
186
187 for (i = 0; i < 3; ++i)
188 rpf->buf_addr[i] = mem->addr[i];
189
190 if (!vsp1_entity_is_streaming(&rpf->entity))
191 return;
192
193 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
194 mem->addr[0] + rpf->offsets[0]);
195 if (mem->num_planes > 1)
196 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
197 mem->addr[1] + rpf->offsets[1]);
198 if (mem->num_planes > 2)
199 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
200 mem->addr[2] + rpf->offsets[1]);
201 }
202
203 static const struct vsp1_rwpf_operations rpf_vdev_ops = {
204 .set_memory = rpf_set_memory,
205 };
206
207 /* -----------------------------------------------------------------------------
208 * Initialization and Cleanup
209 */
210
211 struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
212 {
213 struct v4l2_subdev *subdev;
214 struct vsp1_rwpf *rpf;
215 int ret;
216
217 rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL);
218 if (rpf == NULL)
219 return ERR_PTR(-ENOMEM);
220
221 rpf->ops = &rpf_vdev_ops;
222
223 rpf->max_width = RPF_MAX_WIDTH;
224 rpf->max_height = RPF_MAX_HEIGHT;
225
226 rpf->entity.type = VSP1_ENTITY_RPF;
227 rpf->entity.index = index;
228
229 ret = vsp1_entity_init(vsp1, &rpf->entity, 2);
230 if (ret < 0)
231 return ERR_PTR(ret);
232
233 /* Initialize the V4L2 subdev. */
234 subdev = &rpf->entity.subdev;
235 v4l2_subdev_init(subdev, &rpf_ops);
236
237 subdev->entity.ops = &vsp1_media_ops;
238 subdev->internal_ops = &vsp1_subdev_internal_ops;
239 snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u",
240 dev_name(vsp1->dev), index);
241 v4l2_set_subdevdata(subdev, rpf);
242 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
243
244 vsp1_entity_init_formats(subdev, NULL);
245
246 /* Initialize the control handler. */
247 v4l2_ctrl_handler_init(&rpf->ctrls, 1);
248 v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
249 0, 255, 1, 255);
250
251 rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
252
253 if (rpf->ctrls.error) {
254 dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
255 index);
256 ret = rpf->ctrls.error;
257 goto error;
258 }
259
260 return rpf;
261
262 error:
263 vsp1_entity_destroy(&rpf->entity);
264 return ERR_PTR(ret);
265 }
This page took 0.040305 seconds and 5 git commands to generate.