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

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

DEFINITIONS

This source file includes following definitions.
  1. vsp1_lif_write
  2. lif_enum_mbus_code
  3. lif_enum_frame_size
  4. lif_set_format
  5. lif_configure_stream
  6. vsp1_lif_create

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * vsp1_lif.c  --  R-Car VSP1 LCD Controller Interface
   4  *
   5  * Copyright (C) 2013-2014 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 
  15 #include "vsp1.h"
  16 #include "vsp1_dl.h"
  17 #include "vsp1_lif.h"
  18 
  19 #define LIF_MIN_SIZE                            2U
  20 #define LIF_MAX_SIZE                            8190U
  21 
  22 /* -----------------------------------------------------------------------------
  23  * Device Access
  24  */
  25 
  26 static inline void vsp1_lif_write(struct vsp1_lif *lif,
  27                                   struct vsp1_dl_body *dlb, u32 reg, u32 data)
  28 {
  29         vsp1_dl_body_write(dlb, reg + lif->entity.index * VI6_LIF_OFFSET,
  30                                data);
  31 }
  32 
  33 /* -----------------------------------------------------------------------------
  34  * V4L2 Subdevice Operations
  35  */
  36 
  37 static const unsigned int lif_codes[] = {
  38         MEDIA_BUS_FMT_ARGB8888_1X32,
  39         MEDIA_BUS_FMT_AYUV8_1X32,
  40 };
  41 
  42 static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
  43                               struct v4l2_subdev_pad_config *cfg,
  44                               struct v4l2_subdev_mbus_code_enum *code)
  45 {
  46         return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
  47                                           ARRAY_SIZE(lif_codes));
  48 }
  49 
  50 static int lif_enum_frame_size(struct v4l2_subdev *subdev,
  51                                struct v4l2_subdev_pad_config *cfg,
  52                                struct v4l2_subdev_frame_size_enum *fse)
  53 {
  54         return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LIF_MIN_SIZE,
  55                                            LIF_MIN_SIZE, LIF_MAX_SIZE,
  56                                            LIF_MAX_SIZE);
  57 }
  58 
  59 static int lif_set_format(struct v4l2_subdev *subdev,
  60                           struct v4l2_subdev_pad_config *cfg,
  61                           struct v4l2_subdev_format *fmt)
  62 {
  63         return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
  64                                           ARRAY_SIZE(lif_codes),
  65                                           LIF_MIN_SIZE, LIF_MIN_SIZE,
  66                                           LIF_MAX_SIZE, LIF_MAX_SIZE);
  67 }
  68 
  69 static const struct v4l2_subdev_pad_ops lif_pad_ops = {
  70         .init_cfg = vsp1_entity_init_cfg,
  71         .enum_mbus_code = lif_enum_mbus_code,
  72         .enum_frame_size = lif_enum_frame_size,
  73         .get_fmt = vsp1_subdev_get_pad_format,
  74         .set_fmt = lif_set_format,
  75 };
  76 
  77 static const struct v4l2_subdev_ops lif_ops = {
  78         .pad    = &lif_pad_ops,
  79 };
  80 
  81 /* -----------------------------------------------------------------------------
  82  * VSP1 Entity Operations
  83  */
  84 
  85 static void lif_configure_stream(struct vsp1_entity *entity,
  86                                  struct vsp1_pipeline *pipe,
  87                                  struct vsp1_dl_list *dl,
  88                                  struct vsp1_dl_body *dlb)
  89 {
  90         const struct v4l2_mbus_framefmt *format;
  91         struct vsp1_lif *lif = to_lif(&entity->subdev);
  92         unsigned int hbth;
  93         unsigned int obth;
  94         unsigned int lbth;
  95 
  96         format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
  97                                             LIF_PAD_SOURCE);
  98 
  99         switch (entity->vsp1->version & VI6_IP_VERSION_MODEL_MASK) {
 100         case VI6_IP_VERSION_MODEL_VSPD_GEN2:
 101         case VI6_IP_VERSION_MODEL_VSPD_V2H:
 102                 hbth = 1536;
 103                 obth = min(128U, (format->width + 1) / 2 * format->height - 4);
 104                 lbth = 1520;
 105                 break;
 106 
 107         case VI6_IP_VERSION_MODEL_VSPDL_GEN3:
 108         case VI6_IP_VERSION_MODEL_VSPD_V3:
 109                 hbth = 0;
 110                 obth = 1500;
 111                 lbth = 0;
 112                 break;
 113 
 114         case VI6_IP_VERSION_MODEL_VSPD_GEN3:
 115         default:
 116                 hbth = 0;
 117                 obth = 3000;
 118                 lbth = 0;
 119                 break;
 120         }
 121 
 122         vsp1_lif_write(lif, dlb, VI6_LIF_CSBTH,
 123                         (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) |
 124                         (lbth << VI6_LIF_CSBTH_LBTH_SHIFT));
 125 
 126         vsp1_lif_write(lif, dlb, VI6_LIF_CTRL,
 127                         (obth << VI6_LIF_CTRL_OBTH_SHIFT) |
 128                         (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) |
 129                         VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN);
 130 
 131         /*
 132          * On R-Car V3M the LIF0 buffer attribute register has to be set to a
 133          * non-default value to guarantee proper operation (otherwise artifacts
 134          * may appear on the output). The value required by the manual is not
 135          * explained but is likely a buffer size or threshold.
 136          */
 137         if ((entity->vsp1->version & VI6_IP_VERSION_MASK) ==
 138             (VI6_IP_VERSION_MODEL_VSPD_V3 | VI6_IP_VERSION_SOC_V3M))
 139                 vsp1_lif_write(lif, dlb, VI6_LIF_LBA,
 140                                VI6_LIF_LBA_LBA0 |
 141                                (1536 << VI6_LIF_LBA_LBA1_SHIFT));
 142 }
 143 
 144 static const struct vsp1_entity_operations lif_entity_ops = {
 145         .configure_stream = lif_configure_stream,
 146 };
 147 
 148 /* -----------------------------------------------------------------------------
 149  * Initialization and Cleanup
 150  */
 151 
 152 struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1, unsigned int index)
 153 {
 154         struct vsp1_lif *lif;
 155         int ret;
 156 
 157         lif = devm_kzalloc(vsp1->dev, sizeof(*lif), GFP_KERNEL);
 158         if (lif == NULL)
 159                 return ERR_PTR(-ENOMEM);
 160 
 161         lif->entity.ops = &lif_entity_ops;
 162         lif->entity.type = VSP1_ENTITY_LIF;
 163         lif->entity.index = index;
 164 
 165         /*
 166          * The LIF is never exposed to userspace, but media entity registration
 167          * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just to
 168          * avoid triggering a WARN_ON(), the value won't be seen anywhere.
 169          */
 170         ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops,
 171                                MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
 172         if (ret < 0)
 173                 return ERR_PTR(ret);
 174 
 175         return lif;
 176 }

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