Skip to content

Commit 4a29b70

Browse files
Helen Fornaziermchehab
authored andcommitted
[media] vimc: Subdevices as modules
Change the core structure for adding subdevices in the topology. Instead of calling the specific create function for each subdevice, inject a child platform_device with the driver's name. Each type of node in the topology (sensor, capture, debayer, scaler) will register a platform_driver with the corresponding name through the component subsystem. Implementing a new subdevice type doesn't require vimc-core to be altered. This facilitates future implementation of dynamic entities, where hotpluging an entity in the topology is just a matter of registering/unregistering a platform_device in the system. It also facilitates other implementations of different nodes without touching the core code and remove the need of a header file for each type of node. Signed-off-by: Helen Koike <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 535d296 commit 4a29b70

File tree

8 files changed

+339
-388
lines changed

8 files changed

+339
-388
lines changed
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
vimc-objs := vimc-core.o vimc-capture.o vimc-common.o vimc-sensor.o
1+
vimc-objs := vimc-core.o
2+
vimc_capture-objs := vimc-capture.o
3+
vimc_common-objs := vimc-common.o
4+
vimc_sensor-objs := vimc-sensor.o
25

3-
obj-$(CONFIG_VIDEO_VIMC) += vimc.o
6+
obj-$(CONFIG_VIDEO_VIMC) += vimc.o vimc_capture.o vimc_common.o vimc_sensor.o

drivers/media/platform/vimc/vimc-capture.c

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515
*
1616
*/
1717

18+
#include <linux/component.h>
19+
#include <linux/module.h>
20+
#include <linux/platform_device.h>
1821
#include <media/v4l2-ioctl.h>
1922
#include <media/videobuf2-core.h>
2023
#include <media/videobuf2-vmalloc.h>
2124

22-
#include "vimc-capture.h"
25+
#include "vimc-common.h"
26+
27+
#define VIMC_CAP_DRV_NAME "vimc-capture"
2328

2429
struct vimc_cap_device {
2530
struct vimc_ent_device ved;
2631
struct video_device vdev;
32+
struct device *dev;
2733
struct v4l2_pix_format format;
2834
struct vb2_queue queue;
2935
struct list_head buf_list;
@@ -131,7 +137,7 @@ static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv,
131137

132138
vimc_cap_try_fmt_vid_cap(file, priv, f);
133139

134-
dev_dbg(vcap->vdev.v4l2_dev->dev, "%s: format update: "
140+
dev_dbg(vcap->dev, "%s: format update: "
135141
"old:%dx%d (0x%x, %d, %d, %d, %d) "
136142
"new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name,
137143
/* old */
@@ -309,8 +315,7 @@ static int vimc_cap_buffer_prepare(struct vb2_buffer *vb)
309315
unsigned long size = vcap->format.sizeimage;
310316

311317
if (vb2_plane_size(vb, 0) < size) {
312-
dev_err(vcap->vdev.v4l2_dev->dev,
313-
"%s: buffer too small (%lu < %lu)\n",
318+
dev_err(vcap->dev, "%s: buffer too small (%lu < %lu)\n",
314319
vcap->vdev.name, vb2_plane_size(vb, 0), size);
315320
return -EINVAL;
316321
}
@@ -335,8 +340,10 @@ static const struct media_entity_operations vimc_cap_mops = {
335340
.link_validate = vimc_link_validate,
336341
};
337342

338-
static void vimc_cap_destroy(struct vimc_ent_device *ved)
343+
static void vimc_cap_comp_unbind(struct device *comp, struct device *master,
344+
void *master_data)
339345
{
346+
struct vimc_ent_device *ved = dev_get_drvdata(comp);
340347
struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
341348
ved);
342349

@@ -385,42 +392,35 @@ static void vimc_cap_process_frame(struct vimc_ent_device *ved,
385392
vb2_buffer_done(&vimc_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE);
386393
}
387394

388-
struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
389-
const char *const name,
390-
u16 num_pads,
391-
const unsigned long *pads_flag)
395+
static int vimc_cap_comp_bind(struct device *comp, struct device *master,
396+
void *master_data)
392397
{
398+
struct v4l2_device *v4l2_dev = master_data;
399+
struct vimc_platform_data *pdata = comp->platform_data;
393400
const struct vimc_pix_map *vpix;
394401
struct vimc_cap_device *vcap;
395402
struct video_device *vdev;
396403
struct vb2_queue *q;
397404
int ret;
398405

399-
/*
400-
* Check entity configuration params
401-
* NOTE: we only support a single sink pad
402-
*/
403-
if (!name || num_pads != 1 || !pads_flag ||
404-
!(pads_flag[0] & MEDIA_PAD_FL_SINK))
405-
return ERR_PTR(-EINVAL);
406-
407406
/* Allocate the vimc_cap_device struct */
408407
vcap = kzalloc(sizeof(*vcap), GFP_KERNEL);
409408
if (!vcap)
410-
return ERR_PTR(-ENOMEM);
409+
return -ENOMEM;
411410

412411
/* Allocate the pads */
413-
vcap->ved.pads = vimc_pads_init(num_pads, pads_flag);
412+
vcap->ved.pads =
413+
vimc_pads_init(1, (const unsigned long[1]) {MEDIA_PAD_FL_SINK});
414414
if (IS_ERR(vcap->ved.pads)) {
415415
ret = PTR_ERR(vcap->ved.pads);
416416
goto err_free_vcap;
417417
}
418418

419419
/* Initialize the media entity */
420-
vcap->vdev.entity.name = name;
420+
vcap->vdev.entity.name = pdata->entity_name;
421421
vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L;
422422
ret = media_entity_pads_init(&vcap->vdev.entity,
423-
num_pads, vcap->ved.pads);
423+
1, vcap->ved.pads);
424424
if (ret)
425425
goto err_clean_pads;
426426

@@ -441,9 +441,8 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
441441

442442
ret = vb2_queue_init(q);
443443
if (ret) {
444-
dev_err(vcap->vdev.v4l2_dev->dev,
445-
"%s: vb2 queue init failed (err=%d)\n",
446-
vcap->vdev.name, ret);
444+
dev_err(comp, "%s: vb2 queue init failed (err=%d)\n",
445+
pdata->entity_name, ret);
447446
goto err_clean_m_ent;
448447
}
449448

@@ -459,10 +458,11 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
459458
vcap->format.height;
460459

461460
/* Fill the vimc_ent_device struct */
462-
vcap->ved.destroy = vimc_cap_destroy;
463461
vcap->ved.ent = &vcap->vdev.entity;
464462
vcap->ved.process_frame = vimc_cap_process_frame;
465463
vcap->ved.vdev_get_format = vimc_cap_get_format;
464+
dev_set_drvdata(comp, &vcap->ved);
465+
vcap->dev = comp;
466466

467467
/* Initialize the video_device struct */
468468
vdev = &vcap->vdev;
@@ -475,19 +475,18 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
475475
vdev->queue = q;
476476
vdev->v4l2_dev = v4l2_dev;
477477
vdev->vfl_dir = VFL_DIR_RX;
478-
strlcpy(vdev->name, name, sizeof(vdev->name));
478+
strlcpy(vdev->name, pdata->entity_name, sizeof(vdev->name));
479479
video_set_drvdata(vdev, &vcap->ved);
480480

481481
/* Register the video_device with the v4l2 and the media framework */
482482
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
483483
if (ret) {
484-
dev_err(vcap->vdev.v4l2_dev->dev,
485-
"%s: video register failed (err=%d)\n",
484+
dev_err(comp, "%s: video register failed (err=%d)\n",
486485
vcap->vdev.name, ret);
487486
goto err_release_queue;
488487
}
489488

490-
return &vcap->ved;
489+
return 0;
491490

492491
err_release_queue:
493492
vb2_queue_release(q);
@@ -498,5 +497,45 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
498497
err_free_vcap:
499498
kfree(vcap);
500499

501-
return ERR_PTR(ret);
500+
return ret;
502501
}
502+
503+
static const struct component_ops vimc_cap_comp_ops = {
504+
.bind = vimc_cap_comp_bind,
505+
.unbind = vimc_cap_comp_unbind,
506+
};
507+
508+
static int vimc_cap_probe(struct platform_device *pdev)
509+
{
510+
return component_add(&pdev->dev, &vimc_cap_comp_ops);
511+
}
512+
513+
static int vimc_cap_remove(struct platform_device *pdev)
514+
{
515+
component_del(&pdev->dev, &vimc_cap_comp_ops);
516+
517+
return 0;
518+
}
519+
520+
static struct platform_driver vimc_cap_pdrv = {
521+
.probe = vimc_cap_probe,
522+
.remove = vimc_cap_remove,
523+
.driver = {
524+
.name = VIMC_CAP_DRV_NAME,
525+
},
526+
};
527+
528+
static const struct platform_device_id vimc_cap_driver_ids[] = {
529+
{
530+
.name = VIMC_CAP_DRV_NAME,
531+
},
532+
{ }
533+
};
534+
535+
module_platform_driver(vimc_cap_pdrv);
536+
537+
MODULE_DEVICE_TABLE(platform, vimc_cap_driver_ids);
538+
539+
MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Capture");
540+
MODULE_AUTHOR("Helen Mae Koike Fornazier <[email protected]>");
541+
MODULE_LICENSE("GPL");

drivers/media/platform/vimc/vimc-capture.h

Lines changed: 0 additions & 28 deletions
This file was deleted.

drivers/media/platform/vimc/vimc-common.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*
1616
*/
1717

18+
#include <linux/init.h>
19+
#include <linux/module.h>
20+
1821
#include "vimc-common.h"
1922

2023
static const struct vimc_pix_map vimc_pix_map_list[] = {
@@ -151,6 +154,7 @@ const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i)
151154

152155
return &vimc_pix_map_list[i];
153156
}
157+
EXPORT_SYMBOL_GPL(vimc_pix_map_by_index);
154158

155159
const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
156160
{
@@ -162,6 +166,7 @@ const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
162166
}
163167
return NULL;
164168
}
169+
EXPORT_SYMBOL_GPL(vimc_pix_map_by_code);
165170

166171
const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
167172
{
@@ -173,6 +178,7 @@ const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
173178
}
174179
return NULL;
175180
}
181+
EXPORT_SYMBOL_GPL(vimc_pix_map_by_pixelformat);
176182

177183
int vimc_propagate_frame(struct media_pad *src, const void *frame)
178184
{
@@ -207,6 +213,7 @@ int vimc_propagate_frame(struct media_pad *src, const void *frame)
207213

208214
return 0;
209215
}
216+
EXPORT_SYMBOL_GPL(vimc_propagate_frame);
210217

211218
/* Helper function to allocate and initialize pads */
212219
struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag)
@@ -227,6 +234,7 @@ struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag)
227234

228235
return pads;
229236
}
237+
EXPORT_SYMBOL_GPL(vimc_pads_init);
230238

231239
int vimc_pipeline_s_stream(struct media_entity *ent, int enable)
232240
{
@@ -242,14 +250,8 @@ int vimc_pipeline_s_stream(struct media_entity *ent, int enable)
242250
/* Start the stream in the subdevice direct connected */
243251
pad = media_entity_remote_pad(&ent->pads[i]);
244252

245-
/*
246-
* if this is a raw node from vimc-core, then there is
247-
* nothing to activate
248-
* TODO: remove this when there are no more raw nodes in the
249-
* core and return error instead
250-
*/
251-
if (pad->entity->obj_type == MEDIA_ENTITY_TYPE_BASE)
252-
continue;
253+
if (!is_media_entity_v4l2_subdev(pad->entity))
254+
return -EINVAL;
253255

254256
sd = media_entity_to_v4l2_subdev(pad->entity);
255257
ret = v4l2_subdev_call(sd, video, s_stream, enable);
@@ -259,6 +261,7 @@ int vimc_pipeline_s_stream(struct media_entity *ent, int enable)
259261

260262
return 0;
261263
}
264+
EXPORT_SYMBOL_GPL(vimc_pipeline_s_stream);
262265

263266
static int vimc_get_mbus_format(struct media_pad *pad,
264267
struct v4l2_subdev_format *fmt)
@@ -301,14 +304,6 @@ int vimc_link_validate(struct media_link *link)
301304
struct v4l2_subdev_format source_fmt, sink_fmt;
302305
int ret;
303306

304-
/*
305-
* if it is a raw node from vimc-core, ignore the link for now
306-
* TODO: remove this when there are no more raw nodes in the
307-
* core and return error instead
308-
*/
309-
if (link->source->entity->obj_type == MEDIA_ENTITY_TYPE_BASE)
310-
return 0;
311-
312307
ret = vimc_get_mbus_format(link->source, &source_fmt);
313308
if (ret)
314309
return ret;
@@ -378,6 +373,7 @@ int vimc_link_validate(struct media_link *link)
378373

379374
return 0;
380375
}
376+
EXPORT_SYMBOL_GPL(vimc_link_validate);
381377

382378
static const struct media_entity_operations vimc_ent_sd_mops = {
383379
.link_validate = vimc_link_validate,
@@ -390,8 +386,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
390386
u32 function,
391387
u16 num_pads,
392388
const unsigned long *pads_flag,
393-
const struct v4l2_subdev_ops *sd_ops,
394-
void (*sd_destroy)(struct vimc_ent_device *))
389+
const struct v4l2_subdev_ops *sd_ops)
395390
{
396391
int ret;
397392

@@ -401,7 +396,6 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
401396
return PTR_ERR(ved->pads);
402397

403398
/* Fill the vimc_ent_device struct */
404-
ved->destroy = sd_destroy;
405399
ved->ent = &sd->entity;
406400

407401
/* Initialize the subdev */
@@ -437,10 +431,16 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
437431
vimc_pads_cleanup(ved->pads);
438432
return ret;
439433
}
434+
EXPORT_SYMBOL_GPL(vimc_ent_sd_register);
440435

441436
void vimc_ent_sd_unregister(struct vimc_ent_device *ved, struct v4l2_subdev *sd)
442437
{
443438
v4l2_device_unregister_subdev(sd);
444439
media_entity_cleanup(ved->ent);
445440
vimc_pads_cleanup(ved->pads);
446441
}
442+
EXPORT_SYMBOL_GPL(vimc_ent_sd_unregister);
443+
444+
MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Common");
445+
MODULE_AUTHOR("Helen Koike <[email protected]>");
446+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)