bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0574-drivers-bcm2835_isp-Allow-multiple-users-for-the-ISP.patch
1 From 3d3cffb860398e43856ac5f2c831cb042be68795 Mon Sep 17 00:00:00 2001
2 From: Naushir Patuck <naush@raspberrypi.com>
3 Date: Tue, 16 Nov 2021 12:38:44 +0000
4 Subject: [PATCH] drivers: bcm2835_isp: Allow multiple users for the
5 ISP driver.
6
7 Add a second (identical) set of device nodes to allow concurrent use of the ISP
8 hardware by another user. This change effectively creates a second state
9 structure (struct bcm2835_isp_dev) to maintain independent state for the second
10 user. Node and media entity names are appened with the instance index
11 appropriately.
12
13 Further users can be added by changing the BCM2835_ISP_NUM_INSTANCES define.
14
15 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
16 ---
17 .../bcm2835-isp/bcm2835-v4l2-isp.c | 76 +++++++++++++++----
18 1 file changed, 60 insertions(+), 16 deletions(-)
19
20 --- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
21 +++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
22 @@ -26,13 +26,19 @@
23 #include "bcm2835-isp-ctrls.h"
24 #include "bcm2835-isp-fmts.h"
25
26 +/*
27 + * We want to instantiate 2 independent instances allowing 2 simultaneous users
28 + * of the ISP hardware.
29 + */
30 +#define BCM2835_ISP_NUM_INSTANCES 2
31 +
32 static unsigned int debug;
33 module_param(debug, uint, 0644);
34 MODULE_PARM_DESC(debug, "activates debug info");
35
36 -static unsigned int video_nr = 13;
37 -module_param(video_nr, uint, 0644);
38 -MODULE_PARM_DESC(video_nr, "base video device number");
39 +static unsigned int video_nr[BCM2835_ISP_NUM_INSTANCES] = { 13, 20 };
40 +module_param_array(video_nr, uint, NULL, 0644);
41 +MODULE_PARM_DESC(video_nr, "base video device numbers");
42
43 #define BCM2835_ISP_NAME "bcm2835-isp"
44 #define BCM2835_ISP_ENTITY_NAME_LEN 32
45 @@ -1279,6 +1285,7 @@ static int bcm2835_isp_get_supported_fmt
46 * or output nodes.
47 */
48 static int register_node(struct bcm2835_isp_dev *dev,
49 + unsigned int instance,
50 struct bcm2835_isp_node *node,
51 int index)
52 {
53 @@ -1439,7 +1446,7 @@ static int register_node(struct bcm2835_
54 snprintf(vfd->name, sizeof(node->vfd.name), "%s-%s%d", BCM2835_ISP_NAME,
55 node->name, node->id);
56
57 - ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr + index);
58 + ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr[instance]);
59 if (ret) {
60 v4l2_err(&dev->v4l2_dev,
61 "Failed to register video %s[%d] device node\n",
62 @@ -1660,9 +1667,8 @@ done:
63 return ret;
64 }
65
66 -static int bcm2835_isp_remove(struct platform_device *pdev)
67 +static void bcm2835_isp_remove_instance(struct bcm2835_isp_dev *dev)
68 {
69 - struct bcm2835_isp_dev *dev = platform_get_drvdata(pdev);
70 unsigned int i;
71
72 media_controller_unregister(dev);
73 @@ -1677,11 +1683,11 @@ static int bcm2835_isp_remove(struct pla
74 dev->component);
75
76 vchiq_mmal_finalise(dev->mmal_instance);
77 -
78 - return 0;
79 }
80
81 -static int bcm2835_isp_probe(struct platform_device *pdev)
82 +static int bcm2835_isp_probe_instance(struct platform_device *pdev,
83 + struct bcm2835_isp_dev **dev_int,
84 + unsigned int instance)
85 {
86 struct bcm2835_isp_dev *dev;
87 unsigned int i;
88 @@ -1691,6 +1697,7 @@ static int bcm2835_isp_probe(struct plat
89 if (!dev)
90 return -ENOMEM;
91
92 + *dev_int = dev;
93 dev->dev = &pdev->dev;
94
95 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
96 @@ -1708,7 +1715,7 @@ static int bcm2835_isp_probe(struct plat
97 if (ret) {
98 v4l2_err(&dev->v4l2_dev,
99 "%s: failed to create ril.isp component\n", __func__);
100 - goto error;
101 + return ret;
102 }
103
104 if (dev->component->inputs < BCM2835_ISP_NUM_OUTPUTS ||
105 @@ -1720,7 +1727,7 @@ static int bcm2835_isp_probe(struct plat
106 BCM2835_ISP_NUM_OUTPUTS,
107 dev->component->outputs,
108 BCM2835_ISP_NUM_CAPTURES + BCM2835_ISP_NUM_METADATA);
109 - goto error;
110 + return -EINVAL;
111 }
112
113 atomic_set(&dev->num_streaming, 0);
114 @@ -1728,17 +1735,54 @@ static int bcm2835_isp_probe(struct plat
115 for (i = 0; i < BCM2835_ISP_NUM_NODES; i++) {
116 struct bcm2835_isp_node *node = &dev->node[i];
117
118 - ret = register_node(dev, node, i);
119 + ret = register_node(dev, instance, node, i);
120 if (ret)
121 - goto error;
122 + return ret;
123 }
124
125 ret = media_controller_register(dev);
126 if (ret)
127 - goto error;
128 + return ret;
129 +
130 + return 0;
131 +}
132 +
133 +static int bcm2835_isp_remove(struct platform_device *pdev)
134 +{
135 + struct bcm2835_isp_dev **bcm2835_isp_instances;
136 + unsigned int i;
137 +
138 + bcm2835_isp_instances = platform_get_drvdata(pdev);
139 + for (i = 0; i < BCM2835_ISP_NUM_INSTANCES; i++) {
140 + if (bcm2835_isp_instances[i])
141 + bcm2835_isp_remove_instance(bcm2835_isp_instances[i]);
142 + }
143 +
144 + return 0;
145 +}
146 +
147 +static int bcm2835_isp_probe(struct platform_device *pdev)
148 +{
149 + struct bcm2835_isp_dev **bcm2835_isp_instances;
150 + unsigned int i;
151 + int ret;
152 +
153 + bcm2835_isp_instances = devm_kzalloc(&pdev->dev,
154 + sizeof(bcm2835_isp_instances) *
155 + BCM2835_ISP_NUM_INSTANCES,
156 + GFP_KERNEL);
157 + if (!bcm2835_isp_instances)
158 + return -ENOMEM;
159 +
160 + for (i = 0; i < BCM2835_ISP_NUM_INSTANCES; i++) {
161 + ret = bcm2835_isp_probe_instance(pdev,
162 + &bcm2835_isp_instances[i], i);
163 + if (ret)
164 + goto error;
165 + }
166
167 - platform_set_drvdata(pdev, dev);
168 - v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n", BCM2835_ISP_NAME);
169 + platform_set_drvdata(pdev, bcm2835_isp_instances);
170 + dev_info(&pdev->dev, "Loaded V4L2 %s\n", BCM2835_ISP_NAME);
171 return 0;
172
173 error: