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

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

DEFINITIONS

This source file includes following definitions.
  1. vsp1_hgt_read
  2. vsp1_hgt_write
  3. vsp1_hgt_frame_end
  4. hgt_hue_areas_try_ctrl
  5. hgt_hue_areas_s_ctrl
  6. hgt_configure_stream
  7. vsp1_hgt_create

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * vsp1_hgt.c  --  R-Car VSP1 Histogram Generator 2D
   4  *
   5  * Copyright (C) 2016 Renesas Electronics Corporation
   6  *
   7  * Contact: Niklas Söderlund (niklas.soderlund@ragnatech.se)
   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_hgt.h"
  19 
  20 #define HGT_DATA_SIZE                           ((2 +  6 * 32) * 4)
  21 
  22 /* -----------------------------------------------------------------------------
  23  * Device Access
  24  */
  25 
  26 static inline u32 vsp1_hgt_read(struct vsp1_hgt *hgt, u32 reg)
  27 {
  28         return vsp1_read(hgt->histo.entity.vsp1, reg);
  29 }
  30 
  31 static inline void vsp1_hgt_write(struct vsp1_hgt *hgt,
  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_hgt_frame_end(struct vsp1_entity *entity)
  42 {
  43         struct vsp1_hgt *hgt = to_hgt(&entity->subdev);
  44         struct vsp1_histogram_buffer *buf;
  45         unsigned int m;
  46         unsigned int n;
  47         u32 *data;
  48 
  49         buf = vsp1_histogram_buffer_get(&hgt->histo);
  50         if (!buf)
  51                 return;
  52 
  53         data = buf->addr;
  54 
  55         *data++ = vsp1_hgt_read(hgt, VI6_HGT_MAXMIN);
  56         *data++ = vsp1_hgt_read(hgt, VI6_HGT_SUM);
  57 
  58         for (m = 0; m < 6; ++m)
  59                 for (n = 0; n < 32; ++n)
  60                         *data++ = vsp1_hgt_read(hgt, VI6_HGT_HISTO(m, n));
  61 
  62         vsp1_histogram_buffer_complete(&hgt->histo, buf, HGT_DATA_SIZE);
  63 }
  64 
  65 /* -----------------------------------------------------------------------------
  66  * Controls
  67  */
  68 
  69 #define V4L2_CID_VSP1_HGT_HUE_AREAS     (V4L2_CID_USER_BASE | 0x1001)
  70 
  71 static int hgt_hue_areas_try_ctrl(struct v4l2_ctrl *ctrl)
  72 {
  73         const u8 *values = ctrl->p_new.p_u8;
  74         unsigned int i;
  75 
  76         /*
  77          * The hardware has constraints on the hue area boundaries beyond the
  78          * control min, max and step. The values must match one of the following
  79          * expressions.
  80          *
  81          * 0L <= 0U <= 1L <= 1U <= 2L <= 2U <= 3L <= 3U <= 4L <= 4U <= 5L <= 5U
  82          * 0U <= 1L <= 1U <= 2L <= 2U <= 3L <= 3U <= 4L <= 4U <= 5L <= 5U <= 0L
  83          *
  84          * Start by verifying the common part...
  85          */
  86         for (i = 1; i < (HGT_NUM_HUE_AREAS * 2) - 1; ++i) {
  87                 if (values[i] > values[i+1])
  88                         return -EINVAL;
  89         }
  90 
  91         /* ... and handle 0L separately. */
  92         if (values[0] > values[1] && values[11] > values[0])
  93                 return -EINVAL;
  94 
  95         return 0;
  96 }
  97 
  98 static int hgt_hue_areas_s_ctrl(struct v4l2_ctrl *ctrl)
  99 {
 100         struct vsp1_hgt *hgt = container_of(ctrl->handler, struct vsp1_hgt,
 101                                             ctrls);
 102 
 103         memcpy(hgt->hue_areas, ctrl->p_new.p_u8, sizeof(hgt->hue_areas));
 104         return 0;
 105 }
 106 
 107 static const struct v4l2_ctrl_ops hgt_hue_areas_ctrl_ops = {
 108         .try_ctrl = hgt_hue_areas_try_ctrl,
 109         .s_ctrl = hgt_hue_areas_s_ctrl,
 110 };
 111 
 112 static const struct v4l2_ctrl_config hgt_hue_areas = {
 113         .ops = &hgt_hue_areas_ctrl_ops,
 114         .id = V4L2_CID_VSP1_HGT_HUE_AREAS,
 115         .name = "Boundary Values for Hue Area",
 116         .type = V4L2_CTRL_TYPE_U8,
 117         .min = 0,
 118         .max = 255,
 119         .def = 0,
 120         .step = 1,
 121         .dims = { 12 },
 122 };
 123 
 124 /* -----------------------------------------------------------------------------
 125  * VSP1 Entity Operations
 126  */
 127 
 128 static void hgt_configure_stream(struct vsp1_entity *entity,
 129                                  struct vsp1_pipeline *pipe,
 130                                  struct vsp1_dl_list *dl,
 131                                  struct vsp1_dl_body *dlb)
 132 {
 133         struct vsp1_hgt *hgt = to_hgt(&entity->subdev);
 134         struct v4l2_rect *compose;
 135         struct v4l2_rect *crop;
 136         unsigned int hratio;
 137         unsigned int vratio;
 138         u8 lower;
 139         u8 upper;
 140         unsigned int i;
 141 
 142         crop = vsp1_entity_get_pad_selection(entity, entity->config,
 143                                              HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
 144         compose = vsp1_entity_get_pad_selection(entity, entity->config,
 145                                                 HISTO_PAD_SINK,
 146                                                 V4L2_SEL_TGT_COMPOSE);
 147 
 148         vsp1_hgt_write(hgt, dlb, VI6_HGT_REGRST, VI6_HGT_REGRST_RCLEA);
 149 
 150         vsp1_hgt_write(hgt, dlb, VI6_HGT_OFFSET,
 151                        (crop->left << VI6_HGT_OFFSET_HOFFSET_SHIFT) |
 152                        (crop->top << VI6_HGT_OFFSET_VOFFSET_SHIFT));
 153         vsp1_hgt_write(hgt, dlb, VI6_HGT_SIZE,
 154                        (crop->width << VI6_HGT_SIZE_HSIZE_SHIFT) |
 155                        (crop->height << VI6_HGT_SIZE_VSIZE_SHIFT));
 156 
 157         mutex_lock(hgt->ctrls.lock);
 158         for (i = 0; i < HGT_NUM_HUE_AREAS; ++i) {
 159                 lower = hgt->hue_areas[i*2 + 0];
 160                 upper = hgt->hue_areas[i*2 + 1];
 161                 vsp1_hgt_write(hgt, dlb, VI6_HGT_HUE_AREA(i),
 162                                (lower << VI6_HGT_HUE_AREA_LOWER_SHIFT) |
 163                                (upper << VI6_HGT_HUE_AREA_UPPER_SHIFT));
 164         }
 165         mutex_unlock(hgt->ctrls.lock);
 166 
 167         hratio = crop->width * 2 / compose->width / 3;
 168         vratio = crop->height * 2 / compose->height / 3;
 169         vsp1_hgt_write(hgt, dlb, VI6_HGT_MODE,
 170                        (hratio << VI6_HGT_MODE_HRATIO_SHIFT) |
 171                        (vratio << VI6_HGT_MODE_VRATIO_SHIFT));
 172 }
 173 
 174 static const struct vsp1_entity_operations hgt_entity_ops = {
 175         .configure_stream = hgt_configure_stream,
 176         .destroy = vsp1_histogram_destroy,
 177 };
 178 
 179 /* -----------------------------------------------------------------------------
 180  * Initialization and Cleanup
 181  */
 182 
 183 static const unsigned int hgt_mbus_formats[] = {
 184         MEDIA_BUS_FMT_AHSV8888_1X32,
 185 };
 186 
 187 struct vsp1_hgt *vsp1_hgt_create(struct vsp1_device *vsp1)
 188 {
 189         struct vsp1_hgt *hgt;
 190         int ret;
 191 
 192         hgt = devm_kzalloc(vsp1->dev, sizeof(*hgt), GFP_KERNEL);
 193         if (hgt == NULL)
 194                 return ERR_PTR(-ENOMEM);
 195 
 196         /* Initialize the control handler. */
 197         v4l2_ctrl_handler_init(&hgt->ctrls, 1);
 198         v4l2_ctrl_new_custom(&hgt->ctrls, &hgt_hue_areas, NULL);
 199 
 200         hgt->histo.entity.subdev.ctrl_handler = &hgt->ctrls;
 201 
 202         /* Initialize the video device and queue for statistics data. */
 203         ret = vsp1_histogram_init(vsp1, &hgt->histo, VSP1_ENTITY_HGT, "hgt",
 204                                   &hgt_entity_ops, hgt_mbus_formats,
 205                                   ARRAY_SIZE(hgt_mbus_formats),
 206                                   HGT_DATA_SIZE, V4L2_META_FMT_VSP1_HGT);
 207         if (ret < 0) {
 208                 vsp1_entity_destroy(&hgt->histo.entity);
 209                 return ERR_PTR(ret);
 210         }
 211 
 212         v4l2_ctrl_handler_setup(&hgt->ctrls);
 213 
 214         return hgt;
 215 }

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