aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-common.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2009-05-30 20:45:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-23 02:21:18 -0400
commitb0d3159be9a36fd8b7b1cf88b812d951add53d11 (patch)
treeeb2be10df0843457ed94f8560ceb956fd37dd60c /drivers/media/video/v4l2-common.c
parent2c0b19ac3b73199fe7b3fbff884051046554c048 (diff)
V4L/DVB (11901): v4l2: Create helper function for bounding and aligning images
Most hardware has limits on minimum and maximum image dimensions and also requirements about alignment. For example, image width must be even or a multiple of four. Some hardware has requirements that the total image size (width * height) be a multiple of some power of two. v4l_bound_align_image() will enforce min and max width and height, power of two alignment on width and height, and power of two alignment on total image size. It uses an efficient algorithm that will try to find the "closest" image size that meets the requirements. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-common.c')
-rw-r--r--drivers/media/video/v4l2-common.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index e7b443c116f0..1ebbe738019f 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -1021,4 +1021,77 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
1021} 1021}
1022EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); 1022EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
1023 1023
1024#endif 1024/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
1025 * and max don't have to be aligned, but there must be at least one valid
1026 * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
1027 * of 16 between 17 and 31. */
1028static unsigned int clamp_align(unsigned int x, unsigned int min,
1029 unsigned int max, unsigned int align)
1030{
1031 /* Bits that must be zero to be aligned */
1032 unsigned int mask = ~((1 << align) - 1);
1033
1034 /* Round to nearest aligned value */
1035 if (align)
1036 x = (x + (1 << (align - 1))) & mask;
1037
1038 /* Clamp to aligned value of min and max */
1039 if (x < min)
1040 x = (min + ~mask) & mask;
1041 else if (x > max)
1042 x = max & mask;
1043
1044 return x;
1045}
1046
1047/* Bound an image to have a width between wmin and wmax, and height between
1048 * hmin and hmax, inclusive. Additionally, the width will be a multiple of
1049 * 2^walign, the height will be a multiple of 2^halign, and the overall size
1050 * (width*height) will be a multiple of 2^salign. The image may be shrunk
1051 * or enlarged to fit the alignment constraints.
1052 *
1053 * The width or height maximum must not be smaller than the corresponding
1054 * minimum. The alignments must not be so high there are no possible image
1055 * sizes within the allowed bounds. wmin and hmin must be at least 1
1056 * (don't use 0). If you don't care about a certain alignment, specify 0,
1057 * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If
1058 * you only want to adjust downward, specify a maximum that's the same as
1059 * the initial value.
1060 */
1061void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
1062 unsigned int walign,
1063 u32 *h, unsigned int hmin, unsigned int hmax,
1064 unsigned int halign, unsigned int salign)
1065{
1066 *w = clamp_align(*w, wmin, wmax, walign);
1067 *h = clamp_align(*h, hmin, hmax, halign);
1068
1069 /* Usually we don't need to align the size and are done now. */
1070 if (!salign)
1071 return;
1072
1073 /* How much alignment do we have? */
1074 walign = __ffs(*w);
1075 halign = __ffs(*h);
1076 /* Enough to satisfy the image alignment? */
1077 if (walign + halign < salign) {
1078 /* Max walign where there is still a valid width */
1079 unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
1080 /* Max halign where there is still a valid height */
1081 unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
1082
1083 /* up the smaller alignment until we have enough */
1084 do {
1085 if (halign >= hmaxa ||
1086 (walign <= halign && walign < wmaxa)) {
1087 *w = clamp_align(*w, wmin, wmax, walign + 1);
1088 walign = __ffs(*w);
1089 } else {
1090 *h = clamp_align(*h, hmin, hmax, halign + 1);
1091 halign = __ffs(*h);
1092 }
1093 } while (halign + walign < salign);
1094 }
1095}
1096EXPORT_SYMBOL_GPL(v4l_bound_align_image);
1097#endif /* defined(CONFIG_I2C) */