1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor
5 * Copyright (C) STMicroelectronics SA 2023
8 * for STMicroelectronics.
11 #include <linux/init.h>
12 #include <linux/module.h>
14 #include "dcmipp-common.h"
16 /* Helper function to allocate and initialize pads */
17 struct media_pad *dcmipp_pads_init(u16 num_pads, const unsigned long *pads_flags)
19 struct media_pad *pads;
22 /* Allocate memory for the pads */
23 pads = kcalloc(num_pads, sizeof(*pads), GFP_KERNEL);
25 return ERR_PTR(-ENOMEM);
27 /* Initialize the pads */
28 for (i = 0; i < num_pads; i++) {
30 pads[i].flags = pads_flags[i];
36 static const struct media_entity_operations dcmipp_entity_ops = {
37 .link_validate = v4l2_subdev_link_validate,
40 int dcmipp_ent_sd_register(struct dcmipp_ent_device *ved,
41 struct v4l2_subdev *sd,
42 struct v4l2_device *v4l2_dev,
43 const char *const name,
46 const unsigned long *pads_flag,
47 const struct v4l2_subdev_internal_ops *sd_int_ops,
48 const struct v4l2_subdev_ops *sd_ops,
49 irq_handler_t handler,
50 irq_handler_t thread_fn)
54 /* Allocate the pads. Should be released from the sd_int_op release */
55 ved->pads = dcmipp_pads_init(num_pads, pads_flag);
56 if (IS_ERR(ved->pads))
57 return PTR_ERR(ved->pads);
59 /* Fill the dcmipp_ent_device struct */
60 ved->ent = &sd->entity;
62 /* Initialize the subdev */
63 v4l2_subdev_init(sd, sd_ops);
64 sd->internal_ops = sd_int_ops;
65 sd->entity.function = function;
66 sd->entity.ops = &dcmipp_entity_ops;
67 sd->owner = THIS_MODULE;
68 strscpy(sd->name, name, sizeof(sd->name));
69 v4l2_set_subdevdata(sd, ved);
71 /* Expose this subdev to user space */
72 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
74 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
76 /* Initialize the media entity */
77 ret = media_entity_pads_init(&sd->entity, num_pads, ved->pads);
81 ret = v4l2_subdev_init_finalize(sd);
85 /* Register the subdev with the v4l2 and the media framework */
86 ret = v4l2_device_register_subdev(v4l2_dev, sd);
88 dev_err(v4l2_dev->dev,
89 "%s: subdev register failed (err=%d)\n",
94 ved->handler = handler;
95 ved->thread_fn = thread_fn;
100 media_entity_cleanup(&sd->entity);
102 dcmipp_pads_cleanup(ved->pads);
107 dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved, struct v4l2_subdev *sd)
109 media_entity_cleanup(ved->ent);
110 v4l2_device_unregister_subdev(sd);