1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2021-2022 Bootlin
4  * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/err.h>
10 #include <linux/interrupt.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
17 #include <linux/reset.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-mc.h>
20 
21 #include "sun6i_isp.h"
22 #include "sun6i_isp_capture.h"
23 #include "sun6i_isp_params.h"
24 #include "sun6i_isp_proc.h"
25 #include "sun6i_isp_reg.h"
26 
27 /* Helpers */
28 
29 u32 sun6i_isp_load_read(struct sun6i_isp_device *isp_dev, u32 offset)
30 {
31 	u32 *data = (u32 *)(isp_dev->tables.load.data + offset);
32 
33 	return *data;
34 }
35 
36 void sun6i_isp_load_write(struct sun6i_isp_device *isp_dev, u32 offset,
37 			  u32 value)
38 {
39 	u32 *data = (u32 *)(isp_dev->tables.load.data + offset);
40 
41 	*data = value;
42 }
43 
44 /* State */
45 
46 /*
47  * The ISP works with a load buffer, which gets copied to the actual registers
48  * by the hardware before processing a frame when a specific flag is set.
49  * This is represented by tracking the ISP state in the different parts of
50  * the code with explicit sync points:
51  * - state update: to update the load buffer for the next frame if necessary;
52  * - state complete: to indicate that the state update was applied.
53  */
54 
55 static void sun6i_isp_state_ready(struct sun6i_isp_device *isp_dev)
56 {
57 	struct regmap *regmap = isp_dev->regmap;
58 	u32 value;
59 
60 	regmap_read(regmap, SUN6I_ISP_FE_CTRL_REG, &value);
61 	value |= SUN6I_ISP_FE_CTRL_PARA_READY;
62 	regmap_write(regmap, SUN6I_ISP_FE_CTRL_REG, value);
63 }
64 
65 static void sun6i_isp_state_complete(struct sun6i_isp_device *isp_dev)
66 {
67 	unsigned long flags;
68 
69 	spin_lock_irqsave(&isp_dev->state_lock, flags);
70 
71 	sun6i_isp_capture_state_complete(isp_dev);
72 	sun6i_isp_params_state_complete(isp_dev);
73 
74 	spin_unlock_irqrestore(&isp_dev->state_lock, flags);
75 }
76 
77 void sun6i_isp_state_update(struct sun6i_isp_device *isp_dev, bool ready_hold)
78 {
79 	bool update = false;
80 	unsigned long flags;
81 
82 	spin_lock_irqsave(&isp_dev->state_lock, flags);
83 
84 	sun6i_isp_capture_state_update(isp_dev, &update);
85 	sun6i_isp_params_state_update(isp_dev, &update);
86 
87 	if (update && !ready_hold)
88 		sun6i_isp_state_ready(isp_dev);
89 
90 	spin_unlock_irqrestore(&isp_dev->state_lock, flags);
91 }
92 
93 /* Tables */
94 
95 static int sun6i_isp_table_setup(struct sun6i_isp_device *isp_dev,
96 				 struct sun6i_isp_table *table)
97 {
98 	table->data = dma_alloc_coherent(isp_dev->dev, table->size,
99 					 &table->address, GFP_KERNEL);
100 	if (!table->data)
101 		return -ENOMEM;
102 
103 	return 0;
104 }
105 
106 static void sun6i_isp_table_cleanup(struct sun6i_isp_device *isp_dev,
107 				    struct sun6i_isp_table *table)
108 {
109 	dma_free_coherent(isp_dev->dev, table->size, table->data,
110 			  table->address);
111 }
112 
113 void sun6i_isp_tables_configure(struct sun6i_isp_device *isp_dev)
114 {
115 	struct regmap *regmap = isp_dev->regmap;
116 
117 	regmap_write(regmap, SUN6I_ISP_REG_LOAD_ADDR_REG,
118 		     SUN6I_ISP_ADDR_VALUE(isp_dev->tables.load.address));
119 
120 	regmap_write(regmap, SUN6I_ISP_REG_SAVE_ADDR_REG,
121 		     SUN6I_ISP_ADDR_VALUE(isp_dev->tables.save.address));
122 
123 	regmap_write(regmap, SUN6I_ISP_LUT_TABLE_ADDR_REG,
124 		     SUN6I_ISP_ADDR_VALUE(isp_dev->tables.lut.address));
125 
126 	regmap_write(regmap, SUN6I_ISP_DRC_TABLE_ADDR_REG,
127 		     SUN6I_ISP_ADDR_VALUE(isp_dev->tables.drc.address));
128 
129 	regmap_write(regmap, SUN6I_ISP_STATS_ADDR_REG,
130 		     SUN6I_ISP_ADDR_VALUE(isp_dev->tables.stats.address));
131 }
132 
133 static int sun6i_isp_tables_setup(struct sun6i_isp_device *isp_dev,
134 				  const struct sun6i_isp_variant *variant)
135 {
136 	struct sun6i_isp_tables *tables = &isp_dev->tables;
137 	int ret;
138 
139 	tables->load.size = variant->table_load_save_size;
140 	ret = sun6i_isp_table_setup(isp_dev, &tables->load);
141 	if (ret)
142 		return ret;
143 
144 	tables->save.size = variant->table_load_save_size;
145 	ret = sun6i_isp_table_setup(isp_dev, &tables->save);
146 	if (ret)
147 		return ret;
148 
149 	tables->lut.size = variant->table_lut_size;
150 	ret = sun6i_isp_table_setup(isp_dev, &tables->lut);
151 	if (ret)
152 		return ret;
153 
154 	tables->drc.size = variant->table_drc_size;
155 	ret = sun6i_isp_table_setup(isp_dev, &tables->drc);
156 	if (ret)
157 		return ret;
158 
159 	tables->stats.size = variant->table_stats_size;
160 	ret = sun6i_isp_table_setup(isp_dev, &tables->stats);
161 	if (ret)
162 		return ret;
163 
164 	return 0;
165 }
166 
167 static void sun6i_isp_tables_cleanup(struct sun6i_isp_device *isp_dev)
168 {
169 	struct sun6i_isp_tables *tables = &isp_dev->tables;
170 
171 	sun6i_isp_table_cleanup(isp_dev, &tables->stats);
172 	sun6i_isp_table_cleanup(isp_dev, &tables->drc);
173 	sun6i_isp_table_cleanup(isp_dev, &tables->lut);
174 	sun6i_isp_table_cleanup(isp_dev, &tables->save);
175 	sun6i_isp_table_cleanup(isp_dev, &tables->load);
176 }
177 
178 /* Media */
179 
180 static const struct media_device_ops sun6i_isp_media_ops = {
181 	.link_notify = v4l2_pipeline_link_notify,
182 };
183 
184 /* V4L2 */
185 
186 static int sun6i_isp_v4l2_setup(struct sun6i_isp_device *isp_dev)
187 {
188 	struct sun6i_isp_v4l2 *v4l2 = &isp_dev->v4l2;
189 	struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
190 	struct media_device *media_dev = &v4l2->media_dev;
191 	struct device *dev = isp_dev->dev;
192 	int ret;
193 
194 	/* Media Device */
195 
196 	strscpy(media_dev->model, SUN6I_ISP_DESCRIPTION,
197 		sizeof(media_dev->model));
198 	media_dev->ops = &sun6i_isp_media_ops;
199 	media_dev->hw_revision = 0;
200 	media_dev->dev = dev;
201 
202 	media_device_init(media_dev);
203 
204 	ret = media_device_register(media_dev);
205 	if (ret) {
206 		dev_err(dev, "failed to register media device\n");
207 		return ret;
208 	}
209 
210 	/* V4L2 Device */
211 
212 	v4l2_dev->mdev = media_dev;
213 
214 	ret = v4l2_device_register(dev, v4l2_dev);
215 	if (ret) {
216 		dev_err(dev, "failed to register v4l2 device\n");
217 		goto error_media;
218 	}
219 
220 	return 0;
221 
222 error_media:
223 	media_device_unregister(media_dev);
224 	media_device_cleanup(media_dev);
225 
226 	return ret;
227 }
228 
229 static void sun6i_isp_v4l2_cleanup(struct sun6i_isp_device *isp_dev)
230 {
231 	struct sun6i_isp_v4l2 *v4l2 = &isp_dev->v4l2;
232 
233 	media_device_unregister(&v4l2->media_dev);
234 	v4l2_device_unregister(&v4l2->v4l2_dev);
235 	media_device_cleanup(&v4l2->media_dev);
236 }
237 
238 /* Platform */
239 
240 static irqreturn_t sun6i_isp_interrupt(int irq, void *private)
241 {
242 	struct sun6i_isp_device *isp_dev = private;
243 	struct regmap *regmap = isp_dev->regmap;
244 	u32 status = 0, enable = 0;
245 
246 	regmap_read(regmap, SUN6I_ISP_FE_INT_STA_REG, &status);
247 	regmap_read(regmap, SUN6I_ISP_FE_INT_EN_REG, &enable);
248 
249 	if (!status)
250 		return IRQ_NONE;
251 	else if (!(status & enable))
252 		goto complete;
253 
254 	/*
255 	 * The ISP working cycle starts with a params-load, which makes the
256 	 * state from the load buffer active. Then it starts processing the
257 	 * frame and gives a finish interrupt. Soon after that, the next state
258 	 * coming from the load buffer will be applied for the next frame,
259 	 * giving a params-load as well.
260 	 *
261 	 * Because both frame finish and params-load are received almost
262 	 * at the same time (one ISR call), handle them in chronology order.
263 	 */
264 
265 	if (status & SUN6I_ISP_FE_INT_STA_FINISH)
266 		sun6i_isp_capture_finish(isp_dev);
267 
268 	if (status & SUN6I_ISP_FE_INT_STA_PARA_LOAD) {
269 		sun6i_isp_state_complete(isp_dev);
270 		sun6i_isp_state_update(isp_dev, false);
271 	}
272 
273 complete:
274 	regmap_write(regmap, SUN6I_ISP_FE_INT_STA_REG, status);
275 
276 	return IRQ_HANDLED;
277 }
278 
279 static int sun6i_isp_suspend(struct device *dev)
280 {
281 	struct sun6i_isp_device *isp_dev = dev_get_drvdata(dev);
282 
283 	reset_control_assert(isp_dev->reset);
284 	clk_disable_unprepare(isp_dev->clock_ram);
285 	clk_disable_unprepare(isp_dev->clock_mod);
286 
287 	return 0;
288 }
289 
290 static int sun6i_isp_resume(struct device *dev)
291 {
292 	struct sun6i_isp_device *isp_dev = dev_get_drvdata(dev);
293 	int ret;
294 
295 	ret = reset_control_deassert(isp_dev->reset);
296 	if (ret) {
297 		dev_err(dev, "failed to deassert reset\n");
298 		return ret;
299 	}
300 
301 	ret = clk_prepare_enable(isp_dev->clock_mod);
302 	if (ret) {
303 		dev_err(dev, "failed to enable module clock\n");
304 		goto error_reset;
305 	}
306 
307 	ret = clk_prepare_enable(isp_dev->clock_ram);
308 	if (ret) {
309 		dev_err(dev, "failed to enable ram clock\n");
310 		goto error_clock_mod;
311 	}
312 
313 	return 0;
314 
315 error_clock_mod:
316 	clk_disable_unprepare(isp_dev->clock_mod);
317 
318 error_reset:
319 	reset_control_assert(isp_dev->reset);
320 
321 	return ret;
322 }
323 
324 static const struct dev_pm_ops sun6i_isp_pm_ops = {
325 	.runtime_suspend	= sun6i_isp_suspend,
326 	.runtime_resume		= sun6i_isp_resume,
327 };
328 
329 static const struct regmap_config sun6i_isp_regmap_config = {
330 	.reg_bits       = 32,
331 	.reg_stride     = 4,
332 	.val_bits       = 32,
333 	.max_register	= 0x400,
334 };
335 
336 static int sun6i_isp_resources_setup(struct sun6i_isp_device *isp_dev,
337 				     struct platform_device *platform_dev)
338 {
339 	struct device *dev = isp_dev->dev;
340 	void __iomem *io_base;
341 	int irq;
342 	int ret;
343 
344 	/* Registers */
345 
346 	io_base = devm_platform_ioremap_resource(platform_dev, 0);
347 	if (IS_ERR(io_base))
348 		return PTR_ERR(io_base);
349 
350 	isp_dev->regmap = devm_regmap_init_mmio_clk(dev, "bus", io_base,
351 						    &sun6i_isp_regmap_config);
352 	if (IS_ERR(isp_dev->regmap)) {
353 		dev_err(dev, "failed to init register map\n");
354 		return PTR_ERR(isp_dev->regmap);
355 	}
356 
357 	/* Clocks */
358 
359 	isp_dev->clock_mod = devm_clk_get(dev, "mod");
360 	if (IS_ERR(isp_dev->clock_mod)) {
361 		dev_err(dev, "failed to acquire module clock\n");
362 		return PTR_ERR(isp_dev->clock_mod);
363 	}
364 
365 	isp_dev->clock_ram = devm_clk_get(dev, "ram");
366 	if (IS_ERR(isp_dev->clock_ram)) {
367 		dev_err(dev, "failed to acquire ram clock\n");
368 		return PTR_ERR(isp_dev->clock_ram);
369 	}
370 
371 	ret = clk_set_rate_exclusive(isp_dev->clock_mod, 297000000);
372 	if (ret) {
373 		dev_err(dev, "failed to set mod clock rate\n");
374 		return ret;
375 	}
376 
377 	/* Reset */
378 
379 	isp_dev->reset = devm_reset_control_get_shared(dev, NULL);
380 	if (IS_ERR(isp_dev->reset)) {
381 		dev_err(dev, "failed to acquire reset\n");
382 		ret = PTR_ERR(isp_dev->reset);
383 		goto error_clock_rate_exclusive;
384 	}
385 
386 	/* Interrupt */
387 
388 	irq = platform_get_irq(platform_dev, 0);
389 	if (irq < 0) {
390 		dev_err(dev, "failed to get interrupt\n");
391 		ret = -ENXIO;
392 		goto error_clock_rate_exclusive;
393 	}
394 
395 	ret = devm_request_irq(dev, irq, sun6i_isp_interrupt, IRQF_SHARED,
396 			       SUN6I_ISP_NAME, isp_dev);
397 	if (ret) {
398 		dev_err(dev, "failed to request interrupt\n");
399 		goto error_clock_rate_exclusive;
400 	}
401 
402 	/* Runtime PM */
403 
404 	pm_runtime_enable(dev);
405 
406 	return 0;
407 
408 error_clock_rate_exclusive:
409 	clk_rate_exclusive_put(isp_dev->clock_mod);
410 
411 	return ret;
412 }
413 
414 static void sun6i_isp_resources_cleanup(struct sun6i_isp_device *isp_dev)
415 {
416 	struct device *dev = isp_dev->dev;
417 
418 	pm_runtime_disable(dev);
419 	clk_rate_exclusive_put(isp_dev->clock_mod);
420 }
421 
422 static int sun6i_isp_probe(struct platform_device *platform_dev)
423 {
424 	struct sun6i_isp_device *isp_dev;
425 	struct device *dev = &platform_dev->dev;
426 	const struct sun6i_isp_variant *variant;
427 	int ret;
428 
429 	variant = of_device_get_match_data(dev);
430 	if (!variant)
431 		return -EINVAL;
432 
433 	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
434 	if (!isp_dev)
435 		return -ENOMEM;
436 
437 	isp_dev->dev = dev;
438 	platform_set_drvdata(platform_dev, isp_dev);
439 
440 	spin_lock_init(&isp_dev->state_lock);
441 
442 	ret = sun6i_isp_resources_setup(isp_dev, platform_dev);
443 	if (ret)
444 		return ret;
445 
446 	ret = sun6i_isp_tables_setup(isp_dev, variant);
447 	if (ret) {
448 		dev_err(dev, "failed to setup tables\n");
449 		goto error_resources;
450 	}
451 
452 	ret = sun6i_isp_v4l2_setup(isp_dev);
453 	if (ret) {
454 		dev_err(dev, "failed to setup v4l2\n");
455 		goto error_tables;
456 	}
457 
458 	ret = sun6i_isp_proc_setup(isp_dev);
459 	if (ret) {
460 		dev_err(dev, "failed to setup proc\n");
461 		goto error_v4l2;
462 	}
463 
464 	ret = sun6i_isp_capture_setup(isp_dev);
465 	if (ret) {
466 		dev_err(dev, "failed to setup capture\n");
467 		goto error_proc;
468 	}
469 
470 	ret = sun6i_isp_params_setup(isp_dev);
471 	if (ret) {
472 		dev_err(dev, "failed to setup params\n");
473 		goto error_capture;
474 	}
475 
476 	return 0;
477 
478 error_capture:
479 	sun6i_isp_capture_cleanup(isp_dev);
480 
481 error_proc:
482 	sun6i_isp_proc_cleanup(isp_dev);
483 
484 error_v4l2:
485 	sun6i_isp_v4l2_cleanup(isp_dev);
486 
487 error_tables:
488 	sun6i_isp_tables_cleanup(isp_dev);
489 
490 error_resources:
491 	sun6i_isp_resources_cleanup(isp_dev);
492 
493 	return ret;
494 }
495 
496 static void sun6i_isp_remove(struct platform_device *platform_dev)
497 {
498 	struct sun6i_isp_device *isp_dev = platform_get_drvdata(platform_dev);
499 
500 	sun6i_isp_params_cleanup(isp_dev);
501 	sun6i_isp_capture_cleanup(isp_dev);
502 	sun6i_isp_proc_cleanup(isp_dev);
503 	sun6i_isp_v4l2_cleanup(isp_dev);
504 	sun6i_isp_tables_cleanup(isp_dev);
505 	sun6i_isp_resources_cleanup(isp_dev);
506 }
507 
508 /*
509  * History of sun6i-isp:
510  * - sun4i-a10-isp: initial ISP tied to the CSI0 controller,
511  *   apparently unused in software implementations;
512  * - sun6i-a31-isp: separate ISP loosely based on sun4i-a10-isp,
513  *   adding extra modules and features;
514  * - sun9i-a80-isp: based on sun6i-a31-isp with some register offset changes
515  *   and new modules like saturation and cnr;
516  * - sun8i-a23-isp/sun8i-h3-isp: based on sun9i-a80-isp with most modules
517  *   related to raw removed;
518  * - sun8i-a83t-isp: based on sun9i-a80-isp with some register offset changes
519  * - sun8i-v3s-isp: based on sun8i-a83t-isp with a new disc module;
520  */
521 
522 static const struct sun6i_isp_variant sun8i_v3s_isp_variant = {
523 	.table_load_save_size	= 0x1000,
524 	.table_lut_size		= 0xe00,
525 	.table_drc_size		= 0x600,
526 	.table_stats_size	= 0x2100,
527 };
528 
529 static const struct of_device_id sun6i_isp_of_match[] = {
530 	{
531 		.compatible	= "allwinner,sun8i-v3s-isp",
532 		.data		= &sun8i_v3s_isp_variant,
533 	},
534 	{},
535 };
536 
537 MODULE_DEVICE_TABLE(of, sun6i_isp_of_match);
538 
539 static struct platform_driver sun6i_isp_platform_driver = {
540 	.probe	= sun6i_isp_probe,
541 	.remove_new = sun6i_isp_remove,
542 	.driver	= {
543 		.name		= SUN6I_ISP_NAME,
544 		.of_match_table	= of_match_ptr(sun6i_isp_of_match),
545 		.pm		= &sun6i_isp_pm_ops,
546 	},
547 };
548 
549 module_platform_driver(sun6i_isp_platform_driver);
550 
551 MODULE_DESCRIPTION("Allwinner A31 Image Signal Processor driver");
552 MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>");
553 MODULE_LICENSE("GPL");
554