Skip to content

Commit a3e28ea

Browse files
pinchartlHans Verkuil
authored andcommitted
media: i2c: thp7312: Store frame interval in subdev state
Use the newly added storage for frame interval in the subdev state to simplify the driver. Signed-off-by: Laurent Pinchart <[email protected]> Acked-by: Hans Verkuil <[email protected]> Signed-off-by: Hans Verkuil <[email protected]>
1 parent 95e802a commit a3e28ea

File tree

1 file changed

+81
-77
lines changed

1 file changed

+81
-77
lines changed

drivers/media/i2c/thp7312.c

Lines changed: 81 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
442480
static 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

458509
static 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-
646675
static 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)
20802090
static 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

Comments
 (0)