^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Media entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Sakari Ailus <sakari.ailus@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <media/media-entity.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <media/media-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static inline const char *gobj_type(enum media_gobj_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) case MEDIA_GRAPH_ENTITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return "entity";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) case MEDIA_GRAPH_PAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return "pad";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) case MEDIA_GRAPH_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return "link";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) case MEDIA_GRAPH_INTF_DEVNODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return "intf-devnode";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static inline const char *intf_type(struct media_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) switch (intf->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case MEDIA_INTF_T_DVB_FE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return "dvb-frontend";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) case MEDIA_INTF_T_DVB_DEMUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return "dvb-demux";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) case MEDIA_INTF_T_DVB_DVR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return "dvb-dvr";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case MEDIA_INTF_T_DVB_CA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return "dvb-ca";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) case MEDIA_INTF_T_DVB_NET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return "dvb-net";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case MEDIA_INTF_T_V4L_VIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return "v4l-video";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case MEDIA_INTF_T_V4L_VBI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return "v4l-vbi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case MEDIA_INTF_T_V4L_RADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return "v4l-radio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case MEDIA_INTF_T_V4L_SUBDEV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return "v4l-subdev";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) case MEDIA_INTF_T_V4L_SWRADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return "v4l-swradio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case MEDIA_INTF_T_V4L_TOUCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return "v4l-touch";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return "unknown-intf";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int idx_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) idx_max = ALIGN(idx_max, BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ent_enum->bmap = kcalloc(idx_max / BITS_PER_LONG, sizeof(long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!ent_enum->bmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bitmap_zero(ent_enum->bmap, idx_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ent_enum->idx_max = idx_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) EXPORT_SYMBOL_GPL(__media_entity_enum_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) kfree(ent_enum->bmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * dev_dbg_obj - Prints in debug mode a change on some object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @event_name: Name of the event to report. Could be __func__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @gobj: Pointer to the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * won't produce any code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) switch (media_type(gobj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case MEDIA_GRAPH_ENTITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_dbg(gobj->mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "%s id %u: entity '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) event_name, media_id(gobj),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) gobj_to_entity(gobj)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case MEDIA_GRAPH_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct media_link *link = gobj_to_link(gobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_dbg(gobj->mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) "%s id %u: %s link id %u ==> id %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) event_name, media_id(gobj),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "data" : "interface",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) media_id(link->gobj0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) media_id(link->gobj1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case MEDIA_GRAPH_PAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct media_pad *pad = gobj_to_pad(gobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dev_dbg(gobj->mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "%s id %u: %s%spad '%s':%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) event_name, media_id(gobj),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pad->flags & MEDIA_PAD_FL_SINK ? "sink " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pad->entity->name, pad->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case MEDIA_GRAPH_INTF_DEVNODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct media_interface *intf = gobj_to_intf(gobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct media_intf_devnode *devnode = intf_to_devnode(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dev_dbg(gobj->mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "%s id %u: intf_devnode %s - major: %d, minor: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) event_name, media_id(gobj),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) intf_type(intf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) devnode->major, devnode->minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) void media_gobj_create(struct media_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) enum media_gobj_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct media_gobj *gobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) BUG_ON(!mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) gobj->mdev = mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Create a per-type unique object ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) gobj->id = media_gobj_gen_id(type, ++mdev->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case MEDIA_GRAPH_ENTITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) list_add_tail(&gobj->list, &mdev->entities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case MEDIA_GRAPH_PAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) list_add_tail(&gobj->list, &mdev->pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case MEDIA_GRAPH_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) list_add_tail(&gobj->list, &mdev->links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case MEDIA_GRAPH_INTF_DEVNODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) list_add_tail(&gobj->list, &mdev->interfaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) mdev->topology_version++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev_dbg_obj(__func__, gobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) void media_gobj_destroy(struct media_gobj *gobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* Do nothing if the object is not linked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (gobj->mdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_dbg_obj(__func__, gobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) gobj->mdev->topology_version++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Remove the object from mdev list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) list_del(&gobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) gobj->mdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * TODO: Get rid of this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define MEDIA_ENTITY_MAX_PADS 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct media_pad *pads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct media_device *mdev = entity->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (num_pads >= MEDIA_ENTITY_MAX_PADS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) entity->num_pads = num_pads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) entity->pads = pads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (i = 0; i < num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pads[i].entity = entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pads[i].index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) media_gobj_create(mdev, MEDIA_GRAPH_PAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) &entity->pads[i].graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) EXPORT_SYMBOL_GPL(media_entity_pads_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Graph traversal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static struct media_entity *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) media_entity_other(struct media_entity *entity, struct media_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (link->source->entity == entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return link->sink->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return link->source->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* push an entity to traversal stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static void stack_push(struct media_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) graph->top++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) graph->stack[graph->top].link = entity->links.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) graph->stack[graph->top].entity = entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static struct media_entity *stack_pop(struct media_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct media_entity *entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) entity = graph->stack[graph->top].entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) graph->top--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define link_top(en) ((en)->stack[(en)->top].link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #define stack_top(en) ((en)->stack[(en)->top].entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * media_graph_walk_init - Allocate resources for graph walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * @graph: Media graph structure that will be used to walk the graph
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * @mdev: Media device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Reserve resources for graph walk in media device's current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * state. The memory must be released using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * media_graph_walk_free().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * Returns error on failure, zero on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) __must_check int media_graph_walk_init(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct media_graph *graph, struct media_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return media_entity_enum_init(&graph->ent_enum, mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) EXPORT_SYMBOL_GPL(media_graph_walk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * media_graph_walk_cleanup - Release resources related to graph walking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * @graph: Media graph structure that was used to walk the graph
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void media_graph_walk_cleanup(struct media_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) media_entity_enum_cleanup(&graph->ent_enum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) void media_graph_walk_start(struct media_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) media_entity_enum_zero(&graph->ent_enum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) media_entity_enum_set(&graph->ent_enum, entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) graph->top = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) graph->stack[graph->top].entity = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) stack_push(graph, entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "begin graph walk at '%s'\n", entity->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) EXPORT_SYMBOL_GPL(media_graph_walk_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static void media_graph_walk_iter(struct media_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct media_entity *entity = stack_top(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct media_entity *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) link = list_entry(link_top(graph), typeof(*link), list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* The link is not enabled so we do not follow. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) link_top(graph) = link_top(graph)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) "walk: skipping disabled link '%s':%u -> '%s':%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) link->source->entity->name, link->source->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) link->sink->entity->name, link->sink->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* Get the entity in the other end of the link . */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) next = media_entity_other(entity, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Has the entity already been visited? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) link_top(graph) = link_top(graph)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) "walk: skipping entity '%s' (already seen)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) next->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Push the new entity to stack and start over. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) link_top(graph) = link_top(graph)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) stack_push(graph, next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) next->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct media_entity *media_graph_walk_next(struct media_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct media_entity *entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (stack_top(graph) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Depth first search. Push entity to stack and continue from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * top of the stack until no more entities on the level can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) while (link_top(graph) != &stack_top(graph)->links)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) media_graph_walk_iter(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) entity = stack_pop(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "walk: returning entity '%s'\n", entity->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) EXPORT_SYMBOL_GPL(media_graph_walk_next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int media_entity_get_fwnode_pad(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned long direction_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct fwnode_endpoint endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!entity->ops || !entity->ops->get_fwnode_pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) for (i = 0; i < entity->num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (entity->pads[i].flags & direction_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = entity->ops->get_fwnode_pad(entity, &endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (ret >= entity->num_pads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (!(entity->pads[ret].flags & direction_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Pipeline management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) __must_check int __media_pipeline_start(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct media_pipeline *pipe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct media_device *mdev = entity->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct media_graph *graph = &pipe->graph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct media_entity *entity_err = entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!pipe->streaming_count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = media_graph_walk_init(&pipe->graph, mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) goto error_graph_walk_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) media_graph_walk_start(&pipe->graph, entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) while ((entity = media_graph_walk_next(graph))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) entity->stream_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (entity->pipe && entity->pipe != pipe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pr_err("Pipe active for %s. Can't start for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) entity->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) entity_err->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) entity->pipe = pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* Already streaming --- no need to check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (entity->stream_count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!entity->ops || !entity->ops->link_validate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) bitmap_zero(active, entity->num_pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) bitmap_fill(has_no_links, entity->num_pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) list_for_each_entry(link, &entity->links, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct media_pad *pad = link->sink->entity == entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ? link->sink : link->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Mark that a pad is connected by a link. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) bitmap_clear(has_no_links, pad->index, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * Pads that either do not need to connect or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * are connected through an enabled link are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * fine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) link->flags & MEDIA_LNK_FL_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) bitmap_set(active, pad->index, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * Link validation will only take place for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * sink ends of the link that are enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (link->sink != pad ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) !(link->flags & MEDIA_LNK_FL_ENABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = entity->ops->link_validate(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret < 0 && ret != -ENOIOCTLCMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) "link validation failed for '%s':%u -> '%s':%u, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) link->source->entity->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) link->source->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) entity->name, link->sink->index, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* Either no links or validated links are fine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) bitmap_or(active, active, has_no_links, entity->num_pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!bitmap_full(active, entity->num_pads)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ret = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dev_dbg(entity->graph_obj.mdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) "'%s':%u must be connected by an enabled link\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) entity->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) (unsigned)find_first_zero_bit(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) active, entity->num_pads));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * Link validation on graph failed. We revert what we did and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * return the error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) media_graph_walk_start(graph, entity_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) while ((entity_err = media_graph_walk_next(graph))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* Sanity check for negative stream_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (!WARN_ON_ONCE(entity_err->stream_count <= 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) entity_err->stream_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (entity_err->stream_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) entity_err->pipe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * We haven't increased stream_count further than this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * so we quit here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (entity_err == entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) error_graph_walk_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (!--pipe->streaming_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) media_graph_walk_cleanup(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) EXPORT_SYMBOL_GPL(__media_pipeline_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) __must_check int media_pipeline_start(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct media_pipeline *pipe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct media_device *mdev = entity->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ret = __media_pipeline_start(entity, pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) EXPORT_SYMBOL_GPL(media_pipeline_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) void __media_pipeline_stop(struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct media_graph *graph = &entity->pipe->graph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct media_pipeline *pipe = entity->pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * If the following check fails, the driver has performed an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * unbalanced call to media_pipeline_stop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (WARN_ON(!pipe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) media_graph_walk_start(graph, entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) while ((entity = media_graph_walk_next(graph))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Sanity check for negative stream_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (!WARN_ON_ONCE(entity->stream_count <= 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) entity->stream_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (entity->stream_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) entity->pipe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!--pipe->streaming_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) media_graph_walk_cleanup(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) EXPORT_SYMBOL_GPL(__media_pipeline_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) void media_pipeline_stop(struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct media_device *mdev = entity->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) __media_pipeline_stop(entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) EXPORT_SYMBOL_GPL(media_pipeline_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * Links management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static struct media_link *media_add_link(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) link = kzalloc(sizeof(*link), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (link == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) list_add_tail(&link->list, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static void __media_entity_remove_link(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct media_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct media_link *rlink, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct media_entity *remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (link->source->entity == entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) remote = link->sink->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) remote = link->source->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (rlink != link->reverse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (link->source->entity == entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) remote->num_backlinks--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* Remove the remote link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) list_del(&rlink->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) media_gobj_destroy(&rlink->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) kfree(rlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (--remote->num_links == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) list_del(&link->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) media_gobj_destroy(&link->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int media_get_pad_index(struct media_entity *entity, bool is_sink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) enum media_pad_signal_type sig_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) bool pad_is_sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) for (i = 0; i < entity->num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) pad_is_sink = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pad_is_sink = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) continue; /* This is an error! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (pad_is_sink != is_sink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (entity->pads[i].sig_type == sig_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) EXPORT_SYMBOL_GPL(media_get_pad_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) media_create_pad_link(struct media_entity *source, u16 source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct media_entity *sink, u16 sink_pad, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct media_link *backlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (WARN_ON(!source || !sink) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) WARN_ON(source_pad >= source->num_pads) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) WARN_ON(sink_pad >= sink->num_pads))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) link = media_add_link(&source->links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (link == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) link->source = &source->pads[source_pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) link->sink = &sink->pads[sink_pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* Initialize graph object embedded at the new link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) &link->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* Create the backlink. Backlinks are used to help graph traversal and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * are not reported to userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) backlink = media_add_link(&sink->links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (backlink == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) __media_entity_remove_link(source, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) backlink->source = &source->pads[source_pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) backlink->sink = &sink->pads[sink_pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) backlink->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) backlink->is_backlink = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* Initialize graph object embedded at the new link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) &backlink->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) link->reverse = backlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) backlink->reverse = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) sink->num_backlinks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) sink->num_links++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) source->num_links++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) EXPORT_SYMBOL_GPL(media_create_pad_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int media_create_pad_links(const struct media_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) const u32 source_function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct media_entity *source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) const u16 source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) const u32 sink_function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct media_entity *sink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) const u16 sink_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) const bool allow_both_undefined)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct media_entity *entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) unsigned function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* Trivial case: 1:1 relation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (source && sink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return media_create_pad_link(source, source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) sink, sink_pad, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* Worse case scenario: n:n relation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!source && !sink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!allow_both_undefined)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) media_device_for_each_entity(source, mdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (source->function != source_function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) media_device_for_each_entity(sink, mdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (sink->function != sink_function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = media_create_pad_link(source, source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) sink, sink_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) flags &= ~(MEDIA_LNK_FL_ENABLED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) MEDIA_LNK_FL_IMMUTABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /* Handle 1:n and n:1 cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) function = sink_function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) function = source_function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) media_device_for_each_entity(entity, mdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (entity->function != function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ret = media_create_pad_link(source, source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) entity, sink_pad, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) ret = media_create_pad_link(entity, source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) sink, sink_pad, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) EXPORT_SYMBOL_GPL(media_create_pad_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) void __media_entity_remove_links(struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct media_link *link, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) list_for_each_entry_safe(link, tmp, &entity->links, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) __media_entity_remove_link(entity, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) entity->num_links = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) entity->num_backlinks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) EXPORT_SYMBOL_GPL(__media_entity_remove_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) void media_entity_remove_links(struct media_entity *entity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct media_device *mdev = entity->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* Do nothing if the entity is not registered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (mdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) __media_entity_remove_links(entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) EXPORT_SYMBOL_GPL(media_entity_remove_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* Notify both entities. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ret = media_entity_call(link->source->entity, link_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) link->source, link->sink, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (ret < 0 && ret != -ENOIOCTLCMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ret = media_entity_call(link->sink->entity, link_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) link->sink, link->source, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (ret < 0 && ret != -ENOIOCTLCMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) media_entity_call(link->source->entity, link_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) link->source, link->sink, link->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) link->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) link->reverse->flags = link->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int __media_entity_setup_link(struct media_link *link, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) const u32 mask = MEDIA_LNK_FL_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct media_device *mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct media_entity *source, *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (link == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* The non-modifiable link flags must not be modified. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if ((link->flags & ~mask) != (flags & ~mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return link->flags == flags ? 0 : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (link->flags == flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) source = link->source->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) sink = link->sink->entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) (source->stream_count || sink->stream_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) mdev = source->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (mdev->ops && mdev->ops->link_notify) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) ret = mdev->ops->link_notify(link, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) MEDIA_DEV_NOTIFY_PRE_LINK_CH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ret = __media_entity_setup_link_notify(link, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (mdev->ops && mdev->ops->link_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) mdev->ops->link_notify(link, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) MEDIA_DEV_NOTIFY_POST_LINK_CH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) EXPORT_SYMBOL_GPL(__media_entity_setup_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) int media_entity_setup_link(struct media_link *link, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) mutex_lock(&link->graph_obj.mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ret = __media_entity_setup_link(link, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) mutex_unlock(&link->graph_obj.mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) EXPORT_SYMBOL_GPL(media_entity_setup_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct media_link *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) media_entity_find_link(struct media_pad *source, struct media_pad *sink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) list_for_each_entry(link, &source->entity->links, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (link->source->entity == source->entity &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) link->source->index == source->index &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) link->sink->entity == sink->entity &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) link->sink->index == sink->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) EXPORT_SYMBOL_GPL(media_entity_find_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct media_pad *media_entity_remote_pad(const struct media_pad *pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) list_for_each_entry(link, &pad->entity->links, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (!(link->flags & MEDIA_LNK_FL_ENABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (link->source == pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return link->sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (link->sink == pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return link->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) EXPORT_SYMBOL_GPL(media_entity_remote_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static void media_interface_init(struct media_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct media_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) u32 gobj_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) u32 intf_type, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) intf->type = intf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) intf->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) INIT_LIST_HEAD(&intf->links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) media_gobj_create(mdev, gobj_type, &intf->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /* Functions related to the media interface via device nodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) u32 type, u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) u32 major, u32 minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct media_intf_devnode *devnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (!devnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) devnode->major = major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) devnode->minor = minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) type, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return devnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) EXPORT_SYMBOL_GPL(media_devnode_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) void media_devnode_remove(struct media_intf_devnode *devnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) media_remove_intf_links(&devnode->intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) media_gobj_destroy(&devnode->intf.graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) kfree(devnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) EXPORT_SYMBOL_GPL(media_devnode_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct media_link *media_create_intf_link(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct media_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct media_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) link = media_add_link(&intf->links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (link == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) link->intf = intf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) link->entity = entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* Initialize graph object embedded at the new link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) &link->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) EXPORT_SYMBOL_GPL(media_create_intf_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) void __media_remove_intf_link(struct media_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) list_del(&link->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) media_gobj_destroy(&link->graph_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) EXPORT_SYMBOL_GPL(__media_remove_intf_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) void media_remove_intf_link(struct media_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) struct media_device *mdev = link->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* Do nothing if the intf is not registered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (mdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) __media_remove_intf_link(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) EXPORT_SYMBOL_GPL(media_remove_intf_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) void __media_remove_intf_links(struct media_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct media_link *link, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) list_for_each_entry_safe(link, tmp, &intf->links, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) __media_remove_intf_link(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) EXPORT_SYMBOL_GPL(__media_remove_intf_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) void media_remove_intf_links(struct media_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct media_device *mdev = intf->graph_obj.mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /* Do nothing if the intf is not registered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (mdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) mutex_lock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) __media_remove_intf_links(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) mutex_unlock(&mdev->graph_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) EXPORT_SYMBOL_GPL(media_remove_intf_links);