aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vimc/vimc-scaler.c
diff options
context:
space:
mode:
authorHelen Fornazier <helen.koike@collabora.com>2019-03-13 14:29:37 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-04-22 10:58:51 -0400
commitb6c61a6c37317efd7327199bfe24770af3d7e799 (patch)
treec130cfb12c25543104b880a12d039ccac03ffa12 /drivers/media/platform/vimc/vimc-scaler.c
parentd82b921a7a8a00ec31ba76287245ec663534df9b (diff)
media: vimc: propagate pixel format in the stream
Media bus codes were being mapped to pixelformats, which causes a limitation on vimc because not all pixelformats can be mapped to media bus codes. Also, media bus codes are an internal configuration from the device. Userspace only assures media bus codes matches between pads and expects the image in a given pixelformat. So we can allow almost any media bus format to be configured between pads, except for debayer that expects a media bus code of type bayer in the sink pad. [hverkuil-cisco@xs4all.nl: drop use of v4l2_get_fourcc_name: not yet available] [hverkuil-cisco@xs4all.nl: made vimc_mbus_list static] Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/platform/vimc/vimc-scaler.c')
-rw-r--r--drivers/media/platform/vimc/vimc-scaler.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c
index 2028afa4ef7a..8aecf8e92031 100644
--- a/drivers/media/platform/vimc/vimc-scaler.c
+++ b/drivers/media/platform/vimc/vimc-scaler.c
@@ -35,6 +35,12 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier");
35#define IS_SRC(pad) (pad) 35#define IS_SRC(pad) (pad)
36#define MAX_ZOOM 8 36#define MAX_ZOOM 8
37 37
38static const u32 vimc_sca_supported_pixfmt[] = {
39 V4L2_PIX_FMT_BGR24,
40 V4L2_PIX_FMT_RGB24,
41 V4L2_PIX_FMT_ARGB32,
42};
43
38struct vimc_sca_device { 44struct vimc_sca_device {
39 struct vimc_ent_device ved; 45 struct vimc_ent_device ved;
40 struct v4l2_subdev sd; 46 struct v4l2_subdev sd;
@@ -57,6 +63,16 @@ static const struct v4l2_mbus_framefmt sink_fmt_default = {
57 .colorspace = V4L2_COLORSPACE_DEFAULT, 63 .colorspace = V4L2_COLORSPACE_DEFAULT,
58}; 64};
59 65
66static bool vimc_sca_is_pixfmt_supported(u32 pixelformat)
67{
68 unsigned int i;
69
70 for (i = 0; i < ARRAY_SIZE(vimc_sca_supported_pixfmt); i++)
71 if (vimc_sca_supported_pixfmt[i] == pixelformat)
72 return true;
73 return false;
74}
75
60static int vimc_sca_init_cfg(struct v4l2_subdev *sd, 76static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
61 struct v4l2_subdev_pad_config *cfg) 77 struct v4l2_subdev_pad_config *cfg)
62{ 78{
@@ -76,35 +92,13 @@ static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
76 return 0; 92 return 0;
77} 93}
78 94
79static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd,
80 struct v4l2_subdev_pad_config *cfg,
81 struct v4l2_subdev_mbus_code_enum *code)
82{
83 const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
84
85 /* We don't support bayer format */
86 if (!vpix || vpix->bayer)
87 return -EINVAL;
88
89 code->code = vpix->code;
90
91 return 0;
92}
93
94static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd, 95static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd,
95 struct v4l2_subdev_pad_config *cfg, 96 struct v4l2_subdev_pad_config *cfg,
96 struct v4l2_subdev_frame_size_enum *fse) 97 struct v4l2_subdev_frame_size_enum *fse)
97{ 98{
98 const struct vimc_pix_map *vpix;
99
100 if (fse->index) 99 if (fse->index)
101 return -EINVAL; 100 return -EINVAL;
102 101
103 /* Only accept code in the pix map table in non bayer format */
104 vpix = vimc_pix_map_by_code(fse->code);
105 if (!vpix || vpix->bayer)
106 return -EINVAL;
107
108 fse->min_width = VIMC_FRAME_MIN_WIDTH; 102 fse->min_width = VIMC_FRAME_MIN_WIDTH;
109 fse->min_height = VIMC_FRAME_MIN_HEIGHT; 103 fse->min_height = VIMC_FRAME_MIN_HEIGHT;
110 104
@@ -141,13 +135,6 @@ static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
141 135
142static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt) 136static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
143{ 137{
144 const struct vimc_pix_map *vpix;
145
146 /* Only accept code in the pix map table in non bayer format */
147 vpix = vimc_pix_map_by_code(fmt->code);
148 if (!vpix || vpix->bayer)
149 fmt->code = sink_fmt_default.code;
150
151 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH, 138 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
152 VIMC_FRAME_MAX_WIDTH) & ~1; 139 VIMC_FRAME_MAX_WIDTH) & ~1;
153 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT, 140 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
@@ -166,6 +153,9 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
166 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd); 153 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
167 struct v4l2_mbus_framefmt *sink_fmt; 154 struct v4l2_mbus_framefmt *sink_fmt;
168 155
156 if (!vimc_mbus_code_supported(fmt->format.code))
157 fmt->format.code = sink_fmt_default.code;
158
169 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 159 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
170 /* Do not change the format while stream is on */ 160 /* Do not change the format while stream is on */
171 if (vsca->src_frame) 161 if (vsca->src_frame)
@@ -208,7 +198,7 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
208 198
209static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = { 199static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
210 .init_cfg = vimc_sca_init_cfg, 200 .init_cfg = vimc_sca_init_cfg,
211 .enum_mbus_code = vimc_sca_enum_mbus_code, 201 .enum_mbus_code = vimc_enum_mbus_code,
212 .enum_frame_size = vimc_sca_enum_frame_size, 202 .enum_frame_size = vimc_sca_enum_frame_size,
213 .get_fmt = vimc_sca_get_fmt, 203 .get_fmt = vimc_sca_get_fmt,
214 .set_fmt = vimc_sca_set_fmt, 204 .set_fmt = vimc_sca_set_fmt,
@@ -219,15 +209,22 @@ static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
219 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd); 209 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
220 210
221 if (enable) { 211 if (enable) {
222 const struct vimc_pix_map *vpix; 212 u32 pixelformat = vsca->ved.stream->producer_pixfmt;
213 const struct v4l2_format_info *pix_info;
223 unsigned int frame_size; 214 unsigned int frame_size;
224 215
225 if (vsca->src_frame) 216 if (vsca->src_frame)
226 return 0; 217 return 0;
227 218
219 if (!vimc_sca_is_pixfmt_supported(pixelformat)) {
220 dev_err(vsca->dev, "pixfmt (0x%08x) is not supported\n",
221 pixelformat);
222 return -EINVAL;
223 }
224
228 /* Save the bytes per pixel of the sink */ 225 /* Save the bytes per pixel of the sink */
229 vpix = vimc_pix_map_by_code(vsca->sink_fmt.code); 226 pix_info = v4l2_format_info(pixelformat);
230 vsca->bpp = vpix->bpp; 227 vsca->bpp = pix_info->bpp[0];
231 228
232 /* Calculate the width in bytes of the src frame */ 229 /* Calculate the width in bytes of the src frame */
233 vsca->src_line_size = vsca->sink_fmt.width * 230 vsca->src_line_size = vsca->sink_fmt.width *