static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) { int ret; ret = media_entity_call(link->source->entity, link_setup, link->source, link->sink, flags); if (ret < 0 && ret != -ENOIOCTLCMD) return ret; ret = media_entity_call(link->sink->entity, link_setup, link->sink, link->source, flags); if (ret < 0 && ret != -ENOIOCTLCMD) { media_entity_call(link->source->entity, link_setup, link->source, link->sink, link->flags); return ret; } link->flags = flags; link->reverse->flags = link->flags; return 0; }
/** * __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; }
static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) { const u32 mask = MEDIA_LNK_FL_ENABLED; int ret; /* Notify both entities. */ ret = media_entity_call(link->source->entity, link_setup, link->source, link->sink, flags); if (ret < 0 && ret != -ENOIOCTLCMD) return ret; ret = media_entity_call(link->sink->entity, link_setup, link->sink, link->source, flags); if (ret < 0 && ret != -ENOIOCTLCMD) { media_entity_call(link->source->entity, link_setup, link->source, link->sink, link->flags); return ret; } link->flags = (link->flags & ~mask) | (flags & mask); link->reverse->flags = link->flags; return 0; }
/** * __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_create_pad_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_create_pad_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; }
/** * 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; }
/** * __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; }