2 * drivers/media/video/omap/omap_voutlib.c
4 * Copyright (C) 2005-2009 Texas Instruments.
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
10 * Based on the OMAP2 camera driver
11 * Video-for-Linux (Version 2) camera capture driver for
12 * the OMAP24xx camera controller.
14 * Author: Andy Lowe (source@mvista.com)
16 * Copyright (C) 2004 MontaVista Software, Inc.
17 * Copyright (C) 2009 Texas Instruments.
21 #include <linux/module.h>
22 #include <linux/errno.h>
23 #include <linux/kernel.h>
24 #include <linux/types.h>
25 #include <linux/videodev2.h>
28 MODULE_AUTHOR("Texas Instruments.");
29 MODULE_DESCRIPTION("OMAP Video library");
30 MODULE_LICENSE("GPL");
32 /* Return the default overlay cropping rectangle in crop given the image
33 * size in pix and the video display size in fbuf. The default
34 * cropping rectangle is the largest rectangle no larger than the capture size
35 * that will fit on the display. The default cropping rectangle is centered in
36 * the image. All dimensions and offsets are rounded down to even numbers.
38 void omap_vout_default_crop(struct v4l2_pix_format
*pix
,
39 struct v4l2_framebuffer
*fbuf
, struct v4l2_rect
*crop
)
41 crop
->width
= (pix
->width
< fbuf
->fmt
.width
) ?
42 pix
->width
: fbuf
->fmt
.width
;
43 crop
->height
= (pix
->height
< fbuf
->fmt
.height
) ?
44 pix
->height
: fbuf
->fmt
.height
;
47 crop
->left
= ((pix
->width
- crop
->width
) >> 1) & ~1;
48 crop
->top
= ((pix
->height
- crop
->height
) >> 1) & ~1;
50 EXPORT_SYMBOL_GPL(omap_vout_default_crop
);
52 /* Given a new render window in new_win, adjust the window to the
53 * nearest supported configuration. The adjusted window parameters are
54 * returned in new_win.
55 * Returns zero if succesful, or -EINVAL if the requested window is
56 * impossible and cannot reasonably be adjusted.
58 int omap_vout_try_window(struct v4l2_framebuffer
*fbuf
,
59 struct v4l2_window
*new_win
)
61 struct v4l2_rect try_win
;
63 /* make a working copy of the new_win rectangle */
66 /* adjust the preview window so it fits on the display by clipping any
69 if (try_win
.left
< 0) {
70 try_win
.width
+= try_win
.left
;
73 if (try_win
.top
< 0) {
74 try_win
.height
+= try_win
.top
;
77 try_win
.width
= (try_win
.width
< fbuf
->fmt
.width
) ?
78 try_win
.width
: fbuf
->fmt
.width
;
79 try_win
.height
= (try_win
.height
< fbuf
->fmt
.height
) ?
80 try_win
.height
: fbuf
->fmt
.height
;
81 if (try_win
.left
+ try_win
.width
> fbuf
->fmt
.width
)
82 try_win
.width
= fbuf
->fmt
.width
- try_win
.left
;
83 if (try_win
.top
+ try_win
.height
> fbuf
->fmt
.height
)
84 try_win
.height
= fbuf
->fmt
.height
- try_win
.top
;
88 if (try_win
.width
<= 0 || try_win
.height
<= 0)
91 /* We now have a valid preview window, so go with it */
93 new_win
->field
= V4L2_FIELD_ANY
;
96 EXPORT_SYMBOL_GPL(omap_vout_try_window
);
98 /* Given a new render window in new_win, adjust the window to the
99 * nearest supported configuration. The image cropping window in crop
100 * will also be adjusted if necessary. Preference is given to keeping the
101 * the window as close to the requested configuration as possible. If
102 * successful, new_win, vout->win, and crop are updated.
103 * Returns zero if succesful, or -EINVAL if the requested preview window is
104 * impossible and cannot reasonably be adjusted.
106 int omap_vout_new_window(struct v4l2_rect
*crop
,
107 struct v4l2_window
*win
, struct v4l2_framebuffer
*fbuf
,
108 struct v4l2_window
*new_win
)
112 err
= omap_vout_try_window(fbuf
, new_win
);
116 /* update our preview window */
118 win
->field
= new_win
->field
;
119 win
->chromakey
= new_win
->chromakey
;
121 if (cpu_is_omap24xx()) {
123 * omap24xx supports 8x to 1/2x scaling.
125 if ((crop
->height
/win
->w
.height
) >= 2) {
126 /* The maximum vertical downsizing ratio is 2:1 */
127 crop
->height
= win
->w
.height
* 2;
129 if ((crop
->width
/win
->w
.width
) >= 2) {
130 /* The maximum horizontal downsizing ratio is 2:1 */
131 crop
->width
= win
->w
.width
* 2;
133 if (crop
->width
> 768) {
134 /* The OMAP2420 vertical resizing line buffer is 768
137 if (crop
->height
!= win
->w
.height
)
140 } else if (cpu_is_omap34xx()) {
142 * omap34xx supports 8x to 1/4x scaling.
144 if ((crop
->height
/win
->w
.height
) >= 4) {
145 /* The maximum vertical downsizing ratio is 4:1 */
146 crop
->height
= win
->w
.height
* 4;
148 if ((crop
->width
/win
->w
.width
) >= 4) {
149 /* The maximum horizontal downsizing ratio is 4:1 */
150 crop
->width
= win
->w
.width
* 4;
155 EXPORT_SYMBOL_GPL(omap_vout_new_window
);
157 /* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
158 * the nearest supported configuration. The image render window in win will
159 * also be adjusted if necessary. The preview window is adjusted such that the
160 * horizontal and vertical rescaling ratios stay constant. If the render
161 * window would fall outside the display boundaries, the cropping rectangle
162 * will also be adjusted to maintain the rescaling ratios. If successful, crop
163 * and win are updated.
164 * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is
165 * impossible and cannot reasonably be adjusted.
167 int omap_vout_new_crop(struct v4l2_pix_format
*pix
,
168 struct v4l2_rect
*crop
, struct v4l2_window
*win
,
169 struct v4l2_framebuffer
*fbuf
, const struct v4l2_rect
*new_crop
)
171 struct v4l2_rect try_crop
;
172 unsigned long vresize
, hresize
;
174 /* make a working copy of the new_crop rectangle */
175 try_crop
= *new_crop
;
177 /* adjust the cropping rectangle so it fits in the image */
178 if (try_crop
.left
< 0) {
179 try_crop
.width
+= try_crop
.left
;
182 if (try_crop
.top
< 0) {
183 try_crop
.height
+= try_crop
.top
;
186 try_crop
.width
= (try_crop
.width
< pix
->width
) ?
187 try_crop
.width
: pix
->width
;
188 try_crop
.height
= (try_crop
.height
< pix
->height
) ?
189 try_crop
.height
: pix
->height
;
190 if (try_crop
.left
+ try_crop
.width
> pix
->width
)
191 try_crop
.width
= pix
->width
- try_crop
.left
;
192 if (try_crop
.top
+ try_crop
.height
> pix
->height
)
193 try_crop
.height
= pix
->height
- try_crop
.top
;
194 try_crop
.width
&= ~1;
195 try_crop
.height
&= ~1;
196 if (try_crop
.width
<= 0 || try_crop
.height
<= 0)
199 if (cpu_is_omap24xx()) {
200 if (crop
->height
!= win
->w
.height
) {
201 /* If we're resizing vertically, we can't support a
202 * crop width wider than 768 pixels.
204 if (try_crop
.width
> 768)
205 try_crop
.width
= 768;
208 /* vertical resizing */
209 vresize
= (1024 * crop
->height
) / win
->w
.height
;
210 if (cpu_is_omap24xx()) {
213 else if (vresize
== 0)
215 } else if (cpu_is_omap34xx()) {
218 else if (vresize
== 0)
221 win
->w
.height
= ((1024 * try_crop
.height
) / vresize
) & ~1;
222 if (win
->w
.height
== 0)
224 if (win
->w
.height
+ win
->w
.top
> fbuf
->fmt
.height
) {
225 /* We made the preview window extend below the bottom of the
226 * display, so clip it to the display boundary and resize the
227 * cropping height to maintain the vertical resizing ratio.
229 win
->w
.height
= (fbuf
->fmt
.height
- win
->w
.top
) & ~1;
230 if (try_crop
.height
== 0)
233 /* horizontal resizing */
234 hresize
= (1024 * crop
->width
) / win
->w
.width
;
235 if (cpu_is_omap24xx()) {
238 else if (hresize
== 0)
240 } else if (cpu_is_omap34xx()) {
243 else if (hresize
== 0)
246 win
->w
.width
= ((1024 * try_crop
.width
) / hresize
) & ~1;
247 if (win
->w
.width
== 0)
249 if (win
->w
.width
+ win
->w
.left
> fbuf
->fmt
.width
) {
250 /* We made the preview window extend past the right side of the
251 * display, so clip it to the display boundary and resize the
252 * cropping width to maintain the horizontal resizing ratio.
254 win
->w
.width
= (fbuf
->fmt
.width
- win
->w
.left
) & ~1;
255 if (try_crop
.width
== 0)
258 if (cpu_is_omap24xx()) {
260 * omap24xx supports 8x to 1/2x scaling.
262 if ((try_crop
.height
/win
->w
.height
) >= 2) {
263 /* The maximum vertical downsizing ratio is 2:1 */
264 try_crop
.height
= win
->w
.height
* 2;
266 if ((try_crop
.width
/win
->w
.width
) >= 2) {
267 /* The maximum horizontal downsizing ratio is 2:1 */
268 try_crop
.width
= win
->w
.width
* 2;
270 if (try_crop
.width
> 768) {
271 /* The OMAP2420 vertical resizing line buffer is
274 if (try_crop
.height
!= win
->w
.height
)
275 try_crop
.width
= 768;
277 } else if (cpu_is_omap34xx()) {
278 /* Check for resizing constraints
279 * 34xx allow 8x to 1/4x scaling.
281 if ((try_crop
.height
/win
->w
.height
) >= 4) {
282 /* The maximum vertical downsizing ratio is 4:1 */
283 try_crop
.height
= win
->w
.height
* 4;
285 if ((try_crop
.width
/win
->w
.width
) >= 4) {
286 /* The maximum horizontal downsizing ratio is 4:1 */
287 try_crop
.width
= win
->w
.width
* 4;
290 /* update our cropping rectangle and we're done */
294 EXPORT_SYMBOL_GPL(omap_vout_new_crop
);
296 /* Given a new format in pix and fbuf, crop and win
297 * structures are initialized to default values. crop
298 * is initialized to the largest window size that will fit on the display. The
299 * crop window is centered in the image. win is initialized to
300 * the same size as crop and is centered on the display.
301 * All sizes and offsets are constrained to be even numbers.
303 void omap_vout_new_format(struct v4l2_pix_format
*pix
,
304 struct v4l2_framebuffer
*fbuf
, struct v4l2_rect
*crop
,
305 struct v4l2_window
*win
)
307 /* crop defines the preview source window in the image capture
310 omap_vout_default_crop(pix
, fbuf
, crop
);
312 /* win defines the preview target window on the display */
313 win
->w
.width
= crop
->width
;
314 win
->w
.height
= crop
->height
;
315 win
->w
.left
= ((fbuf
->fmt
.width
- win
->w
.width
) >> 1) & ~1;
316 win
->w
.top
= ((fbuf
->fmt
.height
- win
->w
.height
) >> 1) & ~1;
318 EXPORT_SYMBOL_GPL(omap_vout_new_format
);