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

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

DEFINITIONS

This source file includes following definitions.
  1. vsp1_lut_write
  2. lut_set_table
  3. lut_s_ctrl
  4. lut_enum_mbus_code
  5. lut_enum_frame_size
  6. lut_set_format
  7. lut_configure_stream
  8. lut_configure_frame
  9. lut_destroy
  10. vsp1_lut_create

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * vsp1_lut.c  --  R-Car VSP1 Look-Up Table
   4  *
   5  * Copyright (C) 2013 Renesas 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 
  15 #include "vsp1.h"
  16 #include "vsp1_dl.h"
  17 #include "vsp1_lut.h"
  18 
  19 #define LUT_MIN_SIZE                            4U
  20 #define LUT_MAX_SIZE                            8190U
  21 
  22 #define LUT_SIZE                                256
  23 
  24 /* -----------------------------------------------------------------------------
  25  * Device Access
  26  */
  27 
  28 static inline void vsp1_lut_write(struct vsp1_lut *lut,
  29                                   struct vsp1_dl_body *dlb, u32 reg, u32 data)
  30 {
  31         vsp1_dl_body_write(dlb, reg, data);
  32 }
  33 
  34 /* -----------------------------------------------------------------------------
  35  * Controls
  36  */
  37 
  38 #define V4L2_CID_VSP1_LUT_TABLE                 (V4L2_CID_USER_BASE | 0x1001)
  39 
  40 static int lut_set_table(struct vsp1_lut *lut, struct v4l2_ctrl *ctrl)
  41 {
  42         struct vsp1_dl_body *dlb;
  43         unsigned int i;
  44 
  45         dlb = vsp1_dl_body_get(lut->pool);
  46         if (!dlb)
  47                 return -ENOMEM;
  48 
  49         for (i = 0; i < LUT_SIZE; ++i)
  50                 vsp1_dl_body_write(dlb, VI6_LUT_TABLE + 4 * i,
  51                                        ctrl->p_new.p_u32[i]);
  52 
  53         spin_lock_irq(&lut->lock);
  54         swap(lut->lut, dlb);
  55         spin_unlock_irq(&lut->lock);
  56 
  57         vsp1_dl_body_put(dlb);
  58         return 0;
  59 }
  60 
  61 static int lut_s_ctrl(struct v4l2_ctrl *ctrl)
  62 {
  63         struct vsp1_lut *lut =
  64                 container_of(ctrl->handler, struct vsp1_lut, ctrls);
  65 
  66         switch (ctrl->id) {
  67         case V4L2_CID_VSP1_LUT_TABLE:
  68                 lut_set_table(lut, ctrl);
  69                 break;
  70         }
  71 
  72         return 0;
  73 }
  74 
  75 static const struct v4l2_ctrl_ops lut_ctrl_ops = {
  76         .s_ctrl = lut_s_ctrl,
  77 };
  78 
  79 static const struct v4l2_ctrl_config lut_table_control = {
  80         .ops = &lut_ctrl_ops,
  81         .id = V4L2_CID_VSP1_LUT_TABLE,
  82         .name = "Look-Up Table",
  83         .type = V4L2_CTRL_TYPE_U32,
  84         .min = 0x00000000,
  85         .max = 0x00ffffff,
  86         .step = 1,
  87         .def = 0,
  88         .dims = { LUT_SIZE },
  89 };
  90 
  91 /* -----------------------------------------------------------------------------
  92  * V4L2 Subdevice Pad Operations
  93  */
  94 
  95 static const unsigned int lut_codes[] = {
  96         MEDIA_BUS_FMT_ARGB8888_1X32,
  97         MEDIA_BUS_FMT_AHSV8888_1X32,
  98         MEDIA_BUS_FMT_AYUV8_1X32,
  99 };
 100 
 101 static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
 102                               struct v4l2_subdev_pad_config *cfg,
 103                               struct v4l2_subdev_mbus_code_enum *code)
 104 {
 105         return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
 106                                           ARRAY_SIZE(lut_codes));
 107 }
 108 
 109 static int lut_enum_frame_size(struct v4l2_subdev *subdev,
 110                                struct v4l2_subdev_pad_config *cfg,
 111                                struct v4l2_subdev_frame_size_enum *fse)
 112 {
 113         return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LUT_MIN_SIZE,
 114                                            LUT_MIN_SIZE, LUT_MAX_SIZE,
 115                                            LUT_MAX_SIZE);
 116 }
 117 
 118 static int lut_set_format(struct v4l2_subdev *subdev,
 119                           struct v4l2_subdev_pad_config *cfg,
 120                           struct v4l2_subdev_format *fmt)
 121 {
 122         return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
 123                                           ARRAY_SIZE(lut_codes),
 124                                           LUT_MIN_SIZE, LUT_MIN_SIZE,
 125                                           LUT_MAX_SIZE, LUT_MAX_SIZE);
 126 }
 127 
 128 /* -----------------------------------------------------------------------------
 129  * V4L2 Subdevice Operations
 130  */
 131 
 132 static const struct v4l2_subdev_pad_ops lut_pad_ops = {
 133         .init_cfg = vsp1_entity_init_cfg,
 134         .enum_mbus_code = lut_enum_mbus_code,
 135         .enum_frame_size = lut_enum_frame_size,
 136         .get_fmt = vsp1_subdev_get_pad_format,
 137         .set_fmt = lut_set_format,
 138 };
 139 
 140 static const struct v4l2_subdev_ops lut_ops = {
 141         .pad    = &lut_pad_ops,
 142 };
 143 
 144 /* -----------------------------------------------------------------------------
 145  * VSP1 Entity Operations
 146  */
 147 
 148 static void lut_configure_stream(struct vsp1_entity *entity,
 149                                  struct vsp1_pipeline *pipe,
 150                                  struct vsp1_dl_list *dl,
 151                                  struct vsp1_dl_body *dlb)
 152 {
 153         struct vsp1_lut *lut = to_lut(&entity->subdev);
 154 
 155         vsp1_lut_write(lut, dlb, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
 156 }
 157 
 158 static void lut_configure_frame(struct vsp1_entity *entity,
 159                                 struct vsp1_pipeline *pipe,
 160                                 struct vsp1_dl_list *dl,
 161                                 struct vsp1_dl_body *dlb)
 162 {
 163         struct vsp1_lut *lut = to_lut(&entity->subdev);
 164         struct vsp1_dl_body *lut_dlb;
 165         unsigned long flags;
 166 
 167         spin_lock_irqsave(&lut->lock, flags);
 168         lut_dlb = lut->lut;
 169         lut->lut = NULL;
 170         spin_unlock_irqrestore(&lut->lock, flags);
 171 
 172         if (lut_dlb) {
 173                 vsp1_dl_list_add_body(dl, lut_dlb);
 174 
 175                 /* Release our local reference. */
 176                 vsp1_dl_body_put(lut_dlb);
 177         }
 178 }
 179 
 180 static void lut_destroy(struct vsp1_entity *entity)
 181 {
 182         struct vsp1_lut *lut = to_lut(&entity->subdev);
 183 
 184         vsp1_dl_body_pool_destroy(lut->pool);
 185 }
 186 
 187 static const struct vsp1_entity_operations lut_entity_ops = {
 188         .configure_stream = lut_configure_stream,
 189         .configure_frame = lut_configure_frame,
 190         .destroy = lut_destroy,
 191 };
 192 
 193 /* -----------------------------------------------------------------------------
 194  * Initialization and Cleanup
 195  */
 196 
 197 struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
 198 {
 199         struct vsp1_lut *lut;
 200         int ret;
 201 
 202         lut = devm_kzalloc(vsp1->dev, sizeof(*lut), GFP_KERNEL);
 203         if (lut == NULL)
 204                 return ERR_PTR(-ENOMEM);
 205 
 206         spin_lock_init(&lut->lock);
 207 
 208         lut->entity.ops = &lut_entity_ops;
 209         lut->entity.type = VSP1_ENTITY_LUT;
 210 
 211         ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops,
 212                                MEDIA_ENT_F_PROC_VIDEO_LUT);
 213         if (ret < 0)
 214                 return ERR_PTR(ret);
 215 
 216         /*
 217          * Pre-allocate a body pool, with 3 bodies allowing a userspace update
 218          * before the hardware has committed a previous set of tables, handling
 219          * both the queued and pending dl entries.
 220          */
 221         lut->pool = vsp1_dl_body_pool_create(vsp1, 3, LUT_SIZE, 0);
 222         if (!lut->pool)
 223                 return ERR_PTR(-ENOMEM);
 224 
 225         /* Initialize the control handler. */
 226         v4l2_ctrl_handler_init(&lut->ctrls, 1);
 227         v4l2_ctrl_new_custom(&lut->ctrls, &lut_table_control, NULL);
 228 
 229         lut->entity.subdev.ctrl_handler = &lut->ctrls;
 230 
 231         if (lut->ctrls.error) {
 232                 dev_err(vsp1->dev, "lut: failed to initialize controls\n");
 233                 ret = lut->ctrls.error;
 234                 vsp1_entity_destroy(&lut->entity);
 235                 return ERR_PTR(ret);
 236         }
 237 
 238         v4l2_ctrl_handler_setup(&lut->ctrls);
 239 
 240         return lut;
 241 }

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