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 <hugues.fruchet@foss.st.com>
7 * Alain Volmat <alain.volmat@foss.st.com>
8 * for STMicroelectronics.
9 */
10
11 #include <linux/clk.h>
12 #include <linux/delay.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/pinctrl/consumer.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/property.h>
19 #include <linux/reset.h>
20 #include <media/media-device.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-fwnode.h>
23
24 #include "dcmipp-common.h"
25
26 #define DCMIPP_MDEV_MODEL_NAME "DCMIPP MDEV"
27
28 #define DCMIPP_ENT_LINK(src, srcpad, sink, sinkpad, link_flags) { \
29 .src_ent = src, \
30 .src_pad = srcpad, \
31 .sink_ent = sink, \
32 .sink_pad = sinkpad, \
33 .flags = link_flags, \
34 }
35
36 struct dcmipp_device {
37 /* The platform device */
38 struct platform_device pdev;
39 struct device *dev;
40
41 /* Hardware resources */
42 void __iomem *regs;
43 struct clk *kclk;
44
45 /* The pipeline configuration */
46 const struct dcmipp_pipeline_config *pipe_cfg;
47
48 /* The Associated media_device parent */
49 struct media_device mdev;
50
51 /* Internal v4l2 parent device*/
52 struct v4l2_device v4l2_dev;
53
54 /* Entities */
55 struct dcmipp_ent_device **entity;
56
57 struct v4l2_async_notifier notifier;
58 };
59
60 static inline struct dcmipp_device *
notifier_to_dcmipp(struct v4l2_async_notifier * n)61 notifier_to_dcmipp(struct v4l2_async_notifier *n)
62 {
63 return container_of(n, struct dcmipp_device, notifier);
64 }
65
66 /* Structure which describes individual configuration for each entity */
67 struct dcmipp_ent_config {
68 const char *name;
69 struct dcmipp_ent_device *(*init)
70 (struct device *dev, const char *entity_name,
71 struct v4l2_device *v4l2_dev, void __iomem *regs);
72 void (*release)(struct dcmipp_ent_device *ved);
73 };
74
75 /* Structure which describes links between entities */
76 struct dcmipp_ent_link {
77 unsigned int src_ent;
78 u16 src_pad;
79 unsigned int sink_ent;
80 u16 sink_pad;
81 u32 flags;
82 };
83
84 /* Structure which describes the whole topology */
85 struct dcmipp_pipeline_config {
86 const struct dcmipp_ent_config *ents;
87 size_t num_ents;
88 const struct dcmipp_ent_link *links;
89 size_t num_links;
90 };
91
92 /* --------------------------------------------------------------------------
93 * Topology Configuration
94 */
95
96 static const struct dcmipp_ent_config stm32mp13_ent_config[] = {
97 {
98 .name = "dcmipp_parallel",
99 .init = dcmipp_par_ent_init,
100 .release = dcmipp_par_ent_release,
101 },
102 {
103 .name = "dcmipp_dump_postproc",
104 .init = dcmipp_byteproc_ent_init,
105 .release = dcmipp_byteproc_ent_release,
106 },
107 {
108 .name = "dcmipp_dump_capture",
109 .init = dcmipp_bytecap_ent_init,
110 .release = dcmipp_bytecap_ent_release,
111 },
112 };
113
114 #define ID_PARALLEL 0
115 #define ID_DUMP_BYTEPROC 1
116 #define ID_DUMP_CAPTURE 2
117
118 static const struct dcmipp_ent_link stm32mp13_ent_links[] = {
119 DCMIPP_ENT_LINK(ID_PARALLEL, 1, ID_DUMP_BYTEPROC, 0,
120 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
121 DCMIPP_ENT_LINK(ID_DUMP_BYTEPROC, 1, ID_DUMP_CAPTURE, 0,
122 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
123 };
124
125 static const struct dcmipp_pipeline_config stm32mp13_pipe_cfg = {
126 .ents = stm32mp13_ent_config,
127 .num_ents = ARRAY_SIZE(stm32mp13_ent_config),
128 .links = stm32mp13_ent_links,
129 .num_links = ARRAY_SIZE(stm32mp13_ent_links)
130 };
131
132 #define LINK_FLAG_TO_STR(f) ((f) == 0 ? "" :\
133 (f) == MEDIA_LNK_FL_ENABLED ? "ENABLED" :\
134 (f) == MEDIA_LNK_FL_IMMUTABLE ? "IMMUTABLE" :\
135 (f) == (MEDIA_LNK_FL_ENABLED |\
136 MEDIA_LNK_FL_IMMUTABLE) ?\
137 "ENABLED, IMMUTABLE" :\
138 "UNKNOWN")
139
dcmipp_create_links(struct dcmipp_device * dcmipp)140 static int dcmipp_create_links(struct dcmipp_device *dcmipp)
141 {
142 unsigned int i;
143 int ret;
144
145 /* Initialize the links between entities */
146 for (i = 0; i < dcmipp->pipe_cfg->num_links; i++) {
147 const struct dcmipp_ent_link *link =
148 &dcmipp->pipe_cfg->links[i];
149 struct dcmipp_ent_device *ved_src =
150 dcmipp->entity[link->src_ent];
151 struct dcmipp_ent_device *ved_sink =
152 dcmipp->entity[link->sink_ent];
153
154 dev_dbg(dcmipp->dev, "Create link \"%s\":%d -> %d:\"%s\" [%s]\n",
155 dcmipp->pipe_cfg->ents[link->src_ent].name,
156 link->src_pad, link->sink_pad,
157 dcmipp->pipe_cfg->ents[link->sink_ent].name,
158 LINK_FLAG_TO_STR(link->flags));
159
160 ret = media_create_pad_link(ved_src->ent, link->src_pad,
161 ved_sink->ent, link->sink_pad,
162 link->flags);
163 if (ret)
164 return ret;
165 }
166
167 return 0;
168 }
169
170 static int dcmipp_graph_init(struct dcmipp_device *dcmipp);
171
dcmipp_create_subdevs(struct dcmipp_device * dcmipp)172 static int dcmipp_create_subdevs(struct dcmipp_device *dcmipp)
173 {
174 int ret, i;
175
176 /* Call all subdev inits */
177 for (i = 0; i < dcmipp->pipe_cfg->num_ents; i++) {
178 const char *name = dcmipp->pipe_cfg->ents[i].name;
179
180 dev_dbg(dcmipp->dev, "add subdev %s\n", name);
181 dcmipp->entity[i] =
182 dcmipp->pipe_cfg->ents[i].init(dcmipp->dev, name,
183 &dcmipp->v4l2_dev,
184 dcmipp->regs);
185 if (IS_ERR(dcmipp->entity[i])) {
186 dev_err(dcmipp->dev, "failed to init subdev %s\n",
187 name);
188 ret = PTR_ERR(dcmipp->entity[i]);
189 goto err_init_entity;
190 }
191 }
192
193 /* Initialize links */
194 ret = dcmipp_create_links(dcmipp);
195 if (ret)
196 goto err_init_entity;
197
198 ret = dcmipp_graph_init(dcmipp);
199 if (ret < 0)
200 goto err_init_entity;
201
202 return 0;
203
204 err_init_entity:
205 while (i-- > 0)
206 dcmipp->pipe_cfg->ents[i].release(dcmipp->entity[i]);
207 return ret;
208 }
209
210 static const struct of_device_id dcmipp_of_match[] = {
211 { .compatible = "st,stm32mp13-dcmipp", .data = &stm32mp13_pipe_cfg },
212 { /* end node */ },
213 };
214 MODULE_DEVICE_TABLE(of, dcmipp_of_match);
215
dcmipp_irq_thread(int irq,void * arg)216 static irqreturn_t dcmipp_irq_thread(int irq, void *arg)
217 {
218 struct dcmipp_device *dcmipp = arg;
219 struct dcmipp_ent_device *ved;
220 unsigned int i;
221
222 /* Call irq thread of each entities of pipeline */
223 for (i = 0; i < dcmipp->pipe_cfg->num_ents; i++) {
224 ved = dcmipp->entity[i];
225 if (ved->thread_fn && ved->handler_ret == IRQ_WAKE_THREAD)
226 ved->thread_fn(irq, ved);
227 }
228
229 return IRQ_HANDLED;
230 }
231
dcmipp_irq_callback(int irq,void * arg)232 static irqreturn_t dcmipp_irq_callback(int irq, void *arg)
233 {
234 struct dcmipp_device *dcmipp = arg;
235 struct dcmipp_ent_device *ved;
236 irqreturn_t ret = IRQ_HANDLED;
237 unsigned int i;
238
239 /* Call irq handler of each entities of pipeline */
240 for (i = 0; i < dcmipp->pipe_cfg->num_ents; i++) {
241 ved = dcmipp->entity[i];
242 if (ved->handler)
243 ved->handler_ret = ved->handler(irq, ved);
244 else if (ved->thread_fn)
245 ved->handler_ret = IRQ_WAKE_THREAD;
246 else
247 ved->handler_ret = IRQ_HANDLED;
248 if (ved->handler_ret != IRQ_HANDLED)
249 ret = ved->handler_ret;
250 }
251
252 return ret;
253 }
254
dcmipp_graph_notify_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * subdev,struct v4l2_async_connection * asd)255 static int dcmipp_graph_notify_bound(struct v4l2_async_notifier *notifier,
256 struct v4l2_subdev *subdev,
257 struct v4l2_async_connection *asd)
258 {
259 struct dcmipp_device *dcmipp = notifier_to_dcmipp(notifier);
260 unsigned int ret;
261 int src_pad;
262 struct dcmipp_ent_device *sink;
263 struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_PARALLEL };
264 struct fwnode_handle *ep;
265
266 dev_dbg(dcmipp->dev, "Subdev \"%s\" bound\n", subdev->name);
267
268 /*
269 * Link this sub-device to DCMIPP, it could be
270 * a parallel camera sensor or a CSI-2 to parallel bridge
271 */
272 src_pad = media_entity_get_fwnode_pad(&subdev->entity,
273 subdev->fwnode,
274 MEDIA_PAD_FL_SOURCE);
275
276 /* Get bus characteristics from devicetree */
277 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dcmipp->dev), 0, 0,
278 FWNODE_GRAPH_ENDPOINT_NEXT);
279 if (!ep) {
280 dev_err(dcmipp->dev, "Could not find the endpoint\n");
281 return -ENODEV;
282 }
283
284 /* Check for parallel bus-type first, then bt656 */
285 ret = v4l2_fwnode_endpoint_parse(ep, &vep);
286 if (ret) {
287 vep.bus_type = V4L2_MBUS_BT656;
288 ret = v4l2_fwnode_endpoint_parse(ep, &vep);
289 if (ret) {
290 dev_err(dcmipp->dev, "Could not parse the endpoint\n");
291 fwnode_handle_put(ep);
292 return ret;
293 }
294 }
295
296 fwnode_handle_put(ep);
297
298 if (vep.bus.parallel.bus_width == 0) {
299 dev_err(dcmipp->dev, "Invalid parallel interface bus-width\n");
300 return -ENODEV;
301 }
302
303 /* Only 8 bits bus width supported with BT656 bus */
304 if (vep.bus_type == V4L2_MBUS_BT656 &&
305 vep.bus.parallel.bus_width != 8) {
306 dev_err(dcmipp->dev, "BT656 bus conflicts with %u bits bus width (8 bits required)\n",
307 vep.bus.parallel.bus_width);
308 return -ENODEV;
309 }
310
311 /* Parallel input device detected, connect it to parallel subdev */
312 sink = dcmipp->entity[ID_PARALLEL];
313 sink->bus.flags = vep.bus.parallel.flags;
314 sink->bus.bus_width = vep.bus.parallel.bus_width;
315 sink->bus.data_shift = vep.bus.parallel.data_shift;
316 sink->bus_type = vep.bus_type;
317 ret = media_create_pad_link(&subdev->entity, src_pad, sink->ent, 0,
318 MEDIA_LNK_FL_IMMUTABLE |
319 MEDIA_LNK_FL_ENABLED);
320 if (ret) {
321 dev_err(dcmipp->dev, "Failed to create media pad link with subdev \"%s\"\n",
322 subdev->name);
323 return ret;
324 }
325
326 dev_dbg(dcmipp->dev, "DCMIPP is now linked to \"%s\"\n", subdev->name);
327
328 return 0;
329 }
330
dcmipp_graph_notify_unbind(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_connection * asd)331 static void dcmipp_graph_notify_unbind(struct v4l2_async_notifier *notifier,
332 struct v4l2_subdev *sd,
333 struct v4l2_async_connection *asd)
334 {
335 struct dcmipp_device *dcmipp = notifier_to_dcmipp(notifier);
336
337 dev_dbg(dcmipp->dev, "Removing %s\n", sd->name);
338 }
339
dcmipp_graph_notify_complete(struct v4l2_async_notifier * notifier)340 static int dcmipp_graph_notify_complete(struct v4l2_async_notifier *notifier)
341 {
342 struct dcmipp_device *dcmipp = notifier_to_dcmipp(notifier);
343 int ret;
344
345 /* Register the media device */
346 ret = media_device_register(&dcmipp->mdev);
347 if (ret) {
348 dev_err(dcmipp->mdev.dev,
349 "media device register failed (err=%d)\n", ret);
350 return ret;
351 }
352
353 /* Expose all subdev's nodes*/
354 ret = v4l2_device_register_subdev_nodes(&dcmipp->v4l2_dev);
355 if (ret) {
356 dev_err(dcmipp->mdev.dev,
357 "dcmipp subdev nodes registration failed (err=%d)\n",
358 ret);
359 media_device_unregister(&dcmipp->mdev);
360 return ret;
361 }
362
363 dev_dbg(dcmipp->dev, "Notify complete !\n");
364
365 return 0;
366 }
367
368 static const struct v4l2_async_notifier_operations dcmipp_graph_notify_ops = {
369 .bound = dcmipp_graph_notify_bound,
370 .unbind = dcmipp_graph_notify_unbind,
371 .complete = dcmipp_graph_notify_complete,
372 };
373
dcmipp_graph_init(struct dcmipp_device * dcmipp)374 static int dcmipp_graph_init(struct dcmipp_device *dcmipp)
375 {
376 struct v4l2_async_connection *asd;
377 struct fwnode_handle *ep;
378 int ret;
379
380 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dcmipp->dev), 0, 0,
381 FWNODE_GRAPH_ENDPOINT_NEXT);
382 if (!ep) {
383 dev_err(dcmipp->dev, "Failed to get next endpoint\n");
384 return -EINVAL;
385 }
386
387 v4l2_async_nf_init(&dcmipp->notifier, &dcmipp->v4l2_dev);
388
389 asd = v4l2_async_nf_add_fwnode_remote(&dcmipp->notifier, ep,
390 struct v4l2_async_connection);
391
392 fwnode_handle_put(ep);
393
394 if (IS_ERR(asd)) {
395 dev_err(dcmipp->dev, "Failed to add fwnode remote subdev\n");
396 return PTR_ERR(asd);
397 }
398
399 dcmipp->notifier.ops = &dcmipp_graph_notify_ops;
400
401 ret = v4l2_async_nf_register(&dcmipp->notifier);
402 if (ret < 0) {
403 dev_err(dcmipp->dev, "Failed to register notifier\n");
404 v4l2_async_nf_cleanup(&dcmipp->notifier);
405 return ret;
406 }
407
408 return 0;
409 }
410
dcmipp_probe(struct platform_device * pdev)411 static int dcmipp_probe(struct platform_device *pdev)
412 {
413 struct dcmipp_device *dcmipp;
414 struct clk *kclk;
415 const struct dcmipp_pipeline_config *pipe_cfg;
416 struct reset_control *rstc;
417 int irq;
418 int ret;
419
420 dcmipp = devm_kzalloc(&pdev->dev, sizeof(*dcmipp), GFP_KERNEL);
421 if (!dcmipp)
422 return -ENOMEM;
423
424 dcmipp->dev = &pdev->dev;
425
426 pipe_cfg = device_get_match_data(dcmipp->dev);
427 if (!pipe_cfg) {
428 dev_err(&pdev->dev, "Can't get device data\n");
429 return -ENODEV;
430 }
431 dcmipp->pipe_cfg = pipe_cfg;
432
433 platform_set_drvdata(pdev, dcmipp);
434
435 /* Get hardware resources from devicetree */
436 rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
437 if (IS_ERR(rstc))
438 return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
439 "Could not get reset control\n");
440
441 irq = platform_get_irq(pdev, 0);
442 if (irq < 0)
443 return irq;
444
445 dcmipp->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
446 if (IS_ERR(dcmipp->regs)) {
447 dev_err(&pdev->dev, "Could not map registers\n");
448 return PTR_ERR(dcmipp->regs);
449 }
450
451 ret = devm_request_threaded_irq(&pdev->dev, irq, dcmipp_irq_callback,
452 dcmipp_irq_thread, IRQF_ONESHOT,
453 dev_name(&pdev->dev), dcmipp);
454 if (ret) {
455 dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
456 return ret;
457 }
458
459 /* Reset device */
460 ret = reset_control_assert(rstc);
461 if (ret) {
462 dev_err(&pdev->dev, "Failed to assert the reset line\n");
463 return ret;
464 }
465
466 usleep_range(3000, 5000);
467
468 ret = reset_control_deassert(rstc);
469 if (ret) {
470 dev_err(&pdev->dev, "Failed to deassert the reset line\n");
471 return ret;
472 }
473
474 kclk = devm_clk_get(&pdev->dev, NULL);
475 if (IS_ERR(kclk))
476 return dev_err_probe(&pdev->dev, PTR_ERR(kclk),
477 "Unable to get kclk\n");
478 dcmipp->kclk = kclk;
479
480 dcmipp->entity = devm_kcalloc(&pdev->dev, dcmipp->pipe_cfg->num_ents,
481 sizeof(*dcmipp->entity), GFP_KERNEL);
482 if (!dcmipp->entity)
483 return -ENOMEM;
484
485 /* Register the v4l2 struct */
486 ret = v4l2_device_register(&pdev->dev, &dcmipp->v4l2_dev);
487 if (ret) {
488 dev_err(&pdev->dev,
489 "v4l2 device register failed (err=%d)\n", ret);
490 return ret;
491 }
492
493 /* Link the media device within the v4l2_device */
494 dcmipp->v4l2_dev.mdev = &dcmipp->mdev;
495
496 /* Initialize media device */
497 strscpy(dcmipp->mdev.model, DCMIPP_MDEV_MODEL_NAME,
498 sizeof(dcmipp->mdev.model));
499 dcmipp->mdev.dev = &pdev->dev;
500 media_device_init(&dcmipp->mdev);
501
502 /* Initialize subdevs */
503 ret = dcmipp_create_subdevs(dcmipp);
504 if (ret) {
505 media_device_cleanup(&dcmipp->mdev);
506 v4l2_device_unregister(&dcmipp->v4l2_dev);
507 return ret;
508 }
509
510 pm_runtime_enable(dcmipp->dev);
511
512 dev_info(&pdev->dev, "Probe done");
513
514 return 0;
515 }
516
dcmipp_remove(struct platform_device * pdev)517 static void dcmipp_remove(struct platform_device *pdev)
518 {
519 struct dcmipp_device *dcmipp = platform_get_drvdata(pdev);
520 unsigned int i;
521
522 pm_runtime_disable(&pdev->dev);
523
524 v4l2_async_nf_unregister(&dcmipp->notifier);
525 v4l2_async_nf_cleanup(&dcmipp->notifier);
526
527 for (i = 0; i < dcmipp->pipe_cfg->num_ents; i++)
528 dcmipp->pipe_cfg->ents[i].release(dcmipp->entity[i]);
529
530 media_device_unregister(&dcmipp->mdev);
531 media_device_cleanup(&dcmipp->mdev);
532
533 v4l2_device_unregister(&dcmipp->v4l2_dev);
534 }
535
dcmipp_runtime_suspend(struct device * dev)536 static int dcmipp_runtime_suspend(struct device *dev)
537 {
538 struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
539
540 clk_disable_unprepare(dcmipp->kclk);
541
542 return 0;
543 }
544
dcmipp_runtime_resume(struct device * dev)545 static int dcmipp_runtime_resume(struct device *dev)
546 {
547 struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
548 int ret;
549
550 ret = clk_prepare_enable(dcmipp->kclk);
551 if (ret)
552 dev_err(dev, "%s: Failed to prepare_enable kclk\n", __func__);
553
554 return ret;
555 }
556
dcmipp_suspend(struct device * dev)557 static int dcmipp_suspend(struct device *dev)
558 {
559 /* disable clock */
560 pm_runtime_force_suspend(dev);
561
562 /* change pinctrl state */
563 pinctrl_pm_select_sleep_state(dev);
564
565 return 0;
566 }
567
dcmipp_resume(struct device * dev)568 static int dcmipp_resume(struct device *dev)
569 {
570 /* restore pinctl default state */
571 pinctrl_pm_select_default_state(dev);
572
573 /* clock enable */
574 pm_runtime_force_resume(dev);
575
576 return 0;
577 }
578
579 static const struct dev_pm_ops dcmipp_pm_ops = {
580 SYSTEM_SLEEP_PM_OPS(dcmipp_suspend, dcmipp_resume)
581 RUNTIME_PM_OPS(dcmipp_runtime_suspend, dcmipp_runtime_resume, NULL)
582 };
583
584 static struct platform_driver dcmipp_pdrv = {
585 .probe = dcmipp_probe,
586 .remove_new = dcmipp_remove,
587 .driver = {
588 .name = DCMIPP_PDEV_NAME,
589 .of_match_table = dcmipp_of_match,
590 .pm = pm_ptr(&dcmipp_pm_ops),
591 },
592 };
593
594 module_platform_driver(dcmipp_pdrv);
595
596 MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@foss.st.com>");
597 MODULE_AUTHOR("Alain Volmat <alain.volmat@foss.st.com>");
598 MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface with Pixel Processor driver");
599 MODULE_LICENSE("GPL");
600