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