brintos

brintos / linux-shallow public Read only

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