@@ -266,9 +266,6 @@ struct thp7312_device {
266
266
struct v4l2_ctrl_handler ctrl_handler ;
267
267
bool ctrls_applied ;
268
268
269
- /* These are protected by v4l2 active state */
270
- const struct thp7312_mode_info * current_mode ;
271
- const struct thp7312_frame_rate * current_rate ;
272
269
s64 link_freq ;
273
270
274
271
struct {
@@ -310,6 +307,47 @@ static inline struct thp7312_device *to_thp7312_dev(struct v4l2_subdev *sd)
310
307
return container_of (sd , struct thp7312_device , sd );
311
308
}
312
309
310
+ static const struct thp7312_mode_info *
311
+ thp7312_find_mode (unsigned int width , unsigned int height , bool nearest )
312
+ {
313
+ const struct thp7312_mode_info * mode ;
314
+
315
+ mode = v4l2_find_nearest_size (thp7312_mode_info_data ,
316
+ ARRAY_SIZE (thp7312_mode_info_data ),
317
+ width , height , width , height );
318
+
319
+ if (!nearest && (mode -> width != width || mode -> height != height ))
320
+ return NULL ;
321
+
322
+ return mode ;
323
+ }
324
+
325
+ static const struct thp7312_frame_rate *
326
+ thp7312_find_rate (const struct thp7312_mode_info * mode , unsigned int fps ,
327
+ bool nearest )
328
+ {
329
+ const struct thp7312_frame_rate * best_rate = NULL ;
330
+ const struct thp7312_frame_rate * rate ;
331
+ unsigned int best_delta = UINT_MAX ;
332
+
333
+ if (!mode )
334
+ return NULL ;
335
+
336
+ for (rate = mode -> rates ; rate -> fps && best_delta ; ++ rate ) {
337
+ unsigned int delta = abs (rate -> fps - fps );
338
+
339
+ if (delta <= best_delta ) {
340
+ best_delta = delta ;
341
+ best_rate = rate ;
342
+ }
343
+ }
344
+
345
+ if (!nearest && best_delta )
346
+ return NULL ;
347
+
348
+ return best_rate ;
349
+ }
350
+
313
351
/* -----------------------------------------------------------------------------
314
352
* Device Access & Configuration
315
353
*/
@@ -442,17 +480,30 @@ static int thp7312_set_framefmt(struct thp7312_device *thp7312,
442
480
static int thp7312_init_mode (struct thp7312_device * thp7312 ,
443
481
struct v4l2_subdev_state * sd_state )
444
482
{
483
+ const struct thp7312_mode_info * mode ;
484
+ const struct thp7312_frame_rate * rate ;
445
485
struct v4l2_mbus_framefmt * fmt ;
486
+ struct v4l2_fract * interval ;
446
487
int ret ;
447
488
489
+ /*
490
+ * TODO: The mode and rate should be cached in the subdev state, once
491
+ * support for extending states will be available.
492
+ */
448
493
fmt = v4l2_subdev_state_get_format (sd_state , 0 );
494
+ interval = v4l2_subdev_state_get_interval (sd_state , 0 );
495
+
496
+ mode = thp7312_find_mode (fmt -> width , fmt -> height , false);
497
+ rate = thp7312_find_rate (mode , interval -> denominator , false);
498
+
499
+ if (WARN_ON (!mode || !rate ))
500
+ return - EINVAL ;
449
501
450
502
ret = thp7312_set_framefmt (thp7312 , fmt );
451
503
if (ret )
452
504
return ret ;
453
505
454
- return thp7312_change_mode (thp7312 , thp7312 -> current_mode ,
455
- thp7312 -> current_rate );
506
+ return thp7312_change_mode (thp7312 , mode , rate );
456
507
}
457
508
458
509
static int thp7312_stream_enable (struct thp7312_device * thp7312 , bool enable )
@@ -621,28 +672,6 @@ static bool thp7312_find_bus_code(u32 code)
621
672
return false;
622
673
}
623
674
624
- static const struct thp7312_mode_info *
625
- thp7312_find_mode (unsigned int width , unsigned int height , bool nearest )
626
- {
627
- const struct thp7312_mode_info * mode ;
628
-
629
- mode = v4l2_find_nearest_size (thp7312_mode_info_data ,
630
- ARRAY_SIZE (thp7312_mode_info_data ),
631
- width , height , width , height );
632
-
633
- if (!nearest && (mode -> width != width || mode -> height != height ))
634
- return NULL ;
635
-
636
- return mode ;
637
- }
638
-
639
- static void thp7312_set_frame_rate (struct thp7312_device * thp7312 ,
640
- const struct thp7312_frame_rate * rate )
641
- {
642
- thp7312 -> link_freq = rate -> link_freq ;
643
- thp7312 -> current_rate = rate ;
644
- }
645
-
646
675
static int thp7312_enum_mbus_code (struct v4l2_subdev * sd ,
647
676
struct v4l2_subdev_state * sd_state ,
648
677
struct v4l2_subdev_mbus_code_enum * code )
@@ -707,6 +736,7 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd,
707
736
struct thp7312_device * thp7312 = to_thp7312_dev (sd );
708
737
struct v4l2_mbus_framefmt * mbus_fmt = & format -> format ;
709
738
struct v4l2_mbus_framefmt * fmt ;
739
+ struct v4l2_fract * interval ;
710
740
const struct thp7312_mode_info * mode ;
711
741
712
742
if (!thp7312_find_bus_code (mbus_fmt -> code ))
@@ -726,29 +756,12 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd,
726
756
727
757
* mbus_fmt = * fmt ;
728
758
729
- if (format -> which == V4L2_SUBDEV_FORMAT_ACTIVE ) {
730
- thp7312 -> current_mode = mode ;
731
- thp7312_set_frame_rate (thp7312 , & mode -> rates [0 ]);
732
- }
733
-
734
- return 0 ;
735
- }
759
+ interval = v4l2_subdev_state_get_interval (sd_state , 0 );
760
+ interval -> numerator = 1 ;
761
+ interval -> denominator = mode -> rates [0 ].fps ;
736
762
737
- static int thp7312_get_frame_interval (struct v4l2_subdev * sd ,
738
- struct v4l2_subdev_state * sd_state ,
739
- struct v4l2_subdev_frame_interval * fi )
740
- {
741
- struct thp7312_device * thp7312 = to_thp7312_dev (sd );
742
-
743
- /*
744
- * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
745
- * subdev active state API.
746
- */
747
- if (fi -> which != V4L2_SUBDEV_FORMAT_ACTIVE )
748
- return - EINVAL ;
749
-
750
- fi -> interval .numerator = 1 ;
751
- fi -> interval .denominator = thp7312 -> current_rate -> fps ;
763
+ if (format -> which == V4L2_SUBDEV_FORMAT_ACTIVE )
764
+ thp7312 -> link_freq = mode -> rates [0 ].link_freq ;
752
765
753
766
return 0 ;
754
767
}
@@ -759,38 +772,28 @@ static int thp7312_set_frame_interval(struct v4l2_subdev *sd,
759
772
{
760
773
struct thp7312_device * thp7312 = to_thp7312_dev (sd );
761
774
const struct thp7312_mode_info * mode ;
762
- const struct thp7312_frame_rate * best_rate = NULL ;
763
775
const struct thp7312_frame_rate * rate ;
764
- unsigned int best_delta = UINT_MAX ;
776
+ const struct v4l2_mbus_framefmt * fmt ;
777
+ struct v4l2_fract * interval ;
765
778
unsigned int fps ;
766
779
767
- /*
768
- * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
769
- * subdev active state API.
770
- */
771
- if (fi -> which != V4L2_SUBDEV_FORMAT_ACTIVE )
772
- return - EINVAL ;
773
-
774
780
/* Avoid divisions by 0, pick the highest frame if the interval is 0. */
775
781
fps = fi -> interval .numerator
776
782
? DIV_ROUND_CLOSEST (fi -> interval .denominator , fi -> interval .numerator )
777
783
: UINT_MAX ;
778
784
779
- mode = thp7312 -> current_mode ;
780
-
781
- for (rate = mode -> rates ; rate -> fps && best_delta ; ++ rate ) {
782
- unsigned int delta = abs (rate -> fps - fps );
785
+ fmt = v4l2_subdev_state_get_format (sd_state , 0 );
786
+ mode = thp7312_find_mode (fmt -> width , fmt -> height , false);
787
+ rate = thp7312_find_rate (mode , fps , true);
783
788
784
- if (delta <= best_delta ) {
785
- best_delta = delta ;
786
- best_rate = rate ;
787
- }
788
- }
789
+ interval = v4l2_subdev_state_get_interval (sd_state , 0 );
790
+ interval -> numerator = 1 ;
791
+ interval -> denominator = rate -> fps ;
789
792
790
- thp7312_set_frame_rate (thp7312 , best_rate );
793
+ if (fi -> which == V4L2_SUBDEV_FORMAT_ACTIVE )
794
+ thp7312 -> link_freq = rate -> link_freq ;
791
795
792
- fi -> interval .numerator = 1 ;
793
- fi -> interval .denominator = best_rate -> fps ;
796
+ fi -> interval = * interval ;
794
797
795
798
return 0 ;
796
799
}
@@ -850,8 +853,10 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
850
853
{
851
854
const struct thp7312_mode_info * default_mode = & thp7312_mode_info_data [0 ];
852
855
struct v4l2_mbus_framefmt * fmt ;
856
+ struct v4l2_fract * interval ;
853
857
854
858
fmt = v4l2_subdev_state_get_format (sd_state , 0 );
859
+ interval = v4l2_subdev_state_get_interval (sd_state , 0 );
855
860
856
861
/*
857
862
* default init sequence initialize thp7312 to
@@ -866,6 +871,9 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
866
871
fmt -> height = default_mode -> height ;
867
872
fmt -> field = V4L2_FIELD_NONE ;
868
873
874
+ interval -> numerator = 1 ;
875
+ interval -> denominator = default_mode -> rates [0 ].fps ;
876
+
869
877
return 0 ;
870
878
}
871
879
@@ -883,7 +891,7 @@ static const struct v4l2_subdev_pad_ops thp7312_pad_ops = {
883
891
.enum_mbus_code = thp7312_enum_mbus_code ,
884
892
.get_fmt = v4l2_subdev_get_fmt ,
885
893
.set_fmt = thp7312_set_fmt ,
886
- .get_frame_interval = thp7312_get_frame_interval ,
894
+ .get_frame_interval = v4l2_subdev_get_frame_interval ,
887
895
.set_frame_interval = thp7312_set_frame_interval ,
888
896
.enum_frame_size = thp7312_enum_frame_size ,
889
897
.enum_frame_interval = thp7312_enum_frame_interval ,
@@ -1311,6 +1319,8 @@ static int thp7312_init_controls(struct thp7312_device *thp7312)
1311
1319
V4L2_CID_POWER_LINE_FREQUENCY_60HZ , 0 ,
1312
1320
V4L2_CID_POWER_LINE_FREQUENCY_50HZ );
1313
1321
1322
+ thp7312 -> link_freq = thp7312_mode_info_data [0 ].rates [0 ].link_freq ;
1323
+
1314
1324
link_freq = v4l2_ctrl_new_int_menu (hdl , & thp7312_ctrl_ops ,
1315
1325
V4L2_CID_LINK_FREQ , 0 , 0 ,
1316
1326
& thp7312 -> link_freq );
@@ -2080,7 +2090,6 @@ static int thp7312_parse_dt(struct thp7312_device *thp7312)
2080
2090
static int thp7312_probe (struct i2c_client * client )
2081
2091
{
2082
2092
struct device * dev = & client -> dev ;
2083
- struct v4l2_subdev_state * sd_state ;
2084
2093
struct thp7312_device * thp7312 ;
2085
2094
int ret ;
2086
2095
@@ -2156,11 +2165,6 @@ static int thp7312_probe(struct i2c_client *client)
2156
2165
goto err_free_ctrls ;
2157
2166
}
2158
2167
2159
- sd_state = v4l2_subdev_lock_and_get_active_state (& thp7312 -> sd );
2160
- thp7312 -> current_mode = & thp7312_mode_info_data [0 ];
2161
- thp7312_set_frame_rate (thp7312 , & thp7312 -> current_mode -> rates [0 ]);
2162
- v4l2_subdev_unlock_state (sd_state );
2163
-
2164
2168
/*
2165
2169
* Enable runtime PM with autosuspend. As the device has been powered
2166
2170
* manually, mark it as active, and increase the usage count without
0 commit comments