FILE
vsp1_hsit.c
File preview with syntax highlighting.
linux-6.19.14/drivers/media/platform/renesas/vsp1/vsp1_hsit.c
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * vsp1_hsit.c -- R-Car VSP1 Hue Saturation value (Inverse) Transform 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_entity.h" 18#include "vsp1_hsit.h" 19 20#define HSIT_MIN_SIZE 4U 21#define HSIT_MAX_SIZE 8190U 22 23/* ----------------------------------------------------------------------------- 24 * Device Access 25 */ 26 27static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, 28 struct vsp1_dl_body *dlb, u32 reg, u32 data) 29{ 30 vsp1_dl_body_write(dlb, reg, data); 31} 32 33/* ----------------------------------------------------------------------------- 34 * V4L2 Subdevice Operations 35 */ 36 37static int hsit_enum_mbus_code(struct v4l2_subdev *subdev, 38 struct v4l2_subdev_state *sd_state, 39 struct v4l2_subdev_mbus_code_enum *code) 40{ 41 struct vsp1_hsit *hsit = to_hsit(subdev); 42 43 if (code->index > 0) 44 return -EINVAL; 45 46 if ((code->pad == HSIT_PAD_SINK && !hsit->inverse) | 47 (code->pad == HSIT_PAD_SOURCE && hsit->inverse)) 48 code->code = MEDIA_BUS_FMT_ARGB8888_1X32; 49 else 50 code->code = MEDIA_BUS_FMT_AHSV8888_1X32; 51 52 return 0; 53} 54 55static int hsit_enum_frame_size(struct v4l2_subdev *subdev, 56 struct v4l2_subdev_state *sd_state, 57 struct v4l2_subdev_frame_size_enum *fse) 58{ 59 return vsp1_subdev_enum_frame_size(subdev, sd_state, fse, 60 HSIT_MIN_SIZE, 61 HSIT_MIN_SIZE, HSIT_MAX_SIZE, 62 HSIT_MAX_SIZE); 63} 64 65static int hsit_set_format(struct v4l2_subdev *subdev, 66 struct v4l2_subdev_state *sd_state, 67 struct v4l2_subdev_format *fmt) 68{ 69 struct vsp1_hsit *hsit = to_hsit(subdev); 70 struct v4l2_subdev_state *state; 71 struct v4l2_mbus_framefmt *format; 72 int ret = 0; 73 74 mutex_lock(&hsit->entity.lock); 75 76 state = vsp1_entity_get_state(&hsit->entity, sd_state, fmt->which); 77 if (!state) { 78 ret = -EINVAL; 79 goto done; 80 } 81 82 format = v4l2_subdev_state_get_format(state, fmt->pad); 83 84 if (fmt->pad == HSIT_PAD_SOURCE) { 85 /* 86 * The HST and HSI output format code and resolution can't be 87 * modified. 88 */ 89 fmt->format = *format; 90 goto done; 91 } 92 93 format->code = hsit->inverse ? MEDIA_BUS_FMT_AHSV8888_1X32 94 : MEDIA_BUS_FMT_ARGB8888_1X32; 95 format->width = clamp_t(unsigned int, fmt->format.width, 96 HSIT_MIN_SIZE, HSIT_MAX_SIZE); 97 format->height = clamp_t(unsigned int, fmt->format.height, 98 HSIT_MIN_SIZE, HSIT_MAX_SIZE); 99 format->field = V4L2_FIELD_NONE; 100 101 format->colorspace = fmt->format.colorspace; 102 format->xfer_func = fmt->format.xfer_func; 103 format->ycbcr_enc = fmt->format.ycbcr_enc; 104 format->quantization = fmt->format.quantization; 105 106 vsp1_entity_adjust_color_space(format); 107 108 fmt->format = *format; 109 110 /* Propagate the format to the source pad. */ 111 format = v4l2_subdev_state_get_format(state, HSIT_PAD_SOURCE); 112 *format = fmt->format; 113 format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32 114 : MEDIA_BUS_FMT_AHSV8888_1X32; 115 116 vsp1_entity_adjust_color_space(format); 117 118done: 119 mutex_unlock(&hsit->entity.lock); 120 return ret; 121} 122 123static const struct v4l2_subdev_pad_ops hsit_pad_ops = { 124 .enum_mbus_code = hsit_enum_mbus_code, 125 .enum_frame_size = hsit_enum_frame_size, 126 .get_fmt = vsp1_subdev_get_pad_format, 127 .set_fmt = hsit_set_format, 128}; 129 130static const struct v4l2_subdev_ops hsit_ops = { 131 .pad = &hsit_pad_ops, 132}; 133 134/* ----------------------------------------------------------------------------- 135 * VSP1 Entity Operations 136 */ 137 138static void hsit_configure_stream(struct vsp1_entity *entity, 139 struct v4l2_subdev_state *state, 140 struct vsp1_pipeline *pipe, 141 struct vsp1_dl_list *dl, 142 struct vsp1_dl_body *dlb) 143{ 144 struct vsp1_hsit *hsit = to_hsit(&entity->subdev); 145 146 if (hsit->inverse) 147 vsp1_hsit_write(hsit, dlb, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); 148 else 149 vsp1_hsit_write(hsit, dlb, VI6_HST_CTRL, VI6_HST_CTRL_EN); 150} 151 152static const struct vsp1_entity_operations hsit_entity_ops = { 153 .configure_stream = hsit_configure_stream, 154}; 155 156/* ----------------------------------------------------------------------------- 157 * Initialization and Cleanup 158 */ 159 160struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) 161{ 162 struct vsp1_hsit *hsit; 163 int ret; 164 165 hsit = devm_kzalloc(vsp1->dev, sizeof(*hsit), GFP_KERNEL); 166 if (hsit == NULL) 167 return ERR_PTR(-ENOMEM); 168 169 hsit->inverse = inverse; 170 171 hsit->entity.ops = &hsit_entity_ops; 172 173 if (inverse) 174 hsit->entity.type = VSP1_ENTITY_HSI; 175 else 176 hsit->entity.type = VSP1_ENTITY_HST; 177 178 ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst", 179 2, &hsit_ops, 180 MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV); 181 if (ret < 0) 182 return ERR_PTR(ret); 183 184 return hsit; 185}
~/
Read-only file preview.