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