@@ -43,7 +43,6 @@ struct mxc_isi_m2m_ctx_queue_data {
4343 struct v4l2_pix_format_mplane format ;
4444 const struct mxc_isi_format_info * info ;
4545 u32 sequence ;
46- bool streaming ;
4746};
4847
4948struct mxc_isi_m2m_ctx {
@@ -236,6 +235,65 @@ static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2)
236235 v4l2_m2m_buf_queue (ctx -> fh .m2m_ctx , vbuf );
237236}
238237
238+ static int mxc_isi_m2m_vb2_prepare_streaming (struct vb2_queue * q )
239+ {
240+ struct mxc_isi_m2m_ctx * ctx = vb2_get_drv_priv (q );
241+ const struct v4l2_pix_format_mplane * out_pix = & ctx -> queues .out .format ;
242+ const struct v4l2_pix_format_mplane * cap_pix = & ctx -> queues .cap .format ;
243+ const struct mxc_isi_format_info * cap_info = ctx -> queues .cap .info ;
244+ const struct mxc_isi_format_info * out_info = ctx -> queues .out .info ;
245+ struct mxc_isi_m2m * m2m = ctx -> m2m ;
246+ int ret ;
247+
248+ guard (mutex )(& m2m -> lock );
249+
250+ if (m2m -> usage_count == INT_MAX )
251+ return - EOVERFLOW ;
252+
253+ /*
254+ * Acquire the pipe and initialize the channel with the first user of
255+ * the M2M device.
256+ */
257+ if (m2m -> usage_count == 0 ) {
258+ bool bypass = cap_pix -> width == out_pix -> width &&
259+ cap_pix -> height == out_pix -> height &&
260+ cap_info -> encoding == out_info -> encoding ;
261+
262+ ret = mxc_isi_channel_acquire (m2m -> pipe ,
263+ & mxc_isi_m2m_frame_write_done ,
264+ bypass );
265+ if (ret )
266+ return ret ;
267+
268+ mxc_isi_channel_get (m2m -> pipe );
269+ }
270+
271+ m2m -> usage_count ++ ;
272+
273+ /*
274+ * Allocate resources for the channel, counting how many users require
275+ * buffer chaining.
276+ */
277+ if (!ctx -> chained && out_pix -> width > MXC_ISI_MAX_WIDTH_UNCHAINED ) {
278+ ret = mxc_isi_channel_chain (m2m -> pipe );
279+ if (ret )
280+ goto err_deinit ;
281+
282+ m2m -> chained_count ++ ;
283+ ctx -> chained = true;
284+ }
285+
286+ return 0 ;
287+
288+ err_deinit :
289+ if (-- m2m -> usage_count == 0 ) {
290+ mxc_isi_channel_put (m2m -> pipe );
291+ mxc_isi_channel_release (m2m -> pipe );
292+ }
293+
294+ return ret ;
295+ }
296+
239297static int mxc_isi_m2m_vb2_start_streaming (struct vb2_queue * q ,
240298 unsigned int count )
241299{
@@ -265,15 +323,46 @@ static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q)
265323 }
266324}
267325
326+ static void mxc_isi_m2m_vb2_unprepare_streaming (struct vb2_queue * q )
327+ {
328+ struct mxc_isi_m2m_ctx * ctx = vb2_get_drv_priv (q );
329+ struct mxc_isi_m2m * m2m = ctx -> m2m ;
330+
331+ guard (mutex )(& m2m -> lock );
332+
333+ /*
334+ * If the last context is this one, reset it to make sure the device
335+ * will be reconfigured when streaming is restarted.
336+ */
337+ if (m2m -> last_ctx == ctx )
338+ m2m -> last_ctx = NULL ;
339+
340+ /* Free the channel resources if this is the last chained context. */
341+ if (ctx -> chained && -- m2m -> chained_count == 0 )
342+ mxc_isi_channel_unchain (m2m -> pipe );
343+ ctx -> chained = false;
344+
345+ /* Turn off the light with the last user. */
346+ if (-- m2m -> usage_count == 0 ) {
347+ mxc_isi_channel_disable (m2m -> pipe );
348+ mxc_isi_channel_put (m2m -> pipe );
349+ mxc_isi_channel_release (m2m -> pipe );
350+ }
351+
352+ WARN_ON (m2m -> usage_count < 0 );
353+ }
354+
268355static const struct vb2_ops mxc_isi_m2m_vb2_qops = {
269356 .queue_setup = mxc_isi_m2m_vb2_queue_setup ,
270357 .buf_init = mxc_isi_m2m_vb2_buffer_init ,
271358 .buf_prepare = mxc_isi_m2m_vb2_buffer_prepare ,
272359 .buf_queue = mxc_isi_m2m_vb2_buffer_queue ,
273360 .wait_prepare = vb2_ops_wait_prepare ,
274361 .wait_finish = vb2_ops_wait_finish ,
362+ .prepare_streaming = mxc_isi_m2m_vb2_prepare_streaming ,
275363 .start_streaming = mxc_isi_m2m_vb2_start_streaming ,
276364 .stop_streaming = mxc_isi_m2m_vb2_stop_streaming ,
365+ .unprepare_streaming = mxc_isi_m2m_vb2_unprepare_streaming ,
277366};
278367
279368static int mxc_isi_m2m_queue_init (void * priv , struct vb2_queue * src_vq ,
@@ -483,135 +572,6 @@ static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh,
483572 return 0 ;
484573}
485574
486- static int mxc_isi_m2m_streamon (struct file * file , void * fh ,
487- enum v4l2_buf_type type )
488- {
489- struct mxc_isi_m2m_ctx * ctx = to_isi_m2m_ctx (fh );
490- struct mxc_isi_m2m_ctx_queue_data * q = mxc_isi_m2m_ctx_qdata (ctx , type );
491- const struct v4l2_pix_format_mplane * out_pix = & ctx -> queues .out .format ;
492- const struct v4l2_pix_format_mplane * cap_pix = & ctx -> queues .cap .format ;
493- const struct mxc_isi_format_info * cap_info = ctx -> queues .cap .info ;
494- const struct mxc_isi_format_info * out_info = ctx -> queues .out .info ;
495- struct mxc_isi_m2m * m2m = ctx -> m2m ;
496- int ret ;
497-
498- if (q -> streaming )
499- return 0 ;
500-
501- mutex_lock (& m2m -> lock );
502-
503- if (m2m -> usage_count == INT_MAX ) {
504- ret = - EOVERFLOW ;
505- goto unlock ;
506- }
507-
508- /*
509- * Acquire the pipe and initialize the channel with the first user of
510- * the M2M device.
511- */
512- if (m2m -> usage_count == 0 ) {
513- bool bypass = cap_pix -> width == out_pix -> width &&
514- cap_pix -> height == out_pix -> height &&
515- cap_info -> encoding == out_info -> encoding ;
516-
517- ret = mxc_isi_channel_acquire (m2m -> pipe ,
518- & mxc_isi_m2m_frame_write_done ,
519- bypass );
520- if (ret )
521- goto unlock ;
522-
523- mxc_isi_channel_get (m2m -> pipe );
524- }
525-
526- m2m -> usage_count ++ ;
527-
528- /*
529- * Allocate resources for the channel, counting how many users require
530- * buffer chaining.
531- */
532- if (!ctx -> chained && out_pix -> width > MXC_ISI_MAX_WIDTH_UNCHAINED ) {
533- ret = mxc_isi_channel_chain (m2m -> pipe );
534- if (ret )
535- goto deinit ;
536-
537- m2m -> chained_count ++ ;
538- ctx -> chained = true;
539- }
540-
541- /*
542- * Drop the lock to start the stream, as the .device_run() operation
543- * needs to acquire it.
544- */
545- mutex_unlock (& m2m -> lock );
546- ret = v4l2_m2m_ioctl_streamon (file , fh , type );
547- if (ret ) {
548- /* Reacquire the lock for the cleanup path. */
549- mutex_lock (& m2m -> lock );
550- goto unchain ;
551- }
552-
553- q -> streaming = true;
554-
555- return 0 ;
556-
557- unchain :
558- if (ctx -> chained && -- m2m -> chained_count == 0 )
559- mxc_isi_channel_unchain (m2m -> pipe );
560- ctx -> chained = false;
561-
562- deinit :
563- if (-- m2m -> usage_count == 0 ) {
564- mxc_isi_channel_put (m2m -> pipe );
565- mxc_isi_channel_release (m2m -> pipe );
566- }
567-
568- unlock :
569- mutex_unlock (& m2m -> lock );
570- return ret ;
571- }
572-
573- static int mxc_isi_m2m_streamoff (struct file * file , void * fh ,
574- enum v4l2_buf_type type )
575- {
576- struct mxc_isi_m2m_ctx * ctx = to_isi_m2m_ctx (fh );
577- struct mxc_isi_m2m_ctx_queue_data * q = mxc_isi_m2m_ctx_qdata (ctx , type );
578- struct mxc_isi_m2m * m2m = ctx -> m2m ;
579-
580- v4l2_m2m_ioctl_streamoff (file , fh , type );
581-
582- if (!q -> streaming )
583- return 0 ;
584-
585- mutex_lock (& m2m -> lock );
586-
587- /*
588- * If the last context is this one, reset it to make sure the device
589- * will be reconfigured when streaming is restarted.
590- */
591- if (m2m -> last_ctx == ctx )
592- m2m -> last_ctx = NULL ;
593-
594- /* Free the channel resources if this is the last chained context. */
595- if (ctx -> chained && -- m2m -> chained_count == 0 )
596- mxc_isi_channel_unchain (m2m -> pipe );
597- ctx -> chained = false;
598-
599- /* Turn off the light with the last user. */
600- if (-- m2m -> usage_count == 0 ) {
601- mxc_isi_channel_disable (m2m -> pipe );
602- mxc_isi_channel_put (m2m -> pipe );
603- mxc_isi_channel_release (m2m -> pipe );
604- }
605-
606- WARN_ON (m2m -> usage_count < 0 );
607-
608- mutex_unlock (& m2m -> lock );
609-
610- q -> streaming = false;
611-
612- return 0 ;
613- }
614-
615575static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = {
616576 .vidioc_querycap = mxc_isi_m2m_querycap ,
617577
@@ -632,8 +592,8 @@ static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = {
632592 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf ,
633593 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs ,
634594
635- .vidioc_streamon = mxc_isi_m2m_streamon ,
636- .vidioc_streamoff = mxc_isi_m2m_streamoff ,
595+ .vidioc_streamon = v4l2_m2m_ioctl_streamon ,
596+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff ,
637597
638598 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
639599 .vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
0 commit comments