Commit b8f0fff4279a1b85fa4b6d7d8b538c254edcb4a1
Committed by
Mauro Carvalho Chehab
1 parent
70b654945b
Exists in
master
and in
20 other branches
[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 <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Showing 4 changed files with 55 additions and 20 deletions Side-by-side Diff
drivers/media/i2c/ad9389b.c
... | ... | @@ -648,12 +648,12 @@ |
648 | 648 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
649 | 649 | |
650 | 650 | /* quick sanity check */ |
651 | - if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap)) | |
651 | + if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL)) | |
652 | 652 | return -EINVAL; |
653 | 653 | |
654 | 654 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings |
655 | 655 | if the format is one of the CEA or DMT timings. */ |
656 | - v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0); | |
656 | + v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL); | |
657 | 657 | |
658 | 658 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; |
659 | 659 | |
... | ... | @@ -691,7 +691,8 @@ |
691 | 691 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, |
692 | 692 | struct v4l2_enum_dv_timings *timings) |
693 | 693 | { |
694 | - return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap); | |
694 | + return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap, | |
695 | + NULL, NULL); | |
695 | 696 | } |
696 | 697 | |
697 | 698 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, |
drivers/media/i2c/ths8200.c
... | ... | @@ -378,10 +378,12 @@ |
378 | 378 | |
379 | 379 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
380 | 380 | |
381 | - if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap)) | |
381 | + if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap, | |
382 | + NULL, NULL)) | |
382 | 383 | return -EINVAL; |
383 | 384 | |
384 | - if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10)) { | |
385 | + if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10, | |
386 | + NULL, NULL)) { | |
385 | 387 | v4l2_dbg(1, debug, sd, "Unsupported format\n"); |
386 | 388 | return -EINVAL; |
387 | 389 | } |
... | ... | @@ -411,7 +413,8 @@ |
411 | 413 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, |
412 | 414 | struct v4l2_enum_dv_timings *timings) |
413 | 415 | { |
414 | - return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap); | |
416 | + return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap, | |
417 | + NULL, NULL); | |
415 | 418 | } |
416 | 419 | |
417 | 420 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, |
drivers/media/v4l2-core/v4l2-dv-timings.c
... | ... | @@ -132,7 +132,9 @@ |
132 | 132 | EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); |
133 | 133 | |
134 | 134 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, |
135 | - const struct v4l2_dv_timings_cap *dvcap) | |
135 | + const struct v4l2_dv_timings_cap *dvcap, | |
136 | + v4l2_check_dv_timings_fnc fnc, | |
137 | + void *fnc_handle) | |
136 | 138 | { |
137 | 139 | const struct v4l2_bt_timings *bt = &t->bt; |
138 | 140 | const struct v4l2_bt_timings_cap *cap = &dvcap->bt; |
139 | 141 | |
140 | 142 | |
... | ... | @@ -151,18 +153,21 @@ |
151 | 153 | (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || |
152 | 154 | (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) |
153 | 155 | return false; |
154 | - return true; | |
156 | + return fnc == NULL || fnc(t, fnc_handle); | |
155 | 157 | } |
156 | 158 | EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); |
157 | 159 | |
158 | 160 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, |
159 | - const struct v4l2_dv_timings_cap *cap) | |
161 | + const struct v4l2_dv_timings_cap *cap, | |
162 | + v4l2_check_dv_timings_fnc fnc, | |
163 | + void *fnc_handle) | |
160 | 164 | { |
161 | 165 | u32 i, idx; |
162 | 166 | |
163 | 167 | memset(t->reserved, 0, sizeof(t->reserved)); |
164 | 168 | for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { |
165 | - if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap) && | |
169 | + if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | |
170 | + fnc, fnc_handle) && | |
166 | 171 | idx++ == t->index) { |
167 | 172 | t->timings = v4l2_dv_timings_presets[i]; |
168 | 173 | return 0; |
169 | 174 | |
170 | 175 | |
... | ... | @@ -174,16 +179,20 @@ |
174 | 179 | |
175 | 180 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, |
176 | 181 | const struct v4l2_dv_timings_cap *cap, |
177 | - unsigned pclock_delta) | |
182 | + unsigned pclock_delta, | |
183 | + v4l2_check_dv_timings_fnc fnc, | |
184 | + void *fnc_handle) | |
178 | 185 | { |
179 | 186 | int i; |
180 | 187 | |
181 | - if (!v4l2_valid_dv_timings(t, cap)) | |
188 | + if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle)) | |
182 | 189 | return false; |
183 | 190 | |
184 | 191 | for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) { |
185 | - if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap) && | |
186 | - v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, pclock_delta)) { | |
192 | + if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | |
193 | + fnc, fnc_handle) && | |
194 | + v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, | |
195 | + pclock_delta)) { | |
187 | 196 | *t = v4l2_dv_timings_presets[i]; |
188 | 197 | return true; |
189 | 198 | } |
include/media/v4l2-dv-timings.h
... | ... | @@ -27,46 +27,68 @@ |
27 | 27 | */ |
28 | 28 | extern const struct v4l2_dv_timings v4l2_dv_timings_presets[]; |
29 | 29 | |
30 | +/** v4l2_check_dv_timings_fnc - timings check callback | |
31 | + * @t: the v4l2_dv_timings struct. | |
32 | + * @handle: a handle from the driver. | |
33 | + * | |
34 | + * Returns true if the given timings are valid. | |
35 | + */ | |
36 | +typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle); | |
37 | + | |
30 | 38 | /** v4l2_valid_dv_timings() - are these timings valid? |
31 | 39 | * @t: the v4l2_dv_timings struct. |
32 | 40 | * @cap: the v4l2_dv_timings_cap capabilities. |
41 | + * @fnc: callback to check if this timing is OK. May be NULL. | |
42 | + * @fnc_handle: a handle that is passed on to @fnc. | |
33 | 43 | * |
34 | 44 | * Returns true if the given dv_timings struct is supported by the |
35 | - * hardware capabilities, returns false otherwise. | |
45 | + * hardware capabilities and the callback function (if non-NULL), returns | |
46 | + * false otherwise. | |
36 | 47 | */ |
37 | 48 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, |
38 | - const struct v4l2_dv_timings_cap *cap); | |
49 | + const struct v4l2_dv_timings_cap *cap, | |
50 | + v4l2_check_dv_timings_fnc fnc, | |
51 | + void *fnc_handle); | |
39 | 52 | |
40 | 53 | /** v4l2_enum_dv_timings_cap() - Helper function to enumerate possible DV timings based on capabilities |
41 | 54 | * @t: the v4l2_enum_dv_timings struct. |
42 | 55 | * @cap: the v4l2_dv_timings_cap capabilities. |
56 | + * @fnc: callback to check if this timing is OK. May be NULL. | |
57 | + * @fnc_handle: a handle that is passed on to @fnc. | |
43 | 58 | * |
44 | 59 | * This enumerates dv_timings using the full list of possible CEA-861 and DMT |
45 | 60 | * timings, filtering out any timings that are not supported based on the |
46 | - * hardware capabilities. | |
61 | + * hardware capabilities and the callback function (if non-NULL). | |
47 | 62 | * |
48 | 63 | * If a valid timing for the given index is found, it will fill in @t and |
49 | 64 | * return 0, otherwise it returns -EINVAL. |
50 | 65 | */ |
51 | 66 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, |
52 | - const struct v4l2_dv_timings_cap *cap); | |
67 | + const struct v4l2_dv_timings_cap *cap, | |
68 | + v4l2_check_dv_timings_fnc fnc, | |
69 | + void *fnc_handle); | |
53 | 70 | |
54 | 71 | /** v4l2_find_dv_timings_cap() - Find the closest timings struct |
55 | 72 | * @t: the v4l2_enum_dv_timings struct. |
56 | 73 | * @cap: the v4l2_dv_timings_cap capabilities. |
57 | 74 | * @pclock_delta: maximum delta between t->pixelclock and the timing struct |
58 | 75 | * under consideration. |
76 | + * @fnc: callback to check if a given timings struct is OK. May be NULL. | |
77 | + * @fnc_handle: a handle that is passed on to @fnc. | |
59 | 78 | * |
60 | 79 | * This function tries to map the given timings to an entry in the |
61 | 80 | * full list of possible CEA-861 and DMT timings, filtering out any timings |
62 | - * that are not supported based on the hardware capabilities. | |
81 | + * that are not supported based on the hardware capabilities and the callback | |
82 | + * function (if non-NULL). | |
63 | 83 | * |
64 | 84 | * On success it will fill in @t with the found timings and it returns true. |
65 | 85 | * On failure it will return false. |
66 | 86 | */ |
67 | 87 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, |
68 | 88 | const struct v4l2_dv_timings_cap *cap, |
69 | - unsigned pclock_delta); | |
89 | + unsigned pclock_delta, | |
90 | + v4l2_check_dv_timings_fnc fnc, | |
91 | + void *fnc_handle); | |
70 | 92 | |
71 | 93 | /** v4l2_match_dv_timings() - do two timings match? |
72 | 94 | * @measured: the measured timings data. |