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