scsi: ipr: Fix async error WARN_ON
[cascardo/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_pipe.h"
21 #include "vsp1_rwpf.h"
22 #include "vsp1_video.h"
23
24 #define RPF_MAX_WIDTH                           8190
25 #define RPF_MAX_HEIGHT                          8190
26
27 /* -----------------------------------------------------------------------------
28  * Device Access
29  */
30
31 static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf,
32                                   struct vsp1_dl_list *dl, u32 reg, u32 data)
33 {
34         vsp1_dl_list_write(dl, reg + rpf->entity.index * VI6_RPF_OFFSET, data);
35 }
36
37 /* -----------------------------------------------------------------------------
38  * V4L2 Subdevice Operations
39  */
40
41 static const struct v4l2_subdev_ops rpf_ops = {
42         .pad    = &vsp1_rwpf_pad_ops,
43 };
44
45 /* -----------------------------------------------------------------------------
46  * VSP1 Entity Operations
47  */
48
49 static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
50 {
51         struct vsp1_rwpf *rpf = entity_to_rwpf(entity);
52
53         vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y,
54                        rpf->mem.addr[0] + rpf->offsets[0]);
55         vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0,
56                        rpf->mem.addr[1] + rpf->offsets[1]);
57         vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1,
58                        rpf->mem.addr[2] + rpf->offsets[1]);
59 }
60
61 static void rpf_configure(struct vsp1_entity *entity,
62                           struct vsp1_pipeline *pipe,
63                           struct vsp1_dl_list *dl, bool full)
64 {
65         struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
66         const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
67         const struct v4l2_pix_format_mplane *format = &rpf->format;
68         const struct v4l2_mbus_framefmt *source_format;
69         const struct v4l2_mbus_framefmt *sink_format;
70         const struct v4l2_rect *crop;
71         unsigned int left = 0;
72         unsigned int top = 0;
73         u32 pstride;
74         u32 infmt;
75
76         if (!full) {
77                 vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET,
78                                rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
79                 vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, rpf->mult_alpha |
80                                (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT));
81
82                 vsp1_pipeline_propagate_alpha(pipe, dl, rpf->alpha);
83                 return;
84         }
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         crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config);
93
94         vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
95                        (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
96                        (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
97         vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
98                        (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
99                        (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
100
101         rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline
102                         + crop->left * fmtinfo->bpp[0] / 8;
103         pstride = format->plane_fmt[0].bytesperline
104                 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
105
106         if (format->num_planes > 1) {
107                 rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
108                                 + crop->left * fmtinfo->bpp[1] / 8;
109                 pstride |= format->plane_fmt[1].bytesperline
110                         << VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
111         } else {
112                 rpf->offsets[1] = 0;
113         }
114
115         vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_PSTRIDE, pstride);
116
117         /* Format */
118         sink_format = vsp1_entity_get_pad_format(&rpf->entity,
119                                                  rpf->entity.config,
120                                                  RWPF_PAD_SINK);
121         source_format = vsp1_entity_get_pad_format(&rpf->entity,
122                                                    rpf->entity.config,
123                                                    RWPF_PAD_SOURCE);
124
125         infmt = VI6_RPF_INFMT_CIPM
126               | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT);
127
128         if (fmtinfo->swap_yc)
129                 infmt |= VI6_RPF_INFMT_SPYCS;
130         if (fmtinfo->swap_uv)
131                 infmt |= VI6_RPF_INFMT_SPUVS;
132
133         if (sink_format->code != source_format->code)
134                 infmt |= VI6_RPF_INFMT_CSC;
135
136         vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt);
137         vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
138
139         /* Output location */
140         if (pipe->bru) {
141                 const struct v4l2_rect *compose;
142
143                 compose = vsp1_entity_get_pad_selection(pipe->bru,
144                                                         pipe->bru->config,
145                                                         rpf->bru_input,
146                                                         V4L2_SEL_TGT_COMPOSE);
147                 left = compose->left;
148                 top = compose->top;
149         }
150
151         vsp1_rpf_write(rpf, dl, VI6_RPF_LOC,
152                        (left << VI6_RPF_LOC_HCOORD_SHIFT) |
153                        (top << VI6_RPF_LOC_VCOORD_SHIFT));
154
155         /* On Gen2 use the alpha channel (extended to 8 bits) when available or
156          * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control
157          * otherwise.
158          *
159          * The Gen3 RPF has extended alpha capability and can both multiply the
160          * alpha channel by a fixed global alpha value, and multiply the pixel
161          * components to convert the input to premultiplied alpha.
162          *
163          * As alpha premultiplication is available in the BRU for both Gen2 and
164          * Gen3 we handle it there and use the Gen3 alpha multiplier for global
165          * alpha multiplication only. This however prevents conversion to
166          * premultiplied alpha if no BRU is present in the pipeline. If that use
167          * case turns out to be useful we will revisit the implementation (for
168          * Gen3 only).
169          *
170          * We enable alpha multiplication on Gen3 using the fixed alpha value
171          * set through the V4L2_CID_ALPHA_COMPONENT control when the input
172          * contains an alpha channel. On Gen2 the global alpha is ignored in
173          * that case.
174          *
175          * In all cases, disable color keying.
176          */
177         vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
178                        (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
179                                        : VI6_RPF_ALPH_SEL_ASEL_FIXED));
180
181         if (entity->vsp1->info->gen == 3) {
182                 u32 mult;
183
184                 if (fmtinfo->alpha) {
185                         /* When the input contains an alpha channel enable the
186                          * alpha multiplier. If the input is premultiplied we
187                          * need to multiply both the alpha channel and the pixel
188                          * components by the global alpha value to keep them
189                          * premultiplied. Otherwise multiply the alpha channel
190                          * only.
191                          */
192                         bool premultiplied = format->flags
193                                            & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
194
195                         mult = VI6_RPF_MULT_ALPHA_A_MMD_RATIO
196                              | (premultiplied ?
197                                 VI6_RPF_MULT_ALPHA_P_MMD_RATIO :
198                                 VI6_RPF_MULT_ALPHA_P_MMD_NONE);
199                 } else {
200                         /* When the input doesn't contain an alpha channel the
201                          * global alpha value is applied in the unpacking unit,
202                          * the alpha multiplier isn't needed and must be
203                          * disabled.
204                          */
205                         mult = VI6_RPF_MULT_ALPHA_A_MMD_NONE
206                              | VI6_RPF_MULT_ALPHA_P_MMD_NONE;
207                 }
208
209                 rpf->mult_alpha = mult;
210         }
211
212         vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0);
213         vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0);
214
215 }
216
217 static const struct vsp1_entity_operations rpf_entity_ops = {
218         .set_memory = rpf_set_memory,
219         .configure = rpf_configure,
220 };
221
222 /* -----------------------------------------------------------------------------
223  * Initialization and Cleanup
224  */
225
226 struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
227 {
228         struct vsp1_rwpf *rpf;
229         char name[6];
230         int ret;
231
232         rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL);
233         if (rpf == NULL)
234                 return ERR_PTR(-ENOMEM);
235
236         rpf->max_width = RPF_MAX_WIDTH;
237         rpf->max_height = RPF_MAX_HEIGHT;
238
239         rpf->entity.ops = &rpf_entity_ops;
240         rpf->entity.type = VSP1_ENTITY_RPF;
241         rpf->entity.index = index;
242
243         sprintf(name, "rpf.%u", index);
244         ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops,
245                                MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
246         if (ret < 0)
247                 return ERR_PTR(ret);
248
249         /* Initialize the control handler. */
250         ret = vsp1_rwpf_init_ctrls(rpf, 0);
251         if (ret < 0) {
252                 dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
253                         index);
254                 goto error;
255         }
256
257         v4l2_ctrl_handler_setup(&rpf->ctrls);
258
259         return rpf;
260
261 error:
262         vsp1_entity_destroy(&rpf->entity);
263         return ERR_PTR(ret);
264 }