58f0ba49580f7916f0733ff82a9623c9870a052a
[pandora-kernel.git] / drivers / media / video / s5p-tv / mixer_grp_layer.c
1 /*
2  * Samsung TV Mixer driver
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
5  *
6  * Tomasz Stanislawski, <t.stanislaws@samsung.com>
7  *
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
12  */
13
14 #include "mixer.h"
15
16 #include <media/videobuf2-dma-contig.h>
17
18 /* FORMAT DEFINITIONS */
19
20 static const struct mxr_format mxr_fb_fmt_rgb565 = {
21         .name = "RGB565",
22         .fourcc = V4L2_PIX_FMT_RGB565,
23         .colorspace = V4L2_COLORSPACE_SRGB,
24         .num_planes = 1,
25         .plane = {
26                 { .width = 1, .height = 1, .size = 2 },
27         },
28         .num_subframes = 1,
29         .cookie = 4,
30 };
31
32 static const struct mxr_format mxr_fb_fmt_argb1555 = {
33         .name = "ARGB1555",
34         .num_planes = 1,
35         .fourcc = V4L2_PIX_FMT_RGB555,
36         .colorspace = V4L2_COLORSPACE_SRGB,
37         .plane = {
38                 { .width = 1, .height = 1, .size = 2 },
39         },
40         .num_subframes = 1,
41         .cookie = 5,
42 };
43
44 static const struct mxr_format mxr_fb_fmt_argb4444 = {
45         .name = "ARGB4444",
46         .num_planes = 1,
47         .fourcc = V4L2_PIX_FMT_RGB444,
48         .colorspace = V4L2_COLORSPACE_SRGB,
49         .plane = {
50                 { .width = 1, .height = 1, .size = 2 },
51         },
52         .num_subframes = 1,
53         .cookie = 6,
54 };
55
56 static const struct mxr_format mxr_fb_fmt_argb8888 = {
57         .name = "ARGB8888",
58         .fourcc = V4L2_PIX_FMT_BGR32,
59         .colorspace = V4L2_COLORSPACE_SRGB,
60         .num_planes = 1,
61         .plane = {
62                 { .width = 1, .height = 1, .size = 4 },
63         },
64         .num_subframes = 1,
65         .cookie = 7,
66 };
67
68 static const struct mxr_format *mxr_graph_format[] = {
69         &mxr_fb_fmt_rgb565,
70         &mxr_fb_fmt_argb1555,
71         &mxr_fb_fmt_argb4444,
72         &mxr_fb_fmt_argb8888,
73 };
74
75 /* AUXILIARY CALLBACKS */
76
77 static void mxr_graph_layer_release(struct mxr_layer *layer)
78 {
79         mxr_base_layer_unregister(layer);
80         mxr_base_layer_release(layer);
81 }
82
83 static void mxr_graph_buffer_set(struct mxr_layer *layer,
84         struct mxr_buffer *buf)
85 {
86         dma_addr_t addr = 0;
87
88         if (buf)
89                 addr = vb2_dma_contig_plane_paddr(&buf->vb, 0);
90         mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
91 }
92
93 static void mxr_graph_stream_set(struct mxr_layer *layer, int en)
94 {
95         mxr_reg_graph_layer_stream(layer->mdev, layer->idx, en);
96 }
97
98 static void mxr_graph_format_set(struct mxr_layer *layer)
99 {
100         mxr_reg_graph_format(layer->mdev, layer->idx,
101                 layer->fmt, &layer->geo);
102 }
103
104 static void mxr_graph_fix_geometry(struct mxr_layer *layer)
105 {
106         struct mxr_geometry *geo = &layer->geo;
107
108         /* limit to boundary size */
109         geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
110         geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
111         geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width);
112         geo->src.width = min(geo->src.width, 2047U);
113         /* not possible to crop of Y axis */
114         geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1);
115         geo->src.height = geo->src.full_height - geo->src.y_offset;
116         /* limitting offset */
117         geo->src.x_offset = min(geo->src.x_offset,
118                 geo->src.full_width - geo->src.width);
119
120         /* setting position in output */
121         geo->dst.width = min(geo->dst.width, geo->dst.full_width);
122         geo->dst.height = min(geo->dst.height, geo->dst.full_height);
123
124         /* Mixer supports only 1x and 2x scaling */
125         if (geo->dst.width >= 2 * geo->src.width) {
126                 geo->x_ratio = 1;
127                 geo->dst.width = 2 * geo->src.width;
128         } else {
129                 geo->x_ratio = 0;
130                 geo->dst.width = geo->src.width;
131         }
132
133         if (geo->dst.height >= 2 * geo->src.height) {
134                 geo->y_ratio = 1;
135                 geo->dst.height = 2 * geo->src.height;
136         } else {
137                 geo->y_ratio = 0;
138                 geo->dst.height = geo->src.height;
139         }
140
141         geo->dst.x_offset = min(geo->dst.x_offset,
142                 geo->dst.full_width - geo->dst.width);
143         geo->dst.y_offset = min(geo->dst.y_offset,
144                 geo->dst.full_height - geo->dst.height);
145 }
146
147 /* PUBLIC API */
148
149 struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx)
150 {
151         struct mxr_layer *layer;
152         int ret;
153         struct mxr_layer_ops ops = {
154                 .release = mxr_graph_layer_release,
155                 .buffer_set = mxr_graph_buffer_set,
156                 .stream_set = mxr_graph_stream_set,
157                 .format_set = mxr_graph_format_set,
158                 .fix_geometry = mxr_graph_fix_geometry,
159         };
160         char name[32];
161
162         sprintf(name, "graph%d", idx);
163
164         layer = mxr_base_layer_create(mdev, idx, name, &ops);
165         if (layer == NULL) {
166                 mxr_err(mdev, "failed to initialize layer(%d) base\n", idx);
167                 goto fail;
168         }
169
170         layer->fmt_array = mxr_graph_format;
171         layer->fmt_array_size = ARRAY_SIZE(mxr_graph_format);
172
173         ret = mxr_base_layer_register(layer);
174         if (ret)
175                 goto fail_layer;
176
177         return layer;
178
179 fail_layer:
180         mxr_base_layer_release(layer);
181
182 fail:
183         return NULL;
184 }
185