@@ -272,6 +272,8 @@ struct cfe_node {
272
272
/* Pointer to the parent handle */
273
273
struct cfe_device * cfe ;
274
274
struct media_pad pad ;
275
+ unsigned int fs_count ;
276
+ u64 ts ;
275
277
};
276
278
277
279
struct cfe_device {
@@ -311,9 +313,6 @@ struct cfe_device {
311
313
struct pisp_fe_device fe ;
312
314
313
315
int fe_csi2_channel ;
314
-
315
- unsigned int sequence ;
316
- u64 ts ;
317
316
};
318
317
319
318
static inline bool is_fe_enabled (struct cfe_device * cfe )
@@ -393,17 +392,6 @@ static bool test_all_nodes(struct cfe_device *cfe, unsigned long precond,
393
392
return true;
394
393
}
395
394
396
- static void clear_all_nodes (struct cfe_device * cfe , unsigned long precond ,
397
- unsigned long state )
398
- {
399
- unsigned int i ;
400
-
401
- for (i = 0 ; i < NUM_NODES ; i ++ ) {
402
- if (check_state (cfe , precond , i ))
403
- clear_state (cfe , state , i );
404
- }
405
- }
406
-
407
395
static int mipi_cfg_regs_show (struct seq_file * s , void * data )
408
396
{
409
397
struct cfe_device * cfe = s -> private ;
@@ -656,22 +644,22 @@ static void cfe_prepare_next_job(struct cfe_device *cfe)
656
644
}
657
645
658
646
static void cfe_process_buffer_complete (struct cfe_node * node ,
659
- unsigned int sequence )
647
+ enum vb2_buffer_state state )
660
648
{
661
649
struct cfe_device * cfe = node -> cfe ;
662
650
663
651
cfe_dbg_verbose ("%s: [%s] buffer:%p\n" , __func__ ,
664
652
node_desc [node -> id ].name , & node -> cur_frm -> vb .vb2_buf );
665
653
666
- node -> cur_frm -> vb .sequence = sequence ;
667
- vb2_buffer_done (& node -> cur_frm -> vb .vb2_buf , VB2_BUF_STATE_DONE );
654
+ node -> cur_frm -> vb .sequence = node -> fs_count - 1 ;
655
+ vb2_buffer_done (& node -> cur_frm -> vb .vb2_buf , state );
668
656
}
669
657
670
658
static void cfe_queue_event_sof (struct cfe_node * node )
671
659
{
672
660
struct v4l2_event event = {
673
661
.type = V4L2_EVENT_FRAME_SYNC ,
674
- .u .frame_sync .frame_sequence = node -> cfe -> sequence ,
662
+ .u .frame_sync .frame_sequence = node -> fs_count - 1 ,
675
663
};
676
664
677
665
v4l2_event_queue (& node -> video_dev , & event );
@@ -680,28 +668,53 @@ static void cfe_queue_event_sof(struct cfe_node *node)
680
668
static void cfe_sof_isr_handler (struct cfe_node * node )
681
669
{
682
670
struct cfe_device * cfe = node -> cfe ;
671
+ bool matching_fs = true;
672
+ unsigned int i ;
683
673
684
674
cfe_dbg_verbose ("%s: [%s] seq %u\n" , __func__ , node_desc [node -> id ].name ,
685
- cfe -> sequence );
686
-
687
- node -> cur_frm = node -> next_frm ;
688
- node -> next_frm = NULL ;
675
+ node -> fs_count );
689
676
690
677
/*
691
- * If this is the first node to see a frame start, sample the
692
- * timestamp to use for all frames across all channels.
678
+ * If the sensor is producing unexpected frame event ordering over a
679
+ * sustained period of time, guard against the possibility of coming
680
+ * here and orphaning the cur_frm if it's not been dequeued already.
681
+ * Unfortunately, there is not enough hardware state to tell if this
682
+ * may have occurred.
693
683
*/
694
- if (!test_any_node (cfe , NODE_STREAMING | FS_INT ))
695
- cfe -> ts = ktime_get_ns ();
684
+ if (WARN (node -> cur_frm , "%s: [%s] Orphanded frame at seq %u\n" ,
685
+ __func__ , node_desc [node -> id ].name , node -> fs_count ))
686
+ cfe_process_buffer_complete (node , VB2_BUF_STATE_ERROR );
696
687
697
- set_state (cfe , FS_INT , node -> id );
688
+ node -> cur_frm = node -> next_frm ;
689
+ node -> next_frm = NULL ;
690
+ node -> fs_count ++ ;
698
691
699
- /* If all nodes have seen a frame start, we can queue another job. */
700
- if (test_all_nodes (cfe , NODE_STREAMING , FS_INT ))
692
+ node -> ts = ktime_get_ns ();
693
+ for (i = 0 ; i < NUM_NODES ; i ++ ) {
694
+ if (!check_state (cfe , NODE_STREAMING , i ) || i == node -> id )
695
+ continue ;
696
+ /*
697
+ * This checks if any other node has seen a FS. If yes, use the
698
+ * same timestamp, eventually across all node buffers.
699
+ */
700
+ if (cfe -> node [i ].fs_count >= node -> fs_count )
701
+ node -> ts = cfe -> node [i ].ts ;
702
+ /*
703
+ * This checks if all other node have seen a matching FS. If
704
+ * yes, we can flag another job to be queued.
705
+ */
706
+ if (matching_fs && cfe -> node [i ].fs_count != node -> fs_count )
707
+ matching_fs = false;
708
+ }
709
+
710
+ if (matching_fs )
701
711
cfe -> job_queued = false;
702
712
703
713
if (node -> cur_frm )
704
- node -> cur_frm -> vb .vb2_buf .timestamp = cfe -> ts ;
714
+ node -> cur_frm -> vb .vb2_buf .timestamp = node -> ts ;
715
+
716
+ set_state (cfe , FS_INT , node -> id );
717
+ clear_state (cfe , FE_INT , node -> id );
705
718
706
719
if (is_image_output_node (node ))
707
720
cfe_queue_event_sof (node );
@@ -712,22 +725,14 @@ static void cfe_eof_isr_handler(struct cfe_node *node)
712
725
struct cfe_device * cfe = node -> cfe ;
713
726
714
727
cfe_dbg_verbose ("%s: [%s] seq %u\n" , __func__ , node_desc [node -> id ].name ,
715
- cfe -> sequence );
728
+ node -> fs_count - 1 );
716
729
717
730
if (node -> cur_frm )
718
- cfe_process_buffer_complete (node , cfe -> sequence );
731
+ cfe_process_buffer_complete (node , VB2_BUF_STATE_DONE );
719
732
720
733
node -> cur_frm = NULL ;
721
734
set_state (cfe , FE_INT , node -> id );
722
-
723
- /*
724
- * If all nodes have seen a frame end, we can increment
725
- * the sequence counter now.
726
- */
727
- if (test_all_nodes (cfe , NODE_STREAMING , FE_INT )) {
728
- cfe -> sequence ++ ;
729
- clear_all_nodes (cfe , NODE_STREAMING , FE_INT | FS_INT );
730
- }
735
+ clear_state (cfe , FS_INT , node -> id );
731
736
}
732
737
733
738
static irqreturn_t cfe_isr (int irq , void * dev )
@@ -794,7 +799,8 @@ static irqreturn_t cfe_isr(int irq, void *dev)
794
799
* frame first before the FS handler for the current
795
800
* frame.
796
801
*/
797
- if (check_state (cfe , FS_INT , node -> id )) {
802
+ if (check_state (cfe , FS_INT , node -> id ) &&
803
+ !check_state (cfe , FE_INT , node -> id )) {
798
804
cfe_dbg ("%s: [%s] Handling missing previous FE interrupt\n" ,
799
805
__func__ , node_desc [node -> id ].name );
800
806
cfe_eof_isr_handler (node );
@@ -1131,6 +1137,7 @@ static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count)
1131
1137
1132
1138
clear_state (cfe , FS_INT | FE_INT , node -> id );
1133
1139
set_state (cfe , NODE_STREAMING , node -> id );
1140
+ node -> fs_count = 0 ;
1134
1141
cfe_start_channel (node );
1135
1142
1136
1143
if (!test_all_nodes (cfe , NODE_ENABLED , NODE_STREAMING )) {
@@ -1166,7 +1173,6 @@ static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count)
1166
1173
csi2_open_rx (& cfe -> csi2 );
1167
1174
1168
1175
cfe_dbg ("Starting sensor streaming\n" );
1169
- cfe -> sequence = 0 ;
1170
1176
ret = v4l2_subdev_call (cfe -> sensor , video , s_stream , 1 );
1171
1177
if (ret < 0 ) {
1172
1178
cfe_err ("stream on failed in subdev\n" );
0 commit comments