v4l: exynos/tv: Add TV/HDMI/Mixer driver
[cascardo/linux.git] / drivers / media / video / exynos / 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 #if defined(CONFIG_VIDEOBUF2_CMA_PHYS)
17 #include <media/videobuf2-cma-phys.h>
18 #elif defined(CONFIG_VIDEOBUF2_ION)
19 #include <media/videobuf2-ion.h>
20 #endif
21
22 /* FORMAT DEFINITIONS */
23
24 static const struct mxr_format mxr_fb_fmt_rgb565 = {
25         .name = "RGB565",
26         .fourcc = V4L2_PIX_FMT_RGB565,
27         .colorspace = V4L2_COLORSPACE_SRGB,
28         .num_planes = 1,
29         .plane = {
30                 { .width = 1, .height = 1, .size = 2 },
31         },
32         .num_subframes = 1,
33         .cookie = 4,
34 };
35
36 static const struct mxr_format mxr_fb_fmt_argb1555 = {
37         .name = "ARGB1555",
38         .num_planes = 1,
39         .fourcc = V4L2_PIX_FMT_RGB555,
40         .colorspace = V4L2_COLORSPACE_SRGB,
41         .plane = {
42                 { .width = 1, .height = 1, .size = 2 },
43         },
44         .num_subframes = 1,
45         .cookie = 5,
46 };
47
48 static const struct mxr_format mxr_fb_fmt_argb4444 = {
49         .name = "ARGB4444",
50         .num_planes = 1,
51         .fourcc = V4L2_PIX_FMT_RGB444,
52         .colorspace = V4L2_COLORSPACE_SRGB,
53         .plane = {
54                 { .width = 1, .height = 1, .size = 2 },
55         },
56         .num_subframes = 1,
57         .cookie = 6,
58 };
59
60 static const struct mxr_format mxr_fb_fmt_argb8888 = {
61         .name = "ARGB8888",
62         .fourcc = V4L2_PIX_FMT_BGR32,
63         .colorspace = V4L2_COLORSPACE_SRGB,
64         .num_planes = 1,
65         .plane = {
66                 { .width = 1, .height = 1, .size = 4 },
67         },
68         .num_subframes = 1,
69         .cookie = 7,
70 };
71
72 static const struct mxr_format *mxr_graph_format[] = {
73         &mxr_fb_fmt_rgb565,
74         &mxr_fb_fmt_argb1555,
75         &mxr_fb_fmt_argb4444,
76         &mxr_fb_fmt_argb8888,
77 };
78
79 /* AUXILIARY CALLBACKS */
80
81 static void mxr_graph_layer_release(struct mxr_layer *layer)
82 {
83         mxr_base_layer_unregister(layer);
84         mxr_base_layer_release(layer);
85 }
86
87 static void mxr_graph_buffer_set(struct mxr_layer *layer,
88         struct mxr_buffer *buf)
89 {
90         struct mxr_device *mdev = layer->mdev;
91         dma_addr_t addr = 0;
92
93         if (buf)
94                 addr = mdev->vb2->plane_addr(&buf->vb, 0);
95         mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
96 }
97
98 static void mxr_graph_stream_set(struct mxr_layer *layer, int en)
99 {
100         mxr_reg_graph_layer_stream(layer->mdev, layer->idx, en);
101 }
102
103 static void mxr_graph_format_set(struct mxr_layer *layer)
104 {
105         mxr_reg_graph_format(layer->mdev, layer->idx,
106                         layer->fmt, &layer->geo);
107 }
108
109 static void mxr_graph_fix_geometry(struct mxr_layer *layer)
110 {
111         struct mxr_geometry *geo = &layer->geo;
112
113         mxr_dbg(layer->mdev, "%s start\n", __func__);
114         /* limit to boundary size */
115         geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
116         geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
117
118         /* limit to coordinate of source x, y */
119         geo->src.x_offset = clamp_val(geo->src.x_offset, 0,
120                         geo->src.full_width - 1);
121         geo->src.y_offset = clamp_val(geo->src.y_offset, 0,
122                         geo->src.full_height - 1);
123
124         /* limit to boundary size of crop width, height */
125         geo->src.width = clamp_val(geo->src.width, 1,
126                         geo->src.full_width - geo->src.x_offset);
127         geo->src.height = clamp_val(geo->src.height, 1,
128                         geo->src.full_height - geo->src.y_offset);
129
130         /* dst full resolution and TV display size are same */
131
132         geo->dst.x_offset = clamp_val(geo->dst.x_offset, 0,
133                         geo->dst.full_width - 1);
134         geo->dst.y_offset = clamp_val(geo->dst.y_offset, 0,
135                         geo->dst.full_height - 1);
136
137         /* mixer scale-up is unuseful. so no use it */
138         geo->dst.width = clamp_val(geo->src.width, 1,
139                         geo->dst.full_width - geo->dst.x_offset);
140         geo->dst.height = clamp_val(geo->src.height, 1,
141                         geo->dst.full_height - geo->dst.y_offset);
142 }
143
144 /* PUBLIC API */
145
146 struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int cur_mxr,
147                 int idx, int nr)
148 {
149         struct mxr_layer *layer;
150         int ret;
151         struct mxr_layer_ops ops = {
152                 .release = mxr_graph_layer_release,
153                 .buffer_set = mxr_graph_buffer_set,
154                 .stream_set = mxr_graph_stream_set,
155                 .format_set = mxr_graph_format_set,
156                 .fix_geometry = mxr_graph_fix_geometry,
157         };
158         char name[32];
159
160         sprintf(name, "mxr%d_graph%d", cur_mxr, idx);
161
162         layer = mxr_base_layer_create(mdev, idx, name, &ops);
163         if (layer == NULL) {
164                 mxr_err(mdev, "failed to initialize layer(%d) base\n", idx);
165                 goto fail;
166         }
167
168         layer->fmt_array = mxr_graph_format;
169         layer->fmt_array_size = ARRAY_SIZE(mxr_graph_format);
170         layer->minor = nr;
171         layer->type = MXR_LAYER_TYPE_GRP;
172
173         ret = mxr_base_layer_register(layer);
174         if (ret)
175                 goto fail_layer;
176
177         layer->cur_mxr = cur_mxr;
178         return layer;
179
180 fail_layer:
181         mxr_base_layer_release(layer);
182
183 fail:
184         return NULL;
185 }