/* * isp_subdev_init_entities - Initialize V4L2 subdev and media entity * @asd: ISP CCDC module * * Return 0 on success and a negative error code on failure. */ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) { struct v4l2_subdev *sd = &asd->subdev; struct media_pad *pads = asd->pads; struct media_entity *me = &sd->entity; int ret; asd->input = ATOMISP_SUBDEV_INPUT_NONE; v4l2_subdev_init(sd, &isp_subdev_v4l2_ops); strlcpy(sd->name, "ATOM ISP SUBDEV", sizeof(sd->name)); v4l2_set_subdevdata(sd, asd); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE; asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = V4L2_MBUS_FMT_SBGGR10_1X10; asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = V4L2_MBUS_FMT_SBGGR10_1X10; asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code = V4L2_MBUS_FMT_SBGGR10_1X10; asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code = V4L2_MBUS_FMT_SBGGR10_1X10; me->ops = &isp_subdev_media_ops; me->type = MEDIA_ENT_T_V4L2_SUBDEV; ret = media_entity_init(me, ATOMISP_SUBDEV_PADS_NUM, pads, 0); if (ret < 0) return ret; atomisp_init_subdev_pipe(asd, &asd->video_in, V4L2_BUF_TYPE_VIDEO_OUTPUT); atomisp_init_subdev_pipe(asd, &asd->video_out_preview, V4L2_BUF_TYPE_VIDEO_CAPTURE); atomisp_init_subdev_pipe(asd, &asd->video_out_vf, V4L2_BUF_TYPE_VIDEO_CAPTURE); atomisp_init_subdev_pipe(asd, &asd->video_out_capture, V4L2_BUF_TYPE_VIDEO_CAPTURE); ret = atomisp_video_init(&asd->video_in, "MEMORY"); if (ret < 0) return ret; ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE"); if (ret < 0) return ret; ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER"); if (ret < 0) return ret; ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW"); if (ret < 0) return ret; /* Connect the isp subdev to the video node. */ ret = media_entity_create_link(&asd->video_in.vdev.entity, 0, &asd->subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0); if (ret < 0) return ret; ret = media_entity_create_link(&asd->subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, &asd->video_out_preview.vdev.entity, 0, 0); if (ret < 0) return ret; ret = media_entity_create_link(&asd->subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE_VF, &asd->video_out_vf.vdev.entity, 0, 0); if (ret < 0) return ret; ret = media_entity_create_link(&asd->subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, &asd->video_out_capture.vdev.entity, 0, 0); if (ret < 0) return ret; ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1); if (ret) return ret; asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_fmt_auto, NULL); asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_run_mode, NULL); asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_vfpp, NULL); asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_continuous_mode, NULL); asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_continuous_viewfinder, NULL); asd->continuous_raw_buffer_size = v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_continuous_raw_buffer_size, NULL); /* Make controls visible on subdev as well. */ asd->subdev.ctrl_handler = &asd->ctrl_handler; return asd->ctrl_handler.error; }
/* * isp_subdev_init_entities - Initialize V4L2 subdev and media entity * @isp_subdev: ISP CCDC module * * Return 0 on success and a negative error code on failure. */ static int isp_subdev_init_entities(struct atomisp_sub_device *isp_subdev) { struct v4l2_subdev *sd = &isp_subdev->subdev; struct media_pad *pads = isp_subdev->pads; struct media_entity *me = &sd->entity; int ret; isp_subdev->input = ATOMISP_SUBDEV_INPUT_NONE; v4l2_subdev_init(sd, &isp_subdev_v4l2_ops); strlcpy(sd->name, "ATOM ISP SUBDEV", sizeof(sd->name)); v4l2_set_subdevdata(sd, isp_subdev); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; sd->nevents = 16; /* TBD */ pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; pads[ATOMISP_SUBDEV_PAD_SOURCE_MO].flags = MEDIA_PAD_FL_SOURCE; isp_subdev->formats[ATOMISP_SUBDEV_PAD_SINK].code = V4L2_MBUS_FMT_SBGGR10_1X10; isp_subdev->formats[ATOMISP_SUBDEV_PAD_SOURCE_VF].code = V4L2_MBUS_FMT_SBGGR10_1X10; isp_subdev->formats[ATOMISP_SUBDEV_PAD_SOURCE_MO].code = V4L2_MBUS_FMT_SBGGR10_1X10; me->ops = &isp_subdev_media_ops; me->type = MEDIA_ENT_T_V4L2_SUBDEV; ret = media_entity_init(me, ATOMISP_SUBDEV_PADS_NUM, pads, 0); if (ret < 0) return ret; isp_subdev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; isp_subdev->video_in.isp = isp_subdev->isp; spin_lock_init(&isp_subdev->video_in.irq_lock); isp_subdev->video_out_vf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; isp_subdev->video_out_vf.isp = isp_subdev->isp; isp_subdev->video_out_vf.is_main = false; spin_lock_init(&isp_subdev->video_out_vf.irq_lock); isp_subdev->video_out_mo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; isp_subdev->video_out_mo.isp = isp_subdev->isp; isp_subdev->video_out_mo.is_main = true; spin_lock_init(&isp_subdev->video_out_mo.irq_lock); ret = atomisp_video_init(&isp_subdev->video_in, "MEMORY"); if (ret < 0) return ret; ret = atomisp_video_init(&isp_subdev->video_out_mo, "MAINOUTPUT"); if (ret < 0) return ret; ret = atomisp_video_init(&isp_subdev->video_out_vf, "VIEWFINDER"); if (ret < 0) return ret; /* Connect the isp subdev to the video node. */ ret = media_entity_create_link(&isp_subdev->video_in.vdev.entity, 0, &isp_subdev->subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0); if (ret < 0) return ret; ret = media_entity_create_link(&isp_subdev->subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE_VF, &isp_subdev->video_out_vf.vdev.entity, 0, 0); if (ret < 0) return ret; ret = media_entity_create_link(&isp_subdev->subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE_MO, &isp_subdev->video_out_mo.vdev.entity, 0, 0); if (ret < 0) return ret; return 0; }