diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-08-19 10:21:50 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-08-24 03:30:01 -0400 |
commit | b8f0fff4279a1b85fa4b6d7d8b538c254edcb4a1 (patch) | |
tree | 9ab3d196fe8e7633baa8b7bb6726af43d8187710 /drivers/media | |
parent | 70b654945bacd27622ef1c424f054ae04de597e0 (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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/i2c/ad9389b.c | 7 | ||||
-rw-r--r-- | drivers/media/i2c/ths8200.c | 9 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-dv-timings.c | 25 |
3 files changed, 27 insertions, 14 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, | |||
691 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, | 691 | static 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 | ||
697 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, | 698 | 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, | |||
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, | |||
411 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, | 413 | static 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 | ||
417 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, | 420 | 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[] = { | |||
132 | EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); | 132 | EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); |
133 | 133 | ||
134 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, | 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 | 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 | } |
156 | EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); | 158 | EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); |
157 | 159 | ||
158 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, | 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 | 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 | ||
175 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, | 180 | bool 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 | } |