aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-08-19 10:21:50 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-08-24 03:30:01 -0400
commitb8f0fff4279a1b85fa4b6d7d8b538c254edcb4a1 (patch)
tree9ab3d196fe8e7633baa8b7bb6726af43d8187710
parent70b654945bacd27622ef1c424f054ae04de597e0 (diff)
[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>
-rw-r--r--drivers/media/i2c/ad9389b.c7
-rw-r--r--drivers/media/i2c/ths8200.c9
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c25
-rw-r--r--include/media/v4l2-dv-timings.h34
4 files changed, 55 insertions, 20 deletions
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,
648 v4l2_dbg(1, debug, sd, "%s:\n", __func__); 648 v4l2_dbg(1, debug, sd, "%s:\n", __func__);
649 649
650 /* quick sanity check */ 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 return -EINVAL; 652 return -EINVAL;
653 653
654 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings 654 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
655 if the format is one of the CEA or DMT timings. */ 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 timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; 658 timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
659 659
@@ -691,7 +691,8 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
691static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, 691static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
692 struct v4l2_enum_dv_timings *timings) 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
697static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, 698static 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,
378 378
379 v4l2_dbg(1, debug, sd, "%s:\n", __func__); 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 return -EINVAL; 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 v4l2_dbg(1, debug, sd, "Unsupported format\n"); 387 v4l2_dbg(1, debug, sd, "Unsupported format\n");
386 return -EINVAL; 388 return -EINVAL;
387 } 389 }
@@ -411,7 +413,8 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd,
411static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, 413static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
412 struct v4l2_enum_dv_timings *timings) 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
417static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, 420static 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[] = {
132EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); 132EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
133 133
134bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, 134bool 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 const struct v4l2_bt_timings *bt = &t->bt; 139 const struct v4l2_bt_timings *bt = &t->bt;
138 const struct v4l2_bt_timings_cap *cap = &dvcap->bt; 140 const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
@@ -151,18 +153,21 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
151 (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || 153 (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
152 (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) 154 (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
153 return false; 155 return false;
154 return true; 156 return fnc == NULL || fnc(t, fnc_handle);
155} 157}
156EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); 158EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
157 159
158int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, 160int 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 u32 i, idx; 165 u32 i, idx;
162 166
163 memset(t->reserved, 0, sizeof(t->reserved)); 167 memset(t->reserved, 0, sizeof(t->reserved));
164 for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { 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 idx++ == t->index) { 171 idx++ == t->index) {
167 t->timings = v4l2_dv_timings_presets[i]; 172 t->timings = v4l2_dv_timings_presets[i];
168 return 0; 173 return 0;
@@ -174,16 +179,20 @@ EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap);
174 179
175bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, 180bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
176 const struct v4l2_dv_timings_cap *cap, 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 int i; 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 return false; 189 return false;
183 190
184 for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) { 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) && 192 if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
186 v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, pclock_delta)) { 193 fnc, fnc_handle) &&
194 v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
195 pclock_delta)) {
187 *t = v4l2_dv_timings_presets[i]; 196 *t = v4l2_dv_timings_presets[i];
188 return true; 197 return true;
189 } 198 }
diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h
index bd59df8125c6..4becc6716393 100644
--- a/include/media/v4l2-dv-timings.h
+++ b/include/media/v4l2-dv-timings.h
@@ -27,46 +27,68 @@
27 */ 27 */
28extern const struct v4l2_dv_timings v4l2_dv_timings_presets[]; 28extern 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 */
36typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle);
37
30/** v4l2_valid_dv_timings() - are these timings valid? 38/** v4l2_valid_dv_timings() - are these timings valid?
31 * @t: the v4l2_dv_timings struct. 39 * @t: the v4l2_dv_timings struct.
32 * @cap: the v4l2_dv_timings_cap capabilities. 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 * Returns true if the given dv_timings struct is supported by the 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 */
37bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, 48bool 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/** v4l2_enum_dv_timings_cap() - Helper function to enumerate possible DV timings based on capabilities 53/** v4l2_enum_dv_timings_cap() - Helper function to enumerate possible DV timings based on capabilities
41 * @t: the v4l2_enum_dv_timings struct. 54 * @t: the v4l2_enum_dv_timings struct.
42 * @cap: the v4l2_dv_timings_cap capabilities. 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 * This enumerates dv_timings using the full list of possible CEA-861 and DMT 59 * This enumerates dv_timings using the full list of possible CEA-861 and DMT
45 * timings, filtering out any timings that are not supported based on the 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 * If a valid timing for the given index is found, it will fill in @t and 63 * If a valid timing for the given index is found, it will fill in @t and
49 * return 0, otherwise it returns -EINVAL. 64 * return 0, otherwise it returns -EINVAL.
50 */ 65 */
51int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, 66int 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/** v4l2_find_dv_timings_cap() - Find the closest timings struct 71/** v4l2_find_dv_timings_cap() - Find the closest timings struct
55 * @t: the v4l2_enum_dv_timings struct. 72 * @t: the v4l2_enum_dv_timings struct.
56 * @cap: the v4l2_dv_timings_cap capabilities. 73 * @cap: the v4l2_dv_timings_cap capabilities.
57 * @pclock_delta: maximum delta between t->pixelclock and the timing struct 74 * @pclock_delta: maximum delta between t->pixelclock and the timing struct
58 * under consideration. 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 * This function tries to map the given timings to an entry in the 79 * This function tries to map the given timings to an entry in the
61 * full list of possible CEA-861 and DMT timings, filtering out any timings 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 * On success it will fill in @t with the found timings and it returns true. 84 * On success it will fill in @t with the found timings and it returns true.
65 * On failure it will return false. 85 * On failure it will return false.
66 */ 86 */
67bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, 87bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
68 const struct v4l2_dv_timings_cap *cap, 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/** v4l2_match_dv_timings() - do two timings match? 93/** v4l2_match_dv_timings() - do two timings match?
72 * @measured: the measured timings data. 94 * @measured: the measured timings data.