@@ -1658,101 +1658,143 @@ static const struct v4l2_file_operations cfe_fops = {
16581658 .mmap = vb2_fop_mmap ,
16591659};
16601660
1661- static int cfe_video_link_validate (struct media_link * link )
1661+ static int cfe_video_link_validate (struct cfe_node * node ,
1662+ struct v4l2_subdev * remote_sd ,
1663+ struct v4l2_mbus_framefmt * remote_fmt )
16621664{
1663- struct video_device * vd = container_of (link -> sink -> entity ,
1664- struct video_device , entity );
1665- struct cfe_node * node = container_of (vd , struct cfe_node , video_dev );
16661665 struct cfe_device * cfe = node -> cfe ;
1667- struct v4l2_mbus_framefmt * source_fmt ;
1668- struct v4l2_subdev_state * state ;
1669- struct v4l2_subdev * source_sd ;
1670- int ret = 0 ;
1671-
1672- cfe_dbg ("%s: [%s] link \"%s\":%u -> \"%s\":%u\n" , __func__ ,
1673- node_desc [node -> id ].name ,
1674- link -> source -> entity -> name , link -> source -> index ,
1675- link -> sink -> entity -> name , link -> sink -> index );
16761666
1677- if (!media_entity_remote_source_pad_unique (link -> sink -> entity )) {
1678- cfe_err ("video node %s pad not connected\n" , vd -> name );
1679- return - ENOTCONN ;
1680- }
1681-
1682- source_sd = media_entity_to_v4l2_subdev (link -> source -> entity );
1683-
1684- state = v4l2_subdev_lock_and_get_active_state (source_sd );
1685-
1686- source_fmt = v4l2_subdev_state_get_format (state ,
1687- link -> source -> index );
1688- if (!source_fmt ) {
1689- ret = - EINVAL ;
1690- goto out ;
1667+ if (!remote_fmt ) {
1668+ return - EINVAL ;
16911669 }
16921670
16931671 if (is_image_output_node (node )) {
16941672 struct v4l2_pix_format * pix_fmt = & node -> vid_fmt .fmt .pix ;
16951673 const struct cfe_fmt * fmt = NULL ;
16961674 unsigned int i ;
16971675
1698- if (source_fmt -> width != pix_fmt -> width ||
1699- source_fmt -> height != pix_fmt -> height ) {
1676+ if (remote_fmt -> width != pix_fmt -> width ||
1677+ remote_fmt -> height != pix_fmt -> height ) {
17001678 cfe_err ("Wrong width or height %ux%u (remote pad set to %ux%u)\n" ,
17011679 pix_fmt -> width , pix_fmt -> height ,
1702- source_fmt -> width ,
1703- source_fmt -> height );
1704- ret = - EINVAL ;
1705- goto out ;
1680+ remote_fmt -> width ,
1681+ remote_fmt -> height );
1682+ return - EINVAL ;
17061683 }
17071684
17081685 for (i = 0 ; i < ARRAY_SIZE (formats ); i ++ ) {
1709- if (formats [i ].code == source_fmt -> code &&
1686+ if (formats [i ].code == remote_fmt -> code &&
17101687 formats [i ].fourcc == pix_fmt -> pixelformat ) {
17111688 fmt = & formats [i ];
17121689 break ;
17131690 }
17141691 }
17151692 if (!fmt ) {
17161693 cfe_err ("Format mismatch!\n" );
1717- ret = - EINVAL ;
1718- goto out ;
1694+ return - EINVAL ;
17191695 }
17201696 } else if (is_csi2_node (node ) && is_meta_output_node (node )) {
17211697 struct v4l2_meta_format * meta_fmt = & node -> meta_fmt .fmt .meta ;
17221698 const struct cfe_fmt * fmt ;
1723- u32 source_size ;
1699+ u32 remote_size ;
17241700
1725- fmt = find_format_by_code (source_fmt -> code );
1701+ fmt = find_format_by_code (remote_fmt -> code );
17261702 if (!fmt || fmt -> fourcc != meta_fmt -> dataformat ) {
17271703 cfe_err ("Metadata format mismatch!\n" );
1728- ret = - EINVAL ;
1729- goto out ;
1704+ return - EINVAL ;
17301705 }
17311706
1732- source_size = DIV_ROUND_UP (source_fmt -> width * source_fmt -> height * fmt -> depth , 8 );
1707+ remote_size = DIV_ROUND_UP (remote_fmt -> width * remote_fmt -> height * fmt -> depth , 8 );
17331708
1734- if (source_fmt -> code != MEDIA_BUS_FMT_SENSOR_DATA ) {
1709+ if (remote_fmt -> code != MEDIA_BUS_FMT_SENSOR_DATA ) {
17351710 cfe_err ("Bad metadata mbus format\n" );
1736- ret = - EINVAL ;
1737- goto out ;
1711+ return - EINVAL ;
17381712 }
17391713
1740- if (source_size > meta_fmt -> buffersize ) {
1714+ if (remote_size > meta_fmt -> buffersize ) {
17411715 cfe_err ("Metadata buffer too small: %u < %u\n" ,
1742- meta_fmt -> buffersize , source_size );
1743- ret = - EINVAL ;
1744- goto out ;
1716+ meta_fmt -> buffersize , remote_size );
1717+ return - EINVAL ;
17451718 }
17461719 }
17471720
1748- out :
1721+ return 0 ;
1722+ }
1723+
1724+ static int cfe_video_link_validate_output (struct media_link * link )
1725+ {
1726+ struct video_device * vd = container_of (link -> source -> entity ,
1727+ struct video_device , entity );
1728+ struct cfe_node * node = container_of (vd , struct cfe_node , video_dev );
1729+ struct cfe_device * cfe = node -> cfe ;
1730+ struct v4l2_mbus_framefmt * sink_fmt ;
1731+ struct v4l2_subdev_state * state ;
1732+ struct v4l2_subdev * sink_sd ;
1733+ int ret ;
1734+
1735+ cfe_dbg ("%s: [%s] link \"%s\":%u -> \"%s\":%u\n" , __func__ ,
1736+ node_desc [node -> id ].name ,
1737+ link -> source -> entity -> name , link -> source -> index ,
1738+ link -> sink -> entity -> name , link -> sink -> index );
1739+
1740+ if (!media_entity_remote_source_pad_unique (link -> source -> entity )) {
1741+ cfe_err ("video node %s pad not connected\n" , vd -> name );
1742+ return - ENOTCONN ;
1743+ }
1744+
1745+ sink_sd = media_entity_to_v4l2_subdev (link -> sink -> entity );
1746+
1747+ state = v4l2_subdev_lock_and_get_active_state (sink_sd );
1748+
1749+ sink_fmt = v4l2_subdev_state_get_format (state , link -> sink -> index );
1750+
1751+ ret = cfe_video_link_validate (node , sink_sd , sink_fmt );
1752+
1753+ v4l2_subdev_unlock_state (state );
1754+
1755+ return ret ;
1756+ }
1757+
1758+ static int cfe_video_link_validate_capture (struct media_link * link )
1759+ {
1760+ struct video_device * vd = container_of (link -> sink -> entity ,
1761+ struct video_device , entity );
1762+ struct cfe_node * node = container_of (vd , struct cfe_node , video_dev );
1763+ struct cfe_device * cfe = node -> cfe ;
1764+ struct v4l2_mbus_framefmt * source_fmt ;
1765+ struct v4l2_subdev_state * state ;
1766+ struct v4l2_subdev * source_sd ;
1767+ int ret ;
1768+
1769+ cfe_dbg ("%s: [%s] link \"%s\":%u -> \"%s\":%u\n" , __func__ ,
1770+ node_desc [node -> id ].name ,
1771+ link -> source -> entity -> name , link -> source -> index ,
1772+ link -> sink -> entity -> name , link -> sink -> index );
1773+
1774+ if (!media_entity_remote_source_pad_unique (link -> sink -> entity )) {
1775+ cfe_err ("video node %s pad not connected\n" , vd -> name );
1776+ return - ENOTCONN ;
1777+ }
1778+
1779+ source_sd = media_entity_to_v4l2_subdev (link -> source -> entity );
1780+
1781+ state = v4l2_subdev_lock_and_get_active_state (source_sd );
1782+
1783+ source_fmt = v4l2_subdev_state_get_format (state , link -> source -> index );
1784+
1785+ ret = cfe_video_link_validate (node , source_sd , source_fmt );
1786+
17491787 v4l2_subdev_unlock_state (state );
17501788
17511789 return ret ;
17521790}
17531791
1754- static const struct media_entity_operations cfe_media_entity_ops = {
1755- .link_validate = cfe_video_link_validate ,
1792+ static const struct media_entity_operations cfe_media_entity_ops_output = {
1793+ .link_validate = cfe_video_link_validate_output ,
1794+ };
1795+
1796+ static const struct media_entity_operations cfe_media_entity_ops_capture = {
1797+ .link_validate = cfe_video_link_validate_capture ,
17561798};
17571799
17581800static int cfe_video_link_notify (struct media_link * link , u32 flags ,
@@ -1917,12 +1959,15 @@ static int cfe_register_node(struct cfe_device *cfe, int id)
19171959 vdev -> release = cfe_node_release ;
19181960 vdev -> fops = & cfe_fops ;
19191961 vdev -> ioctl_ops = & cfe_ioctl_ops ;
1920- vdev -> entity .ops = & cfe_media_entity_ops ;
19211962 vdev -> v4l2_dev = & cfe -> v4l2_dev ;
1922- vdev -> vfl_dir = (node_supports_image_output (node ) ||
1923- node_supports_meta_output (node )) ?
1924- VFL_DIR_RX :
1925- VFL_DIR_TX ;
1963+ if ((node_supports_image_output (node ) ||
1964+ node_supports_meta_output (node ))) {
1965+ vdev -> entity .ops = & cfe_media_entity_ops_capture ;
1966+ vdev -> vfl_dir = VFL_DIR_RX ;
1967+ } else {
1968+ vdev -> entity .ops = & cfe_media_entity_ops_output ;
1969+ vdev -> vfl_dir = VFL_DIR_TX ;
1970+ }
19261971 vdev -> queue = q ;
19271972 vdev -> lock = & node -> lock ;
19281973 vdev -> device_caps = node_desc [id ].caps ;
0 commit comments