|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
| 2 | +/* |
| 3 | + * Copyright (C) 2025 Advanced Micro Devices, Inc. |
| 4 | + */ |
| 5 | + |
| 6 | +#include <linux/pm_runtime.h> |
| 7 | +#include <linux/vmalloc.h> |
| 8 | +#include <media/v4l2-ioctl.h> |
| 9 | + |
| 10 | +#include "isp4.h" |
| 11 | + |
| 12 | +#define ISP4_DRV_NAME "amd_isp_capture" |
| 13 | + |
| 14 | +static const struct { |
| 15 | + const char *name; |
| 16 | + u32 status_mask; |
| 17 | + u32 en_mask; |
| 18 | + u32 ack_mask; |
| 19 | + u32 rb_int_num; |
| 20 | +} isp4_irq[] = { |
| 21 | + /* The IRQ order is aligned with the isp4_subdev.fw_resp_thread order */ |
| 22 | + { |
| 23 | + .name = "isp_irq_global", |
| 24 | + .rb_int_num = 4, /* ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12 */ |
| 25 | + }, |
| 26 | + { |
| 27 | + .name = "isp_irq_stream1", |
| 28 | + .rb_int_num = 0, /* ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9 */ |
| 29 | + }, |
| 30 | +}; |
| 31 | + |
| 32 | +static irqreturn_t isp4_irq_handler(int irq, void *arg) |
| 33 | +{ |
| 34 | + return IRQ_HANDLED; |
| 35 | +} |
| 36 | + |
| 37 | +static int isp4_capture_probe(struct platform_device *pdev) |
| 38 | +{ |
| 39 | + struct device *dev = &pdev->dev; |
| 40 | + int irq[ARRAY_SIZE(isp4_irq)]; |
| 41 | + struct isp4_device *isp_dev; |
| 42 | + int ret; |
| 43 | + |
| 44 | + isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL); |
| 45 | + if (!isp_dev) |
| 46 | + return -ENOMEM; |
| 47 | + |
| 48 | + dev->init_name = ISP4_DRV_NAME; |
| 49 | + |
| 50 | + for (size_t i = 0; i < ARRAY_SIZE(isp4_irq); i++) { |
| 51 | + irq[i] = platform_get_irq(pdev, isp4_irq[i].rb_int_num); |
| 52 | + if (irq[i] < 0) |
| 53 | + return dev_err_probe(dev, irq[i], |
| 54 | + "fail to get irq %d\n", |
| 55 | + isp4_irq[i].rb_int_num); |
| 56 | + |
| 57 | + ret = devm_request_irq(dev, irq[i], isp4_irq_handler, |
| 58 | + IRQF_NO_AUTOEN, isp4_irq[i].name, dev); |
| 59 | + if (ret) |
| 60 | + return dev_err_probe(dev, ret, "fail to req irq %d\n", |
| 61 | + irq[i]); |
| 62 | + } |
| 63 | + |
| 64 | + isp_dev->v4l2_dev.mdev = &isp_dev->mdev; |
| 65 | + |
| 66 | + strscpy(isp_dev->mdev.model, "amd_isp41_mdev", |
| 67 | + sizeof(isp_dev->mdev.model)); |
| 68 | + isp_dev->mdev.dev = dev; |
| 69 | + media_device_init(&isp_dev->mdev); |
| 70 | + |
| 71 | + snprintf(isp_dev->v4l2_dev.name, sizeof(isp_dev->v4l2_dev.name), |
| 72 | + "AMD-V4L2-ROOT"); |
| 73 | + ret = v4l2_device_register(dev, &isp_dev->v4l2_dev); |
| 74 | + if (ret) { |
| 75 | + dev_err_probe(dev, ret, "fail register v4l2 device\n"); |
| 76 | + goto err_clean_media; |
| 77 | + } |
| 78 | + |
| 79 | + pm_runtime_set_suspended(dev); |
| 80 | + pm_runtime_enable(dev); |
| 81 | + ret = media_device_register(&isp_dev->mdev); |
| 82 | + if (ret) { |
| 83 | + dev_err_probe(dev, ret, "fail to register media device\n"); |
| 84 | + goto err_isp4_deinit; |
| 85 | + } |
| 86 | + |
| 87 | + platform_set_drvdata(pdev, isp_dev); |
| 88 | + |
| 89 | + return 0; |
| 90 | + |
| 91 | +err_isp4_deinit: |
| 92 | + pm_runtime_disable(dev); |
| 93 | + v4l2_device_unregister(&isp_dev->v4l2_dev); |
| 94 | +err_clean_media: |
| 95 | + media_device_cleanup(&isp_dev->mdev); |
| 96 | + |
| 97 | + return ret; |
| 98 | +} |
| 99 | + |
| 100 | +static void isp4_capture_remove(struct platform_device *pdev) |
| 101 | +{ |
| 102 | + struct isp4_device *isp_dev = platform_get_drvdata(pdev); |
| 103 | + struct device *dev = &pdev->dev; |
| 104 | + |
| 105 | + media_device_unregister(&isp_dev->mdev); |
| 106 | + pm_runtime_disable(dev); |
| 107 | + v4l2_device_unregister(&isp_dev->v4l2_dev); |
| 108 | + media_device_cleanup(&isp_dev->mdev); |
| 109 | +} |
| 110 | + |
| 111 | +static struct platform_driver isp4_capture_drv = { |
| 112 | + .probe = isp4_capture_probe, |
| 113 | + .remove = isp4_capture_remove, |
| 114 | + .driver = { |
| 115 | + .name = ISP4_DRV_NAME, |
| 116 | + } |
| 117 | +}; |
| 118 | + |
| 119 | +module_platform_driver(isp4_capture_drv); |
| 120 | + |
| 121 | +MODULE_ALIAS("platform:" ISP4_DRV_NAME); |
| 122 | +MODULE_IMPORT_NS("DMA_BUF"); |
| 123 | + |
| 124 | +MODULE_DESCRIPTION("AMD ISP4 Driver"); |
| 125 | +MODULE_AUTHOR("Bin Du <bin.du@amd.com>"); |
| 126 | +MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>"); |
| 127 | +MODULE_LICENSE("GPL"); |
0 commit comments