LCOV - code coverage report
Current view: top level - drivers/media/v4l2-core - v4l2-mc.c (source / functions) Hit Total Coverage
Test: Real Lines: 7 193 3.6 %
Date: 2020-10-17 15:46:16 Functions: 0 9 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : 
       3                 :            : /*
       4                 :            :  * Media Controller ancillary functions
       5                 :            :  *
       6                 :            :  * Copyright (c) 2016 Mauro Carvalho Chehab <mchehab@kernel.org>
       7                 :            :  * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
       8                 :            :  * Copyright (C) 2006-2010 Nokia Corporation
       9                 :            :  * Copyright (c) 2016 Intel Corporation.
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/module.h>
      13                 :            : #include <linux/pci.h>
      14                 :            : #include <linux/usb.h>
      15                 :            : #include <media/media-device.h>
      16                 :            : #include <media/media-entity.h>
      17                 :            : #include <media/v4l2-fh.h>
      18                 :            : #include <media/v4l2-mc.h>
      19                 :            : #include <media/v4l2-subdev.h>
      20                 :            : #include <media/videobuf2-core.h>
      21                 :            : 
      22                 :          0 : int v4l2_mc_create_media_graph(struct media_device *mdev)
      23                 :            : 
      24                 :            : {
      25                 :            :         struct media_entity *entity;
      26                 :            :         struct media_entity *if_vid = NULL, *if_aud = NULL;
      27                 :            :         struct media_entity *tuner = NULL, *decoder = NULL;
      28                 :            :         struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
      29                 :            :         bool is_webcam = false;
      30                 :            :         u32 flags;
      31                 :            :         int ret, pad_sink, pad_source;
      32                 :            : 
      33                 :          0 :         if (!mdev)
      34                 :            :                 return 0;
      35                 :            : 
      36                 :          0 :         media_device_for_each_entity(entity, mdev) {
      37                 :          0 :                 switch (entity->function) {
      38                 :            :                 case MEDIA_ENT_F_IF_VID_DECODER:
      39                 :            :                         if_vid = entity;
      40                 :          0 :                         break;
      41                 :            :                 case MEDIA_ENT_F_IF_AUD_DECODER:
      42                 :            :                         if_aud = entity;
      43                 :          0 :                         break;
      44                 :            :                 case MEDIA_ENT_F_TUNER:
      45                 :            :                         tuner = entity;
      46                 :          0 :                         break;
      47                 :            :                 case MEDIA_ENT_F_ATV_DECODER:
      48                 :            :                         decoder = entity;
      49                 :          0 :                         break;
      50                 :            :                 case MEDIA_ENT_F_IO_V4L:
      51                 :            :                         io_v4l = entity;
      52                 :          0 :                         break;
      53                 :            :                 case MEDIA_ENT_F_IO_VBI:
      54                 :            :                         io_vbi = entity;
      55                 :          0 :                         break;
      56                 :            :                 case MEDIA_ENT_F_IO_SWRADIO:
      57                 :            :                         io_swradio = entity;
      58                 :          0 :                         break;
      59                 :            :                 case MEDIA_ENT_F_CAM_SENSOR:
      60                 :            :                         is_webcam = true;
      61                 :          0 :                         break;
      62                 :            :                 }
      63                 :            :         }
      64                 :            : 
      65                 :            :         /* It should have at least one I/O entity */
      66                 :          0 :         if (!io_v4l && !io_vbi && !io_swradio) {
      67                 :          0 :                 dev_warn(mdev->dev, "Didn't find any I/O entity\n");
      68                 :          0 :                 return -EINVAL;
      69                 :            :         }
      70                 :            : 
      71                 :            :         /*
      72                 :            :          * Here, webcams are modelled on a very simple way: the sensor is
      73                 :            :          * connected directly to the I/O entity. All dirty details, like
      74                 :            :          * scaler and crop HW are hidden. While such mapping is not enough
      75                 :            :          * for mc-centric hardware, it is enough for v4l2 interface centric
      76                 :            :          * PC-consumer's hardware.
      77                 :            :          */
      78                 :          0 :         if (is_webcam) {
      79                 :          0 :                 if (!io_v4l) {
      80                 :          0 :                         dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n");
      81                 :          0 :                         return -EINVAL;
      82                 :            :                 }
      83                 :            : 
      84                 :          0 :                 media_device_for_each_entity(entity, mdev) {
      85                 :          0 :                         if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
      86                 :          0 :                                 continue;
      87                 :          0 :                         ret = media_create_pad_link(entity, 0,
      88                 :            :                                                     io_v4l, 0,
      89                 :            :                                                     MEDIA_LNK_FL_ENABLED);
      90                 :          0 :                         if (ret) {
      91                 :          0 :                                 dev_warn(mdev->dev, "Failed to create a sensor link\n");
      92                 :          0 :                                 return ret;
      93                 :            :                         }
      94                 :            :                 }
      95                 :          0 :                 if (!decoder)
      96                 :            :                         return 0;
      97                 :            :         }
      98                 :            : 
      99                 :            :         /* The device isn't a webcam. So, it should have a decoder */
     100                 :          0 :         if (!decoder) {
     101                 :          0 :                 dev_warn(mdev->dev, "Decoder not found\n");
     102                 :          0 :                 return -EINVAL;
     103                 :            :         }
     104                 :            : 
     105                 :            :         /* Link the tuner and IF video output pads */
     106                 :          0 :         if (tuner) {
     107                 :          0 :                 if (if_vid) {
     108                 :          0 :                         pad_source = media_get_pad_index(tuner, false,
     109                 :            :                                                          PAD_SIGNAL_ANALOG);
     110                 :          0 :                         pad_sink = media_get_pad_index(if_vid, true,
     111                 :            :                                                        PAD_SIGNAL_ANALOG);
     112                 :          0 :                         if (pad_source < 0 || pad_sink < 0) {
     113                 :          0 :                                 dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
     114                 :            :                                          pad_source, pad_sink);
     115                 :          0 :                                 return -EINVAL;
     116                 :            :                         }
     117                 :          0 :                         ret = media_create_pad_link(tuner, pad_source,
     118                 :            :                                                     if_vid, pad_sink,
     119                 :            :                                                     MEDIA_LNK_FL_ENABLED);
     120                 :          0 :                         if (ret) {
     121                 :          0 :                                 dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n");
     122                 :          0 :                                 return ret;
     123                 :            :                         }
     124                 :            : 
     125                 :          0 :                         pad_source = media_get_pad_index(if_vid, false,
     126                 :            :                                                          PAD_SIGNAL_ANALOG);
     127                 :          0 :                         pad_sink = media_get_pad_index(decoder, true,
     128                 :            :                                                        PAD_SIGNAL_ANALOG);
     129                 :          0 :                         if (pad_source < 0 || pad_sink < 0) {
     130                 :          0 :                                 dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
     131                 :            :                                          pad_source, pad_sink);
     132                 :          0 :                                 return -EINVAL;
     133                 :            :                         }
     134                 :          0 :                         ret = media_create_pad_link(if_vid, pad_source,
     135                 :            :                                                     decoder, pad_sink,
     136                 :            :                                                     MEDIA_LNK_FL_ENABLED);
     137                 :          0 :                         if (ret) {
     138                 :          0 :                                 dev_warn(mdev->dev, "couldn't link PLL to decoder\n");
     139                 :          0 :                                 return ret;
     140                 :            :                         }
     141                 :            :                 } else {
     142                 :          0 :                         pad_source = media_get_pad_index(tuner, false,
     143                 :            :                                                          PAD_SIGNAL_ANALOG);
     144                 :          0 :                         pad_sink = media_get_pad_index(decoder, true,
     145                 :            :                                                        PAD_SIGNAL_ANALOG);
     146                 :          0 :                         if (pad_source < 0 || pad_sink < 0) {
     147                 :          0 :                                 dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
     148                 :            :                                          pad_source, pad_sink);
     149                 :          0 :                                 return -EINVAL;
     150                 :            :                         }
     151                 :          0 :                         ret = media_create_pad_link(tuner, pad_source,
     152                 :            :                                                     decoder, pad_sink,
     153                 :            :                                                     MEDIA_LNK_FL_ENABLED);
     154                 :          0 :                         if (ret)
     155                 :            :                                 return ret;
     156                 :            :                 }
     157                 :            : 
     158                 :          0 :                 if (if_aud) {
     159                 :          0 :                         pad_source = media_get_pad_index(tuner, false,
     160                 :            :                                                          PAD_SIGNAL_AUDIO);
     161                 :          0 :                         pad_sink = media_get_pad_index(if_aud, true,
     162                 :            :                                                        PAD_SIGNAL_AUDIO);
     163                 :          0 :                         if (pad_source < 0 || pad_sink < 0) {
     164                 :          0 :                                 dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
     165                 :            :                                          pad_source, pad_sink);
     166                 :          0 :                                 return -EINVAL;
     167                 :            :                         }
     168                 :          0 :                         ret = media_create_pad_link(tuner, pad_source,
     169                 :            :                                                     if_aud, pad_sink,
     170                 :            :                                                     MEDIA_LNK_FL_ENABLED);
     171                 :          0 :                         if (ret) {
     172                 :          0 :                                 dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n");
     173                 :          0 :                                 return ret;
     174                 :            :                         }
     175                 :            :                 } else {
     176                 :            :                         if_aud = tuner;
     177                 :            :                 }
     178                 :            : 
     179                 :            :         }
     180                 :            : 
     181                 :            :         /* Create demod to V4L, VBI and SDR radio links */
     182                 :          0 :         if (io_v4l) {
     183                 :          0 :                 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
     184                 :          0 :                 if (pad_source < 0) {
     185                 :          0 :                         dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
     186                 :          0 :                         return -EINVAL;
     187                 :            :                 }
     188                 :          0 :                 ret = media_create_pad_link(decoder, pad_source,
     189                 :            :                                             io_v4l, 0,
     190                 :            :                                             MEDIA_LNK_FL_ENABLED);
     191                 :          0 :                 if (ret) {
     192                 :          0 :                         dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n");
     193                 :          0 :                         return ret;
     194                 :            :                 }
     195                 :            :         }
     196                 :            : 
     197                 :          0 :         if (io_swradio) {
     198                 :          0 :                 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
     199                 :          0 :                 if (pad_source < 0) {
     200                 :          0 :                         dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
     201                 :          0 :                         return -EINVAL;
     202                 :            :                 }
     203                 :          0 :                 ret = media_create_pad_link(decoder, pad_source,
     204                 :            :                                             io_swradio, 0,
     205                 :            :                                             MEDIA_LNK_FL_ENABLED);
     206                 :          0 :                 if (ret) {
     207                 :          0 :                         dev_warn(mdev->dev, "couldn't link decoder output to SDR\n");
     208                 :          0 :                         return ret;
     209                 :            :                 }
     210                 :            :         }
     211                 :            : 
     212                 :          0 :         if (io_vbi) {
     213                 :          0 :                 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
     214                 :          0 :                 if (pad_source < 0) {
     215                 :          0 :                         dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
     216                 :          0 :                         return -EINVAL;
     217                 :            :                 }
     218                 :          0 :                 ret = media_create_pad_link(decoder, pad_source,
     219                 :            :                                             io_vbi, 0,
     220                 :            :                                             MEDIA_LNK_FL_ENABLED);
     221                 :          0 :                 if (ret) {
     222                 :          0 :                         dev_warn(mdev->dev, "couldn't link decoder output to VBI\n");
     223                 :          0 :                         return ret;
     224                 :            :                 }
     225                 :            :         }
     226                 :            : 
     227                 :            :         /* Create links for the media connectors */
     228                 :            :         flags = MEDIA_LNK_FL_ENABLED;
     229                 :          0 :         media_device_for_each_entity(entity, mdev) {
     230                 :          0 :                 switch (entity->function) {
     231                 :            :                 case MEDIA_ENT_F_CONN_RF:
     232                 :          0 :                         if (!tuner)
     233                 :          0 :                                 continue;
     234                 :          0 :                         pad_sink = media_get_pad_index(tuner, true,
     235                 :            :                                                        PAD_SIGNAL_ANALOG);
     236                 :          0 :                         if (pad_sink < 0) {
     237                 :          0 :                                 dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
     238                 :          0 :                                 return -EINVAL;
     239                 :            :                         }
     240                 :          0 :                         ret = media_create_pad_link(entity, 0, tuner,
     241                 :            :                                                     pad_sink,
     242                 :            :                                                     flags);
     243                 :          0 :                         break;
     244                 :            :                 case MEDIA_ENT_F_CONN_SVIDEO:
     245                 :            :                 case MEDIA_ENT_F_CONN_COMPOSITE:
     246                 :          0 :                         pad_sink = media_get_pad_index(decoder, true,
     247                 :            :                                                        PAD_SIGNAL_ANALOG);
     248                 :          0 :                         if (pad_sink < 0) {
     249                 :          0 :                                 dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
     250                 :          0 :                                 return -EINVAL;
     251                 :            :                         }
     252                 :          0 :                         ret = media_create_pad_link(entity, 0, decoder,
     253                 :            :                                                     pad_sink,
     254                 :            :                                                     flags);
     255                 :          0 :                         break;
     256                 :            :                 default:
     257                 :          0 :                         continue;
     258                 :            :                 }
     259                 :          0 :                 if (ret)
     260                 :          0 :                         return ret;
     261                 :            : 
     262                 :            :                 flags = 0;
     263                 :            :         }
     264                 :            : 
     265                 :            :         return 0;
     266                 :            : }
     267                 :            : EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph);
     268                 :            : 
     269                 :          0 : int v4l_enable_media_source(struct video_device *vdev)
     270                 :            : {
     271                 :          0 :         struct media_device *mdev = vdev->entity.graph_obj.mdev;
     272                 :            :         int ret = 0, err;
     273                 :            : 
     274                 :          0 :         if (!mdev)
     275                 :            :                 return 0;
     276                 :            : 
     277                 :          0 :         mutex_lock(&mdev->graph_mutex);
     278                 :          0 :         if (!mdev->enable_source)
     279                 :            :                 goto end;
     280                 :          0 :         err = mdev->enable_source(&vdev->entity, &vdev->pipe);
     281                 :          0 :         if (err)
     282                 :            :                 ret = -EBUSY;
     283                 :            : end:
     284                 :          0 :         mutex_unlock(&mdev->graph_mutex);
     285                 :          0 :         return ret;
     286                 :            : }
     287                 :            : EXPORT_SYMBOL_GPL(v4l_enable_media_source);
     288                 :            : 
     289                 :          3 : void v4l_disable_media_source(struct video_device *vdev)
     290                 :            : {
     291                 :          3 :         struct media_device *mdev = vdev->entity.graph_obj.mdev;
     292                 :            : 
     293                 :          3 :         if (mdev) {
     294                 :          3 :                 mutex_lock(&mdev->graph_mutex);
     295                 :          3 :                 if (mdev->disable_source)
     296                 :          0 :                         mdev->disable_source(&vdev->entity);
     297                 :          3 :                 mutex_unlock(&mdev->graph_mutex);
     298                 :            :         }
     299                 :          3 : }
     300                 :            : EXPORT_SYMBOL_GPL(v4l_disable_media_source);
     301                 :            : 
     302                 :          0 : int v4l_vb2q_enable_media_source(struct vb2_queue *q)
     303                 :            : {
     304                 :          0 :         struct v4l2_fh *fh = q->owner;
     305                 :            : 
     306                 :          0 :         if (fh && fh->vdev)
     307                 :          0 :                 return v4l_enable_media_source(fh->vdev);
     308                 :            :         return 0;
     309                 :            : }
     310                 :            : EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
     311                 :            : 
     312                 :            : /* -----------------------------------------------------------------------------
     313                 :            :  * Pipeline power management
     314                 :            :  *
     315                 :            :  * Entities must be powered up when part of a pipeline that contains at least
     316                 :            :  * one open video device node.
     317                 :            :  *
     318                 :            :  * To achieve this use the entity use_count field to track the number of users.
     319                 :            :  * For entities corresponding to video device nodes the use_count field stores
     320                 :            :  * the users count of the node. For entities corresponding to subdevs the
     321                 :            :  * use_count field stores the total number of users of all video device nodes
     322                 :            :  * in the pipeline.
     323                 :            :  *
     324                 :            :  * The v4l2_pipeline_pm_use() function must be called in the open() and
     325                 :            :  * close() handlers of video device nodes. It increments or decrements the use
     326                 :            :  * count of all subdev entities in the pipeline.
     327                 :            :  *
     328                 :            :  * To react to link management on powered pipelines, the link setup notification
     329                 :            :  * callback updates the use count of all entities in the source and sink sides
     330                 :            :  * of the link.
     331                 :            :  */
     332                 :            : 
     333                 :            : /*
     334                 :            :  * pipeline_pm_use_count - Count the number of users of a pipeline
     335                 :            :  * @entity: The entity
     336                 :            :  *
     337                 :            :  * Return the total number of users of all video device nodes in the pipeline.
     338                 :            :  */
     339                 :          0 : static int pipeline_pm_use_count(struct media_entity *entity,
     340                 :            :         struct media_graph *graph)
     341                 :            : {
     342                 :            :         int use = 0;
     343                 :            : 
     344                 :          0 :         media_graph_walk_start(graph, entity);
     345                 :            : 
     346                 :          0 :         while ((entity = media_graph_walk_next(graph))) {
     347                 :          0 :                 if (is_media_entity_v4l2_video_device(entity))
     348                 :          0 :                         use += entity->use_count;
     349                 :            :         }
     350                 :            : 
     351                 :          0 :         return use;
     352                 :            : }
     353                 :            : 
     354                 :            : /*
     355                 :            :  * pipeline_pm_power_one - Apply power change to an entity
     356                 :            :  * @entity: The entity
     357                 :            :  * @change: Use count change
     358                 :            :  *
     359                 :            :  * Change the entity use count by @change. If the entity is a subdev update its
     360                 :            :  * power state by calling the core::s_power operation when the use count goes
     361                 :            :  * from 0 to != 0 or from != 0 to 0.
     362                 :            :  *
     363                 :            :  * Return 0 on success or a negative error code on failure.
     364                 :            :  */
     365                 :          0 : static int pipeline_pm_power_one(struct media_entity *entity, int change)
     366                 :            : {
     367                 :            :         struct v4l2_subdev *subdev;
     368                 :            :         int ret;
     369                 :            : 
     370                 :            :         subdev = is_media_entity_v4l2_subdev(entity)
     371                 :          0 :                ? media_entity_to_v4l2_subdev(entity) : NULL;
     372                 :            : 
     373                 :          0 :         if (entity->use_count == 0 && change > 0 && subdev != NULL) {
     374                 :          0 :                 ret = v4l2_subdev_call(subdev, core, s_power, 1);
     375                 :          0 :                 if (ret < 0 && ret != -ENOIOCTLCMD)
     376                 :            :                         return ret;
     377                 :            :         }
     378                 :            : 
     379                 :          0 :         entity->use_count += change;
     380                 :          0 :         WARN_ON(entity->use_count < 0);
     381                 :            : 
     382                 :          0 :         if (entity->use_count == 0 && change < 0 && subdev != NULL)
     383                 :          0 :                 v4l2_subdev_call(subdev, core, s_power, 0);
     384                 :            : 
     385                 :            :         return 0;
     386                 :            : }
     387                 :            : 
     388                 :            : /*
     389                 :            :  * pipeline_pm_power - Apply power change to all entities in a pipeline
     390                 :            :  * @entity: The entity
     391                 :            :  * @change: Use count change
     392                 :            :  *
     393                 :            :  * Walk the pipeline to update the use count and the power state of all non-node
     394                 :            :  * entities.
     395                 :            :  *
     396                 :            :  * Return 0 on success or a negative error code on failure.
     397                 :            :  */
     398                 :          0 : static int pipeline_pm_power(struct media_entity *entity, int change,
     399                 :            :         struct media_graph *graph)
     400                 :            : {
     401                 :            :         struct media_entity *first = entity;
     402                 :            :         int ret = 0;
     403                 :            : 
     404                 :          0 :         if (!change)
     405                 :            :                 return 0;
     406                 :            : 
     407                 :          0 :         media_graph_walk_start(graph, entity);
     408                 :            : 
     409                 :          0 :         while (!ret && (entity = media_graph_walk_next(graph)))
     410                 :          0 :                 if (is_media_entity_v4l2_subdev(entity))
     411                 :          0 :                         ret = pipeline_pm_power_one(entity, change);
     412                 :            : 
     413                 :          0 :         if (!ret)
     414                 :          0 :                 return ret;
     415                 :            : 
     416                 :          0 :         media_graph_walk_start(graph, first);
     417                 :            : 
     418                 :          0 :         while ((first = media_graph_walk_next(graph))
     419                 :          0 :                && first != entity)
     420                 :          0 :                 if (is_media_entity_v4l2_subdev(first))
     421                 :          0 :                         pipeline_pm_power_one(first, -change);
     422                 :            : 
     423                 :          0 :         return ret;
     424                 :            : }
     425                 :            : 
     426                 :          0 : int v4l2_pipeline_pm_use(struct media_entity *entity, int use)
     427                 :            : {
     428                 :          0 :         struct media_device *mdev = entity->graph_obj.mdev;
     429                 :          0 :         int change = use ? 1 : -1;
     430                 :            :         int ret;
     431                 :            : 
     432                 :          0 :         mutex_lock(&mdev->graph_mutex);
     433                 :            : 
     434                 :            :         /* Apply use count to node. */
     435                 :          0 :         entity->use_count += change;
     436                 :          0 :         WARN_ON(entity->use_count < 0);
     437                 :            : 
     438                 :            :         /* Apply power change to connected non-nodes. */
     439                 :          0 :         ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk);
     440                 :          0 :         if (ret < 0)
     441                 :          0 :                 entity->use_count -= change;
     442                 :            : 
     443                 :          0 :         mutex_unlock(&mdev->graph_mutex);
     444                 :            : 
     445                 :          0 :         return ret;
     446                 :            : }
     447                 :            : EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_use);
     448                 :            : 
     449                 :          0 : int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
     450                 :            :                               unsigned int notification)
     451                 :            : {
     452                 :          0 :         struct media_graph *graph = &link->graph_obj.mdev->pm_count_walk;
     453                 :          0 :         struct media_entity *source = link->source->entity;
     454                 :          0 :         struct media_entity *sink = link->sink->entity;
     455                 :            :         int source_use;
     456                 :            :         int sink_use;
     457                 :            :         int ret = 0;
     458                 :            : 
     459                 :          0 :         source_use = pipeline_pm_use_count(source, graph);
     460                 :          0 :         sink_use = pipeline_pm_use_count(sink, graph);
     461                 :            : 
     462                 :          0 :         if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
     463                 :          0 :             !(flags & MEDIA_LNK_FL_ENABLED)) {
     464                 :            :                 /* Powering off entities is assumed to never fail. */
     465                 :          0 :                 pipeline_pm_power(source, -sink_use, graph);
     466                 :          0 :                 pipeline_pm_power(sink, -source_use, graph);
     467                 :          0 :                 return 0;
     468                 :            :         }
     469                 :            : 
     470                 :          0 :         if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
     471                 :          0 :                 (flags & MEDIA_LNK_FL_ENABLED)) {
     472                 :            : 
     473                 :          0 :                 ret = pipeline_pm_power(source, sink_use, graph);
     474                 :          0 :                 if (ret < 0)
     475                 :            :                         return ret;
     476                 :            : 
     477                 :          0 :                 ret = pipeline_pm_power(sink, source_use, graph);
     478                 :          0 :                 if (ret < 0)
     479                 :          0 :                         pipeline_pm_power(source, -sink_use, graph);
     480                 :            :         }
     481                 :            : 
     482                 :          0 :         return ret;
     483                 :            : }
     484                 :            : EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify);
    

Generated by: LCOV version 1.14