Full support for Ginger Console
[linux-ginger.git] / drivers / media / video / ti-media / omap_voutlib.c
blobff4f7f7e1c196ff3f82e8871617372f656d0396a
1 /*
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>
26 #include <plat/cpu.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;
45 crop->width &= ~1;
46 crop->height &= ~1;
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 */
64 try_win = new_win->w;
66 /* adjust the preview window so it fits on the display by clipping any
67 * offscreen areas
69 if (try_win.left < 0) {
70 try_win.width += try_win.left;
71 try_win.left = 0;
73 if (try_win.top < 0) {
74 try_win.height += try_win.top;
75 try_win.top = 0;
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;
85 try_win.width &= ~1;
86 try_win.height &= ~1;
88 if (try_win.width <= 0 || try_win.height <= 0)
89 return -EINVAL;
91 /* We now have a valid preview window, so go with it */
92 new_win->w = try_win;
93 new_win->field = V4L2_FIELD_ANY;
94 return 0;
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)
110 int err;
112 err = omap_vout_try_window(fbuf, new_win);
113 if (err)
114 return err;
116 /* update our preview window */
117 win->w = new_win->w;
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
135 * pixels wide.
137 if (crop->height != win->w.height)
138 crop->width = 768;
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;
153 return 0;
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;
180 try_crop.left = 0;
182 if (try_crop.top < 0) {
183 try_crop.height += try_crop.top;
184 try_crop.top = 0;
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)
197 return -EINVAL;
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()) {
211 if (vresize > 2048)
212 vresize = 2048;
213 else if (vresize == 0)
214 vresize = 1;
215 } else if (cpu_is_omap34xx()) {
216 if (vresize > 4096)
217 vresize = 4096;
218 else if (vresize == 0)
219 vresize = 1;
221 win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
222 if (win->w.height == 0)
223 win->w.height = 2;
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)
231 try_crop.height = 2;
233 /* horizontal resizing */
234 hresize = (1024 * crop->width) / win->w.width;
235 if (cpu_is_omap24xx()) {
236 if (hresize > 2048)
237 hresize = 2048;
238 else if (hresize == 0)
239 hresize = 1;
240 } else if (cpu_is_omap34xx()) {
241 if (hresize > 4096)
242 hresize = 4096;
243 else if (hresize == 0)
244 hresize = 1;
246 win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
247 if (win->w.width == 0)
248 win->w.width = 2;
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)
256 try_crop.width = 2;
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
272 * 768 pixels wide.
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 */
291 *crop = try_crop;
292 return 0;
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
308 * buffer
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);