mc-entity.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Media entity
  4. *
  5. * Copyright (C) 2010 Nokia Corporation
  6. *
  7. * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  8. * Sakari Ailus <sakari.ailus@iki.fi>
  9. */
  10. #include <linux/bitmap.h>
  11. #include <linux/list.h>
  12. #include <linux/property.h>
  13. #include <linux/slab.h>
  14. #include <media/media-entity.h>
  15. #include <media/media-device.h>
  16. static inline const char *intf_type(struct media_interface *intf)
  17. {
  18. switch (intf->type) {
  19. case MEDIA_INTF_T_DVB_FE:
  20. return "dvb-frontend";
  21. case MEDIA_INTF_T_DVB_DEMUX:
  22. return "dvb-demux";
  23. case MEDIA_INTF_T_DVB_DVR:
  24. return "dvb-dvr";
  25. case MEDIA_INTF_T_DVB_CA:
  26. return "dvb-ca";
  27. case MEDIA_INTF_T_DVB_NET:
  28. return "dvb-net";
  29. case MEDIA_INTF_T_V4L_VIDEO:
  30. return "v4l-video";
  31. case MEDIA_INTF_T_V4L_VBI:
  32. return "v4l-vbi";
  33. case MEDIA_INTF_T_V4L_RADIO:
  34. return "v4l-radio";
  35. case MEDIA_INTF_T_V4L_SUBDEV:
  36. return "v4l-subdev";
  37. case MEDIA_INTF_T_V4L_SWRADIO:
  38. return "v4l-swradio";
  39. case MEDIA_INTF_T_V4L_TOUCH:
  40. return "v4l-touch";
  41. default:
  42. return "unknown-intf";
  43. }
  44. };
  45. static inline const char *link_type_name(struct media_link *link)
  46. {
  47. switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
  48. case MEDIA_LNK_FL_DATA_LINK:
  49. return "data";
  50. case MEDIA_LNK_FL_INTERFACE_LINK:
  51. return "interface";
  52. case MEDIA_LNK_FL_ANCILLARY_LINK:
  53. return "ancillary";
  54. default:
  55. return "unknown";
  56. }
  57. }
  58. __must_check int media_entity_enum_init(struct media_entity_enum *ent_enum,
  59. struct media_device *mdev)
  60. {
  61. int idx_max;
  62. idx_max = ALIGN(mdev->entity_internal_idx_max + 1, BITS_PER_LONG);
  63. ent_enum->bmap = bitmap_zalloc(idx_max, GFP_KERNEL);
  64. if (!ent_enum->bmap)
  65. return -ENOMEM;
  66. ent_enum->idx_max = idx_max;
  67. return 0;
  68. }
  69. EXPORT_SYMBOL_GPL(media_entity_enum_init);
  70. void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
  71. {
  72. bitmap_free(ent_enum->bmap);
  73. }
  74. EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
  75. /**
  76. * dev_dbg_obj - Prints in debug mode a change on some object
  77. *
  78. * @event_name: Name of the event to report. Could be __func__
  79. * @gobj: Pointer to the object
  80. *
  81. * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
  82. * won't produce any code.
  83. */
  84. static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj)
  85. {
  86. #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
  87. switch (media_type(gobj)) {
  88. case MEDIA_GRAPH_ENTITY:
  89. dev_dbg(gobj->mdev->dev,
  90. "%s id %u: entity '%s'\n",
  91. event_name, media_id(gobj),
  92. gobj_to_entity(gobj)->name);
  93. break;
  94. case MEDIA_GRAPH_LINK:
  95. {
  96. struct media_link *link = gobj_to_link(gobj);
  97. dev_dbg(gobj->mdev->dev,
  98. "%s id %u: %s link id %u ==> id %u\n",
  99. event_name, media_id(gobj), link_type_name(link),
  100. media_id(link->gobj0),
  101. media_id(link->gobj1));
  102. break;
  103. }
  104. case MEDIA_GRAPH_PAD:
  105. {
  106. struct media_pad *pad = gobj_to_pad(gobj);
  107. dev_dbg(gobj->mdev->dev,
  108. "%s id %u: %s%spad '%s':%d\n",
  109. event_name, media_id(gobj),
  110. pad->flags & MEDIA_PAD_FL_SINK ? "sink " : "",
  111. pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "",
  112. pad->entity->name, pad->index);
  113. break;
  114. }
  115. case MEDIA_GRAPH_INTF_DEVNODE:
  116. {
  117. struct media_interface *intf = gobj_to_intf(gobj);
  118. struct media_intf_devnode *devnode = intf_to_devnode(intf);
  119. dev_dbg(gobj->mdev->dev,
  120. "%s id %u: intf_devnode %s - major: %d, minor: %d\n",
  121. event_name, media_id(gobj),
  122. intf_type(intf),
  123. devnode->major, devnode->minor);
  124. break;
  125. }
  126. }
  127. #endif
  128. }
  129. void media_gobj_create(struct media_device *mdev,
  130. enum media_gobj_type type,
  131. struct media_gobj *gobj)
  132. {
  133. BUG_ON(!mdev);
  134. gobj->mdev = mdev;
  135. /* Create a per-type unique object ID */
  136. gobj->id = media_gobj_gen_id(type, ++mdev->id);
  137. switch (type) {
  138. case MEDIA_GRAPH_ENTITY:
  139. list_add_tail(&gobj->list, &mdev->entities);
  140. break;
  141. case MEDIA_GRAPH_PAD:
  142. list_add_tail(&gobj->list, &mdev->pads);
  143. break;
  144. case MEDIA_GRAPH_LINK:
  145. list_add_tail(&gobj->list, &mdev->links);
  146. break;
  147. case MEDIA_GRAPH_INTF_DEVNODE:
  148. list_add_tail(&gobj->list, &mdev->interfaces);
  149. break;
  150. }
  151. mdev->topology_version++;
  152. dev_dbg_obj(__func__, gobj);
  153. }
  154. void media_gobj_destroy(struct media_gobj *gobj)
  155. {
  156. /* Do nothing if the object is not linked. */
  157. if (gobj->mdev == NULL)
  158. return;
  159. dev_dbg_obj(__func__, gobj);
  160. gobj->mdev->topology_version++;
  161. /* Remove the object from mdev list */
  162. list_del(&gobj->list);
  163. gobj->mdev = NULL;
  164. }
  165. /*
  166. * TODO: Get rid of this.
  167. */
  168. #define MEDIA_ENTITY_MAX_PADS 512
  169. int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
  170. struct media_pad *pads)
  171. {
  172. struct media_device *mdev = entity->graph_obj.mdev;
  173. struct media_pad *iter;
  174. unsigned int i = 0;
  175. int ret = 0;
  176. if (num_pads >= MEDIA_ENTITY_MAX_PADS)
  177. return -E2BIG;
  178. entity->num_pads = num_pads;
  179. entity->pads = pads;
  180. if (mdev)
  181. mutex_lock(&mdev->graph_mutex);
  182. media_entity_for_each_pad(entity, iter) {
  183. iter->entity = entity;
  184. iter->index = i++;
  185. if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK |
  186. MEDIA_PAD_FL_SOURCE)) != 1) {
  187. ret = -EINVAL;
  188. break;
  189. }
  190. if (mdev)
  191. media_gobj_create(mdev, MEDIA_GRAPH_PAD,
  192. &iter->graph_obj);
  193. }
  194. if (ret && mdev) {
  195. media_entity_for_each_pad(entity, iter)
  196. media_gobj_destroy(&iter->graph_obj);
  197. }
  198. if (mdev)
  199. mutex_unlock(&mdev->graph_mutex);
  200. return ret;
  201. }
  202. EXPORT_SYMBOL_GPL(media_entity_pads_init);
  203. /* -----------------------------------------------------------------------------
  204. * Graph traversal
  205. */
  206. /**
  207. * media_entity_has_pad_interdep - Check interdependency between two pads
  208. *
  209. * @entity: The entity
  210. * @pad0: The first pad index
  211. * @pad1: The second pad index
  212. *
  213. * This function checks the interdependency inside the entity between @pad0
  214. * and @pad1. If two pads are interdependent they are part of the same pipeline
  215. * and enabling one of the pads means that the other pad will become "locked"
  216. * and doesn't allow configuration changes.
  217. *
  218. * This function uses the &media_entity_operations.has_pad_interdep() operation
  219. * to check the dependency inside the entity between @pad0 and @pad1. If the
  220. * has_pad_interdep operation is not implemented, all pads of the entity are
  221. * considered to be interdependent.
  222. *
  223. * One of @pad0 and @pad1 must be a sink pad and the other one a source pad.
  224. * The function returns false if both pads are sinks or sources.
  225. *
  226. * The caller must hold entity->graph_obj.mdev->mutex.
  227. *
  228. * Return: true if the pads are connected internally and false otherwise.
  229. */
  230. static bool media_entity_has_pad_interdep(struct media_entity *entity,
  231. unsigned int pad0, unsigned int pad1)
  232. {
  233. if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
  234. return false;
  235. if (entity->pads[pad0].flags & entity->pads[pad1].flags &
  236. (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE))
  237. return false;
  238. if (!entity->ops || !entity->ops->has_pad_interdep)
  239. return true;
  240. return entity->ops->has_pad_interdep(entity, pad0, pad1);
  241. }
  242. static struct media_entity *
  243. media_entity_other(struct media_entity *entity, struct media_link *link)
  244. {
  245. if (link->source->entity == entity)
  246. return link->sink->entity;
  247. else
  248. return link->source->entity;
  249. }
  250. /* push an entity to traversal stack */
  251. static void stack_push(struct media_graph *graph,
  252. struct media_entity *entity)
  253. {
  254. if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
  255. WARN_ON(1);
  256. return;
  257. }
  258. graph->top++;
  259. graph->stack[graph->top].link = entity->links.next;
  260. graph->stack[graph->top].entity = entity;
  261. }
  262. static struct media_entity *stack_pop(struct media_graph *graph)
  263. {
  264. struct media_entity *entity;
  265. entity = graph->stack[graph->top].entity;
  266. graph->top--;
  267. return entity;
  268. }
  269. #define link_top(en) ((en)->stack[(en)->top].link)
  270. #define stack_top(en) ((en)->stack[(en)->top].entity)
  271. /**
  272. * media_graph_walk_init - Allocate resources for graph walk
  273. * @graph: Media graph structure that will be used to walk the graph
  274. * @mdev: Media device
  275. *
  276. * Reserve resources for graph walk in media device's current
  277. * state. The memory must be released using
  278. * media_graph_walk_cleanup().
  279. *
  280. * Returns error on failure, zero on success.
  281. */
  282. __must_check int media_graph_walk_init(
  283. struct media_graph *graph, struct media_device *mdev)
  284. {
  285. return media_entity_enum_init(&graph->ent_enum, mdev);
  286. }
  287. EXPORT_SYMBOL_GPL(media_graph_walk_init);
  288. /**
  289. * media_graph_walk_cleanup - Release resources related to graph walking
  290. * @graph: Media graph structure that was used to walk the graph
  291. */
  292. void media_graph_walk_cleanup(struct media_graph *graph)
  293. {
  294. media_entity_enum_cleanup(&graph->ent_enum);
  295. }
  296. EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
  297. void media_graph_walk_start(struct media_graph *graph,
  298. struct media_entity *entity)
  299. {
  300. media_entity_enum_zero(&graph->ent_enum);
  301. media_entity_enum_set(&graph->ent_enum, entity);
  302. graph->top = 0;
  303. graph->stack[graph->top].entity = NULL;
  304. stack_push(graph, entity);
  305. dev_dbg(entity->graph_obj.mdev->dev,
  306. "begin graph walk at '%s'\n", entity->name);
  307. }
  308. EXPORT_SYMBOL_GPL(media_graph_walk_start);
  309. static void media_graph_walk_iter(struct media_graph *graph)
  310. {
  311. struct media_entity *entity = stack_top(graph);
  312. struct media_link *link;
  313. struct media_entity *next;
  314. link = list_entry(link_top(graph), typeof(*link), list);
  315. /* If the link is not a data link, don't follow it */
  316. if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
  317. link_top(graph) = link_top(graph)->next;
  318. return;
  319. }
  320. /* The link is not enabled so we do not follow. */
  321. if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
  322. link_top(graph) = link_top(graph)->next;
  323. dev_dbg(entity->graph_obj.mdev->dev,
  324. "walk: skipping disabled link '%s':%u -> '%s':%u\n",
  325. link->source->entity->name, link->source->index,
  326. link->sink->entity->name, link->sink->index);
  327. return;
  328. }
  329. /* Get the entity at the other end of the link. */
  330. next = media_entity_other(entity, link);
  331. /* Has the entity already been visited? */
  332. if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
  333. link_top(graph) = link_top(graph)->next;
  334. dev_dbg(entity->graph_obj.mdev->dev,
  335. "walk: skipping entity '%s' (already seen)\n",
  336. next->name);
  337. return;
  338. }
  339. /* Push the new entity to stack and start over. */
  340. link_top(graph) = link_top(graph)->next;
  341. stack_push(graph, next);
  342. dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
  343. next->name);
  344. lockdep_assert_held(&entity->graph_obj.mdev->graph_mutex);
  345. }
  346. struct media_entity *media_graph_walk_next(struct media_graph *graph)
  347. {
  348. struct media_entity *entity;
  349. if (stack_top(graph) == NULL)
  350. return NULL;
  351. /*
  352. * Depth first search. Push entity to stack and continue from
  353. * top of the stack until no more entities on the level can be
  354. * found.
  355. */
  356. while (link_top(graph) != &stack_top(graph)->links)
  357. media_graph_walk_iter(graph);
  358. entity = stack_pop(graph);
  359. dev_dbg(entity->graph_obj.mdev->dev,
  360. "walk: returning entity '%s'\n", entity->name);
  361. return entity;
  362. }
  363. EXPORT_SYMBOL_GPL(media_graph_walk_next);
  364. /* -----------------------------------------------------------------------------
  365. * Pipeline management
  366. */
  367. /*
  368. * The pipeline traversal stack stores pads that are reached during graph
  369. * traversal, with a list of links to be visited to continue the traversal.
  370. * When a new pad is reached, an entry is pushed on the top of the stack and
  371. * points to the incoming pad and the first link of the entity.
  372. *
  373. * To find further pads in the pipeline, the traversal algorithm follows
  374. * internal pad dependencies in the entity, and then links in the graph. It
  375. * does so by iterating over all links of the entity, and following enabled
  376. * links that originate from a pad that is internally connected to the incoming
  377. * pad, as reported by the media_entity_has_pad_interdep() function.
  378. */
  379. /**
  380. * struct media_pipeline_walk_entry - Entry in the pipeline traversal stack
  381. *
  382. * @pad: The media pad being visited
  383. * @links: Links left to be visited
  384. */
  385. struct media_pipeline_walk_entry {
  386. struct media_pad *pad;
  387. struct list_head *links;
  388. };
  389. /**
  390. * struct media_pipeline_walk - State used by the media pipeline traversal
  391. * algorithm
  392. *
  393. * @mdev: The media device
  394. * @stack: Depth-first search stack
  395. * @stack.size: Number of allocated entries in @stack.entries
  396. * @stack.top: Index of the top stack entry (-1 if the stack is empty)
  397. * @stack.entries: Stack entries
  398. */
  399. struct media_pipeline_walk {
  400. struct media_device *mdev;
  401. struct {
  402. unsigned int size;
  403. int top;
  404. struct media_pipeline_walk_entry *entries;
  405. } stack;
  406. };
  407. #define MEDIA_PIPELINE_STACK_GROW_STEP 16
  408. static struct media_pipeline_walk_entry *
  409. media_pipeline_walk_top(struct media_pipeline_walk *walk)
  410. {
  411. return &walk->stack.entries[walk->stack.top];
  412. }
  413. static bool media_pipeline_walk_empty(struct media_pipeline_walk *walk)
  414. {
  415. return walk->stack.top == -1;
  416. }
  417. /* Increase the stack size by MEDIA_PIPELINE_STACK_GROW_STEP elements. */
  418. static int media_pipeline_walk_resize(struct media_pipeline_walk *walk)
  419. {
  420. struct media_pipeline_walk_entry *entries;
  421. unsigned int new_size;
  422. /* Safety check, to avoid stack overflows in case of bugs. */
  423. if (walk->stack.size >= 256)
  424. return -E2BIG;
  425. new_size = walk->stack.size + MEDIA_PIPELINE_STACK_GROW_STEP;
  426. entries = krealloc(walk->stack.entries,
  427. new_size * sizeof(*walk->stack.entries),
  428. GFP_KERNEL);
  429. if (!entries)
  430. return -ENOMEM;
  431. walk->stack.entries = entries;
  432. walk->stack.size = new_size;
  433. return 0;
  434. }
  435. /* Push a new entry on the stack. */
  436. static int media_pipeline_walk_push(struct media_pipeline_walk *walk,
  437. struct media_pad *pad)
  438. {
  439. struct media_pipeline_walk_entry *entry;
  440. int ret;
  441. if (walk->stack.top + 1 >= walk->stack.size) {
  442. ret = media_pipeline_walk_resize(walk);
  443. if (ret)
  444. return ret;
  445. }
  446. walk->stack.top++;
  447. entry = media_pipeline_walk_top(walk);
  448. entry->pad = pad;
  449. entry->links = pad->entity->links.next;
  450. dev_dbg(walk->mdev->dev,
  451. "media pipeline: pushed entry %u: '%s':%u\n",
  452. walk->stack.top, pad->entity->name, pad->index);
  453. return 0;
  454. }
  455. /*
  456. * Move the top entry link cursor to the next link. If all links of the entry
  457. * have been visited, pop the entry itself. Return true if the entry has been
  458. * popped.
  459. */
  460. static bool media_pipeline_walk_pop(struct media_pipeline_walk *walk)
  461. {
  462. struct media_pipeline_walk_entry *entry;
  463. if (WARN_ON(walk->stack.top < 0))
  464. return false;
  465. entry = media_pipeline_walk_top(walk);
  466. if (entry->links->next == &entry->pad->entity->links) {
  467. dev_dbg(walk->mdev->dev,
  468. "media pipeline: entry %u has no more links, popping\n",
  469. walk->stack.top);
  470. walk->stack.top--;
  471. return true;
  472. }
  473. entry->links = entry->links->next;
  474. dev_dbg(walk->mdev->dev,
  475. "media pipeline: moved entry %u to next link\n",
  476. walk->stack.top);
  477. return false;
  478. }
  479. /* Free all memory allocated while walking the pipeline. */
  480. static void media_pipeline_walk_destroy(struct media_pipeline_walk *walk)
  481. {
  482. kfree(walk->stack.entries);
  483. }
  484. /* Add a pad to the pipeline and push it to the stack. */
  485. static int media_pipeline_add_pad(struct media_pipeline *pipe,
  486. struct media_pipeline_walk *walk,
  487. struct media_pad *pad)
  488. {
  489. struct media_pipeline_pad *ppad;
  490. list_for_each_entry(ppad, &pipe->pads, list) {
  491. if (ppad->pad == pad) {
  492. dev_dbg(pad->graph_obj.mdev->dev,
  493. "media pipeline: already contains pad '%s':%u\n",
  494. pad->entity->name, pad->index);
  495. return 0;
  496. }
  497. }
  498. ppad = kzalloc(sizeof(*ppad), GFP_KERNEL);
  499. if (!ppad)
  500. return -ENOMEM;
  501. ppad->pipe = pipe;
  502. ppad->pad = pad;
  503. list_add_tail(&ppad->list, &pipe->pads);
  504. dev_dbg(pad->graph_obj.mdev->dev,
  505. "media pipeline: added pad '%s':%u\n",
  506. pad->entity->name, pad->index);
  507. return media_pipeline_walk_push(walk, pad);
  508. }
  509. /* Explore the next link of the entity at the top of the stack. */
  510. static int media_pipeline_explore_next_link(struct media_pipeline *pipe,
  511. struct media_pipeline_walk *walk)
  512. {
  513. struct media_pipeline_walk_entry *entry = media_pipeline_walk_top(walk);
  514. struct media_pad *origin;
  515. struct media_link *link;
  516. struct media_pad *local;
  517. struct media_pad *remote;
  518. bool last_link;
  519. int ret;
  520. origin = entry->pad;
  521. link = list_entry(entry->links, typeof(*link), list);
  522. last_link = media_pipeline_walk_pop(walk);
  523. if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
  524. dev_dbg(walk->mdev->dev,
  525. "media pipeline: skipping link (not data-link)\n");
  526. return 0;
  527. }
  528. dev_dbg(walk->mdev->dev,
  529. "media pipeline: exploring link '%s':%u -> '%s':%u\n",
  530. link->source->entity->name, link->source->index,
  531. link->sink->entity->name, link->sink->index);
  532. /* Get the local pad and remote pad. */
  533. if (link->source->entity == origin->entity) {
  534. local = link->source;
  535. remote = link->sink;
  536. } else {
  537. local = link->sink;
  538. remote = link->source;
  539. }
  540. /*
  541. * Skip links that originate from a different pad than the incoming pad
  542. * that is not connected internally in the entity to the incoming pad.
  543. */
  544. if (origin != local &&
  545. !media_entity_has_pad_interdep(origin->entity, origin->index,
  546. local->index)) {
  547. dev_dbg(walk->mdev->dev,
  548. "media pipeline: skipping link (no route)\n");
  549. goto done;
  550. }
  551. /*
  552. * Add the local pad of the link to the pipeline and push it to the
  553. * stack, if not already present.
  554. */
  555. ret = media_pipeline_add_pad(pipe, walk, local);
  556. if (ret)
  557. return ret;
  558. /* Similarly, add the remote pad, but only if the link is enabled. */
  559. if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
  560. dev_dbg(walk->mdev->dev,
  561. "media pipeline: skipping link (disabled)\n");
  562. goto done;
  563. }
  564. ret = media_pipeline_add_pad(pipe, walk, remote);
  565. if (ret)
  566. return ret;
  567. done:
  568. /*
  569. * If we're done iterating over links, iterate over pads of the entity.
  570. * This is necessary to discover pads that are not connected with any
  571. * link. Those are dead ends from a pipeline exploration point of view,
  572. * but are still part of the pipeline and need to be added to enable
  573. * proper validation.
  574. */
  575. if (!last_link)
  576. return 0;
  577. dev_dbg(walk->mdev->dev,
  578. "media pipeline: adding unconnected pads of '%s'\n",
  579. local->entity->name);
  580. media_entity_for_each_pad(origin->entity, local) {
  581. /*
  582. * Skip the origin pad (already handled), pad that have links
  583. * (already discovered through iterating over links) and pads
  584. * not internally connected.
  585. */
  586. if (origin == local || !local->num_links ||
  587. !media_entity_has_pad_interdep(origin->entity, origin->index,
  588. local->index))
  589. continue;
  590. ret = media_pipeline_add_pad(pipe, walk, local);
  591. if (ret)
  592. return ret;
  593. }
  594. return 0;
  595. }
  596. static void media_pipeline_cleanup(struct media_pipeline *pipe)
  597. {
  598. while (!list_empty(&pipe->pads)) {
  599. struct media_pipeline_pad *ppad;
  600. ppad = list_first_entry(&pipe->pads, typeof(*ppad), list);
  601. list_del(&ppad->list);
  602. kfree(ppad);
  603. }
  604. }
  605. static int media_pipeline_populate(struct media_pipeline *pipe,
  606. struct media_pad *pad)
  607. {
  608. struct media_pipeline_walk walk = { };
  609. struct media_pipeline_pad *ppad;
  610. int ret;
  611. /*
  612. * Populate the media pipeline by walking the media graph, starting
  613. * from @pad.
  614. */
  615. INIT_LIST_HEAD(&pipe->pads);
  616. pipe->mdev = pad->graph_obj.mdev;
  617. walk.mdev = pipe->mdev;
  618. walk.stack.top = -1;
  619. ret = media_pipeline_add_pad(pipe, &walk, pad);
  620. if (ret)
  621. goto done;
  622. /*
  623. * Use a depth-first search algorithm: as long as the stack is not
  624. * empty, explore the next link of the top entry. The
  625. * media_pipeline_explore_next_link() function will either move to the
  626. * next link, pop the entry if fully visited, or add new entries on
  627. * top.
  628. */
  629. while (!media_pipeline_walk_empty(&walk)) {
  630. ret = media_pipeline_explore_next_link(pipe, &walk);
  631. if (ret)
  632. goto done;
  633. }
  634. dev_dbg(pad->graph_obj.mdev->dev,
  635. "media pipeline populated, found pads:\n");
  636. list_for_each_entry(ppad, &pipe->pads, list)
  637. dev_dbg(pad->graph_obj.mdev->dev, "- '%s':%u\n",
  638. ppad->pad->entity->name, ppad->pad->index);
  639. WARN_ON(walk.stack.top != -1);
  640. ret = 0;
  641. done:
  642. media_pipeline_walk_destroy(&walk);
  643. if (ret)
  644. media_pipeline_cleanup(pipe);
  645. return ret;
  646. }
  647. __must_check int __media_pipeline_start(struct media_pad *pad,
  648. struct media_pipeline *pipe)
  649. {
  650. struct media_device *mdev = pad->graph_obj.mdev;
  651. struct media_pipeline_pad *err_ppad;
  652. struct media_pipeline_pad *ppad;
  653. int ret;
  654. lockdep_assert_held(&mdev->graph_mutex);
  655. /*
  656. * If the pad is already part of a pipeline, that pipeline must be the
  657. * same as the pipe given to media_pipeline_start().
  658. */
  659. if (WARN_ON(pad->pipe && pad->pipe != pipe))
  660. return -EINVAL;
  661. /*
  662. * If the pipeline has already been started, it is guaranteed to be
  663. * valid, so just increase the start count.
  664. */
  665. if (pipe->start_count) {
  666. pipe->start_count++;
  667. return 0;
  668. }
  669. /*
  670. * Populate the pipeline. This populates the media_pipeline pads list
  671. * with media_pipeline_pad instances for each pad found during graph
  672. * walk.
  673. */
  674. ret = media_pipeline_populate(pipe, pad);
  675. if (ret)
  676. return ret;
  677. /*
  678. * Now that all the pads in the pipeline have been gathered, perform
  679. * the validation steps.
  680. */
  681. list_for_each_entry(ppad, &pipe->pads, list) {
  682. struct media_pad *pad = ppad->pad;
  683. struct media_entity *entity = pad->entity;
  684. bool has_enabled_link = false;
  685. struct media_link *link;
  686. dev_dbg(mdev->dev, "Validating pad '%s':%u\n", pad->entity->name,
  687. pad->index);
  688. /*
  689. * 1. Ensure that the pad doesn't already belong to a different
  690. * pipeline.
  691. */
  692. if (pad->pipe) {
  693. dev_dbg(mdev->dev, "Failed to start pipeline: pad '%s':%u busy\n",
  694. pad->entity->name, pad->index);
  695. ret = -EBUSY;
  696. goto error;
  697. }
  698. /*
  699. * 2. Validate all active links whose sink is the current pad.
  700. * Validation of the source pads is performed in the context of
  701. * the connected sink pad to avoid duplicating checks.
  702. */
  703. for_each_media_entity_data_link(entity, link) {
  704. /* Skip links unrelated to the current pad. */
  705. if (link->sink != pad && link->source != pad)
  706. continue;
  707. /* Record if the pad has links and enabled links. */
  708. if (link->flags & MEDIA_LNK_FL_ENABLED)
  709. has_enabled_link = true;
  710. /*
  711. * Validate the link if it's enabled and has the
  712. * current pad as its sink.
  713. */
  714. if (!(link->flags & MEDIA_LNK_FL_ENABLED))
  715. continue;
  716. if (link->sink != pad)
  717. continue;
  718. if (!entity->ops || !entity->ops->link_validate)
  719. continue;
  720. ret = entity->ops->link_validate(link);
  721. if (ret) {
  722. dev_dbg(mdev->dev,
  723. "Link '%s':%u -> '%s':%u failed validation: %d\n",
  724. link->source->entity->name,
  725. link->source->index,
  726. link->sink->entity->name,
  727. link->sink->index, ret);
  728. goto error;
  729. }
  730. dev_dbg(mdev->dev,
  731. "Link '%s':%u -> '%s':%u is valid\n",
  732. link->source->entity->name,
  733. link->source->index,
  734. link->sink->entity->name,
  735. link->sink->index);
  736. }
  737. /*
  738. * 3. If the pad has the MEDIA_PAD_FL_MUST_CONNECT flag set,
  739. * ensure that it has either no link or an enabled link.
  740. */
  741. if ((pad->flags & MEDIA_PAD_FL_MUST_CONNECT) &&
  742. !has_enabled_link) {
  743. dev_dbg(mdev->dev,
  744. "Pad '%s':%u must be connected by an enabled link\n",
  745. pad->entity->name, pad->index);
  746. ret = -ENOLINK;
  747. goto error;
  748. }
  749. /* Validation passed, store the pipe pointer in the pad. */
  750. pad->pipe = pipe;
  751. }
  752. pipe->start_count++;
  753. return 0;
  754. error:
  755. /*
  756. * Link validation on graph failed. We revert what we did and
  757. * return the error.
  758. */
  759. list_for_each_entry(err_ppad, &pipe->pads, list) {
  760. if (err_ppad == ppad)
  761. break;
  762. err_ppad->pad->pipe = NULL;
  763. }
  764. media_pipeline_cleanup(pipe);
  765. return ret;
  766. }
  767. EXPORT_SYMBOL_GPL(__media_pipeline_start);
  768. __must_check int media_pipeline_start(struct media_pad *pad,
  769. struct media_pipeline *pipe)
  770. {
  771. struct media_device *mdev = pad->graph_obj.mdev;
  772. int ret;
  773. mutex_lock(&mdev->graph_mutex);
  774. ret = __media_pipeline_start(pad, pipe);
  775. mutex_unlock(&mdev->graph_mutex);
  776. return ret;
  777. }
  778. EXPORT_SYMBOL_GPL(media_pipeline_start);
  779. void __media_pipeline_stop(struct media_pad *pad)
  780. {
  781. struct media_pipeline *pipe = pad->pipe;
  782. struct media_pipeline_pad *ppad;
  783. /*
  784. * If the following check fails, the driver has performed an
  785. * unbalanced call to media_pipeline_stop()
  786. */
  787. if (WARN_ON(!pipe))
  788. return;
  789. if (--pipe->start_count)
  790. return;
  791. list_for_each_entry(ppad, &pipe->pads, list)
  792. ppad->pad->pipe = NULL;
  793. media_pipeline_cleanup(pipe);
  794. if (pipe->allocated)
  795. kfree(pipe);
  796. }
  797. EXPORT_SYMBOL_GPL(__media_pipeline_stop);
  798. void media_pipeline_stop(struct media_pad *pad)
  799. {
  800. struct media_device *mdev = pad->graph_obj.mdev;
  801. mutex_lock(&mdev->graph_mutex);
  802. __media_pipeline_stop(pad);
  803. mutex_unlock(&mdev->graph_mutex);
  804. }
  805. EXPORT_SYMBOL_GPL(media_pipeline_stop);
  806. __must_check int media_pipeline_alloc_start(struct media_pad *pad)
  807. {
  808. struct media_device *mdev = pad->graph_obj.mdev;
  809. struct media_pipeline *new_pipe = NULL;
  810. struct media_pipeline *pipe;
  811. int ret;
  812. mutex_lock(&mdev->graph_mutex);
  813. /*
  814. * Is the pad already part of a pipeline? If not, we need to allocate
  815. * a pipe.
  816. */
  817. pipe = media_pad_pipeline(pad);
  818. if (!pipe) {
  819. new_pipe = kzalloc(sizeof(*new_pipe), GFP_KERNEL);
  820. if (!new_pipe) {
  821. ret = -ENOMEM;
  822. goto out;
  823. }
  824. pipe = new_pipe;
  825. pipe->allocated = true;
  826. }
  827. ret = __media_pipeline_start(pad, pipe);
  828. if (ret)
  829. kfree(new_pipe);
  830. out:
  831. mutex_unlock(&mdev->graph_mutex);
  832. return ret;
  833. }
  834. EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
  835. struct media_pad *
  836. __media_pipeline_pad_iter_next(struct media_pipeline *pipe,
  837. struct media_pipeline_pad_iter *iter,
  838. struct media_pad *pad)
  839. {
  840. if (!pad)
  841. iter->cursor = pipe->pads.next;
  842. if (iter->cursor == &pipe->pads)
  843. return NULL;
  844. pad = list_entry(iter->cursor, struct media_pipeline_pad, list)->pad;
  845. iter->cursor = iter->cursor->next;
  846. return pad;
  847. }
  848. EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
  849. int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
  850. struct media_pipeline_entity_iter *iter)
  851. {
  852. return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
  853. }
  854. EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
  855. void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
  856. {
  857. media_entity_enum_cleanup(&iter->ent_enum);
  858. }
  859. EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
  860. struct media_entity *
  861. __media_pipeline_entity_iter_next(struct media_pipeline *pipe,
  862. struct media_pipeline_entity_iter *iter,
  863. struct media_entity *entity)
  864. {
  865. if (!entity)
  866. iter->cursor = pipe->pads.next;
  867. while (iter->cursor != &pipe->pads) {
  868. struct media_pipeline_pad *ppad;
  869. struct media_entity *entity;
  870. ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
  871. entity = ppad->pad->entity;
  872. iter->cursor = iter->cursor->next;
  873. if (!media_entity_enum_test_and_set(&iter->ent_enum, entity))
  874. return entity;
  875. }
  876. return NULL;
  877. }
  878. EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
  879. /* -----------------------------------------------------------------------------
  880. * Links management
  881. */
  882. static struct media_link *media_add_link(struct list_head *head)
  883. {
  884. struct media_link *link;
  885. link = kzalloc(sizeof(*link), GFP_KERNEL);
  886. if (link == NULL)
  887. return NULL;
  888. list_add_tail(&link->list, head);
  889. return link;
  890. }
  891. static void __media_entity_remove_link(struct media_entity *entity,
  892. struct media_link *link)
  893. {
  894. struct media_link *rlink, *tmp;
  895. struct media_entity *remote;
  896. /* Remove the reverse links for a data link. */
  897. if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
  898. link->source->num_links--;
  899. link->sink->num_links--;
  900. if (link->source->entity == entity)
  901. remote = link->sink->entity;
  902. else
  903. remote = link->source->entity;
  904. list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
  905. if (rlink != link->reverse)
  906. continue;
  907. if (link->source->entity == entity)
  908. remote->num_backlinks--;
  909. /* Remove the remote link */
  910. list_del(&rlink->list);
  911. media_gobj_destroy(&rlink->graph_obj);
  912. kfree(rlink);
  913. if (--remote->num_links == 0)
  914. break;
  915. }
  916. }
  917. list_del(&link->list);
  918. media_gobj_destroy(&link->graph_obj);
  919. kfree(link);
  920. }
  921. int media_get_pad_index(struct media_entity *entity, u32 pad_type,
  922. enum media_pad_signal_type sig_type)
  923. {
  924. unsigned int i;
  925. if (!entity)
  926. return -EINVAL;
  927. for (i = 0; i < entity->num_pads; i++) {
  928. if ((entity->pads[i].flags &
  929. (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type)
  930. continue;
  931. if (entity->pads[i].sig_type == sig_type)
  932. return i;
  933. }
  934. return -EINVAL;
  935. }
  936. EXPORT_SYMBOL_GPL(media_get_pad_index);
  937. int
  938. media_create_pad_link(struct media_entity *source, u16 source_pad,
  939. struct media_entity *sink, u16 sink_pad, u32 flags)
  940. {
  941. struct media_link *link;
  942. struct media_link *backlink;
  943. if (flags & MEDIA_LNK_FL_LINK_TYPE)
  944. return -EINVAL;
  945. flags |= MEDIA_LNK_FL_DATA_LINK;
  946. if (WARN_ON(!source || !sink) ||
  947. WARN_ON(source_pad >= source->num_pads) ||
  948. WARN_ON(sink_pad >= sink->num_pads))
  949. return -EINVAL;
  950. if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
  951. return -EINVAL;
  952. if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
  953. return -EINVAL;
  954. link = media_add_link(&source->links);
  955. if (link == NULL)
  956. return -ENOMEM;
  957. link->source = &source->pads[source_pad];
  958. link->sink = &sink->pads[sink_pad];
  959. link->flags = flags;
  960. /* Initialize graph object embedded at the new link */
  961. media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
  962. &link->graph_obj);
  963. /* Create the backlink. Backlinks are used to help graph traversal and
  964. * are not reported to userspace.
  965. */
  966. backlink = media_add_link(&sink->links);
  967. if (backlink == NULL) {
  968. __media_entity_remove_link(source, link);
  969. return -ENOMEM;
  970. }
  971. backlink->source = &source->pads[source_pad];
  972. backlink->sink = &sink->pads[sink_pad];
  973. backlink->flags = flags;
  974. backlink->is_backlink = true;
  975. /* Initialize graph object embedded at the new link */
  976. media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
  977. &backlink->graph_obj);
  978. link->reverse = backlink;
  979. backlink->reverse = link;
  980. sink->num_backlinks++;
  981. sink->num_links++;
  982. source->num_links++;
  983. link->source->num_links++;
  984. link->sink->num_links++;
  985. return 0;
  986. }
  987. EXPORT_SYMBOL_GPL(media_create_pad_link);
  988. int media_create_pad_links(const struct media_device *mdev,
  989. const u32 source_function,
  990. struct media_entity *source,
  991. const u16 source_pad,
  992. const u32 sink_function,
  993. struct media_entity *sink,
  994. const u16 sink_pad,
  995. u32 flags,
  996. const bool allow_both_undefined)
  997. {
  998. struct media_entity *entity;
  999. unsigned function;
  1000. int ret;
  1001. /* Trivial case: 1:1 relation */
  1002. if (source && sink)
  1003. return media_create_pad_link(source, source_pad,
  1004. sink, sink_pad, flags);
  1005. /* Worse case scenario: n:n relation */
  1006. if (!source && !sink) {
  1007. if (!allow_both_undefined)
  1008. return 0;
  1009. media_device_for_each_entity(source, mdev) {
  1010. if (source->function != source_function)
  1011. continue;
  1012. media_device_for_each_entity(sink, mdev) {
  1013. if (sink->function != sink_function)
  1014. continue;
  1015. ret = media_create_pad_link(source, source_pad,
  1016. sink, sink_pad,
  1017. flags);
  1018. if (ret)
  1019. return ret;
  1020. flags &= ~(MEDIA_LNK_FL_ENABLED |
  1021. MEDIA_LNK_FL_IMMUTABLE);
  1022. }
  1023. }
  1024. return 0;
  1025. }
  1026. /* Handle 1:n and n:1 cases */
  1027. if (source)
  1028. function = sink_function;
  1029. else
  1030. function = source_function;
  1031. media_device_for_each_entity(entity, mdev) {
  1032. if (entity->function != function)
  1033. continue;
  1034. if (source)
  1035. ret = media_create_pad_link(source, source_pad,
  1036. entity, sink_pad, flags);
  1037. else
  1038. ret = media_create_pad_link(entity, source_pad,
  1039. sink, sink_pad, flags);
  1040. if (ret)
  1041. return ret;
  1042. flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
  1043. }
  1044. return 0;
  1045. }
  1046. EXPORT_SYMBOL_GPL(media_create_pad_links);
  1047. void __media_entity_remove_links(struct media_entity *entity)
  1048. {
  1049. struct media_link *link, *tmp;
  1050. list_for_each_entry_safe(link, tmp, &entity->links, list)
  1051. __media_entity_remove_link(entity, link);
  1052. entity->num_links = 0;
  1053. entity->num_backlinks = 0;
  1054. }
  1055. EXPORT_SYMBOL_GPL(__media_entity_remove_links);
  1056. void media_entity_remove_links(struct media_entity *entity)
  1057. {
  1058. struct media_device *mdev = entity->graph_obj.mdev;
  1059. /* Do nothing if the entity is not registered. */
  1060. if (mdev == NULL)
  1061. return;
  1062. mutex_lock(&mdev->graph_mutex);
  1063. __media_entity_remove_links(entity);
  1064. mutex_unlock(&mdev->graph_mutex);
  1065. }
  1066. EXPORT_SYMBOL_GPL(media_entity_remove_links);
  1067. static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
  1068. {
  1069. int ret;
  1070. /* Notify both entities. */
  1071. ret = media_entity_call(link->source->entity, link_setup,
  1072. link->source, link->sink, flags);
  1073. if (ret < 0 && ret != -ENOIOCTLCMD)
  1074. return ret;
  1075. ret = media_entity_call(link->sink->entity, link_setup,
  1076. link->sink, link->source, flags);
  1077. if (ret < 0 && ret != -ENOIOCTLCMD) {
  1078. media_entity_call(link->source->entity, link_setup,
  1079. link->source, link->sink, link->flags);
  1080. return ret;
  1081. }
  1082. link->flags = flags;
  1083. link->reverse->flags = link->flags;
  1084. return 0;
  1085. }
  1086. int __media_entity_setup_link(struct media_link *link, u32 flags)
  1087. {
  1088. const u32 mask = MEDIA_LNK_FL_ENABLED;
  1089. struct media_device *mdev;
  1090. struct media_pad *source, *sink;
  1091. int ret = -EBUSY;
  1092. if (link == NULL)
  1093. return -EINVAL;
  1094. /* The non-modifiable link flags must not be modified. */
  1095. if ((link->flags & ~mask) != (flags & ~mask))
  1096. return -EINVAL;
  1097. if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
  1098. return link->flags == flags ? 0 : -EINVAL;
  1099. if (link->flags == flags)
  1100. return 0;
  1101. source = link->source;
  1102. sink = link->sink;
  1103. if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
  1104. (media_pad_is_streaming(source) || media_pad_is_streaming(sink)))
  1105. return -EBUSY;
  1106. mdev = source->graph_obj.mdev;
  1107. if (mdev->ops && mdev->ops->link_notify) {
  1108. ret = mdev->ops->link_notify(link, flags,
  1109. MEDIA_DEV_NOTIFY_PRE_LINK_CH);
  1110. if (ret < 0)
  1111. return ret;
  1112. }
  1113. ret = __media_entity_setup_link_notify(link, flags);
  1114. if (mdev->ops && mdev->ops->link_notify)
  1115. mdev->ops->link_notify(link, flags,
  1116. MEDIA_DEV_NOTIFY_POST_LINK_CH);
  1117. return ret;
  1118. }
  1119. EXPORT_SYMBOL_GPL(__media_entity_setup_link);
  1120. int media_entity_setup_link(struct media_link *link, u32 flags)
  1121. {
  1122. int ret;
  1123. mutex_lock(&link->graph_obj.mdev->graph_mutex);
  1124. ret = __media_entity_setup_link(link, flags);
  1125. mutex_unlock(&link->graph_obj.mdev->graph_mutex);
  1126. return ret;
  1127. }
  1128. EXPORT_SYMBOL_GPL(media_entity_setup_link);
  1129. struct media_link *
  1130. media_entity_find_link(struct media_pad *source, struct media_pad *sink)
  1131. {
  1132. struct media_link *link;
  1133. for_each_media_entity_data_link(source->entity, link) {
  1134. if (link->source->entity == source->entity &&
  1135. link->source->index == source->index &&
  1136. link->sink->entity == sink->entity &&
  1137. link->sink->index == sink->index)
  1138. return link;
  1139. }
  1140. return NULL;
  1141. }
  1142. EXPORT_SYMBOL_GPL(media_entity_find_link);
  1143. struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)
  1144. {
  1145. struct media_link *link;
  1146. for_each_media_entity_data_link(pad->entity, link) {
  1147. if (!(link->flags & MEDIA_LNK_FL_ENABLED))
  1148. continue;
  1149. if (link->source == pad)
  1150. return link->sink;
  1151. if (link->sink == pad)
  1152. return link->source;
  1153. }
  1154. return NULL;
  1155. }
  1156. EXPORT_SYMBOL_GPL(media_pad_remote_pad_first);
  1157. struct media_pad *
  1158. media_entity_remote_pad_unique(const struct media_entity *entity,
  1159. unsigned int type)
  1160. {
  1161. struct media_pad *pad = NULL;
  1162. struct media_link *link;
  1163. list_for_each_entry(link, &entity->links, list) {
  1164. struct media_pad *local_pad;
  1165. struct media_pad *remote_pad;
  1166. if (((link->flags & MEDIA_LNK_FL_LINK_TYPE) !=
  1167. MEDIA_LNK_FL_DATA_LINK) ||
  1168. !(link->flags & MEDIA_LNK_FL_ENABLED))
  1169. continue;
  1170. if (type == MEDIA_PAD_FL_SOURCE) {
  1171. local_pad = link->sink;
  1172. remote_pad = link->source;
  1173. } else {
  1174. local_pad = link->source;
  1175. remote_pad = link->sink;
  1176. }
  1177. if (local_pad->entity == entity) {
  1178. if (pad)
  1179. return ERR_PTR(-ENOTUNIQ);
  1180. pad = remote_pad;
  1181. }
  1182. }
  1183. if (!pad)
  1184. return ERR_PTR(-ENOLINK);
  1185. return pad;
  1186. }
  1187. EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique);
  1188. struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
  1189. {
  1190. struct media_pad *found_pad = NULL;
  1191. struct media_link *link;
  1192. list_for_each_entry(link, &pad->entity->links, list) {
  1193. struct media_pad *remote_pad;
  1194. if (!(link->flags & MEDIA_LNK_FL_ENABLED))
  1195. continue;
  1196. if (link->sink == pad)
  1197. remote_pad = link->source;
  1198. else if (link->source == pad)
  1199. remote_pad = link->sink;
  1200. else
  1201. continue;
  1202. if (found_pad)
  1203. return ERR_PTR(-ENOTUNIQ);
  1204. found_pad = remote_pad;
  1205. }
  1206. if (!found_pad)
  1207. return ERR_PTR(-ENOLINK);
  1208. return found_pad;
  1209. }
  1210. EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
  1211. int media_entity_get_fwnode_pad(struct media_entity *entity,
  1212. const struct fwnode_handle *fwnode,
  1213. unsigned long direction_flags)
  1214. {
  1215. struct fwnode_endpoint endpoint;
  1216. unsigned int i;
  1217. int ret;
  1218. if (!entity->ops || !entity->ops->get_fwnode_pad) {
  1219. for (i = 0; i < entity->num_pads; i++) {
  1220. if (entity->pads[i].flags & direction_flags)
  1221. return i;
  1222. }
  1223. return -ENXIO;
  1224. }
  1225. ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
  1226. if (ret)
  1227. return ret;
  1228. ret = entity->ops->get_fwnode_pad(entity, &endpoint);
  1229. if (ret < 0)
  1230. return ret;
  1231. if (ret >= entity->num_pads)
  1232. return -ENXIO;
  1233. if (!(entity->pads[ret].flags & direction_flags))
  1234. return -ENXIO;
  1235. return ret;
  1236. }
  1237. EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
  1238. struct media_pipeline *media_entity_pipeline(struct media_entity *entity)
  1239. {
  1240. struct media_pad *pad;
  1241. media_entity_for_each_pad(entity, pad) {
  1242. if (pad->pipe)
  1243. return pad->pipe;
  1244. }
  1245. return NULL;
  1246. }
  1247. EXPORT_SYMBOL_GPL(media_entity_pipeline);
  1248. struct media_pipeline *media_pad_pipeline(struct media_pad *pad)
  1249. {
  1250. return pad->pipe;
  1251. }
  1252. EXPORT_SYMBOL_GPL(media_pad_pipeline);
  1253. static void media_interface_init(struct media_device *mdev,
  1254. struct media_interface *intf,
  1255. u32 gobj_type,
  1256. u32 intf_type, u32 flags)
  1257. {
  1258. intf->type = intf_type;
  1259. intf->flags = flags;
  1260. INIT_LIST_HEAD(&intf->links);
  1261. media_gobj_create(mdev, gobj_type, &intf->graph_obj);
  1262. }
  1263. /* Functions related to the media interface via device nodes */
  1264. struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
  1265. u32 type, u32 flags,
  1266. u32 major, u32 minor)
  1267. {
  1268. struct media_intf_devnode *devnode;
  1269. devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
  1270. if (!devnode)
  1271. return NULL;
  1272. devnode->major = major;
  1273. devnode->minor = minor;
  1274. media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
  1275. type, flags);
  1276. return devnode;
  1277. }
  1278. EXPORT_SYMBOL_GPL(media_devnode_create);
  1279. void media_devnode_remove(struct media_intf_devnode *devnode)
  1280. {
  1281. media_remove_intf_links(&devnode->intf);
  1282. media_gobj_destroy(&devnode->intf.graph_obj);
  1283. kfree(devnode);
  1284. }
  1285. EXPORT_SYMBOL_GPL(media_devnode_remove);
  1286. struct media_link *media_create_intf_link(struct media_entity *entity,
  1287. struct media_interface *intf,
  1288. u32 flags)
  1289. {
  1290. struct media_link *link;
  1291. link = media_add_link(&intf->links);
  1292. if (link == NULL)
  1293. return NULL;
  1294. link->intf = intf;
  1295. link->entity = entity;
  1296. link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
  1297. /* Initialize graph object embedded at the new link */
  1298. media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
  1299. &link->graph_obj);
  1300. return link;
  1301. }
  1302. EXPORT_SYMBOL_GPL(media_create_intf_link);
  1303. void __media_remove_intf_link(struct media_link *link)
  1304. {
  1305. list_del(&link->list);
  1306. media_gobj_destroy(&link->graph_obj);
  1307. kfree(link);
  1308. }
  1309. EXPORT_SYMBOL_GPL(__media_remove_intf_link);
  1310. void media_remove_intf_link(struct media_link *link)
  1311. {
  1312. struct media_device *mdev = link->graph_obj.mdev;
  1313. /* Do nothing if the intf is not registered. */
  1314. if (mdev == NULL)
  1315. return;
  1316. mutex_lock(&mdev->graph_mutex);
  1317. __media_remove_intf_link(link);
  1318. mutex_unlock(&mdev->graph_mutex);
  1319. }
  1320. EXPORT_SYMBOL_GPL(media_remove_intf_link);
  1321. void __media_remove_intf_links(struct media_interface *intf)
  1322. {
  1323. struct media_link *link, *tmp;
  1324. list_for_each_entry_safe(link, tmp, &intf->links, list)
  1325. __media_remove_intf_link(link);
  1326. }
  1327. EXPORT_SYMBOL_GPL(__media_remove_intf_links);
  1328. void media_remove_intf_links(struct media_interface *intf)
  1329. {
  1330. struct media_device *mdev = intf->graph_obj.mdev;
  1331. /* Do nothing if the intf is not registered. */
  1332. if (mdev == NULL)
  1333. return;
  1334. mutex_lock(&mdev->graph_mutex);
  1335. __media_remove_intf_links(intf);
  1336. mutex_unlock(&mdev->graph_mutex);
  1337. }
  1338. EXPORT_SYMBOL_GPL(media_remove_intf_links);
  1339. struct media_link *media_create_ancillary_link(struct media_entity *primary,
  1340. struct media_entity *ancillary)
  1341. {
  1342. struct media_link *link;
  1343. link = media_add_link(&primary->links);
  1344. if (!link)
  1345. return ERR_PTR(-ENOMEM);
  1346. link->gobj0 = &primary->graph_obj;
  1347. link->gobj1 = &ancillary->graph_obj;
  1348. link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
  1349. MEDIA_LNK_FL_ANCILLARY_LINK;
  1350. /* Initialize graph object embedded in the new link */
  1351. media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
  1352. &link->graph_obj);
  1353. return link;
  1354. }
  1355. EXPORT_SYMBOL_GPL(media_create_ancillary_link);
  1356. struct media_link *__media_entity_next_link(struct media_entity *entity,
  1357. struct media_link *link,
  1358. unsigned long link_type)
  1359. {
  1360. link = link ? list_next_entry(link, list)
  1361. : list_first_entry(&entity->links, typeof(*link), list);
  1362. list_for_each_entry_from(link, &entity->links, list)
  1363. if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == link_type)
  1364. return link;
  1365. return NULL;
  1366. }
  1367. EXPORT_SYMBOL_GPL(__media_entity_next_link);