]> Git Repo - linux.git/blob - drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.c
Linux 6.14-rc3
[linux.git] / drivers / media / platform / st / stm32 / stm32-dcmipp / dcmipp-common.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for STM32 Digital Camera Memory Interface Pixel Processor
4  *
5  * Copyright (C) STMicroelectronics SA 2023
6  * Authors: Hugues Fruchet <[email protected]>
7  *          Alain Volmat <[email protected]>
8  *          for STMicroelectronics.
9  */
10
11 #include <linux/init.h>
12 #include <linux/module.h>
13
14 #include "dcmipp-common.h"
15
16 /* Helper function to allocate and initialize pads */
17 struct media_pad *dcmipp_pads_init(u16 num_pads, const unsigned long *pads_flags)
18 {
19         struct media_pad *pads;
20         unsigned int i;
21
22         /* Allocate memory for the pads */
23         pads = kcalloc(num_pads, sizeof(*pads), GFP_KERNEL);
24         if (!pads)
25                 return ERR_PTR(-ENOMEM);
26
27         /* Initialize the pads */
28         for (i = 0; i < num_pads; i++) {
29                 pads[i].index = i;
30                 pads[i].flags = pads_flags[i];
31         }
32
33         return pads;
34 }
35
36 static const struct media_entity_operations dcmipp_entity_ops = {
37         .link_validate = v4l2_subdev_link_validate,
38 };
39
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,
44                            u32 function,
45                            u16 num_pads,
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)
51 {
52         int ret;
53
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);
58
59         /* Fill the dcmipp_ent_device struct */
60         ved->ent = &sd->entity;
61
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);
70
71         /* Expose this subdev to user space */
72         sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
73         if (sd->ctrl_handler)
74                 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
75
76         /* Initialize the media entity */
77         ret = media_entity_pads_init(&sd->entity, num_pads, ved->pads);
78         if (ret)
79                 goto err_clean_pads;
80
81         ret = v4l2_subdev_init_finalize(sd);
82         if (ret < 0)
83                 goto err_clean_m_ent;
84
85         /* Register the subdev with the v4l2 and the media framework */
86         ret = v4l2_device_register_subdev(v4l2_dev, sd);
87         if (ret) {
88                 dev_err(v4l2_dev->dev,
89                         "%s: subdev register failed (err=%d)\n",
90                         name, ret);
91                 goto err_clean_m_ent;
92         }
93
94         ved->handler = handler;
95         ved->thread_fn = thread_fn;
96
97         return 0;
98
99 err_clean_m_ent:
100         media_entity_cleanup(&sd->entity);
101 err_clean_pads:
102         dcmipp_pads_cleanup(ved->pads);
103         return ret;
104 }
105
106 void
107 dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved, struct v4l2_subdev *sd)
108 {
109         media_entity_cleanup(ved->ent);
110         v4l2_device_unregister_subdev(sd);
111 }
This page took 0.03656 seconds and 4 git commands to generate.