File Index
Files and directories
Sign in
FILE

dcmipp-common.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor
  4 *
  5 * Copyright (C) STMicroelectronics SA 2023
  6 * Authors: Hugues Fruchet <hugues.fruchet@foss.st.com>
  7 *          Alain Volmat <alain.volmat@foss.st.com>
  8 *          for STMicroelectronics.
  9 */
 10
 11#include <linux/init.h>
 12#include <linux/module.h>
 13
 14#include "dcmipp-common.h"
 15
 16/* Helper function to allocate and initialize pads */
 17struct media_pad *dcmipp_pads_init(u16 num_pads, const unsigned long *pads_flags)
 18{
 19	struct media_pad *pads;
 20	unsigned int i;
 21
 22	/* Allocate memory for the pads */
 23	pads = kcalloc(num_pads, sizeof(*pads), GFP_KERNEL);
 24	if (!pads)
 25		return ERR_PTR(-ENOMEM);
 26
 27	/* Initialize the pads */
 28	for (i = 0; i < num_pads; i++) {
 29		pads[i].index = i;
 30		pads[i].flags = pads_flags[i];
 31	}
 32
 33	return pads;
 34}
 35
 36static const struct media_entity_operations dcmipp_entity_ops = {
 37	.link_validate = v4l2_subdev_link_validate,
 38};
 39
 40int dcmipp_ent_sd_register(struct dcmipp_ent_device *ved,
 41			   struct v4l2_subdev *sd,
 42			   struct v4l2_device *v4l2_dev,
 43			   const char *const name,
 44			   u32 function,
 45			   u16 num_pads,
 46			   const unsigned long *pads_flag,
 47			   const struct v4l2_subdev_internal_ops *sd_int_ops,
 48			   const struct v4l2_subdev_ops *sd_ops,
 49			   irq_handler_t handler,
 50			   irq_handler_t thread_fn)
 51{
 52	int ret;
 53
 54	/* Allocate the pads. Should be released from the sd_int_op release */
 55	ved->pads = dcmipp_pads_init(num_pads, pads_flag);
 56	if (IS_ERR(ved->pads))
 57		return PTR_ERR(ved->pads);
 58
 59	/* Fill the dcmipp_ent_device struct */
 60	ved->ent = &sd->entity;
 61
 62	/* Initialize the subdev */
 63	v4l2_subdev_init(sd, sd_ops);
 64	sd->internal_ops = sd_int_ops;
 65	sd->entity.function = function;
 66	sd->entity.ops = &dcmipp_entity_ops;
 67	sd->owner = THIS_MODULE;
 68	strscpy(sd->name, name, sizeof(sd->name));
 69	v4l2_set_subdevdata(sd, ved);
 70
 71	/* Expose this subdev to user space */
 72	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 73	if (sd->ctrl_handler)
 74		sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
 75
 76	/* Initialize the media entity */
 77	ret = media_entity_pads_init(&sd->entity, num_pads, ved->pads);
 78	if (ret)
 79		goto err_clean_pads;
 80
 81	ret = v4l2_subdev_init_finalize(sd);
 82	if (ret < 0)
 83		goto err_clean_m_ent;
 84
 85	/* Register the subdev with the v4l2 and the media framework */
 86	ret = v4l2_device_register_subdev(v4l2_dev, sd);
 87	if (ret) {
 88		dev_err(v4l2_dev->dev,
 89			"%s: subdev register failed (err=%d)\n",
 90			name, ret);
 91		goto err_clean_m_ent;
 92	}
 93
 94	ved->handler = handler;
 95	ved->thread_fn = thread_fn;
 96
 97	return 0;
 98
 99err_clean_m_ent:
100	media_entity_cleanup(&sd->entity);
101err_clean_pads:
102	dcmipp_pads_cleanup(ved->pads);
103	return ret;
104}
105
106void
107dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved, struct v4l2_subdev *sd)
108{
109	media_entity_cleanup(ved->ent);
110	v4l2_device_unregister_subdev(sd);
111}
~/ Read-only file preview.