aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0574-drivers-bcm2835_isp-Allow-multiple-users-for-the-ISP.patch
blob: a9bb7ecba31055eebc1d5ec38795f2a340629e15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From 3d3cffb860398e43856ac5f2c831cb042be68795 Mon Sep 17 00:00:00 2001
From: Naushir Patuck <naush@raspberrypi.com>
Date: Tue, 16 Nov 2021 12:38:44 +0000
Subject: [PATCH] drivers: bcm2835_isp: Allow multiple users for the
 ISP driver.

Add a second (identical) set of device nodes to allow concurrent use of the ISP
hardware by another user. This change effectively creates a second state
structure (struct bcm2835_isp_dev) to maintain independent state for the second
user. Node and media entity names are appened with the instance index
appropriately.

Further users can be added by changing the BCM2835_ISP_NUM_INSTANCES define.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
---
 .../bcm2835-isp/bcm2835-v4l2-isp.c            | 76 +++++++++++++++----
 1 file changed, 60 insertions(+), 16 deletions(-)

--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
@@ -26,13 +26,19 @@
 #include "bcm2835-isp-ctrls.h"
 #include "bcm2835-isp-fmts.h"
 
+/*
+ * We want to instantiate 2 independent instances allowing 2 simultaneous users
+ * of the ISP hardware.
+ */
+#define BCM2835_ISP_NUM_INSTANCES 2
+
 static unsigned int debug;
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-static unsigned int video_nr = 13;
-module_param(video_nr, uint, 0644);
-MODULE_PARM_DESC(video_nr, "base video device number");
+static unsigned int video_nr[BCM2835_ISP_NUM_INSTANCES] = { 13, 20 };
+module_param_array(video_nr, uint, NULL, 0644);
+MODULE_PARM_DESC(video_nr, "base video device numbers");
 
 #define BCM2835_ISP_NAME "bcm2835-isp"
 #define BCM2835_ISP_ENTITY_NAME_LEN 32
@@ -1279,6 +1285,7 @@ static int bcm2835_isp_get_supported_fmt
  * or output nodes.
  */
 static int register_node(struct bcm2835_isp_dev *dev,
+			 unsigned int instance,
 			 struct bcm2835_isp_node *node,
 			 int index)
 {
@@ -1439,7 +1446,7 @@ static int register_node(struct bcm2835_
 	snprintf(vfd->name, sizeof(node->vfd.name), "%s-%s%d", BCM2835_ISP_NAME,
 		 node->name, node->id);
 
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr + index);
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr[instance]);
 	if (ret) {
 		v4l2_err(&dev->v4l2_dev,
 			 "Failed to register video %s[%d] device node\n",
@@ -1660,9 +1667,8 @@ done:
 	return ret;
 }
 
-static int bcm2835_isp_remove(struct platform_device *pdev)
+static void bcm2835_isp_remove_instance(struct bcm2835_isp_dev *dev)
 {
-	struct bcm2835_isp_dev *dev = platform_get_drvdata(pdev);
 	unsigned int i;
 
 	media_controller_unregister(dev);
@@ -1677,11 +1683,11 @@ static int bcm2835_isp_remove(struct pla
 					      dev->component);
 
 	vchiq_mmal_finalise(dev->mmal_instance);
-
-	return 0;
 }
 
-static int bcm2835_isp_probe(struct platform_device *pdev)
+static int bcm2835_isp_probe_instance(struct platform_device *pdev,
+				      struct bcm2835_isp_dev **dev_int,
+				      unsigned int instance)
 {
 	struct bcm2835_isp_dev *dev;
 	unsigned int i;
@@ -1691,6 +1697,7 @@ static int bcm2835_isp_probe(struct plat
 	if (!dev)
 		return -ENOMEM;
 
+	*dev_int = dev;
 	dev->dev = &pdev->dev;
 
 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
@@ -1708,7 +1715,7 @@ static int bcm2835_isp_probe(struct plat
 	if (ret) {
 		v4l2_err(&dev->v4l2_dev,
 			 "%s: failed to create ril.isp component\n", __func__);
-		goto error;
+		return ret;
 	}
 
 	if (dev->component->inputs < BCM2835_ISP_NUM_OUTPUTS ||
@@ -1720,7 +1727,7 @@ static int bcm2835_isp_probe(struct plat
 			  BCM2835_ISP_NUM_OUTPUTS,
 			  dev->component->outputs,
 			  BCM2835_ISP_NUM_CAPTURES + BCM2835_ISP_NUM_METADATA);
-		goto error;
+		return -EINVAL;
 	}
 
 	atomic_set(&dev->num_streaming, 0);
@@ -1728,17 +1735,54 @@ static int bcm2835_isp_probe(struct plat
 	for (i = 0; i < BCM2835_ISP_NUM_NODES; i++) {
 		struct bcm2835_isp_node *node = &dev->node[i];
 
-		ret = register_node(dev, node, i);
+		ret = register_node(dev, instance, node, i);
 		if (ret)
-			goto error;
+			return ret;
 	}
 
 	ret = media_controller_register(dev);
 	if (ret)
-		goto error;
+		return ret;
+
+	return 0;
+}
+
+static int bcm2835_isp_remove(struct platform_device *pdev)
+{
+	struct bcm2835_isp_dev **bcm2835_isp_instances;
+	unsigned int i;
+
+	bcm2835_isp_instances = platform_get_drvdata(pdev);
+	for (i = 0; i < BCM2835_ISP_NUM_INSTANCES; i++) {
+		if (bcm2835_isp_instances[i])
+			bcm2835_isp_remove_instance(bcm2835_isp_instances[i]);
+	}
+
+	return 0;
+}
+
+static int bcm2835_isp_probe(struct platform_device *pdev)
+{
+	struct bcm2835_isp_dev **bcm2835_isp_instances;
+	unsigned int i;
+	int ret;
+
+	bcm2835_isp_instances = devm_kzalloc(&pdev->dev,
+					     sizeof(bcm2835_isp_instances) *
+						      BCM2835_ISP_NUM_INSTANCES,
+					     GFP_KERNEL);
+	if (!bcm2835_isp_instances)
+		return -ENOMEM;
+
+	for (i = 0; i < BCM2835_ISP_NUM_INSTANCES; i++) {
+		ret = bcm2835_isp_probe_instance(pdev,
+						 &bcm2835_isp_instances[i], i);
+		if (ret)
+			goto error;
+	}
 
-	platform_set_drvdata(pdev, dev);
-	v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n", BCM2835_ISP_NAME);
+	platform_set_drvdata(pdev, bcm2835_isp_instances);
+	dev_info(&pdev->dev, "Loaded V4L2 %s\n", BCM2835_ISP_NAME);
 	return 0;
 
 error: