From b8f0fff4279a1b85fa4b6d7d8b538c254edcb4a1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 19 Aug 2013 11:21:50 -0300 Subject: [media] v4l2-dv-timings: add callback to handle exceptions In most cases the v4l2_bt_timings_cap struct has all the information necessary to determine valid timings, but occasionally there are exceptions. Add a callback function to be able to test for those exceptions. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 7 ++++--- drivers/media/i2c/ths8200.c | 9 ++++++--- drivers/media/v4l2-core/v4l2-dv-timings.c | 25 +++++++++++++++++-------- 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index fc608516fc43..836978602973 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -648,12 +648,12 @@ static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "%s:\n", __func__); /* quick sanity check */ - if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap)) + if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL)) return -EINVAL; /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings if the format is one of the CEA or DMT timings. */ - v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0); + v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL); timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; @@ -691,7 +691,8 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd, static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings) { - return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap); + return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap, + NULL, NULL); } static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 6abf0fb36079..a58a8f663ffb 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -378,10 +378,12 @@ static int ths8200_s_dv_timings(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "%s:\n", __func__); - if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap)) + if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap, + NULL, NULL)) return -EINVAL; - if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10)) { + if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10, + NULL, NULL)) { v4l2_dbg(1, debug, sd, "Unsupported format\n"); return -EINVAL; } @@ -411,7 +413,8 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd, static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings) { - return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap); + return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap, + NULL, NULL); } static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index a77f20145881..ee52b9f4a944 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -132,7 +132,9 @@ const struct v4l2_dv_timings v4l2_dv_timings_presets[] = { EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, - const struct v4l2_dv_timings_cap *dvcap) + const struct v4l2_dv_timings_cap *dvcap, + v4l2_check_dv_timings_fnc fnc, + void *fnc_handle) { const struct v4l2_bt_timings *bt = &t->bt; const struct v4l2_bt_timings_cap *cap = &dvcap->bt; @@ -151,18 +153,21 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) return false; - return true; + return fnc == NULL || fnc(t, fnc_handle); } EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, - const struct v4l2_dv_timings_cap *cap) + const struct v4l2_dv_timings_cap *cap, + v4l2_check_dv_timings_fnc fnc, + void *fnc_handle) { u32 i, idx; memset(t->reserved, 0, sizeof(t->reserved)); for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { - if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap) && + if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, + fnc, fnc_handle) && idx++ == t->index) { t->timings = v4l2_dv_timings_presets[i]; return 0; @@ -174,16 +179,20 @@ EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap); bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, const struct v4l2_dv_timings_cap *cap, - unsigned pclock_delta) + unsigned pclock_delta, + v4l2_check_dv_timings_fnc fnc, + void *fnc_handle) { int i; - if (!v4l2_valid_dv_timings(t, cap)) + if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle)) return false; for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) { - if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap) && - v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, pclock_delta)) { + if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, + fnc, fnc_handle) && + v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, + pclock_delta)) { *t = v4l2_dv_timings_presets[i]; return true; } -- cgit v1.2.3