Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-block.git] / drivers / media / platform / video-mux.c
CommitLineData
68803ad4
PZ
1/*
2 * video stream multiplexer controlled via mux control
3 *
4 * Copyright (C) 2013 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
5 * Copyright (C) 2016-2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/err.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
435945e0 20#include <linux/mux/consumer.h>
68803ad4
PZ
21#include <linux/of.h>
22#include <linux/of_graph.h>
23#include <linux/platform_device.h>
c5afc789 24#include <linux/slab.h>
68803ad4
PZ
25#include <media/v4l2-async.h>
26#include <media/v4l2-device.h>
c5afc789 27#include <media/v4l2-fwnode.h>
68803ad4
PZ
28#include <media/v4l2-subdev.h>
29
30struct video_mux {
31 struct v4l2_subdev subdev;
32 struct media_pad *pads;
33 struct v4l2_mbus_framefmt *format_mbus;
435945e0 34 struct mux_control *mux;
68803ad4
PZ
35 struct mutex lock;
36 int active;
37};
38
efe1958e
PZ
39static const struct v4l2_mbus_framefmt video_mux_format_mbus_default = {
40 .width = 1,
41 .height = 1,
42 .code = MEDIA_BUS_FMT_Y8_1X8,
43 .field = V4L2_FIELD_NONE,
44};
45
68803ad4
PZ
46static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev *sd)
47{
48 return container_of(sd, struct video_mux, subdev);
49}
50
51static int video_mux_link_setup(struct media_entity *entity,
52 const struct media_pad *local,
53 const struct media_pad *remote, u32 flags)
54{
55 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
56 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
fd32d534 57 u16 source_pad = entity->num_pads - 1;
68803ad4
PZ
58 int ret = 0;
59
60 /*
61 * The mux state is determined by the enabled sink pad link.
62 * Enabling or disabling the source pad link has no effect.
63 */
64 if (local->flags & MEDIA_PAD_FL_SOURCE)
65 return 0;
66
67 dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
68 remote->entity->name, remote->index, local->entity->name,
69 local->index, flags & MEDIA_LNK_FL_ENABLED);
70
71 mutex_lock(&vmux->lock);
72
73 if (flags & MEDIA_LNK_FL_ENABLED) {
74 if (vmux->active == local->index)
75 goto out;
76
77 if (vmux->active >= 0) {
78 ret = -EBUSY;
79 goto out;
80 }
81
82 dev_dbg(sd->dev, "setting %d active\n", local->index);
435945e0 83 ret = mux_control_try_select(vmux->mux, local->index);
68803ad4
PZ
84 if (ret < 0)
85 goto out;
86 vmux->active = local->index;
fd32d534
CL
87
88 /* Propagate the active format to the source */
89 vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active];
68803ad4
PZ
90 } else {
91 if (vmux->active != local->index)
92 goto out;
93
94 dev_dbg(sd->dev, "going inactive\n");
435945e0 95 mux_control_deselect(vmux->mux);
68803ad4
PZ
96 vmux->active = -1;
97 }
98
99out:
100 mutex_unlock(&vmux->lock);
101 return ret;
102}
103
104static const struct media_entity_operations video_mux_ops = {
105 .link_setup = video_mux_link_setup,
106 .link_validate = v4l2_subdev_link_validate,
107};
108
109static int video_mux_s_stream(struct v4l2_subdev *sd, int enable)
110{
111 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
112 struct v4l2_subdev *upstream_sd;
113 struct media_pad *pad;
114
115 if (vmux->active == -1) {
116 dev_err(sd->dev, "Can not start streaming on inactive mux\n");
117 return -EINVAL;
118 }
119
120 pad = media_entity_remote_pad(&sd->entity.pads[vmux->active]);
121 if (!pad) {
122 dev_err(sd->dev, "Failed to find remote source pad\n");
123 return -ENOLINK;
124 }
125
126 if (!is_media_entity_v4l2_subdev(pad->entity)) {
127 dev_err(sd->dev, "Upstream entity is not a v4l2 subdev\n");
128 return -ENODEV;
129 }
130
131 upstream_sd = media_entity_to_v4l2_subdev(pad->entity);
132
133 return v4l2_subdev_call(upstream_sd, video, s_stream, enable);
134}
135
136static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = {
137 .s_stream = video_mux_s_stream,
138};
139
140static struct v4l2_mbus_framefmt *
141__video_mux_get_pad_format(struct v4l2_subdev *sd,
142 struct v4l2_subdev_pad_config *cfg,
143 unsigned int pad, u32 which)
144{
145 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
146
147 switch (which) {
148 case V4L2_SUBDEV_FORMAT_TRY:
149 return v4l2_subdev_get_try_format(sd, cfg, pad);
150 case V4L2_SUBDEV_FORMAT_ACTIVE:
151 return &vmux->format_mbus[pad];
152 default:
153 return NULL;
154 }
155}
156
157static int video_mux_get_format(struct v4l2_subdev *sd,
158 struct v4l2_subdev_pad_config *cfg,
159 struct v4l2_subdev_format *sdformat)
160{
161 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
162
163 mutex_lock(&vmux->lock);
164
165 sdformat->format = *__video_mux_get_pad_format(sd, cfg, sdformat->pad,
166 sdformat->which);
167
168 mutex_unlock(&vmux->lock);
169
170 return 0;
171}
172
173static int video_mux_set_format(struct v4l2_subdev *sd,
174 struct v4l2_subdev_pad_config *cfg,
175 struct v4l2_subdev_format *sdformat)
176{
177 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
fd32d534 178 struct v4l2_mbus_framefmt *mbusformat, *source_mbusformat;
68803ad4 179 struct media_pad *pad = &vmux->pads[sdformat->pad];
fd32d534 180 u16 source_pad = sd->entity.num_pads - 1;
68803ad4
PZ
181
182 mbusformat = __video_mux_get_pad_format(sd, cfg, sdformat->pad,
183 sdformat->which);
184 if (!mbusformat)
185 return -EINVAL;
186
fd32d534
CL
187 source_mbusformat = __video_mux_get_pad_format(sd, cfg, source_pad,
188 sdformat->which);
189 if (!source_mbusformat)
190 return -EINVAL;
191
efe1958e
PZ
192 /* No size limitations except V4L2 compliance requirements */
193 v4l_bound_align_image(&sdformat->format.width, 1, 65536, 0,
194 &sdformat->format.height, 1, 65536, 0, 0);
195
196 /* All formats except LVDS and vendor specific formats are acceptable */
197 switch (sdformat->format.code) {
198 case MEDIA_BUS_FMT_RGB444_1X12:
199 case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
200 case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
201 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
202 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
203 case MEDIA_BUS_FMT_RGB565_1X16:
204 case MEDIA_BUS_FMT_BGR565_2X8_BE:
205 case MEDIA_BUS_FMT_BGR565_2X8_LE:
206 case MEDIA_BUS_FMT_RGB565_2X8_BE:
207 case MEDIA_BUS_FMT_RGB565_2X8_LE:
208 case MEDIA_BUS_FMT_RGB666_1X18:
209 case MEDIA_BUS_FMT_RBG888_1X24:
210 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
211 case MEDIA_BUS_FMT_BGR888_1X24:
212 case MEDIA_BUS_FMT_GBR888_1X24:
213 case MEDIA_BUS_FMT_RGB888_1X24:
214 case MEDIA_BUS_FMT_RGB888_2X12_BE:
215 case MEDIA_BUS_FMT_RGB888_2X12_LE:
216 case MEDIA_BUS_FMT_ARGB8888_1X32:
217 case MEDIA_BUS_FMT_RGB888_1X32_PADHI:
218 case MEDIA_BUS_FMT_RGB101010_1X30:
219 case MEDIA_BUS_FMT_RGB121212_1X36:
220 case MEDIA_BUS_FMT_RGB161616_1X48:
221 case MEDIA_BUS_FMT_Y8_1X8:
222 case MEDIA_BUS_FMT_UV8_1X8:
223 case MEDIA_BUS_FMT_UYVY8_1_5X8:
224 case MEDIA_BUS_FMT_VYUY8_1_5X8:
225 case MEDIA_BUS_FMT_YUYV8_1_5X8:
226 case MEDIA_BUS_FMT_YVYU8_1_5X8:
227 case MEDIA_BUS_FMT_UYVY8_2X8:
228 case MEDIA_BUS_FMT_VYUY8_2X8:
229 case MEDIA_BUS_FMT_YUYV8_2X8:
230 case MEDIA_BUS_FMT_YVYU8_2X8:
231 case MEDIA_BUS_FMT_Y10_1X10:
232 case MEDIA_BUS_FMT_UYVY10_2X10:
233 case MEDIA_BUS_FMT_VYUY10_2X10:
234 case MEDIA_BUS_FMT_YUYV10_2X10:
235 case MEDIA_BUS_FMT_YVYU10_2X10:
236 case MEDIA_BUS_FMT_Y12_1X12:
237 case MEDIA_BUS_FMT_UYVY12_2X12:
238 case MEDIA_BUS_FMT_VYUY12_2X12:
239 case MEDIA_BUS_FMT_YUYV12_2X12:
240 case MEDIA_BUS_FMT_YVYU12_2X12:
241 case MEDIA_BUS_FMT_UYVY8_1X16:
242 case MEDIA_BUS_FMT_VYUY8_1X16:
243 case MEDIA_BUS_FMT_YUYV8_1X16:
244 case MEDIA_BUS_FMT_YVYU8_1X16:
245 case MEDIA_BUS_FMT_YDYUYDYV8_1X16:
246 case MEDIA_BUS_FMT_UYVY10_1X20:
247 case MEDIA_BUS_FMT_VYUY10_1X20:
248 case MEDIA_BUS_FMT_YUYV10_1X20:
249 case MEDIA_BUS_FMT_YVYU10_1X20:
250 case MEDIA_BUS_FMT_VUY8_1X24:
251 case MEDIA_BUS_FMT_YUV8_1X24:
252 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
253 case MEDIA_BUS_FMT_UYVY12_1X24:
254 case MEDIA_BUS_FMT_VYUY12_1X24:
255 case MEDIA_BUS_FMT_YUYV12_1X24:
256 case MEDIA_BUS_FMT_YVYU12_1X24:
257 case MEDIA_BUS_FMT_YUV10_1X30:
258 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
259 case MEDIA_BUS_FMT_AYUV8_1X32:
260 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
261 case MEDIA_BUS_FMT_YUV12_1X36:
262 case MEDIA_BUS_FMT_YUV16_1X48:
263 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
264 case MEDIA_BUS_FMT_JPEG_1X8:
265 case MEDIA_BUS_FMT_AHSV8888_1X32:
7637c261
RMS
266 case MEDIA_BUS_FMT_SBGGR8_1X8:
267 case MEDIA_BUS_FMT_SGBRG8_1X8:
268 case MEDIA_BUS_FMT_SGRBG8_1X8:
269 case MEDIA_BUS_FMT_SRGGB8_1X8:
270 case MEDIA_BUS_FMT_SBGGR10_1X10:
271 case MEDIA_BUS_FMT_SGBRG10_1X10:
272 case MEDIA_BUS_FMT_SGRBG10_1X10:
273 case MEDIA_BUS_FMT_SRGGB10_1X10:
274 case MEDIA_BUS_FMT_SBGGR12_1X12:
275 case MEDIA_BUS_FMT_SGBRG12_1X12:
276 case MEDIA_BUS_FMT_SGRBG12_1X12:
277 case MEDIA_BUS_FMT_SRGGB12_1X12:
278 case MEDIA_BUS_FMT_SBGGR14_1X14:
279 case MEDIA_BUS_FMT_SGBRG14_1X14:
280 case MEDIA_BUS_FMT_SGRBG14_1X14:
281 case MEDIA_BUS_FMT_SRGGB14_1X14:
282 case MEDIA_BUS_FMT_SBGGR16_1X16:
283 case MEDIA_BUS_FMT_SGBRG16_1X16:
284 case MEDIA_BUS_FMT_SGRBG16_1X16:
285 case MEDIA_BUS_FMT_SRGGB16_1X16:
efe1958e
PZ
286 break;
287 default:
288 sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8;
289 break;
290 }
291 if (sdformat->format.field == V4L2_FIELD_ANY)
292 sdformat->format.field = V4L2_FIELD_NONE;
293
68803ad4
PZ
294 mutex_lock(&vmux->lock);
295
296 /* Source pad mirrors active sink pad, no limitations on sink pads */
297 if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0)
298 sdformat->format = vmux->format_mbus[vmux->active];
299
300 *mbusformat = sdformat->format;
301
fd32d534
CL
302 /* Propagate the format from an active sink to source */
303 if ((pad->flags & MEDIA_PAD_FL_SINK) && (pad->index == vmux->active))
304 *source_mbusformat = sdformat->format;
305
68803ad4
PZ
306 mutex_unlock(&vmux->lock);
307
308 return 0;
309}
310
efe1958e
PZ
311static int video_mux_init_cfg(struct v4l2_subdev *sd,
312 struct v4l2_subdev_pad_config *cfg)
313{
314 struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
315 struct v4l2_mbus_framefmt *mbusformat;
316 unsigned int i;
317
318 mutex_lock(&vmux->lock);
319
320 for (i = 0; i < sd->entity.num_pads; i++) {
321 mbusformat = v4l2_subdev_get_try_format(sd, cfg, i);
322 *mbusformat = video_mux_format_mbus_default;
323 }
324
325 mutex_unlock(&vmux->lock);
326
327 return 0;
328}
329
68803ad4 330static const struct v4l2_subdev_pad_ops video_mux_pad_ops = {
efe1958e 331 .init_cfg = video_mux_init_cfg,
68803ad4
PZ
332 .get_fmt = video_mux_get_format,
333 .set_fmt = video_mux_set_format,
334};
335
336static const struct v4l2_subdev_ops video_mux_subdev_ops = {
337 .pad = &video_mux_pad_ops,
338 .video = &video_mux_subdev_video_ops,
339};
340
c5afc789
SL
341static int video_mux_parse_endpoint(struct device *dev,
342 struct v4l2_fwnode_endpoint *vep,
343 struct v4l2_async_subdev *asd)
344{
345 /*
346 * it's not an error if remote is missing on a video-mux
347 * input port, return -ENOTCONN to skip this endpoint with
348 * no error.
349 */
350 return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
351}
352
353static int video_mux_async_register(struct video_mux *vmux,
354 unsigned int num_input_pads)
355{
356 unsigned int i, *ports;
357 int ret;
358
359 ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL);
360 if (!ports)
361 return -ENOMEM;
362 for (i = 0; i < num_input_pads; i++)
363 ports[i] = i;
364
365 ret = v4l2_async_register_fwnode_subdev(
366 &vmux->subdev, sizeof(struct v4l2_async_subdev),
367 ports, num_input_pads, video_mux_parse_endpoint);
368
369 kfree(ports);
370 return ret;
371}
372
68803ad4
PZ
373static int video_mux_probe(struct platform_device *pdev)
374{
375 struct device_node *np = pdev->dev.of_node;
376 struct device *dev = &pdev->dev;
377 struct device_node *ep;
378 struct video_mux *vmux;
379 unsigned int num_pads = 0;
efe1958e 380 unsigned int i;
68803ad4 381 int ret;
68803ad4
PZ
382
383 vmux = devm_kzalloc(dev, sizeof(*vmux), GFP_KERNEL);
384 if (!vmux)
385 return -ENOMEM;
386
387 platform_set_drvdata(pdev, vmux);
388
389 v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops);
f764e6d6 390 snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np);
68803ad4
PZ
391 vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
392 vmux->subdev.dev = dev;
393
394 /*
395 * The largest numbered port is the output port. It determines
396 * total number of pads.
397 */
398 for_each_endpoint_of_node(np, ep) {
399 struct of_endpoint endpoint;
400
401 of_graph_parse_endpoint(ep, &endpoint);
402 num_pads = max(num_pads, endpoint.port + 1);
403 }
404
405 if (num_pads < 2) {
406 dev_err(dev, "Not enough ports %d\n", num_pads);
407 return -EINVAL;
408 }
409
435945e0
PZ
410 vmux->mux = devm_mux_control_get(dev, NULL);
411 if (IS_ERR(vmux->mux)) {
412 ret = PTR_ERR(vmux->mux);
68803ad4
PZ
413 if (ret != -EPROBE_DEFER)
414 dev_err(dev, "Failed to get mux: %d\n", ret);
415 return ret;
416 }
417
418 mutex_init(&vmux->lock);
419 vmux->active = -1;
420 vmux->pads = devm_kcalloc(dev, num_pads, sizeof(*vmux->pads),
421 GFP_KERNEL);
aeb0d0f5
KL
422 if (!vmux->pads)
423 return -ENOMEM;
424
68803ad4
PZ
425 vmux->format_mbus = devm_kcalloc(dev, num_pads,
426 sizeof(*vmux->format_mbus),
427 GFP_KERNEL);
aeb0d0f5
KL
428 if (!vmux->format_mbus)
429 return -ENOMEM;
68803ad4 430
efe1958e
PZ
431 for (i = 0; i < num_pads; i++) {
432 vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK
433 : MEDIA_PAD_FL_SOURCE;
434 vmux->format_mbus[i] = video_mux_format_mbus_default;
435 }
68803ad4
PZ
436
437 vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX;
438 ret = media_entity_pads_init(&vmux->subdev.entity, num_pads,
439 vmux->pads);
440 if (ret < 0)
441 return ret;
442
443 vmux->subdev.entity.ops = &video_mux_ops;
444
c5afc789 445 return video_mux_async_register(vmux, num_pads - 1);
68803ad4
PZ
446}
447
448static int video_mux_remove(struct platform_device *pdev)
449{
450 struct video_mux *vmux = platform_get_drvdata(pdev);
451 struct v4l2_subdev *sd = &vmux->subdev;
452
453 v4l2_async_unregister_subdev(sd);
454 media_entity_cleanup(&sd->entity);
455
456 return 0;
457}
458
459static const struct of_device_id video_mux_dt_ids[] = {
460 { .compatible = "video-mux", },
461 { /* sentinel */ }
462};
463MODULE_DEVICE_TABLE(of, video_mux_dt_ids);
464
465static struct platform_driver video_mux_driver = {
466 .probe = video_mux_probe,
467 .remove = video_mux_remove,
468 .driver = {
469 .of_match_table = video_mux_dt_ids,
470 .name = "video-mux",
471 },
472};
473
474module_platform_driver(video_mux_driver);
475
476MODULE_DESCRIPTION("video stream multiplexer");
477MODULE_AUTHOR("Sascha Hauer, Pengutronix");
478MODULE_AUTHOR("Philipp Zabel, Pengutronix");
479MODULE_LICENSE("GPL");