diff options
Diffstat (limited to 'drivers/media/video/v4l2-common.c')
-rw-r--r-- | drivers/media/video/v4l2-common.c | 75 |
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 | } |
1022 | EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); | 1022 | EXPORT_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. */ | ||
1028 | static 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 | */ | ||
1061 | void 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 | } | ||
1096 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | ||
1097 | #endif /* defined(CONFIG_I2C) */ | ||