e7b6abbb00244d216ad9c6bf5e4ef3d3a0351a0e
[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_dl.h"
20 #include "vsp1_rwpf.h"
21 #include "vsp1_video.h"
22
23 #define RPF_MAX_WIDTH 8190
24 #define RPF_MAX_HEIGHT 8190
25
26 /* -----------------------------------------------------------------------------
27 * Device Access
28 */
29
30 static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf,
31 struct vsp1_dl_list *dl, u32 reg, u32 data)
32 {
33 vsp1_dl_list_write(dl, reg + rpf->entity.index * VI6_RPF_OFFSET, data);
34 }
35
36 /* -----------------------------------------------------------------------------
37 * V4L2 Subdevice Operations
38 */
39
40 static struct v4l2_subdev_ops rpf_ops = {
41 .pad = &vsp1_rwpf_pad_ops,
42 };
43
44 /* -----------------------------------------------------------------------------
45 * VSP1 Entity Operations
46 */
47
48 static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
49 {
50 struct vsp1_rwpf *rpf = entity_to_rwpf(entity);
51
52 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y,
53 rpf->mem.addr[0] + rpf->offsets[0]);
54 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0,
55 rpf->mem.addr[1] + rpf->offsets[1]);
56 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1,
57 rpf->mem.addr[2] + rpf->offsets[1]);
58 }
59
60 static void rpf_configure(struct vsp1_entity *entity,
61 struct vsp1_pipeline *pipe,
62 struct vsp1_dl_list *dl)
63 {
64 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
65 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
66 const struct v4l2_pix_format_mplane *format = &rpf->format;
67 const struct v4l2_mbus_framefmt *source_format;
68 const struct v4l2_mbus_framefmt *sink_format;
69 const struct v4l2_rect *crop;
70 unsigned int left = 0;
71 unsigned int top = 0;
72 u32 pstride;
73 u32 infmt;
74
75 /* Source size, stride and crop offsets.
76 *
77 * The crop offsets correspond to the location of the crop rectangle top
78 * left corner in the plane buffer. Only two offsets are needed, as
79 * planes 2 and 3 always have identical strides.
80 */
81 crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config);
82
83 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
84 (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
85 (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
86 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
87 (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
88 (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
89
90 rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline
91 + crop->left * fmtinfo->bpp[0] / 8;
92 pstride = format->plane_fmt[0].bytesperline
93 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
94
95 if (format->num_planes > 1) {
96 rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
97 + crop->left * fmtinfo->bpp[1] / 8;
98 pstride |= format->plane_fmt[1].bytesperline
99 << VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
100 } else {
101 rpf->offsets[1] = 0;
102 }
103
104 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_PSTRIDE, pstride);
105
106 /* Format */
107 sink_format = vsp1_entity_get_pad_format(&rpf->entity,
108 rpf->entity.config,
109 RWPF_PAD_SINK);
110 source_format = vsp1_entity_get_pad_format(&rpf->entity,
111 rpf->entity.config,
112 RWPF_PAD_SOURCE);
113
114 infmt = VI6_RPF_INFMT_CIPM
115 | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT);
116
117 if (fmtinfo->swap_yc)
118 infmt |= VI6_RPF_INFMT_SPYCS;
119 if (fmtinfo->swap_uv)
120 infmt |= VI6_RPF_INFMT_SPUVS;
121
122 if (sink_format->code != source_format->code)
123 infmt |= VI6_RPF_INFMT_CSC;
124
125 vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt);
126 vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
127
128 /* Output location */
129 if (pipe->bru) {
130 const struct v4l2_rect *compose;
131
132 compose = vsp1_entity_get_pad_compose(pipe->bru,
133 pipe->bru->config,
134 rpf->bru_input);
135 left = compose->left;
136 top = compose->top;
137 }
138
139 vsp1_rpf_write(rpf, dl, VI6_RPF_LOC,
140 (left << VI6_RPF_LOC_HCOORD_SHIFT) |
141 (top << VI6_RPF_LOC_VCOORD_SHIFT));
142
143 /* Use the alpha channel (extended to 8 bits) when available or an
144 * alpha value set through the V4L2_CID_ALPHA_COMPONENT control
145 * otherwise. Disable color keying.
146 */
147 vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
148 (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
149 : VI6_RPF_ALPH_SEL_ASEL_FIXED));
150
151 vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET,
152 rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
153
154 vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, dl, rpf->alpha);
155
156 vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0);
157 vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0);
158 }
159
160 static const struct vsp1_entity_operations rpf_entity_ops = {
161 .set_memory = rpf_set_memory,
162 .configure = rpf_configure,
163 };
164
165 /* -----------------------------------------------------------------------------
166 * Initialization and Cleanup
167 */
168
169 struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
170 {
171 struct vsp1_rwpf *rpf;
172 char name[6];
173 int ret;
174
175 rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL);
176 if (rpf == NULL)
177 return ERR_PTR(-ENOMEM);
178
179 rpf->max_width = RPF_MAX_WIDTH;
180 rpf->max_height = RPF_MAX_HEIGHT;
181
182 rpf->entity.ops = &rpf_entity_ops;
183 rpf->entity.type = VSP1_ENTITY_RPF;
184 rpf->entity.index = index;
185
186 sprintf(name, "rpf.%u", index);
187 ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops);
188 if (ret < 0)
189 return ERR_PTR(ret);
190
191 /* Initialize the control handler. */
192 ret = vsp1_rwpf_init_ctrls(rpf);
193 if (ret < 0) {
194 dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
195 index);
196 goto error;
197 }
198
199 return rpf;
200
201 error:
202 vsp1_entity_destroy(&rpf->entity);
203 return ERR_PTR(ret);
204 }
This page took 0.065783 seconds and 5 git commands to generate.