Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / media / platform / vsp1 / vsp1_rwpf.c
1 /*
2  * vsp1_rwpf.c  --  R-Car VSP1 Read and Write Pixel Formatters
3  *
4  * Copyright (C) 2013 Renesas 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 <media/v4l2-subdev.h>
15
16 #include "vsp1.h"
17 #include "vsp1_rwpf.h"
18 #include "vsp1_video.h"
19
20 #define RWPF_MIN_WIDTH                          1
21 #define RWPF_MIN_HEIGHT                         1
22
23 /* -----------------------------------------------------------------------------
24  * V4L2 Subdevice Pad Operations
25  */
26
27 int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
28                              struct v4l2_subdev_fh *fh,
29                              struct v4l2_subdev_mbus_code_enum *code)
30 {
31         static const unsigned int codes[] = {
32                 V4L2_MBUS_FMT_ARGB8888_1X32,
33                 V4L2_MBUS_FMT_AYUV8_1X32,
34         };
35
36         if (code->index >= ARRAY_SIZE(codes))
37                 return -EINVAL;
38
39         code->code = codes[code->index];
40
41         return 0;
42 }
43
44 int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
45                               struct v4l2_subdev_fh *fh,
46                               struct v4l2_subdev_frame_size_enum *fse)
47 {
48         struct vsp1_rwpf *rwpf = to_rwpf(subdev);
49         struct v4l2_mbus_framefmt *format;
50
51         format = v4l2_subdev_get_try_format(fh, fse->pad);
52
53         if (fse->index || fse->code != format->code)
54                 return -EINVAL;
55
56         if (fse->pad == RWPF_PAD_SINK) {
57                 fse->min_width = RWPF_MIN_WIDTH;
58                 fse->max_width = rwpf->max_width;
59                 fse->min_height = RWPF_MIN_HEIGHT;
60                 fse->max_height = rwpf->max_height;
61         } else {
62                 /* The size on the source pad are fixed and always identical to
63                  * the size on the sink pad.
64                  */
65                 fse->min_width = format->width;
66                 fse->max_width = format->width;
67                 fse->min_height = format->height;
68                 fse->max_height = format->height;
69         }
70
71         return 0;
72 }
73
74 int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
75                          struct v4l2_subdev_format *fmt)
76 {
77         struct vsp1_rwpf *rwpf = to_rwpf(subdev);
78
79         fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
80                                                   fmt->which);
81
82         return 0;
83 }
84
85 int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
86                          struct v4l2_subdev_format *fmt)
87 {
88         struct vsp1_rwpf *rwpf = to_rwpf(subdev);
89         struct v4l2_mbus_framefmt *format;
90
91         /* Default to YUV if the requested format is not supported. */
92         if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
93             fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
94                 fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
95
96         format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
97                                             fmt->which);
98
99         if (fmt->pad == RWPF_PAD_SOURCE) {
100                 /* The RWPF performs format conversion but can't scale, only the
101                  * format code can be changed on the source pad.
102                  */
103                 format->code = fmt->format.code;
104                 fmt->format = *format;
105                 return 0;
106         }
107
108         format->code = fmt->format.code;
109         format->width = clamp_t(unsigned int, fmt->format.width,
110                                 RWPF_MIN_WIDTH, rwpf->max_width);
111         format->height = clamp_t(unsigned int, fmt->format.height,
112                                  RWPF_MIN_HEIGHT, rwpf->max_height);
113         format->field = V4L2_FIELD_NONE;
114         format->colorspace = V4L2_COLORSPACE_SRGB;
115
116         fmt->format = *format;
117
118         /* Propagate the format to the source pad. */
119         format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE,
120                                             fmt->which);
121         *format = fmt->format;
122
123         return 0;
124 }