4 * Copyright (C) 2005-2010 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) 2010 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>
29 MODULE_AUTHOR("Texas Instruments");
30 MODULE_DESCRIPTION("OMAP Video library");
31 MODULE_LICENSE("GPL");
33 /* Return the default overlay cropping rectangle in crop given the image
34 * size in pix and the video display size in fbuf. The default
35 * cropping rectangle is the largest rectangle no larger than the capture size
36 * that will fit on the display. The default cropping rectangle is centered in
37 * the image. All dimensions and offsets are rounded down to even numbers.
39 void omap_vout_default_crop(struct v4l2_pix_format
*pix
,
40 struct v4l2_framebuffer
*fbuf
, struct v4l2_rect
*crop
)
42 crop
->width
= (pix
->width
< fbuf
->fmt
.width
) ?
43 pix
->width
: fbuf
->fmt
.width
;
44 crop
->height
= (pix
->height
< fbuf
->fmt
.height
) ?
45 pix
->height
: fbuf
->fmt
.height
;
48 crop
->left
= ((pix
->width
- crop
->width
) >> 1) & ~1;
49 crop
->top
= ((pix
->height
- crop
->height
) >> 1) & ~1;
51 EXPORT_SYMBOL_GPL(omap_vout_default_crop
);
53 /* Given a new render window in new_win, adjust the window to the
54 * nearest supported configuration. The adjusted window parameters are
55 * returned in new_win.
56 * Returns zero if successful, or -EINVAL if the requested window is
57 * impossible and cannot reasonably be adjusted.
59 int omap_vout_try_window(struct v4l2_framebuffer
*fbuf
,
60 struct v4l2_window
*new_win
)
62 struct v4l2_rect try_win
;
64 /* make a working copy of the new_win rectangle */
67 /* adjust the preview window so it fits on the display by clipping any
70 if (try_win
.left
< 0) {
71 try_win
.width
+= try_win
.left
;
74 if (try_win
.top
< 0) {
75 try_win
.height
+= try_win
.top
;
78 try_win
.width
= (try_win
.width
< fbuf
->fmt
.width
) ?
79 try_win
.width
: fbuf
->fmt
.width
;
80 try_win
.height
= (try_win
.height
< fbuf
->fmt
.height
) ?
81 try_win
.height
: fbuf
->fmt
.height
;
82 if (try_win
.left
+ try_win
.width
> fbuf
->fmt
.width
)
83 try_win
.width
= fbuf
->fmt
.width
- try_win
.left
;
84 if (try_win
.top
+ try_win
.height
> fbuf
->fmt
.height
)
85 try_win
.height
= fbuf
->fmt
.height
- try_win
.top
;
89 if (try_win
.width
<= 0 || try_win
.height
<= 0)
92 /* We now have a valid preview window, so go with it */
94 new_win
->field
= V4L2_FIELD_ANY
;
97 EXPORT_SYMBOL_GPL(omap_vout_try_window
);
99 /* Given a new render window in new_win, adjust the window to the
100 * nearest supported configuration. The image cropping window in crop
101 * will also be adjusted if necessary. Preference is given to keeping the
102 * the window as close to the requested configuration as possible. If
103 * successful, new_win, vout->win, and crop are updated.
104 * Returns zero if successful, or -EINVAL if the requested preview window is
105 * impossible and cannot reasonably be adjusted.
107 int omap_vout_new_window(struct v4l2_rect
*crop
,
108 struct v4l2_window
*win
, struct v4l2_framebuffer
*fbuf
,
109 struct v4l2_window
*new_win
)
113 err
= omap_vout_try_window(fbuf
, new_win
);
117 /* update our preview window */
119 win
->field
= new_win
->field
;
120 win
->chromakey
= new_win
->chromakey
;
122 /* Adjust the cropping window to allow for resizing limitation */
123 if (cpu_is_omap24xx()) {
124 /* For 24xx limit is 8x to 1/2x scaling. */
125 if ((crop
->height
/win
->w
.height
) >= 2)
126 crop
->height
= win
->w
.height
* 2;
128 if ((crop
->width
/win
->w
.width
) >= 2)
129 crop
->width
= win
->w
.width
* 2;
131 if (crop
->width
> 768) {
132 /* The OMAP2420 vertical resizing line buffer is 768
133 * pixels wide. If the cropped image is wider than
134 * 768 pixels then it cannot be vertically resized.
136 if (crop
->height
!= win
->w
.height
)
139 } else if (cpu_is_omap34xx()) {
140 /* For 34xx limit is 8x to 1/4x scaling. */
141 if ((crop
->height
/win
->w
.height
) >= 4)
142 crop
->height
= win
->w
.height
* 4;
144 if ((crop
->width
/win
->w
.width
) >= 4)
145 crop
->width
= win
->w
.width
* 4;
149 EXPORT_SYMBOL_GPL(omap_vout_new_window
);
151 /* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
152 * the nearest supported configuration. The image render window in win will
153 * also be adjusted if necessary. The preview window is adjusted such that the
154 * horizontal and vertical rescaling ratios stay constant. If the render
155 * window would fall outside the display boundaries, the cropping rectangle
156 * will also be adjusted to maintain the rescaling ratios. If successful, crop
157 * and win are updated.
158 * Returns zero if successful, or -EINVAL if the requested cropping rectangle is
159 * impossible and cannot reasonably be adjusted.
161 int omap_vout_new_crop(struct v4l2_pix_format
*pix
,
162 struct v4l2_rect
*crop
, struct v4l2_window
*win
,
163 struct v4l2_framebuffer
*fbuf
, const struct v4l2_rect
*new_crop
)
165 struct v4l2_rect try_crop
;
166 unsigned long vresize
, hresize
;
168 /* make a working copy of the new_crop rectangle */
169 try_crop
= *new_crop
;
171 /* adjust the cropping rectangle so it fits in the image */
172 if (try_crop
.left
< 0) {
173 try_crop
.width
+= try_crop
.left
;
176 if (try_crop
.top
< 0) {
177 try_crop
.height
+= try_crop
.top
;
180 try_crop
.width
= (try_crop
.width
< pix
->width
) ?
181 try_crop
.width
: pix
->width
;
182 try_crop
.height
= (try_crop
.height
< pix
->height
) ?
183 try_crop
.height
: pix
->height
;
184 if (try_crop
.left
+ try_crop
.width
> pix
->width
)
185 try_crop
.width
= pix
->width
- try_crop
.left
;
186 if (try_crop
.top
+ try_crop
.height
> pix
->height
)
187 try_crop
.height
= pix
->height
- try_crop
.top
;
189 try_crop
.width
&= ~1;
190 try_crop
.height
&= ~1;
192 if (try_crop
.width
<= 0 || try_crop
.height
<= 0)
195 if (cpu_is_omap24xx()) {
196 if (crop
->height
!= win
->w
.height
) {
197 /* If we're resizing vertically, we can't support a
198 * crop width wider than 768 pixels.
200 if (try_crop
.width
> 768)
201 try_crop
.width
= 768;
204 /* vertical resizing */
205 vresize
= (1024 * crop
->height
) / win
->w
.height
;
206 if (cpu_is_omap24xx() && (vresize
> 2048))
208 else if (cpu_is_omap34xx() && (vresize
> 4096))
211 win
->w
.height
= ((1024 * try_crop
.height
) / vresize
) & ~1;
212 if (win
->w
.height
== 0)
214 if (win
->w
.height
+ win
->w
.top
> fbuf
->fmt
.height
) {
215 /* We made the preview window extend below the bottom of the
216 * display, so clip it to the display boundary and resize the
217 * cropping height to maintain the vertical resizing ratio.
219 win
->w
.height
= (fbuf
->fmt
.height
- win
->w
.top
) & ~1;
220 if (try_crop
.height
== 0)
223 /* horizontal resizing */
224 hresize
= (1024 * crop
->width
) / win
->w
.width
;
225 if (cpu_is_omap24xx() && (hresize
> 2048))
227 else if (cpu_is_omap34xx() && (hresize
> 4096))
230 win
->w
.width
= ((1024 * try_crop
.width
) / hresize
) & ~1;
231 if (win
->w
.width
== 0)
233 if (win
->w
.width
+ win
->w
.left
> fbuf
->fmt
.width
) {
234 /* We made the preview window extend past the right side of the
235 * display, so clip it to the display boundary and resize the
236 * cropping width to maintain the horizontal resizing ratio.
238 win
->w
.width
= (fbuf
->fmt
.width
- win
->w
.left
) & ~1;
239 if (try_crop
.width
== 0)
242 if (cpu_is_omap24xx()) {
243 if ((try_crop
.height
/win
->w
.height
) >= 2)
244 try_crop
.height
= win
->w
.height
* 2;
246 if ((try_crop
.width
/win
->w
.width
) >= 2)
247 try_crop
.width
= win
->w
.width
* 2;
249 if (try_crop
.width
> 768) {
250 /* The OMAP2420 vertical resizing line buffer is
251 * 768 pixels wide. If the cropped image is wider
252 * than 768 pixels then it cannot be vertically resized.
254 if (try_crop
.height
!= win
->w
.height
)
255 try_crop
.width
= 768;
257 } else if (cpu_is_omap34xx()) {
258 if ((try_crop
.height
/win
->w
.height
) >= 4)
259 try_crop
.height
= win
->w
.height
* 4;
261 if ((try_crop
.width
/win
->w
.width
) >= 4)
262 try_crop
.width
= win
->w
.width
* 4;
264 /* update our cropping rectangle and we're done */
268 EXPORT_SYMBOL_GPL(omap_vout_new_crop
);
270 /* Given a new format in pix and fbuf, crop and win
271 * structures are initialized to default values. crop
272 * is initialized to the largest window size that will fit on the display. The
273 * crop window is centered in the image. win is initialized to
274 * the same size as crop and is centered on the display.
275 * All sizes and offsets are constrained to be even numbers.
277 void omap_vout_new_format(struct v4l2_pix_format
*pix
,
278 struct v4l2_framebuffer
*fbuf
, struct v4l2_rect
*crop
,
279 struct v4l2_window
*win
)
281 /* crop defines the preview source window in the image capture
284 omap_vout_default_crop(pix
, fbuf
, crop
);
286 /* win defines the preview target window on the display */
287 win
->w
.width
= crop
->width
;
288 win
->w
.height
= crop
->height
;
289 win
->w
.left
= ((fbuf
->fmt
.width
- win
->w
.width
) >> 1) & ~1;
290 win
->w
.top
= ((fbuf
->fmt
.height
- win
->w
.height
) >> 1) & ~1;
292 EXPORT_SYMBOL_GPL(omap_vout_new_format
);