Linux 4.16.11
[linux/fpc-iii.git] / drivers / media / platform / vsp1 / vsp1_hgo.c
blob50309c053b787cf6bcc7c6bb15f1b4527c5ef604
1 /*
2 * vsp1_hgo.c -- R-Car VSP1 Histogram Generator 1D
4 * Copyright (C) 2016 Renesas Electronics Corporation
6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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 by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/device.h>
15 #include <linux/gfp.h>
17 #include <media/v4l2-subdev.h>
18 #include <media/videobuf2-vmalloc.h>
20 #include "vsp1.h"
21 #include "vsp1_dl.h"
22 #include "vsp1_hgo.h"
24 #define HGO_DATA_SIZE ((2 + 256) * 4)
26 /* -----------------------------------------------------------------------------
27 * Device Access
30 static inline u32 vsp1_hgo_read(struct vsp1_hgo *hgo, u32 reg)
32 return vsp1_read(hgo->histo.entity.vsp1, reg);
35 static inline void vsp1_hgo_write(struct vsp1_hgo *hgo, struct vsp1_dl_list *dl,
36 u32 reg, u32 data)
38 vsp1_dl_list_write(dl, reg, data);
41 /* -----------------------------------------------------------------------------
42 * Frame End Handler
45 void vsp1_hgo_frame_end(struct vsp1_entity *entity)
47 struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
48 struct vsp1_histogram_buffer *buf;
49 unsigned int i;
50 size_t size;
51 u32 *data;
53 buf = vsp1_histogram_buffer_get(&hgo->histo);
54 if (!buf)
55 return;
57 data = buf->addr;
59 if (hgo->num_bins == 256) {
60 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
61 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
63 for (i = 0; i < 256; ++i) {
64 vsp1_write(hgo->histo.entity.vsp1,
65 VI6_HGO_EXT_HIST_ADDR, i);
66 *data++ = vsp1_hgo_read(hgo, VI6_HGO_EXT_HIST_DATA);
69 size = (2 + 256) * sizeof(u32);
70 } else if (hgo->max_rgb) {
71 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
72 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
74 for (i = 0; i < 64; ++i)
75 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
77 size = (2 + 64) * sizeof(u32);
78 } else {
79 *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_MAXMIN);
80 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
81 *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_MAXMIN);
83 *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_SUM);
84 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
85 *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_SUM);
87 for (i = 0; i < 64; ++i) {
88 data[i] = vsp1_hgo_read(hgo, VI6_HGO_R_HISTO(i));
89 data[i+64] = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
90 data[i+128] = vsp1_hgo_read(hgo, VI6_HGO_B_HISTO(i));
93 size = (6 + 64 * 3) * sizeof(u32);
96 vsp1_histogram_buffer_complete(&hgo->histo, buf, size);
99 /* -----------------------------------------------------------------------------
100 * Controls
103 #define V4L2_CID_VSP1_HGO_MAX_RGB (V4L2_CID_USER_BASE | 0x1001)
104 #define V4L2_CID_VSP1_HGO_NUM_BINS (V4L2_CID_USER_BASE | 0x1002)
106 static const struct v4l2_ctrl_config hgo_max_rgb_control = {
107 .id = V4L2_CID_VSP1_HGO_MAX_RGB,
108 .name = "Maximum RGB Mode",
109 .type = V4L2_CTRL_TYPE_BOOLEAN,
110 .min = 0,
111 .max = 1,
112 .def = 0,
113 .step = 1,
114 .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
117 static const s64 hgo_num_bins[] = {
118 64, 256,
121 static const struct v4l2_ctrl_config hgo_num_bins_control = {
122 .id = V4L2_CID_VSP1_HGO_NUM_BINS,
123 .name = "Number of Bins",
124 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
125 .min = 0,
126 .max = 1,
127 .def = 0,
128 .qmenu_int = hgo_num_bins,
129 .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
132 /* -----------------------------------------------------------------------------
133 * VSP1 Entity Operations
136 static void hgo_configure(struct vsp1_entity *entity,
137 struct vsp1_pipeline *pipe,
138 struct vsp1_dl_list *dl,
139 enum vsp1_entity_params params)
141 struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
142 struct v4l2_rect *compose;
143 struct v4l2_rect *crop;
144 unsigned int hratio;
145 unsigned int vratio;
147 if (params != VSP1_ENTITY_PARAMS_INIT)
148 return;
150 crop = vsp1_entity_get_pad_selection(entity, entity->config,
151 HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
152 compose = vsp1_entity_get_pad_selection(entity, entity->config,
153 HISTO_PAD_SINK,
154 V4L2_SEL_TGT_COMPOSE);
156 vsp1_hgo_write(hgo, dl, VI6_HGO_REGRST, VI6_HGO_REGRST_RCLEA);
158 vsp1_hgo_write(hgo, dl, VI6_HGO_OFFSET,
159 (crop->left << VI6_HGO_OFFSET_HOFFSET_SHIFT) |
160 (crop->top << VI6_HGO_OFFSET_VOFFSET_SHIFT));
161 vsp1_hgo_write(hgo, dl, VI6_HGO_SIZE,
162 (crop->width << VI6_HGO_SIZE_HSIZE_SHIFT) |
163 (crop->height << VI6_HGO_SIZE_VSIZE_SHIFT));
165 mutex_lock(hgo->ctrls.handler.lock);
166 hgo->max_rgb = hgo->ctrls.max_rgb->cur.val;
167 if (hgo->ctrls.num_bins)
168 hgo->num_bins = hgo_num_bins[hgo->ctrls.num_bins->cur.val];
169 mutex_unlock(hgo->ctrls.handler.lock);
171 hratio = crop->width * 2 / compose->width / 3;
172 vratio = crop->height * 2 / compose->height / 3;
173 vsp1_hgo_write(hgo, dl, VI6_HGO_MODE,
174 (hgo->num_bins == 256 ? VI6_HGO_MODE_STEP : 0) |
175 (hgo->max_rgb ? VI6_HGO_MODE_MAXRGB : 0) |
176 (hratio << VI6_HGO_MODE_HRATIO_SHIFT) |
177 (vratio << VI6_HGO_MODE_VRATIO_SHIFT));
180 static const struct vsp1_entity_operations hgo_entity_ops = {
181 .configure = hgo_configure,
182 .destroy = vsp1_histogram_destroy,
185 /* -----------------------------------------------------------------------------
186 * Initialization and Cleanup
189 static const unsigned int hgo_mbus_formats[] = {
190 MEDIA_BUS_FMT_AYUV8_1X32,
191 MEDIA_BUS_FMT_ARGB8888_1X32,
192 MEDIA_BUS_FMT_AHSV8888_1X32,
195 struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1)
197 struct vsp1_hgo *hgo;
198 int ret;
200 hgo = devm_kzalloc(vsp1->dev, sizeof(*hgo), GFP_KERNEL);
201 if (hgo == NULL)
202 return ERR_PTR(-ENOMEM);
204 /* Initialize the control handler. */
205 v4l2_ctrl_handler_init(&hgo->ctrls.handler,
206 vsp1->info->gen == 3 ? 2 : 1);
207 hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler,
208 &hgo_max_rgb_control, NULL);
209 if (vsp1->info->gen == 3)
210 hgo->ctrls.num_bins =
211 v4l2_ctrl_new_custom(&hgo->ctrls.handler,
212 &hgo_num_bins_control, NULL);
214 hgo->max_rgb = false;
215 hgo->num_bins = 64;
217 hgo->histo.entity.subdev.ctrl_handler = &hgo->ctrls.handler;
219 /* Initialize the video device and queue for statistics data. */
220 ret = vsp1_histogram_init(vsp1, &hgo->histo, VSP1_ENTITY_HGO, "hgo",
221 &hgo_entity_ops, hgo_mbus_formats,
222 ARRAY_SIZE(hgo_mbus_formats),
223 HGO_DATA_SIZE, V4L2_META_FMT_VSP1_HGO);
224 if (ret < 0) {
225 vsp1_entity_destroy(&hgo->histo.entity);
226 return ERR_PTR(ret);
229 return hgo;