brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 562933e Raw
112 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor4 *5 * Copyright (C) STMicroelectronics SA 20236 * 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 106void107dcmipp_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}112