2 * Samsung TV Mixer driver
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
6 * Tomasz Stanislawski, <t.stanislaws@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundiation. either version 2 of the License,
11 * or (at your option) any later version
16 #include <media/videobuf2-dma-contig.h>
18 /* FORMAT DEFINITIONS */
20 static const struct mxr_format mxr_fb_fmt_rgb565
= {
22 .fourcc
= V4L2_PIX_FMT_RGB565
,
23 .colorspace
= V4L2_COLORSPACE_SRGB
,
26 { .width
= 1, .height
= 1, .size
= 2 },
32 static const struct mxr_format mxr_fb_fmt_argb1555
= {
35 .fourcc
= V4L2_PIX_FMT_RGB555
,
36 .colorspace
= V4L2_COLORSPACE_SRGB
,
38 { .width
= 1, .height
= 1, .size
= 2 },
44 static const struct mxr_format mxr_fb_fmt_argb4444
= {
47 .fourcc
= V4L2_PIX_FMT_RGB444
,
48 .colorspace
= V4L2_COLORSPACE_SRGB
,
50 { .width
= 1, .height
= 1, .size
= 2 },
56 static const struct mxr_format mxr_fb_fmt_argb8888
= {
58 .fourcc
= V4L2_PIX_FMT_BGR32
,
59 .colorspace
= V4L2_COLORSPACE_SRGB
,
62 { .width
= 1, .height
= 1, .size
= 4 },
68 static const struct mxr_format
*mxr_graph_format
[] = {
75 /* AUXILIARY CALLBACKS */
77 static void mxr_graph_layer_release(struct mxr_layer
*layer
)
79 mxr_base_layer_unregister(layer
);
80 mxr_base_layer_release(layer
);
83 static void mxr_graph_buffer_set(struct mxr_layer
*layer
,
84 struct mxr_buffer
*buf
)
89 addr
= vb2_dma_contig_plane_dma_addr(&buf
->vb
, 0);
90 mxr_reg_graph_buffer(layer
->mdev
, layer
->idx
, addr
);
93 static void mxr_graph_stream_set(struct mxr_layer
*layer
, int en
)
95 mxr_reg_graph_layer_stream(layer
->mdev
, layer
->idx
, en
);
98 static void mxr_graph_format_set(struct mxr_layer
*layer
)
100 mxr_reg_graph_format(layer
->mdev
, layer
->idx
,
101 layer
->fmt
, &layer
->geo
);
104 static inline unsigned int closest(unsigned int x
, unsigned int a
,
105 unsigned int b
, unsigned long flags
)
107 unsigned int mid
= (a
+ b
) / 2;
109 /* choosing closest value with constraints according to table:
110 * -------------+-----+-----+-----+-------+
111 * flags | 0 | LE | GE | LE|GE |
112 * -------------+-----+-----+-----+-------+
113 * x <= a | a | a | a | a |
114 * a < x <= mid | a | a | b | a |
115 * mid < x < b | b | a | b | b |
116 * b <= x | b | b | b | b |
117 * -------------+-----+-----+-----+-------+
120 /* remove all non-constraint flags */
121 flags
&= V4L2_SEL_FLAG_LE
| V4L2_SEL_FLAG_GE
;
127 if (flags
== V4L2_SEL_FLAG_LE
)
129 if (flags
== V4L2_SEL_FLAG_GE
)
136 static inline unsigned int do_center(unsigned int center
,
137 unsigned int size
, unsigned int upper
, unsigned int flags
)
141 if (flags
& MXR_NO_OFFSET
)
144 lower
= center
- min(center
, size
/ 2);
145 return min(lower
, upper
- size
);
148 static void mxr_graph_fix_geometry(struct mxr_layer
*layer
,
149 enum mxr_geometry_stage stage
, unsigned long flags
)
151 struct mxr_geometry
*geo
= &layer
->geo
;
152 struct mxr_crop
*src
= &geo
->src
;
153 struct mxr_crop
*dst
= &geo
->dst
;
154 unsigned int x_center
, y_center
;
158 case MXR_GEOMETRY_SINK
: /* nothing to be fixed here */
162 case MXR_GEOMETRY_COMPOSE
:
163 /* remember center of the area */
164 x_center
= dst
->x_offset
+ dst
->width
/ 2;
165 y_center
= dst
->y_offset
+ dst
->height
/ 2;
166 /* round up/down to 2 multiple depending on flags */
167 if (flags
& V4L2_SEL_FLAG_LE
) {
168 dst
->width
= round_down(dst
->width
, 2);
169 dst
->height
= round_down(dst
->height
, 2);
171 dst
->width
= round_up(dst
->width
, 2);
172 dst
->height
= round_up(dst
->height
, 2);
174 /* assure that compose rect is inside display area */
175 dst
->width
= min(dst
->width
, dst
->full_width
);
176 dst
->height
= min(dst
->height
, dst
->full_height
);
178 /* ensure that compose is reachable using 2x scaling */
179 dst
->width
= min(dst
->width
, 2 * src
->full_width
);
180 dst
->height
= min(dst
->height
, 2 * src
->full_height
);
183 dst
->x_offset
= do_center(x_center
, dst
->width
,
184 dst
->full_width
, flags
);
185 dst
->y_offset
= do_center(y_center
, dst
->height
,
186 dst
->full_height
, flags
);
190 case MXR_GEOMETRY_CROP
:
191 /* remember center of the area */
192 x_center
= src
->x_offset
+ src
->width
/ 2;
193 y_center
= src
->y_offset
+ src
->height
/ 2;
194 /* ensure that cropping area lies inside the buffer */
195 if (src
->full_width
< dst
->width
)
196 src
->width
= dst
->width
/ 2;
198 src
->width
= closest(src
->width
, dst
->width
/ 2,
201 if (src
->width
== dst
->width
)
206 if (src
->full_height
< dst
->height
)
207 src
->height
= dst
->height
/ 2;
209 src
->height
= closest(src
->height
, dst
->height
/ 2,
212 if (src
->height
== dst
->height
)
218 src
->x_offset
= do_center(x_center
, src
->width
,
219 src
->full_width
, flags
);
220 src
->y_offset
= do_center(y_center
, src
->height
,
221 src
->full_height
, flags
);
224 case MXR_GEOMETRY_SOURCE
:
225 src
->full_width
= clamp_val(src
->full_width
,
226 src
->width
+ src
->x_offset
, 32767);
227 src
->full_height
= clamp_val(src
->full_height
,
228 src
->height
+ src
->y_offset
, 2047);
234 struct mxr_layer
*mxr_graph_layer_create(struct mxr_device
*mdev
, int idx
)
236 struct mxr_layer
*layer
;
238 struct mxr_layer_ops ops
= {
239 .release
= mxr_graph_layer_release
,
240 .buffer_set
= mxr_graph_buffer_set
,
241 .stream_set
= mxr_graph_stream_set
,
242 .format_set
= mxr_graph_format_set
,
243 .fix_geometry
= mxr_graph_fix_geometry
,
247 sprintf(name
, "graph%d", idx
);
249 layer
= mxr_base_layer_create(mdev
, idx
, name
, &ops
);
251 mxr_err(mdev
, "failed to initialize layer(%d) base\n", idx
);
255 layer
->fmt_array
= mxr_graph_format
;
256 layer
->fmt_array_size
= ARRAY_SIZE(mxr_graph_format
);
258 ret
= mxr_base_layer_register(layer
);
265 mxr_base_layer_release(layer
);