aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
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 /drivers/media
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>
Diffstat (limited to 'drivers/media')
-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
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,
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 }