aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-common.c
diff options
context:
space:
mode:
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) */