/* Create links from FIMC-LITE source pads to other entities */ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) { struct media_entity *source, *sink; int i, ret = 0; for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { struct fimc_lite *fimc = fmd->fimc_lite[i]; if (fimc == NULL) continue; source = &fimc->subdev.entity; sink = &fimc->ve.vdev.entity; /* FIMC-LITE's subdev and video node */ ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA, sink, 0, 0); if (ret) break; /* Link from FIMC-LITE to IS-ISP subdev */ sink = &fmd->fimc_is->isp.subdev.entity; ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_ISP, sink, 0, 0); if (ret) break; } return ret; }
/* Create FIMC-IS links */ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) { struct fimc_isp *isp = &fmd->fimc_is->isp; struct media_entity *source, *sink; int i, ret; source = &isp->subdev.entity; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (fmd->fimc[i] == NULL) continue; /* Link from FIMC-IS-ISP subdev to FIMC */ sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_FIFO, sink, FIMC_SD_PAD_SINK_FIFO, 0); if (ret) return ret; } /* Link from FIMC-IS-ISP subdev to fimc-is-isp.capture video node */ sink = &isp->video_capture.ve.vdev.entity; /* Skip this link if the fimc-is-isp video node driver isn't built-in */ if (sink->num_pads == 0) return 0; return media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_DMA, sink, 0, 0); }
static int atomisp_initialize_modules(struct atomisp_device *isp) { int ret; ret = atomisp_mipi_csi2_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "mipi csi2 initialization failed\n"); goto error_mipi_csi2; } ret = atomisp_file_input_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "file input device initialization failed\n"); goto error_file_input; } ret = atomisp_tpg_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "tpg initialization failed\n"); goto error_tpg; } ret = atomisp_subdev_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "ISP subdev initialization failed\n"); goto error_isp_subdev; } /* connet submoduels */ ret = media_entity_create_link( &isp->csi2_4p.subdev.entity, CSI2_PAD_SOURCE, &isp->isp_subdev.subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0); if (ret < 0) goto error_link; ret = media_entity_create_link( &isp->csi2_1p.subdev.entity, CSI2_PAD_SOURCE, &isp->isp_subdev.subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0); if (ret < 0) goto error_link; return 0; error_link: error_isp_subdev: atomisp_subdev_cleanup(isp); error_tpg: atomisp_tpg_cleanup(isp); error_file_input: atomisp_file_input_cleanup(isp); error_mipi_csi2: atomisp_mipi_csi2_cleanup(isp); return ret; }
int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer, struct v4l2_device *vdev) { int ret; unsigned int flags = 0; struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); /* Register the subdev */ ret = v4l2_device_register_subdev(vdev, &resizer->subdev); if (ret < 0) { printk(KERN_ERR "failed to register resizer as v4l2-subdev\n"); return ret; } ret = vpfe_video_register(&resizer->video_in, vdev); if (ret) { printk(KERN_ERR "failed to register RSZ video-in device\n"); goto out_video_in_register; } resizer->video_in.vpfe_dev = vpfe_dev; ret = vpfe_video_register(&resizer->video_out, vdev); if (ret) { printk(KERN_ERR "failed to register RSZ video-out device\n"); goto out_video_out_register; } resizer->video_out.vpfe_dev = vpfe_dev; ret = media_entity_create_link(&resizer->video_in.video_dev.entity, 0, &resizer->subdev.entity, 0, flags); if (ret < 0) goto out_create_link; ret = media_entity_create_link(&resizer->subdev.entity, 1, &resizer->video_out.video_dev.entity, 0, flags); if (ret < 0) goto out_create_link; return 0; out_create_link: vpfe_video_unregister(&resizer->video_out); out_video_out_register: vpfe_video_unregister(&resizer->video_in); out_video_in_register: media_entity_cleanup(&resizer->subdev.entity); v4l2_device_unregister_subdev(&resizer->subdev); return ret; }
int create_link_mipi(struct decon_device *decon) { int i, ret = 0; int n_pad = decon->n_sink_pad + decon->n_src_pad; int flags = 0; char err[80]; struct exynos_md *md = decon->mdev; if (IS_ERR_OR_NULL(md->dsim_sd[decon->id])) { decon_err("failed to get subdev of dsim%d\n", decon->id); return -EINVAL; } flags = MEDIA_LNK_FL_ENABLED; for (i = decon->n_sink_pad; i < n_pad ; i++) { ret = media_entity_create_link(&decon->sd.entity, i, &md->dsim_sd[decon->id]->entity, 0, flags); if (ret) { snprintf(err, sizeof(err), "%s --> %s", decon->sd.entity.name, decon->output_sd->entity.name); return ret; } decon_info("%s[%d] --> [0]%s link is created successfully\n", decon->sd.entity.name, i, decon->output_sd->entity.name); } return ret; }
int create_link_hdmi(struct decon_device *decon) { int i, ret = 0; int n_pad = decon->n_sink_pad + decon->n_src_pad; int flags = 0; char err[80]; if (!strcmp(decon->output_sd->name, "s5p-hdmi-sd")) flags = MEDIA_LNK_FL_ENABLED; for (i = decon->n_sink_pad; i < n_pad ; i++) { ret = media_entity_create_link(&decon->sd.entity, i, &decon->output_sd->entity, 0, flags); if (ret) { snprintf(err, sizeof(err), "%s --> %s", decon->sd.entity.name, decon->output_sd->entity.name); return ret; } decon_info("%s[%d] --> [0]%s link is created successfully\n", decon->sd.entity.name, i, decon->output_sd->entity.name); } return ret; }
static int gsc_capture_create_link(struct gsc_dev *gsc) { struct media_entity *source, *sink; struct exynos_platform_gscaler *pdata = gsc->pdata; struct exynos_isp_info *isp_info; u32 num_clients = pdata->num_clients; int ret, i; enum cam_port id; /* GSC-SUBDEV ------> GSC-VIDEO (Always link enable) */ source = &gsc->cap.sd_cap->entity; sink = &gsc->cap.vfd->entity; if (source && sink) { ret = media_entity_create_link(source, GSC_PAD_SOURCE, sink, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { gsc_err("failed link flite to gsc\n"); return ret; } } for (i = 0; i < num_clients; i++) { isp_info = pdata->isp_info[i]; id = isp_info->cam_port; /* FIMC-LITE ------> GSC-SUBDEV (ITU & MIPI common) */ source = &gsc->cap.sd_flite[id]->entity; sink = &gsc->cap.sd_cap->entity; if (source && sink) { if (pdata->cam_preview) ret = media_entity_create_link(source, FLITE_PAD_SOURCE_PREV, sink, GSC_PAD_SINK, 0); if (!ret && pdata->cam_camcording) ret = media_entity_create_link(source, FLITE_PAD_SOURCE_CAMCORD, sink, GSC_PAD_SINK, 0); if (ret) { gsc_err("failed link flite to gsc\n"); return ret; } } } return 0; }
static int atomisp_initialize_modules(struct atomisp_device *isp) { int ret; unsigned int i, j; ret = atomisp_mipi_csi2_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "mipi csi2 initialization failed\n"); goto error_mipi_csi2; } ret = atomisp_file_input_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "file input device initialization failed\n"); goto error_file_input; } ret = atomisp_tpg_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "tpg initialization failed\n"); goto error_tpg; } ret = atomisp_subdev_init(isp); if (ret < 0) { v4l2_err(&atomisp_dev, "ISP subdev initialization failed\n"); goto error_isp_subdev; } /* connet submoduels */ for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { for (j = 0; j < isp->num_of_streams; j++) { ret = media_entity_create_link( &isp->csi2_port[i].subdev.entity, CSI2_PAD_SOURCE, &isp->isp_subdev[j].subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0); if (ret < 0) goto error_link; } } return 0; error_link: error_isp_subdev: atomisp_subdev_cleanup(isp); error_tpg: atomisp_tpg_cleanup(isp); error_file_input: atomisp_file_input_cleanup(isp); error_mipi_csi2: atomisp_mipi_csi2_cleanup(isp); return ret; }
/* * csi2_init_entities - Initialize subdev and media entity. * @csi2: Pointer to csi2 structure. * return -ENOMEM or zero on success */ static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) { struct v4l2_subdev *sd = &csi2->subdev; struct media_pad *pads = csi2->pads; struct media_entity *me = &sd->entity; int ret; char name[V4L2_SUBDEV_NAME_SIZE]; v4l2_subdev_init(sd, &csi2_ops); sd->internal_ops = &csi2_internal_ops; sprintf(name, "CSI2%s", subname); snprintf(sd->name, sizeof(sd->name), "OMAP4 ISS %s", name); sd->grp_id = 1 << 16; /* group ID for iss subdevs */ v4l2_set_subdevdata(sd, csi2); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; me->ops = &csi2_media_ops; ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); if (ret < 0) return ret; csi2_init_formats(sd, NULL); /* Video device node */ csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; csi2->video_out.ops = &csi2_issvideo_ops; csi2->video_out.bpl_alignment = 32; csi2->video_out.bpl_zero_padding = 1; csi2->video_out.bpl_max = 0x1ffe0; csi2->video_out.iss = csi2->iss; csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; ret = omap4iss_video_init(&csi2->video_out, name); if (ret < 0) goto error_video; /* Connect the CSI2 subdev to the video node. */ ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE, &csi2->video_out.video.entity, 0, 0); if (ret < 0) goto error_link; return 0; error_link: omap4iss_video_cleanup(&csi2->video_out); error_video: media_entity_cleanup(&csi2->subdev.entity); return ret; }
static int camif_create_media_links(struct camif_dev *camif) { int i, ret; ret = media_entity_create_link(&camif->sensor.sd->entity, 0, &camif->subdev.entity, CAMIF_SD_PAD_SINK, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) return ret; for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) { ret = media_entity_create_link(&camif->subdev.entity, i, &camif->vp[i - 1].vdev.entity, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); } return ret; }
/** * __fimc_md_create_fimc_links - create links to all FIMC entities * @fmd: fimc media device * @source: the source entity to create links to all fimc entities from * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null * @pad: the source entity pad index * @fimc_id: index of the fimc device for which link should be enabled */ static int __fimc_md_create_fimc_links(struct fimc_md *fmd, struct media_entity *source, struct v4l2_subdev *sensor, int pad, int fimc_id) { struct fimc_sensor_info *s_info; struct media_entity *sink; unsigned int flags; int ret, i; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) break; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (sensor->grp_id == SENSOR_GROUP_ID && !fmd->fimc[i]->variant->has_cam_if) continue; flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; sink = &fmd->fimc[i]->vid_cap.subdev->entity; ret = media_entity_create_link(source, pad, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[0], &source->pads[pad], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); if (flags == 0) continue; s_info = v4l2_get_subdev_hostdata(sensor); if (!WARN_ON(s_info == NULL)) { unsigned long irq_flags; spin_lock_irqsave(&fmd->slock, irq_flags); s_info->host = fmd->fimc[i]; spin_unlock_irqrestore(&fmd->slock, irq_flags); } } return 0; }
/* * ipipeif_init_entities - Initialize V4L2 subdev and media entity * @ipipeif: ISS ISP IPIPEIF module * * Return 0 on success and a negative error code on failure. */ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) { struct v4l2_subdev *sd = &ipipeif->subdev; struct media_pad *pads = ipipeif->pads; struct media_entity *me = &sd->entity; int ret; ipipeif->input = IPIPEIF_INPUT_NONE; v4l2_subdev_init(sd, &ipipeif_v4l2_ops); sd->internal_ops = &ipipeif_v4l2_internal_ops; strlcpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for iss subdevs */ v4l2_set_subdevdata(sd, ipipeif); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE; pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; me->ops = &ipipeif_media_ops; ret = media_entity_init(me, IPIPEIF_PADS_NUM, pads, 0); if (ret < 0) return ret; ipipeif_init_formats(sd, NULL); ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ipipeif->video_out.ops = &ipipeif_video_ops; ipipeif->video_out.iss = to_iss_device(ipipeif); ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; ipipeif->video_out.bpl_alignment = 32; ipipeif->video_out.bpl_zero_padding = 1; ipipeif->video_out.bpl_max = 0x1ffe0; ret = omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); if (ret < 0) return ret; /* Connect the IPIPEIF subdev to the video node. */ ret = media_entity_create_link(&ipipeif->subdev.entity, IPIPEIF_PAD_SOURCE_ISIF_SF, &ipipeif->video_out.video.entity, 0, 0); if (ret < 0) return ret; return 0; }
/* * ispcsi2_init_entities - Initialize subdev and media entity. * @csi2: Pointer to ispcsi2 structure. * return -ENOMEM or zero on success */ static int isp_csi2_init_entities(struct isp_csi2_device *csi2) { struct v4l2_subdev *sd = &csi2->subdev; struct media_pad *pads = csi2->pads; struct media_entity *me = &sd->entity; int ret; v4l2_subdev_init(sd, &csi2_ops); strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, csi2); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; v4l2_ctrl_handler_init(&csi2->ctrls, 1); sd->ctrl_handler = &csi2->ctrls; pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FLAG_OUTPUT; pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FLAG_INPUT; me->ops = &csi2_media_ops; ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); if (ret < 0) return ret; csi2_init_formats(sd, NULL); /* Video device node */ csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; csi2->video_out.ops = &csi2_ispvideo_ops; csi2->video_out.bpl_alignment = 32; csi2->video_out.bpl_zero_padding = 1; csi2->video_out.bpl_max = 0x1ffe0; csi2->video_out.isp = csi2->isp; csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; ret = isp_video_init(&csi2->video_out, "CSI2a"); if (ret < 0) return ret; /* Connect the CSI2 subdev to the video node. */ ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE, &csi2->video_out.video.entity, 0, 0); if (ret < 0) return ret; return 0; }
static int gsc_capture_create_link(struct gsc_dev *gsc) { struct media_entity *source, *sink; int ret; /* GSC-SUBDEV ------> GSC-VIDEO (Always link enable) */ source = &gsc->cap.sd_cap->entity; sink = &gsc->cap.vfd->entity; if (source && sink) { ret = media_entity_create_link(source, GSC_PAD_SOURCE, sink, 0, 0); if (ret) { gsc_err("failed link flite to gsc\n"); return ret; } } return 0; }
static int gsc_capture_create_link(struct gsc_dev *gsc) { struct media_entity *source, *sink; int ret; /* GSC-SUBDEV ------> GSC-VIDEO (Always link enable) */ source = &gsc->cap.sd->entity; sink = &gsc->cap.vfd->entity; if (source && sink) { ret = media_entity_create_link(source, GSC_PAD_SOURCE, sink, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); if (ret) { gsc_err("failed link sd-gsc to vd-gsc\n"); return ret; } } return 0; }
/* Create links from FIMC-LITE source pads to other entities */ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) { struct media_entity *source, *sink; unsigned int flags = MEDIA_LNK_FL_ENABLED; int i, ret; for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { struct fimc_lite *fimc = fmd->fimc_lite[i]; if (fimc == NULL) continue; source = &fimc->subdev.entity; sink = &fimc->vfd.entity; /* FIMC-LITE's subdev and video node */ ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); if (ret) break; /* TODO: create links to other entities */ } return ret; }
/** * fimc_md_create_links - create default links between registered entities * * Parallel interface sensor entities are connected directly to FIMC capture * entities. The sensors using MIPI CSIS bus are connected through immutable * link with CSI receiver entity specified by mux_id. Any registered CSIS * entity has a link to each registered FIMC capture entity. Enabled links * are created by default between each subsequent registered sensor and * subsequent FIMC capture entity. The number of default active links is * determined by the number of available sensors or FIMC entities, * whichever is less. */ static int fimc_md_create_links(struct fimc_md *fmd) { struct v4l2_subdev *sensor, *csis; struct fimc_sensor_info *s_info; struct s5p_fimc_isp_info *pdata; struct media_entity *source, *sink; int i, j, ret = 0; u32 flags = 0; for (j = 0; j < fmd->num_sensors; j++) { if (fmd->sensor[j].subdev == NULL) { v4l2_warn(&fmd->v4l2_dev, "fmd->sensor[%d].subdev = NULL!!\n", j); continue; } sensor = fmd->sensor[j].subdev; s_info = v4l2_get_subdev_hostdata(sensor); if (!s_info) { v4l2_warn(&fmd->v4l2_dev, "(%d) fimc_sensor_info = NULL!!\n", j); continue; } pdata = &s_info->pdata; switch (pdata->bus_type) { case FIMC_ITU_601...FIMC_ITU_656: /* TODO : add ITU configuration */ break; case FIMC_MIPI_CSI2: /* 1. create link beween sensor and mipi-csi */ if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, "Wrong CSI channel id: %d\n", pdata->mux_id)) return -EINVAL; csis = fmd->csis[pdata->mux_id].sd; if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, flags); if (ret) return ret; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", sensor->entity.name, csis->entity.name); /* 2. create link beween mipi-csi and fimc */ source = &csis->entity; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[FIMC_SD_PAD_SINK], &source->pads[CSIS_PAD_SOURCE], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } break; case FIMC_IS_WB: /* 1. create link beween sensor and mipi-csi */ if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, "Wrong CSI channel id: %d\n", pdata->mux_id)) return -EINVAL; csis = fmd->csis[pdata->mux_id].sd; if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, flags); if (ret) return ret; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", sensor->entity.name, csis->entity.name); /* 2. create link beween mipi-csi and fimc-lite */ source = &csis->entity; sink = &fmd->fimc_lite[pdata->mux_id]->subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FLITE_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC-LITE subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[CSIS_PAD_SOURCE], &sink->pads[FLITE_SD_PAD_SINK], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", source->name, sink->name); /* 3. create link beween fimc-lite and fimc-is */ source = &fmd->fimc_lite[pdata->mux_id]->subdev.entity; sink = &fmd->fimc_is->isp.subdev.entity; ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE, sink, FIMC_IS_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC-IS subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[FLITE_SD_PAD_SOURCE], &sink->pads[FIMC_IS_SD_PAD_SINK], flags); v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", source->name, sink->name); /* 4. create link beween fimc-is and fimc */ source = &fmd->fimc_is->isp.subdev.entity; for (i = 0; i < (FIMC_MAX_DEVS - 1); i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[CSIS_PAD_SOURCE], &sink->pads[FIMC_SD_PAD_SINK], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } break; default: v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", pdata->bus_type); return -EINVAL; } } /* Create immutable link between each FIMC's subdev and video node */ flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; source = &fmd->fimc[i]->vid_cap.subdev.entity; sink = &fmd->fimc[i]->vid_cap.vfd.entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } return ret; }
static int atomisp_register_entities(struct atomisp_device *isp) { int ret = 0; unsigned int i; isp->media_dev.dev = isp->dev; strlcpy(isp->media_dev.model, "Intel Atom ISP", sizeof(isp->media_dev.model)); ret = media_device_register(&isp->media_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: Media device registration " "failed (%d)\n", __func__, ret); return ret; } isp->v4l2_dev.mdev = &isp->media_dev; ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: V4L2 device registration failed (%d)\n", __func__, ret); goto v4l2_device_failed; } ret = atomisp_subdev_probe(isp); if (ret < 0) goto csi_and_subdev_probe_failed; /* Register internal entities */ for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { ret = atomisp_mipi_csi2_register_entities(&isp->csi2_port[i], &isp->v4l2_dev); if (ret == 0) continue; /* error case */ v4l2_err(&atomisp_dev, "failed to register the CSI port: %d\n", i); /* deregister all registered CSI ports */ while (i--) atomisp_mipi_csi2_unregister_entities( &isp->csi2_port[i]); goto csi_and_subdev_probe_failed; } ret = atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_file_input_register_entities\n"); goto file_input_register_failed; } ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n"); goto tpg_register_failed; } for (i = 0; i < isp->num_of_streams; i++) { ret = atomisp_subdev_register_entities(&isp->isp_subdev[i], &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_subdev_register_entities fail\n"); goto subdev_register_failed; } } for (i = 0; i < isp->input_cnt; i++) { if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) { v4l2_err(&atomisp_dev, "isp->inputs port %d not supported\n", isp->inputs[i].port); ret = -EINVAL; goto link_failed; } ret = media_entity_create_link( &isp->inputs[i].camera->entity, 0, &isp->csi2_port[isp->inputs[i].port].subdev.entity, CSI2_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) { dev_err(isp->dev, "link create from sensor to csi-2 receiver failed\n"); goto link_failed; } } v4l2_dbg(1, dbg_level, &atomisp_dev, "FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = FILE_INPUT; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd; if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { v4l2_dbg(1, dbg_level, &atomisp_dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = TEST_PATTERN; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; } else { v4l2_warn(&atomisp_dev, "too many atomisp inputs, TPG ignored.\n"); } ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); if (ret < 0) goto link_failed; return ret; link_failed: for (i = 0; i < isp->num_of_streams; i++) atomisp_subdev_unregister_entities(&isp->isp_subdev[i]); subdev_register_failed: while (i--) atomisp_subdev_unregister_entities(&isp->isp_subdev[i]); atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: atomisp_file_input_unregister_entities(&isp->file_dev); file_input_register_failed: for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]); csi_and_subdev_probe_failed: v4l2_device_unregister(&isp->v4l2_dev); v4l2_device_failed: media_device_unregister(&isp->media_dev); return ret; }
/* * 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; }
/** * __fimc_md_create_fimc_links - create links to all FIMC entities * @fmd: fimc media device * @source: the source entity to create links to all fimc entities from * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null * @pad: the source entity pad index * @link_mask: bitmask of the fimc devices for which link should be enabled */ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, struct media_entity *source, struct v4l2_subdev *sensor, int pad, int link_mask) { struct fimc_source_info *si = NULL; struct media_entity *sink; unsigned int flags = 0; int i, ret = 0; if (sensor) { si = v4l2_get_subdev_hostdata(sensor); /* Skip direct FIMC links in the logical FIMC-IS sensor path */ if (si && si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) ret = 1; } for (i = 0; !ret && i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, pad, sink, FIMC_SD_PAD_SINK_CAM, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[0], &source->pads[pad], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n", source->name, flags ? '=' : '-', sink->name); } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { if (!fmd->fimc_lite[i]) continue; sink = &fmd->fimc_lite[i]->subdev.entity; ret = media_entity_create_link(source, pad, sink, FLITE_SD_PAD_SINK, 0); if (ret) return ret; /* Notify FIMC-LITE subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[0], &source->pads[pad], 0); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]\n", source->name, sink->name); } return 0; }
static int atomisp_register_entities(struct atomisp_device *isp) { int ret = 0; int i = 0; struct v4l2_subdev *subdev = NULL; struct media_entity *input = NULL; unsigned int flags; unsigned int pad; isp->media_dev.dev = isp->dev; strlcpy(isp->media_dev.model, "Intel Atom ISP", sizeof(isp->media_dev.model)); ret = media_device_register(&isp->media_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: Media device registration " "failed (%d)\n", __func__, ret); return ret; } isp->v4l2_dev.mdev = &isp->media_dev; ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: V4L2 device registration failed (%d)\n", __func__, ret); goto v4l2_device_failed; } /* * fixing me! * not sub device exists on * mrfld vp */ if (!IS_MRFLD) { ret = atomisp_subdev_probe(isp); if (ret < 0) goto lane4_and_subdev_probe_failed; } /* Register internal entities */ ret = atomisp_mipi_csi2_register_entities(&isp->csi2_4p, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_mipi_csi2_register_entities 4p\n"); goto lane4_and_subdev_probe_failed; } ret = atomisp_mipi_csi2_register_entities(&isp->csi2_1p, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_mipi_csi2_register_entities 1p\n"); goto lane1_failed; } ret = atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_file_input_register_entities\n"); goto file_input_register_failed; } ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n"); goto tpg_register_failed; } ret = atomisp_subdev_register_entities(&isp->isp_subdev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_subdev_register_entities fail\n"); goto subdev_register_failed; } for (i = 0; i < isp->input_cnt; i++) { subdev = isp->inputs[i].camera; switch (isp->inputs[i].port) { case ATOMISP_CAMERA_PORT_PRIMARY: input = &isp->csi2_4p.subdev.entity; pad = CSI2_PAD_SINK; flags = 0; break; case ATOMISP_CAMERA_PORT_SECONDARY: input = &isp->csi2_1p.subdev.entity; pad = CSI2_PAD_SINK; flags = 0; break; default: v4l2_dbg(1, dbg_level, &atomisp_dev, "isp->inputs type not supported\n"); break; } ret = media_entity_create_link(&subdev->entity, 0, input, pad, flags); if (ret < 0) { v4l2_err(&atomisp_dev, "snr to mipi csi link failed\n"); goto link_failed; } } v4l2_dbg(1, dbg_level, &atomisp_dev, "FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = FILE_INPUT; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd; if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { v4l2_dbg(1, dbg_level, &atomisp_dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = TEST_PATTERN; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; } else { v4l2_warn(&atomisp_dev, "too many atomisp inputs, TPG ignored.\n"); } ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); if (ret < 0) goto link_failed; return ret; link_failed: atomisp_subdev_unregister_entities(&isp->isp_subdev); subdev_register_failed: atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: atomisp_file_input_unregister_entities(&isp->file_dev); file_input_register_failed: atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p); lane1_failed: atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p); lane4_and_subdev_probe_failed: v4l2_device_unregister(&isp->v4l2_dev); v4l2_device_failed: media_device_unregister(&isp->media_dev); return ret; }
/** * fimc_md_create_links - create default links between registered entities * * Parallel interface sensor entities are connected directly to FIMC capture * entities. The sensors using MIPI CSIS bus are connected through immutable * link with CSI receiver entity specified by mux_id. Any registered CSIS * entity has a link to each registered FIMC capture entity. Enabled links * are created by default between each subsequent registered sensor and * subsequent FIMC capture entity. The number of default active links is * determined by the number of available sensors or FIMC entities, * whichever is less. */ static int fimc_md_create_links(struct fimc_md *fmd) { struct v4l2_subdev *sensor, *csis; struct s5p_fimc_isp_info *pdata; struct fimc_sensor_info *s_info; struct media_entity *source, *sink; int i, pad, fimc_id = 0; int ret = 0; u32 flags; for (i = 0; i < fmd->num_sensors; i++) { if (fmd->sensor[i].subdev == NULL) continue; sensor = fmd->sensor[i].subdev; s_info = v4l2_get_subdev_hostdata(sensor); if (!s_info || !s_info->pdata) continue; source = NULL; pdata = s_info->pdata; switch (pdata->bus_type) { case FIMC_MIPI_CSI2: if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, "Wrong CSI channel id: %d\n", pdata->mux_id)) return -EINVAL; csis = fmd->csis[pdata->mux_id].sd; if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) return ret; v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]", sensor->entity.name, csis->entity.name); source = &csis->entity; pad = CSIS_PAD_SOURCE; break; case FIMC_ITU_601...FIMC_ITU_656: source = &sensor->entity; pad = 0; break; default: v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", pdata->bus_type); return -EINVAL; } if (source == NULL) continue; ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad, fimc_id++); } /* Create immutable links between each FIMC's subdev and video node */ flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; source = &fmd->fimc[i]->vid_cap.subdev->entity; sink = &fmd->fimc[i]->vid_cap.vfd->entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); if (ret) break; } return ret; }
struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; struct vsp1_video *video; struct vsp1_rwpf *wpf; unsigned int flags; int ret; wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); if (wpf == NULL) return ERR_PTR(-ENOMEM); wpf->max_width = WPF_MAX_WIDTH; wpf->max_height = WPF_MAX_HEIGHT; wpf->entity.type = VSP1_ENTITY_WPF; wpf->entity.index = index; wpf->entity.id = VI6_DPR_NODE_WPF(index); ret = vsp1_entity_init(vsp1, &wpf->entity, 2); if (ret < 0) return ERR_PTR(ret); /* Initialize the V4L2 subdev. */ subdev = &wpf->entity.subdev; v4l2_subdev_init(subdev, &wpf_ops); subdev->entity.ops = &vsp1_media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", dev_name(vsp1->dev), index); v4l2_set_subdevdata(subdev, wpf); subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; vsp1_entity_init_formats(subdev, NULL); /* Initialize the video device. */ video = &wpf->video; video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; video->vsp1 = vsp1; video->ops = &wpf_vdev_ops; ret = vsp1_video_init(video, &wpf->entity); if (ret < 0) goto error_video; /* Connect the video device to the WPF. All connections are immutable * except for the WPF0 source link if a LIF is present. */ flags = MEDIA_LNK_FL_ENABLED; if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0) flags |= MEDIA_LNK_FL_IMMUTABLE; ret = media_entity_create_link(&wpf->entity.subdev.entity, RWPF_PAD_SOURCE, &wpf->video.video.entity, 0, flags); if (ret < 0) goto error_link; wpf->entity.sink = &wpf->video.video.entity; return wpf; error_link: vsp1_video_cleanup(video); error_video: media_entity_cleanup(&wpf->entity.subdev.entity); return ERR_PTR(ret); }
struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; struct vsp1_video *video; struct vsp1_rwpf *rpf; int ret; rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL); if (rpf == NULL) return ERR_PTR(-ENOMEM); rpf->max_width = RPF_MAX_WIDTH; rpf->max_height = RPF_MAX_HEIGHT; rpf->entity.type = VSP1_ENTITY_RPF; rpf->entity.index = index; ret = vsp1_entity_init(vsp1, &rpf->entity, 2); if (ret < 0) return ERR_PTR(ret); /* Initialize the V4L2 subdev. */ subdev = &rpf->entity.subdev; v4l2_subdev_init(subdev, &rpf_ops); subdev->entity.ops = &vsp1_media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u", dev_name(vsp1->dev), index); v4l2_set_subdevdata(subdev, rpf); subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; vsp1_entity_init_formats(subdev, NULL); /* Initialize the video device. */ video = &rpf->video; video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; video->vsp1 = vsp1; video->ops = &rpf_vdev_ops; ret = vsp1_video_init(video, &rpf->entity); if (ret < 0) goto error_video; /* Connect the video device to the RPF. */ ret = media_entity_create_link(&rpf->video.video.entity, 0, &rpf->entity.subdev.entity, RWPF_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) goto error_link; return rpf; error_link: vsp1_video_cleanup(video); error_video: media_entity_cleanup(&rpf->entity.subdev.entity); return ERR_PTR(ret); }
static int unicam_register_entities(struct unicam_device *unicam) { struct unicam_platform_data *pdata = unicam->pdata; struct unicam_v4l2_subdevs_groups *subdevs; int ret, i; /* media device registration */ unicam->media_dev.dev = unicam->dev; strlcpy(unicam->media_dev.model, "Broadcom Kona Unicam", sizeof(unicam->media_dev.model)); unicam->media_dev.hw_revision = unicam->revision; unicam->media_dev.link_notify = unicam_pipeline_link_notify; ret = media_device_register(&unicam->media_dev); if (ret < 0) { dev_err(unicam->dev, "media device registration failed (%d)\n", ret); return ret; } /* v4l2 device registration */ unicam->v4l2_dev.mdev = &unicam->media_dev; ret = v4l2_device_register(unicam->dev, &unicam->v4l2_dev); if (ret < 0) { dev_err(unicam->dev, "V4L2 device registration failed (%d)\n", ret); goto done; } /* now register all enitites */ ret = kona_unicam_csi2_register_entities(&unicam->csi2a, &unicam->v4l2_dev); if (ret < 0) { dev_err(unicam->dev, "failed to register csi2a entities (%d)\n", ret); goto done; } /* now register external entities */ for (i = 0; i < pdata->num_subdevs; i++) { struct v4l2_subdev *sensor; struct media_entity *input; unsigned int pad; subdevs = &pdata->subdevs[i]; sensor = unicam_register_subdev_group(unicam, subdevs->i2c_info); if (sensor == NULL) continue; sensor->host_priv = subdevs; /* * connect the sensor to the correct interface module. * we only have one receiver here */ switch (subdevs->interface) { case UNICAM_INTERFACE_CSI2_PHY1: input = &unicam->csi2a.subdev.entity; pad = CSI2_PAD_SINK; break; default: dev_err(unicam->dev, "invalid interface type %u\n", subdevs->interface); goto done; } ret = media_entity_create_link(&sensor->entity, 0, input, pad, 0); if (ret < 0) goto done; }; ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev); done: if (ret < 0) unicam_unregister_entities(unicam); return ret; }
static int vpfe_register_entities(struct vpfe_device *vpfe_dev) { int ret, i; unsigned int flags = 0; /* register i2c devices first */ ret = register_i2c_devices(vpfe_dev); if (ret) return ret; /* register rest of the sub-devs */ ret = vpfe_ccdc_register_entities(&vpfe_dev->vpfe_ccdc, &vpfe_dev->v4l2_dev); if (ret) return ret; ret = vpfe_previewer_register_entities(&vpfe_dev->vpfe_previewer, &vpfe_dev->v4l2_dev); if (ret) goto out_ccdc_register; ret = vpfe_resizer_register_entities(&vpfe_dev->vpfe_resizer, &vpfe_dev->v4l2_dev); if (ret) goto out_previewer_register; ret = vpfe_aew_register_entities(&vpfe_dev->vpfe_aew, &vpfe_dev->v4l2_dev); if (ret) goto out_resizer_register; ret = vpfe_af_register_entities(&vpfe_dev->vpfe_af, &vpfe_dev->v4l2_dev); if (ret) goto out_aew_register; /* create links now, starting with external(i2c) entities */ for (i = 0; i < vpfe_dev->num_subdevs; i++) { /* if entity has no pads (ex: amplifier), cant establish link */ if (vpfe_dev->sd[i]->entity.num_pads) { ret = media_entity_create_link(&vpfe_dev->sd[i]->entity, 0, &vpfe_dev->vpfe_ccdc.subdev.entity, 0, flags); if (ret < 0) goto out_resizer_register; } } ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity, 1, &vpfe_dev->vpfe_aew.subdev.entity, 0, flags); if (ret < 0) goto out_resizer_register; ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity, 1, &vpfe_dev->vpfe_af.subdev.entity, 0, flags); if (ret < 0) goto out_resizer_register; ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity, 1, &vpfe_dev->vpfe_previewer.subdev.entity, 0, flags); if (ret < 0) goto out_resizer_register; ret = media_entity_create_link(&vpfe_dev->vpfe_previewer.subdev.entity, 1, &vpfe_dev->vpfe_resizer.subdev.entity, 0, flags); if (ret < 0) goto out_resizer_register; return 0; out_aew_register: vpfe_aew_unregister_entities(&vpfe_dev->vpfe_aew); out_resizer_register: vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer); out_previewer_register: vpfe_previewer_unregister_entities(&vpfe_dev->vpfe_previewer); out_ccdc_register: vpfe_ccdc_unregister_entities(&vpfe_dev->vpfe_ccdc); return ret; }
struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; struct vsp1_video *video; struct vsp1_rwpf *wpf; unsigned int flags; int ret; wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); if (wpf == NULL) return ERR_PTR(-ENOMEM); wpf->max_width = WPF_MAX_WIDTH; wpf->max_height = WPF_MAX_HEIGHT; wpf->entity.type = VSP1_ENTITY_WPF; wpf->entity.index = index; ret = vsp1_entity_init(vsp1, &wpf->entity, 2); if (ret < 0) return ERR_PTR(ret); /* Initialize the V4L2 subdev. */ subdev = &wpf->entity.subdev; v4l2_subdev_init(subdev, &wpf_ops); subdev->entity.ops = &vsp1_media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", dev_name(vsp1->dev), index); v4l2_set_subdevdata(subdev, wpf); subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; vsp1_entity_init_formats(subdev, NULL); /* Initialize the control handler. */ v4l2_ctrl_handler_init(&wpf->ctrls, 1); v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); wpf->entity.subdev.ctrl_handler = &wpf->ctrls; if (wpf->ctrls.error) { dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", index); ret = wpf->ctrls.error; goto error; } /* Initialize the video device. */ video = &wpf->video; video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; video->vsp1 = vsp1; video->ops = &wpf_vdev_ops; ret = vsp1_video_init(video, &wpf->entity); if (ret < 0) goto error; wpf->entity.video = video; /* Connect the video device to the WPF. All connections are immutable * except for the WPF0 source link if a LIF is present. */ flags = MEDIA_LNK_FL_ENABLED; if (!(vsp1->pdata.features & VSP1_HAS_LIF) || index != 0) flags |= MEDIA_LNK_FL_IMMUTABLE; ret = media_entity_create_link(&wpf->entity.subdev.entity, RWPF_PAD_SOURCE, &wpf->video.video.entity, 0, flags); if (ret < 0) goto error; wpf->entity.sink = &wpf->video.video.entity; return wpf; error: vsp1_entity_destroy(&wpf->entity); return ERR_PTR(ret); }
int register_nxp_out(struct nxp_out *me) { int ret; pr_debug("%s\n", __func__); ret = register_nxp_mlc(me->mlcs[0]); if (ret < 0) { pr_err("%s: failed to register_nxp_mlc(0)\n", __func__); goto error_out; } ret = register_nxp_mlc(me->mlcs[1]); if (ret < 0) { pr_err("%s: failed to register_nxp_mlc(1)\n", __func__); goto error_out; } #if defined(CONFIG_NXP_OUT_RESOLUTION_CONVERTER) ret = register_nxp_resc(me->resc); if (ret < 0) { pr_err("%s: failed to register_nxp_resc()\n", __func__); goto error_out; } /* create link */ /* link mlc0 pad source to hdmi pad sink */ ret = media_entity_create_link( &me->mlcs[0]->subdev.entity, NXP_MLC_PAD_SOURCE, &me->resc->subdev.entity, 0, 0); if (ret < 0) { pr_err("%s: failed to link mlc0 to resc\n", __func__); goto error_out; } /* link mlc1 pad source to resc pad sink */ ret = media_entity_create_link( &me->mlcs[1]->subdev.entity, NXP_MLC_PAD_SOURCE, &me->resc->subdev.entity, 0, 0); if (ret < 0) { pr_err("%s: failed to link mlc1 to resc\n", __func__); goto error_out; } #endif #if defined(CONFIG_NXP_OUT_HDMI) ret = register_nxp_hdmi(me->hdmi); if (ret < 0) { pr_err("%s: failed to register_nxp_hdmi()\n", __func__); goto error_out; } /* create link */ /* link mlc0 pad source to hdmi pad sink */ ret = media_entity_create_link( &me->mlcs[0]->subdev.entity, NXP_MLC_PAD_SOURCE, &me->hdmi->sd.entity, 0, 0); if (ret < 0) { pr_err("%s: failed to link mlc0 to hdmi\n", __func__); goto error_out; } /* link mlc1 pad source to hdmi pad sink */ ret = media_entity_create_link( &me->mlcs[1]->subdev.entity, NXP_MLC_PAD_SOURCE, &me->hdmi->sd.entity, 0, 0); if (ret < 0) { pr_err("%s: failed to link mlc1 to hdmi\n", __func__); goto error_out; } #if defined(CONFIG_NXP_OUT_RESOLUTION_CONVERTER) /* link resc pad source to hdmi pad sink */ ret = media_entity_create_link( &me->resc->subdev.entity, NXP_RESC_PAD_SOURCE, &me->hdmi->sd.entity, 0, 0); if (ret < 0) { pr_err("%s: failed to link resc to hdmi\n", __func__); goto error_out; } #endif #endif return 0; error_out: #if defined(CONFIG_NXP_OUT_RESOLUTION_CONVERTER) unregister_nxp_resc(me->resc); #endif #if defined(CONFIG_NXP_OUT_HDMI) unregister_nxp_hdmi(me->hdmi); #endif unregister_nxp_mlc(me->mlcs[1]); unregister_nxp_mlc(me->mlcs[0]); return ret; }
/** * __fimc_md_create_fimc_links - create links to all FIMC entities * @fmd: fimc media device * @source: the source entity to create links to all fimc entities from * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null * @pad: the source entity pad index * @link_mask: bitmask of the fimc devices for which link should be enabled */ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, struct media_entity *source, struct v4l2_subdev *sensor, int pad, int link_mask) { struct fimc_sensor_info *s_info; struct media_entity *sink; unsigned int flags = 0; int ret, i; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, pad, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[0], &source->pads[pad], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); if (flags == 0 || sensor == NULL) continue; s_info = v4l2_get_subdev_hostdata(sensor); if (!(s_info == NULL)&&!i) { unsigned long irq_flags; spin_lock_irqsave(&fmd->slock, irq_flags); s_info->host = fmd->fimc[i]; spin_unlock_irqrestore(&fmd->slock, irq_flags); } } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { if (!fmd->fimc_lite[i]) continue; if (link_mask & (1 << (i + FIMC_MAX_DEVS))) flags = MEDIA_LNK_FL_ENABLED; else flags = 0; sink = &fmd->fimc_lite[i]->subdev.entity; ret = media_entity_create_link(source, pad, sink, FLITE_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC-LITE subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[0], &source->pads[pad], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } return 0; }
/* * 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; }