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
36struct 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
60static inline struct dcmipp_device *
61notifier_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 */
67struct 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 */
76struct 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 */
85struct 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
96static 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
118static 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
125static 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
140static 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
170static int dcmipp_graph_init(struct dcmipp_device *dcmipp);
171
172static 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
204err_init_entity:
205	while (i > 0)
206		dcmipp->pipe_cfg->ents[i - 1].release(dcmipp->entity[i - 1]);
207	return ret;
208}
209
210static const struct of_device_id dcmipp_of_match[] = {
211	{ .compatible = "st,stm32mp13-dcmipp", .data = &stm32mp13_pipe_cfg },
212	{ /* end node */ },
213};
214MODULE_DEVICE_TABLE(of, dcmipp_of_match);
215
216static 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
232static 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
255static 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
331static 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
340static 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
368static 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
374static 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
411static 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		if (irq != -EPROBE_DEFER)
444			dev_err(&pdev->dev, "Could not get irq\n");
445		return irq ? irq : -ENXIO;
446	}
447
448	dcmipp->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
449	if (IS_ERR(dcmipp->regs)) {
450		dev_err(&pdev->dev, "Could not map registers\n");
451		return PTR_ERR(dcmipp->regs);
452	}
453
454	ret = devm_request_threaded_irq(&pdev->dev, irq, dcmipp_irq_callback,
455					dcmipp_irq_thread, IRQF_ONESHOT,
456					dev_name(&pdev->dev), dcmipp);
457	if (ret) {
458		dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
459		return ret;
460	}
461
462	/* Reset device */
463	ret = reset_control_assert(rstc);
464	if (ret) {
465		dev_err(&pdev->dev, "Failed to assert the reset line\n");
466		return ret;
467	}
468
469	usleep_range(3000, 5000);
470
471	ret = reset_control_deassert(rstc);
472	if (ret) {
473		dev_err(&pdev->dev, "Failed to deassert the reset line\n");
474		return ret;
475	}
476
477	kclk = devm_clk_get(&pdev->dev, NULL);
478	if (IS_ERR(kclk))
479		return dev_err_probe(&pdev->dev, PTR_ERR(kclk),
480				     "Unable to get kclk\n");
481	dcmipp->kclk = kclk;
482
483	dcmipp->entity = devm_kcalloc(&pdev->dev, dcmipp->pipe_cfg->num_ents,
484				      sizeof(*dcmipp->entity), GFP_KERNEL);
485	if (!dcmipp->entity)
486		return -ENOMEM;
487
488	/* Register the v4l2 struct */
489	ret = v4l2_device_register(&pdev->dev, &dcmipp->v4l2_dev);
490	if (ret) {
491		dev_err(&pdev->dev,
492			"v4l2 device register failed (err=%d)\n", ret);
493		return ret;
494	}
495
496	/* Link the media device within the v4l2_device */
497	dcmipp->v4l2_dev.mdev = &dcmipp->mdev;
498
499	/* Initialize media device */
500	strscpy(dcmipp->mdev.model, DCMIPP_MDEV_MODEL_NAME,
501		sizeof(dcmipp->mdev.model));
502	dcmipp->mdev.dev = &pdev->dev;
503	media_device_init(&dcmipp->mdev);
504
505	/* Initialize subdevs */
506	ret = dcmipp_create_subdevs(dcmipp);
507	if (ret) {
508		media_device_cleanup(&dcmipp->mdev);
509		v4l2_device_unregister(&dcmipp->v4l2_dev);
510		return ret;
511	}
512
513	pm_runtime_enable(dcmipp->dev);
514
515	dev_info(&pdev->dev, "Probe done");
516
517	return 0;
518}
519
520static void dcmipp_remove(struct platform_device *pdev)
521{
522	struct dcmipp_device *dcmipp = platform_get_drvdata(pdev);
523	unsigned int i;
524
525	pm_runtime_disable(&pdev->dev);
526
527	v4l2_async_nf_unregister(&dcmipp->notifier);
528	v4l2_async_nf_cleanup(&dcmipp->notifier);
529
530	for (i = 0; i < dcmipp->pipe_cfg->num_ents; i++)
531		dcmipp->pipe_cfg->ents[i].release(dcmipp->entity[i]);
532
533	media_device_unregister(&dcmipp->mdev);
534	media_device_cleanup(&dcmipp->mdev);
535
536	v4l2_device_unregister(&dcmipp->v4l2_dev);
537}
538
539static int dcmipp_runtime_suspend(struct device *dev)
540{
541	struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
542
543	clk_disable_unprepare(dcmipp->kclk);
544
545	return 0;
546}
547
548static int dcmipp_runtime_resume(struct device *dev)
549{
550	struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
551	int ret;
552
553	ret = clk_prepare_enable(dcmipp->kclk);
554	if (ret)
555		dev_err(dev, "%s: Failed to prepare_enable kclk\n", __func__);
556
557	return ret;
558}
559
560static int dcmipp_suspend(struct device *dev)
561{
562	/* disable clock */
563	pm_runtime_force_suspend(dev);
564
565	/* change pinctrl state */
566	pinctrl_pm_select_sleep_state(dev);
567
568	return 0;
569}
570
571static int dcmipp_resume(struct device *dev)
572{
573	/* restore pinctl default state */
574	pinctrl_pm_select_default_state(dev);
575
576	/* clock enable */
577	pm_runtime_force_resume(dev);
578
579	return 0;
580}
581
582static const struct dev_pm_ops dcmipp_pm_ops = {
583	SYSTEM_SLEEP_PM_OPS(dcmipp_suspend, dcmipp_resume)
584	RUNTIME_PM_OPS(dcmipp_runtime_suspend, dcmipp_runtime_resume, NULL)
585};
586
587static struct platform_driver dcmipp_pdrv = {
588	.probe		= dcmipp_probe,
589	.remove_new	= dcmipp_remove,
590	.driver		= {
591		.name	= DCMIPP_PDEV_NAME,
592		.of_match_table = dcmipp_of_match,
593		.pm = pm_ptr(&dcmipp_pm_ops),
594	},
595};
596
597module_platform_driver(dcmipp_pdrv);
598
599MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@foss.st.com>");
600MODULE_AUTHOR("Alain Volmat <alain.volmat@foss.st.com>");
601MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface with Pixel Processor driver");
602MODULE_LICENSE("GPL");
603