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