root/drivers/media/platform/vsp1/vsp1_hgo.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vsp1_hgo_read
  2. vsp1_hgo_write
  3. vsp1_hgo_frame_end
  4. hgo_configure_stream
  5. vsp1_hgo_create

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * vsp1_hgo.c  --  R-Car VSP1 Histogram Generator 1D
   4  *
   5  * Copyright (C) 2016 Renesas Electronics Corporation
   6  *
   7  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   8  */
   9 
  10 #include <linux/device.h>
  11 #include <linux/gfp.h>
  12 
  13 #include <media/v4l2-subdev.h>
  14 #include <media/videobuf2-vmalloc.h>
  15 
  16 #include "vsp1.h"
  17 #include "vsp1_dl.h"
  18 #include "vsp1_hgo.h"
  19 
  20 #define HGO_DATA_SIZE                           ((2 + 256) * 4)
  21 
  22 /* -----------------------------------------------------------------------------
  23  * Device Access
  24  */
  25 
  26 static inline u32 vsp1_hgo_read(struct vsp1_hgo *hgo, u32 reg)
  27 {
  28         return vsp1_read(hgo->histo.entity.vsp1, reg);
  29 }
  30 
  31 static inline void vsp1_hgo_write(struct vsp1_hgo *hgo,
  32                                   struct vsp1_dl_body *dlb, u32 reg, u32 data)
  33 {
  34         vsp1_dl_body_write(dlb, reg, data);
  35 }
  36 
  37 /* -----------------------------------------------------------------------------
  38  * Frame End Handler
  39  */
  40 
  41 void vsp1_hgo_frame_end(struct vsp1_entity *entity)
  42 {
  43         struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
  44         struct vsp1_histogram_buffer *buf;
  45         unsigned int i;
  46         size_t size;
  47         u32 *data;
  48 
  49         buf = vsp1_histogram_buffer_get(&hgo->histo);
  50         if (!buf)
  51                 return;
  52 
  53         data = buf->addr;
  54 
  55         if (hgo->num_bins == 256) {
  56                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  57                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  58 
  59                 for (i = 0; i < 256; ++i) {
  60                         vsp1_write(hgo->histo.entity.vsp1,
  61                                    VI6_HGO_EXT_HIST_ADDR, i);
  62                         *data++ = vsp1_hgo_read(hgo, VI6_HGO_EXT_HIST_DATA);
  63                 }
  64 
  65                 size = (2 + 256) * sizeof(u32);
  66         } else if (hgo->max_rgb) {
  67                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  68                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  69 
  70                 for (i = 0; i < 64; ++i)
  71                         *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
  72 
  73                 size = (2 + 64) * sizeof(u32);
  74         } else {
  75                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_MAXMIN);
  76                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  77                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_MAXMIN);
  78 
  79                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_SUM);
  80                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  81                 *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_SUM);
  82 
  83                 for (i = 0; i < 64; ++i) {
  84                         data[i] = vsp1_hgo_read(hgo, VI6_HGO_R_HISTO(i));
  85                         data[i+64] = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
  86                         data[i+128] = vsp1_hgo_read(hgo, VI6_HGO_B_HISTO(i));
  87                 }
  88 
  89                 size = (6 + 64 * 3) * sizeof(u32);
  90         }
  91 
  92         vsp1_histogram_buffer_complete(&hgo->histo, buf, size);
  93 }
  94 
  95 /* -----------------------------------------------------------------------------
  96  * Controls
  97  */
  98 
  99 #define V4L2_CID_VSP1_HGO_MAX_RGB               (V4L2_CID_USER_BASE | 0x1001)
 100 #define V4L2_CID_VSP1_HGO_NUM_BINS              (V4L2_CID_USER_BASE | 0x1002)
 101 
 102 static const struct v4l2_ctrl_config hgo_max_rgb_control = {
 103         .id = V4L2_CID_VSP1_HGO_MAX_RGB,
 104         .name = "Maximum RGB Mode",
 105         .type = V4L2_CTRL_TYPE_BOOLEAN,
 106         .min = 0,
 107         .max = 1,
 108         .def = 0,
 109         .step = 1,
 110         .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
 111 };
 112 
 113 static const s64 hgo_num_bins[] = {
 114         64, 256,
 115 };
 116 
 117 static const struct v4l2_ctrl_config hgo_num_bins_control = {
 118         .id = V4L2_CID_VSP1_HGO_NUM_BINS,
 119         .name = "Number of Bins",
 120         .type = V4L2_CTRL_TYPE_INTEGER_MENU,
 121         .min = 0,
 122         .max = 1,
 123         .def = 0,
 124         .qmenu_int = hgo_num_bins,
 125         .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
 126 };
 127 
 128 /* -----------------------------------------------------------------------------
 129  * VSP1 Entity Operations
 130  */
 131 
 132 static void hgo_configure_stream(struct vsp1_entity *entity,
 133                                  struct vsp1_pipeline *pipe,
 134                                  struct vsp1_dl_list *dl,
 135                                  struct vsp1_dl_body *dlb)
 136 {
 137         struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
 138         struct v4l2_rect *compose;
 139         struct v4l2_rect *crop;
 140         unsigned int hratio;
 141         unsigned int vratio;
 142 
 143         crop = vsp1_entity_get_pad_selection(entity, entity->config,
 144                                              HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
 145         compose = vsp1_entity_get_pad_selection(entity, entity->config,
 146                                                 HISTO_PAD_SINK,
 147                                                 V4L2_SEL_TGT_COMPOSE);
 148 
 149         vsp1_hgo_write(hgo, dlb, VI6_HGO_REGRST, VI6_HGO_REGRST_RCLEA);
 150 
 151         vsp1_hgo_write(hgo, dlb, VI6_HGO_OFFSET,
 152                        (crop->left << VI6_HGO_OFFSET_HOFFSET_SHIFT) |
 153                        (crop->top << VI6_HGO_OFFSET_VOFFSET_SHIFT));
 154         vsp1_hgo_write(hgo, dlb, VI6_HGO_SIZE,
 155                        (crop->width << VI6_HGO_SIZE_HSIZE_SHIFT) |
 156                        (crop->height << VI6_HGO_SIZE_VSIZE_SHIFT));
 157 
 158         mutex_lock(hgo->ctrls.handler.lock);
 159         hgo->max_rgb = hgo->ctrls.max_rgb->cur.val;
 160         if (hgo->ctrls.num_bins)
 161                 hgo->num_bins = hgo_num_bins[hgo->ctrls.num_bins->cur.val];
 162         mutex_unlock(hgo->ctrls.handler.lock);
 163 
 164         hratio = crop->width * 2 / compose->width / 3;
 165         vratio = crop->height * 2 / compose->height / 3;
 166         vsp1_hgo_write(hgo, dlb, VI6_HGO_MODE,
 167                        (hgo->num_bins == 256 ? VI6_HGO_MODE_STEP : 0) |
 168                        (hgo->max_rgb ? VI6_HGO_MODE_MAXRGB : 0) |
 169                        (hratio << VI6_HGO_MODE_HRATIO_SHIFT) |
 170                        (vratio << VI6_HGO_MODE_VRATIO_SHIFT));
 171 }
 172 
 173 static const struct vsp1_entity_operations hgo_entity_ops = {
 174         .configure_stream = hgo_configure_stream,
 175         .destroy = vsp1_histogram_destroy,
 176 };
 177 
 178 /* -----------------------------------------------------------------------------
 179  * Initialization and Cleanup
 180  */
 181 
 182 static const unsigned int hgo_mbus_formats[] = {
 183         MEDIA_BUS_FMT_AYUV8_1X32,
 184         MEDIA_BUS_FMT_ARGB8888_1X32,
 185         MEDIA_BUS_FMT_AHSV8888_1X32,
 186 };
 187 
 188 struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1)
 189 {
 190         struct vsp1_hgo *hgo;
 191         int ret;
 192 
 193         hgo = devm_kzalloc(vsp1->dev, sizeof(*hgo), GFP_KERNEL);
 194         if (hgo == NULL)
 195                 return ERR_PTR(-ENOMEM);
 196 
 197         /* Initialize the control handler. */
 198         v4l2_ctrl_handler_init(&hgo->ctrls.handler,
 199                                vsp1->info->gen == 3 ? 2 : 1);
 200         hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler,
 201                                                   &hgo_max_rgb_control, NULL);
 202         if (vsp1->info->gen == 3)
 203                 hgo->ctrls.num_bins =
 204                         v4l2_ctrl_new_custom(&hgo->ctrls.handler,
 205                                              &hgo_num_bins_control, NULL);
 206 
 207         hgo->max_rgb = false;
 208         hgo->num_bins = 64;
 209 
 210         hgo->histo.entity.subdev.ctrl_handler = &hgo->ctrls.handler;
 211 
 212         /* Initialize the video device and queue for statistics data. */
 213         ret = vsp1_histogram_init(vsp1, &hgo->histo, VSP1_ENTITY_HGO, "hgo",
 214                                   &hgo_entity_ops, hgo_mbus_formats,
 215                                   ARRAY_SIZE(hgo_mbus_formats),
 216                                   HGO_DATA_SIZE, V4L2_META_FMT_VSP1_HGO);
 217         if (ret < 0) {
 218                 vsp1_entity_destroy(&hgo->histo.entity);
 219                 return ERR_PTR(ret);
 220         }
 221 
 222         return hgo;
 223 }

/* [<][>][^][v][top][bottom][index][help] */