drivers/media/platform/amd/isp4/isp4.c
Source file repositories/reference/linux-study-clean/drivers/media/platform/amd/isp4/isp4.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/media/platform/amd/isp4/isp4.c- Extension
.c- Size
- 6848 bytes
- Lines
- 241
- Domain
- Driver Families
- Bucket
- drivers/media
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/irq.hlinux/pm_runtime.hlinux/vmalloc.hmedia/v4l2-ioctl.hisp4.hisp4_debug.hisp4_hw_reg.h
Detected Declarations
function isp4_intr_enablefunction isp4_wake_up_resp_threadfunction isp4_irq_handlerfunction isp4_capture_probefunction isp4_capture_remove
Annotated Snippet
if (intr_status & isp4_irq[i].status_mask) {
intr_ack |= isp4_irq[i].ack_mask;
intr_en |= isp4_irq[i].en_mask;
seen |= BIT(i);
}
}
/*
* Disable the ISP_SYS interrupts that fired. Must be done before waking
* the response threads, since they re-enable interrupts when finished.
* The lock synchronizes RMW of INT0_EN with isp4_enable_interrupt().
*/
spin_lock(&isp_subdev->irq_lock);
intr_en = isp4hw_rreg(isp_subdev->mmio, ISP_SYS_INT0_EN) & ~intr_en;
isp4hw_wreg(isp_subdev->mmio, ISP_SYS_INT0_EN, intr_en);
spin_unlock(&isp_subdev->irq_lock);
/*
* Clear the ISP_SYS interrupts. This must be done after the interrupts
* are disabled, so that ISP FW won't flag any new interrupts on these
* streams, and thus we don't need to clear interrupts again before
* re-enabling them in the response thread.
*/
isp4hw_wreg(isp_subdev->mmio, ISP_SYS_INT0_ACK, intr_ack);
/*
* The operation `(seen >> i) << i` is logically equivalent to
* `seen &= ~BIT(i)`, with fewer instructions after compilation.
*/
for (int i; (i = ffs(seen)); seen = (seen >> i) << i)
isp4_wake_up_resp_thread(isp_subdev, i - 1);
return IRQ_HANDLED;
}
static int isp4_capture_probe(struct platform_device *pdev)
{
int irq[ISP4SD_MAX_FW_RESP_STREAM_NUM];
struct device *dev = &pdev->dev;
struct isp4_subdev *isp_subdev;
struct isp4_device *isp_dev;
int ret;
isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
if (!isp_dev)
return -ENOMEM;
dev->init_name = ISP4_DRV_NAME;
isp_subdev = &isp_dev->isp_subdev;
isp_subdev->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(isp_subdev->mmio))
return dev_err_probe(dev, PTR_ERR(isp_subdev->mmio),
"isp ioremap fail\n");
for (size_t i = 0; i < ARRAY_SIZE(isp4_irq); i++) {
irq[i] = platform_get_irq(pdev, isp4_irq[i].rb_int_num);
if (irq[i] < 0)
return dev_err_probe(dev, irq[i],
"fail to get irq %d\n",
isp4_irq[i].rb_int_num);
ret = devm_request_irq(dev, irq[i], isp4_irq_handler,
IRQF_NO_AUTOEN, isp4_irq[i].name,
isp_subdev);
if (ret)
return dev_err_probe(dev, ret, "fail to req irq %d\n",
irq[i]);
}
isp_dev->v4l2_dev.mdev = &isp_dev->mdev;
strscpy(isp_dev->mdev.model, "amd_isp41_mdev",
sizeof(isp_dev->mdev.model));
isp_dev->mdev.dev = dev;
media_device_init(&isp_dev->mdev);
snprintf(isp_dev->v4l2_dev.name, sizeof(isp_dev->v4l2_dev.name),
"AMD-V4L2-ROOT");
ret = v4l2_device_register(dev, &isp_dev->v4l2_dev);
if (ret) {
dev_err_probe(dev, ret, "fail register v4l2 device\n");
goto err_clean_media;
}
pm_runtime_set_suspended(dev);
pm_runtime_enable(dev);
spin_lock_init(&isp_subdev->irq_lock);
ret = isp4sd_init(&isp_dev->isp_subdev, &isp_dev->v4l2_dev, irq);
if (ret) {
Annotation
- Immediate include surface: `linux/irq.h`, `linux/pm_runtime.h`, `linux/vmalloc.h`, `media/v4l2-ioctl.h`, `isp4.h`, `isp4_debug.h`, `isp4_hw_reg.h`.
- Detected declarations: `function isp4_intr_enable`, `function isp4_wake_up_resp_thread`, `function isp4_irq_handler`, `function isp4_capture_probe`, `function isp4_capture_remove`.
- Atlas domain: Driver Families / drivers/media.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.