@@ -266,9 +266,6 @@ struct thp7312_device {
266266 struct v4l2_ctrl_handler ctrl_handler ;
267267 bool ctrls_applied ;
268268
269- /* These are protected by v4l2 active state */
270- const struct thp7312_mode_info * current_mode ;
271- const struct thp7312_frame_rate * current_rate ;
272269 s64 link_freq ;
273270
274271 struct {
@@ -310,6 +307,47 @@ static inline struct thp7312_device *to_thp7312_dev(struct v4l2_subdev *sd)
310307 return container_of (sd , struct thp7312_device , sd );
311308}
312309
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+
313351/* -----------------------------------------------------------------------------
314352 * Device Access & Configuration
315353 */
@@ -442,17 +480,30 @@ static int thp7312_set_framefmt(struct thp7312_device *thp7312,
442480static int thp7312_init_mode (struct thp7312_device * thp7312 ,
443481 struct v4l2_subdev_state * sd_state )
444482{
483+ const struct thp7312_mode_info * mode ;
484+ const struct thp7312_frame_rate * rate ;
445485 struct v4l2_mbus_framefmt * fmt ;
486+ struct v4l2_fract * interval ;
446487 int ret ;
447488
489+ /*
490+ * TODO: The mode and rate should be cached in the subdev state, once
491+ * support for extending states will be available.
492+ */
448493 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 ;
449501
450502 ret = thp7312_set_framefmt (thp7312 , fmt );
451503 if (ret )
452504 return ret ;
453505
454- return thp7312_change_mode (thp7312 , thp7312 -> current_mode ,
455- thp7312 -> current_rate );
506+ return thp7312_change_mode (thp7312 , mode , rate );
456507}
457508
458509static int thp7312_stream_enable (struct thp7312_device * thp7312 , bool enable )
@@ -621,28 +672,6 @@ static bool thp7312_find_bus_code(u32 code)
621672 return false;
622673}
623674
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-
646675static int thp7312_enum_mbus_code (struct v4l2_subdev * sd ,
647676 struct v4l2_subdev_state * sd_state ,
648677 struct v4l2_subdev_mbus_code_enum * code )
@@ -707,6 +736,7 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd,
707736 struct thp7312_device * thp7312 = to_thp7312_dev (sd );
708737 struct v4l2_mbus_framefmt * mbus_fmt = & format -> format ;
709738 struct v4l2_mbus_framefmt * fmt ;
739+ struct v4l2_fract * interval ;
710740 const struct thp7312_mode_info * mode ;
711741
712742 if (!thp7312_find_bus_code (mbus_fmt -> code ))
@@ -726,29 +756,12 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd,
726756
727757 * mbus_fmt = * fmt ;
728758
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 ;
736762
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 ;
752765
753766 return 0 ;
754767}
@@ -759,38 +772,28 @@ static int thp7312_set_frame_interval(struct v4l2_subdev *sd,
759772{
760773 struct thp7312_device * thp7312 = to_thp7312_dev (sd );
761774 const struct thp7312_mode_info * mode ;
762- const struct thp7312_frame_rate * best_rate = NULL ;
763775 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 ;
765778 unsigned int fps ;
766779
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-
774780 /* Avoid divisions by 0, pick the highest frame if the interval is 0. */
775781 fps = fi -> interval .numerator
776782 ? DIV_ROUND_CLOSEST (fi -> interval .denominator , fi -> interval .numerator )
777783 : UINT_MAX ;
778784
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);
783788
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 ;
789792
790- thp7312_set_frame_rate (thp7312 , best_rate );
793+ if (fi -> which == V4L2_SUBDEV_FORMAT_ACTIVE )
794+ thp7312 -> link_freq = rate -> link_freq ;
791795
792- fi -> interval .numerator = 1 ;
793- fi -> interval .denominator = best_rate -> fps ;
796+ fi -> interval = * interval ;
794797
795798 return 0 ;
796799}
@@ -850,8 +853,10 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
850853{
851854 const struct thp7312_mode_info * default_mode = & thp7312_mode_info_data [0 ];
852855 struct v4l2_mbus_framefmt * fmt ;
856+ struct v4l2_fract * interval ;
853857
854858 fmt = v4l2_subdev_state_get_format (sd_state , 0 );
859+ interval = v4l2_subdev_state_get_interval (sd_state , 0 );
855860
856861 /*
857862 * default init sequence initialize thp7312 to
@@ -866,6 +871,9 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
866871 fmt -> height = default_mode -> height ;
867872 fmt -> field = V4L2_FIELD_NONE ;
868873
874+ interval -> numerator = 1 ;
875+ interval -> denominator = default_mode -> rates [0 ].fps ;
876+
869877 return 0 ;
870878}
871879
@@ -883,7 +891,7 @@ static const struct v4l2_subdev_pad_ops thp7312_pad_ops = {
883891 .enum_mbus_code = thp7312_enum_mbus_code ,
884892 .get_fmt = v4l2_subdev_get_fmt ,
885893 .set_fmt = thp7312_set_fmt ,
886- .get_frame_interval = thp7312_get_frame_interval ,
894+ .get_frame_interval = v4l2_subdev_get_frame_interval ,
887895 .set_frame_interval = thp7312_set_frame_interval ,
888896 .enum_frame_size = thp7312_enum_frame_size ,
889897 .enum_frame_interval = thp7312_enum_frame_interval ,
@@ -1311,6 +1319,8 @@ static int thp7312_init_controls(struct thp7312_device *thp7312)
13111319 V4L2_CID_POWER_LINE_FREQUENCY_60HZ , 0 ,
13121320 V4L2_CID_POWER_LINE_FREQUENCY_50HZ );
13131321
1322+ thp7312 -> link_freq = thp7312_mode_info_data [0 ].rates [0 ].link_freq ;
1323+
13141324 link_freq = v4l2_ctrl_new_int_menu (hdl , & thp7312_ctrl_ops ,
13151325 V4L2_CID_LINK_FREQ , 0 , 0 ,
13161326 & thp7312 -> link_freq );
@@ -2080,7 +2090,6 @@ static int thp7312_parse_dt(struct thp7312_device *thp7312)
20802090static int thp7312_probe (struct i2c_client * client )
20812091{
20822092 struct device * dev = & client -> dev ;
2083- struct v4l2_subdev_state * sd_state ;
20842093 struct thp7312_device * thp7312 ;
20852094 int ret ;
20862095
@@ -2156,11 +2165,6 @@ static int thp7312_probe(struct i2c_client *client)
21562165 goto err_free_ctrls ;
21572166 }
21582167
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-
21642168 /*
21652169 * Enable runtime PM with autosuspend. As the device has been powered
21662170 * manually, mark it as active, and increase the usage count without
0 commit comments