Merge tag 'mvebu-fixes-3.19' of git://git.infradead.org/linux-mvebu into fixes
[cascardo/linux.git] / drivers / media / platform / vivid / vivid-vid-common.c
1 /*
2  * vivid-vid-common.c - common video support functions.
3  *
4  * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5  *
6  * This program is free software; you may redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17  * SOFTWARE.
18  */
19
20 #include <linux/errno.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/videodev2.h>
24 #include <linux/v4l2-dv-timings.h>
25 #include <media/v4l2-common.h>
26 #include <media/v4l2-event.h>
27 #include <media/v4l2-dv-timings.h>
28
29 #include "vivid-core.h"
30 #include "vivid-vid-common.h"
31
32 const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
33         .type = V4L2_DV_BT_656_1120,
34         /* keep this initialization for compatibility with GCC < 4.4.6 */
35         .reserved = { 0 },
36         V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 25000000, 600000000,
37                 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT,
38                 V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
39 };
40
41 /* ------------------------------------------------------------------
42         Basic structures
43    ------------------------------------------------------------------*/
44
45 struct vivid_fmt vivid_formats[] = {
46         {
47                 .name     = "4:2:2, packed, YUYV",
48                 .fourcc   = V4L2_PIX_FMT_YUYV,
49                 .depth    = 16,
50                 .is_yuv   = true,
51                 .planes   = 1,
52                 .data_offset = { PLANE0_DATA_OFFSET, 0 },
53         },
54         {
55                 .name     = "4:2:2, packed, UYVY",
56                 .fourcc   = V4L2_PIX_FMT_UYVY,
57                 .depth    = 16,
58                 .is_yuv   = true,
59                 .planes   = 1,
60         },
61         {
62                 .name     = "4:2:2, packed, YVYU",
63                 .fourcc   = V4L2_PIX_FMT_YVYU,
64                 .depth    = 16,
65                 .is_yuv   = true,
66                 .planes   = 1,
67         },
68         {
69                 .name     = "4:2:2, packed, VYUY",
70                 .fourcc   = V4L2_PIX_FMT_VYUY,
71                 .depth    = 16,
72                 .is_yuv   = true,
73                 .planes   = 1,
74         },
75         {
76                 .name     = "RGB565 (LE)",
77                 .fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
78                 .depth    = 16,
79                 .planes   = 1,
80                 .can_do_overlay = true,
81         },
82         {
83                 .name     = "RGB565 (BE)",
84                 .fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
85                 .depth    = 16,
86                 .planes   = 1,
87                 .can_do_overlay = true,
88         },
89         {
90                 .name     = "RGB555 (LE)",
91                 .fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
92                 .depth    = 16,
93                 .planes   = 1,
94                 .can_do_overlay = true,
95         },
96         {
97                 .name     = "XRGB555 (LE)",
98                 .fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
99                 .depth    = 16,
100                 .planes   = 1,
101                 .can_do_overlay = true,
102         },
103         {
104                 .name     = "ARGB555 (LE)",
105                 .fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
106                 .depth    = 16,
107                 .planes   = 1,
108                 .can_do_overlay = true,
109                 .alpha_mask = 0x8000,
110         },
111         {
112                 .name     = "RGB555 (BE)",
113                 .fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
114                 .depth    = 16,
115                 .planes   = 1,
116                 .can_do_overlay = true,
117         },
118         {
119                 .name     = "RGB24 (LE)",
120                 .fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
121                 .depth    = 24,
122                 .planes   = 1,
123         },
124         {
125                 .name     = "RGB24 (BE)",
126                 .fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
127                 .depth    = 24,
128                 .planes   = 1,
129         },
130         {
131                 .name     = "RGB32 (LE)",
132                 .fourcc   = V4L2_PIX_FMT_RGB32, /* argb */
133                 .depth    = 32,
134                 .planes   = 1,
135         },
136         {
137                 .name     = "RGB32 (BE)",
138                 .fourcc   = V4L2_PIX_FMT_BGR32, /* bgra */
139                 .depth    = 32,
140                 .planes   = 1,
141         },
142         {
143                 .name     = "XRGB32 (LE)",
144                 .fourcc   = V4L2_PIX_FMT_XRGB32, /* argb */
145                 .depth    = 32,
146                 .planes   = 1,
147         },
148         {
149                 .name     = "XRGB32 (BE)",
150                 .fourcc   = V4L2_PIX_FMT_XBGR32, /* bgra */
151                 .depth    = 32,
152                 .planes   = 1,
153         },
154         {
155                 .name     = "ARGB32 (LE)",
156                 .fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
157                 .depth    = 32,
158                 .planes   = 1,
159                 .alpha_mask = 0x000000ff,
160         },
161         {
162                 .name     = "ARGB32 (BE)",
163                 .fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
164                 .depth    = 32,
165                 .planes   = 1,
166                 .alpha_mask = 0xff000000,
167         },
168         {
169                 .name     = "4:2:2, planar, YUV",
170                 .fourcc   = V4L2_PIX_FMT_NV16M,
171                 .depth    = 8,
172                 .is_yuv   = true,
173                 .planes   = 2,
174                 .data_offset = { PLANE0_DATA_OFFSET, 0 },
175         },
176         {
177                 .name     = "4:2:2, planar, YVU",
178                 .fourcc   = V4L2_PIX_FMT_NV61M,
179                 .depth    = 8,
180                 .is_yuv   = true,
181                 .planes   = 2,
182                 .data_offset = { 0, PLANE0_DATA_OFFSET },
183         },
184 };
185
186 /* There are 2 multiplanar formats in the list */
187 #define VIVID_MPLANAR_FORMATS 2
188
189 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
190 {
191         const struct vivid_fmt *fmt;
192         unsigned k;
193
194         for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
195                 fmt = &vivid_formats[k];
196                 if (fmt->fourcc == pixelformat)
197                         if (fmt->planes == 1 || dev->multiplanar)
198                                 return fmt;
199         }
200
201         return NULL;
202 }
203
204 bool vivid_vid_can_loop(struct vivid_dev *dev)
205 {
206         if (dev->src_rect.width != dev->sink_rect.width ||
207             dev->src_rect.height != dev->sink_rect.height)
208                 return false;
209         if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
210                 return false;
211         if (dev->field_cap != dev->field_out)
212                 return false;
213         if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
214                 if (!(dev->std_cap & V4L2_STD_525_60) !=
215                     !(dev->std_out & V4L2_STD_525_60))
216                         return false;
217                 return true;
218         }
219         if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
220                 return true;
221         return false;
222 }
223
224 void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
225 {
226         struct v4l2_event ev = {
227                 .type = V4L2_EVENT_SOURCE_CHANGE,
228                 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
229         };
230         unsigned i;
231
232         for (i = 0; i < dev->num_inputs; i++) {
233                 ev.id = i;
234                 if (dev->input_type[i] == type) {
235                         if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
236                                 v4l2_event_queue(&dev->vid_cap_dev, &ev);
237                         if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
238                                 v4l2_event_queue(&dev->vbi_cap_dev, &ev);
239                 }
240         }
241 }
242
243 /*
244  * Conversion function that converts a single-planar format to a
245  * single-plane multiplanar format.
246  */
247 void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
248 {
249         struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
250         struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
251         const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
252         bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
253
254         memset(mp->reserved, 0, sizeof(mp->reserved));
255         mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
256                            V4L2_CAP_VIDEO_CAPTURE_MPLANE;
257         mp->width = pix->width;
258         mp->height = pix->height;
259         mp->pixelformat = pix->pixelformat;
260         mp->field = pix->field;
261         mp->colorspace = pix->colorspace;
262         mp->ycbcr_enc = pix->ycbcr_enc;
263         mp->quantization = pix->quantization;
264         mp->num_planes = 1;
265         mp->flags = pix->flags;
266         ppix->sizeimage = pix->sizeimage;
267         ppix->bytesperline = pix->bytesperline;
268         memset(ppix->reserved, 0, sizeof(ppix->reserved));
269 }
270
271 int fmt_sp2mp_func(struct file *file, void *priv,
272                 struct v4l2_format *f, fmtfunc func)
273 {
274         struct v4l2_format fmt;
275         struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
276         struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
277         struct v4l2_pix_format *pix = &f->fmt.pix;
278         int ret;
279
280         /* Converts to a mplane format */
281         fmt_sp2mp(f, &fmt);
282         /* Passes it to the generic mplane format function */
283         ret = func(file, priv, &fmt);
284         /* Copies back the mplane data to the single plane format */
285         pix->width = mp->width;
286         pix->height = mp->height;
287         pix->pixelformat = mp->pixelformat;
288         pix->field = mp->field;
289         pix->colorspace = mp->colorspace;
290         pix->ycbcr_enc = mp->ycbcr_enc;
291         pix->quantization = mp->quantization;
292         pix->sizeimage = ppix->sizeimage;
293         pix->bytesperline = ppix->bytesperline;
294         pix->flags = mp->flags;
295         return ret;
296 }
297
298 /* v4l2_rect helper function: copy the width/height values */
299 void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size)
300 {
301         r->width = size->width;
302         r->height = size->height;
303 }
304
305 /* v4l2_rect helper function: width and height of r should be >= min_size */
306 void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size)
307 {
308         if (r->width < min_size->width)
309                 r->width = min_size->width;
310         if (r->height < min_size->height)
311                 r->height = min_size->height;
312 }
313
314 /* v4l2_rect helper function: width and height of r should be <= max_size */
315 void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size)
316 {
317         if (r->width > max_size->width)
318                 r->width = max_size->width;
319         if (r->height > max_size->height)
320                 r->height = max_size->height;
321 }
322
323 /* v4l2_rect helper function: r should be inside boundary */
324 void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary)
325 {
326         rect_set_max_size(r, boundary);
327         if (r->left < boundary->left)
328                 r->left = boundary->left;
329         if (r->top < boundary->top)
330                 r->top = boundary->top;
331         if (r->left + r->width > boundary->width)
332                 r->left = boundary->width - r->width;
333         if (r->top + r->height > boundary->height)
334                 r->top = boundary->height - r->height;
335 }
336
337 /* v4l2_rect helper function: return true if r1 has the same size as r2 */
338 bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
339 {
340         return r1->width == r2->width && r1->height == r2->height;
341 }
342
343 /* v4l2_rect helper function: calculate the intersection of two rects */
344 struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b)
345 {
346         struct v4l2_rect r;
347         int right, bottom;
348
349         r.top = max(a->top, b->top);
350         r.left = max(a->left, b->left);
351         bottom = min(a->top + a->height, b->top + b->height);
352         right = min(a->left + a->width, b->left + b->width);
353         r.height = max(0, bottom - r.top);
354         r.width = max(0, right - r.left);
355         return r;
356 }
357
358 /*
359  * v4l2_rect helper function: scale rect r by to->width / from->width and
360  * to->height / from->height.
361  */
362 void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from,
363                                      const struct v4l2_rect *to)
364 {
365         if (from->width == 0 || from->height == 0) {
366                 r->left = r->top = r->width = r->height = 0;
367                 return;
368         }
369         r->left = (((r->left - from->left) * to->width) / from->width) & ~1;
370         r->width = ((r->width * to->width) / from->width) & ~1;
371         r->top = ((r->top - from->top) * to->height) / from->height;
372         r->height = (r->height * to->height) / from->height;
373 }
374
375 bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
376 {
377         /*
378          * IF the left side of r1 is to the right of the right side of r2 OR
379          *    the left side of r2 is to the right of the right side of r1 THEN
380          * they do not overlap.
381          */
382         if (r1->left >= r2->left + r2->width ||
383             r2->left >= r1->left + r1->width)
384                 return false;
385         /*
386          * IF the top side of r1 is below the bottom of r2 OR
387          *    the top side of r2 is below the bottom of r1 THEN
388          * they do not overlap.
389          */
390         if (r1->top >= r2->top + r2->height ||
391             r2->top >= r1->top + r1->height)
392                 return false;
393         return true;
394 }
395 int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
396 {
397         unsigned w = r->width;
398         unsigned h = r->height;
399
400         if (!(flags & V4L2_SEL_FLAG_LE)) {
401                 w++;
402                 h++;
403                 if (w < 2)
404                         w = 2;
405                 if (h < 2)
406                         h = 2;
407         }
408         if (!(flags & V4L2_SEL_FLAG_GE)) {
409                 if (w > MAX_WIDTH)
410                         w = MAX_WIDTH;
411                 if (h > MAX_HEIGHT)
412                         h = MAX_HEIGHT;
413         }
414         w = w & ~1;
415         h = h & ~1;
416         if (w < 2 || h < 2)
417                 return -ERANGE;
418         if (w > MAX_WIDTH || h > MAX_HEIGHT)
419                 return -ERANGE;
420         if (r->top < 0)
421                 r->top = 0;
422         if (r->left < 0)
423                 r->left = 0;
424         r->left &= ~1;
425         r->top &= ~1;
426         if (r->left + w > MAX_WIDTH)
427                 r->left = MAX_WIDTH - w;
428         if (r->top + h > MAX_HEIGHT)
429                 r->top = MAX_HEIGHT - h;
430         if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
431                         (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
432             (r->width != w || r->height != h))
433                 return -ERANGE;
434         r->width = w;
435         r->height = h;
436         return 0;
437 }
438
439 int vivid_enum_fmt_vid(struct file *file, void  *priv,
440                                         struct v4l2_fmtdesc *f)
441 {
442         struct vivid_dev *dev = video_drvdata(file);
443         const struct vivid_fmt *fmt;
444
445         if (f->index >= ARRAY_SIZE(vivid_formats) -
446             (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
447                 return -EINVAL;
448
449         fmt = &vivid_formats[f->index];
450
451         strlcpy(f->description, fmt->name, sizeof(f->description));
452         f->pixelformat = fmt->fourcc;
453         return 0;
454 }
455
456 int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
457                                         struct v4l2_fmtdesc *f)
458 {
459         struct vivid_dev *dev = video_drvdata(file);
460
461         if (!dev->multiplanar)
462                 return -ENOTTY;
463         return vivid_enum_fmt_vid(file, priv, f);
464 }
465
466 int vidioc_enum_fmt_vid(struct file *file, void  *priv,
467                                         struct v4l2_fmtdesc *f)
468 {
469         struct vivid_dev *dev = video_drvdata(file);
470
471         if (dev->multiplanar)
472                 return -ENOTTY;
473         return vivid_enum_fmt_vid(file, priv, f);
474 }
475
476 int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
477 {
478         struct vivid_dev *dev = video_drvdata(file);
479         struct video_device *vdev = video_devdata(file);
480
481         if (vdev->vfl_dir == VFL_DIR_RX) {
482                 if (!vivid_is_sdtv_cap(dev))
483                         return -ENODATA;
484                 *id = dev->std_cap;
485         } else {
486                 if (!vivid_is_svid_out(dev))
487                         return -ENODATA;
488                 *id = dev->std_out;
489         }
490         return 0;
491 }
492
493 int vidioc_g_dv_timings(struct file *file, void *_fh,
494                                     struct v4l2_dv_timings *timings)
495 {
496         struct vivid_dev *dev = video_drvdata(file);
497         struct video_device *vdev = video_devdata(file);
498
499         if (vdev->vfl_dir == VFL_DIR_RX) {
500                 if (!vivid_is_hdmi_cap(dev))
501                         return -ENODATA;
502                 *timings = dev->dv_timings_cap;
503         } else {
504                 if (!vivid_is_hdmi_out(dev))
505                         return -ENODATA;
506                 *timings = dev->dv_timings_out;
507         }
508         return 0;
509 }
510
511 int vidioc_enum_dv_timings(struct file *file, void *_fh,
512                                     struct v4l2_enum_dv_timings *timings)
513 {
514         struct vivid_dev *dev = video_drvdata(file);
515         struct video_device *vdev = video_devdata(file);
516
517         if (vdev->vfl_dir == VFL_DIR_RX) {
518                 if (!vivid_is_hdmi_cap(dev))
519                         return -ENODATA;
520         } else {
521                 if (!vivid_is_hdmi_out(dev))
522                         return -ENODATA;
523         }
524         return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
525                         NULL, NULL);
526 }
527
528 int vidioc_dv_timings_cap(struct file *file, void *_fh,
529                                     struct v4l2_dv_timings_cap *cap)
530 {
531         struct vivid_dev *dev = video_drvdata(file);
532         struct video_device *vdev = video_devdata(file);
533
534         if (vdev->vfl_dir == VFL_DIR_RX) {
535                 if (!vivid_is_hdmi_cap(dev))
536                         return -ENODATA;
537         } else {
538                 if (!vivid_is_hdmi_out(dev))
539                         return -ENODATA;
540         }
541         *cap = vivid_dv_timings_cap;
542         return 0;
543 }
544
545 int vidioc_g_edid(struct file *file, void *_fh,
546                          struct v4l2_edid *edid)
547 {
548         struct vivid_dev *dev = video_drvdata(file);
549         struct video_device *vdev = video_devdata(file);
550
551         memset(edid->reserved, 0, sizeof(edid->reserved));
552         if (vdev->vfl_dir == VFL_DIR_RX) {
553                 if (edid->pad >= dev->num_inputs)
554                         return -EINVAL;
555                 if (dev->input_type[edid->pad] != HDMI)
556                         return -EINVAL;
557         } else {
558                 if (edid->pad >= dev->num_outputs)
559                         return -EINVAL;
560                 if (dev->output_type[edid->pad] != HDMI)
561                         return -EINVAL;
562         }
563         if (edid->start_block == 0 && edid->blocks == 0) {
564                 edid->blocks = dev->edid_blocks;
565                 return 0;
566         }
567         if (dev->edid_blocks == 0)
568                 return -ENODATA;
569         if (edid->start_block >= dev->edid_blocks)
570                 return -EINVAL;
571         if (edid->start_block + edid->blocks > dev->edid_blocks)
572                 edid->blocks = dev->edid_blocks - edid->start_block;
573         memcpy(edid->edid, dev->edid, edid->blocks * 128);
574         return 0;
575 }