Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] v4l: vsp1: Add HST and HSI support

The Hue Saturation value Transform and Hue Saturation value Inverse
transform entities convert from RGB to HSV and back.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

authored by

Laurent Pinchart and committed by
Mauro Carvalho Chehab
5cdf5741 7e941a79

+287 -1
+1 -1
drivers/media/platform/vsp1/Makefile
··· 1 1 vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o 2 2 vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o 3 - vsp1-y += vsp1_lif.o vsp1_uds.o 3 + vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_uds.o 4 4 5 5 obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o
+3
drivers/media/platform/vsp1/vsp1.h
··· 28 28 struct device; 29 29 30 30 struct vsp1_platform_data; 31 + struct vsp1_hsit; 31 32 struct vsp1_lif; 32 33 struct vsp1_rwpf; 33 34 struct vsp1_uds; ··· 48 47 struct mutex lock; 49 48 int ref_count; 50 49 50 + struct vsp1_hsit *hsi; 51 + struct vsp1_hsit *hst; 51 52 struct vsp1_lif *lif; 52 53 struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; 53 54 struct vsp1_uds *uds[VPS1_MAX_UDS];
+17
drivers/media/platform/vsp1/vsp1_drv.c
··· 20 20 #include <linux/videodev2.h> 21 21 22 22 #include "vsp1.h" 23 + #include "vsp1_hsit.h" 23 24 #include "vsp1_lif.h" 24 25 #include "vsp1_rwpf.h" 25 26 #include "vsp1_uds.h" ··· 153 152 } 154 153 155 154 /* Instantiate all the entities. */ 155 + vsp1->hsi = vsp1_hsit_create(vsp1, true); 156 + if (IS_ERR(vsp1->hsi)) { 157 + ret = PTR_ERR(vsp1->hsi); 158 + goto done; 159 + } 160 + 161 + list_add_tail(&vsp1->hsi->entity.list_dev, &vsp1->entities); 162 + 163 + vsp1->hst = vsp1_hsit_create(vsp1, false); 164 + if (IS_ERR(vsp1->hst)) { 165 + ret = PTR_ERR(vsp1->hst); 166 + goto done; 167 + } 168 + 169 + list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities); 170 + 156 171 if (vsp1->pdata->features & VSP1_HAS_LIF) { 157 172 vsp1->lif = vsp1_lif_create(vsp1); 158 173 if (IS_ERR(vsp1->lif)) {
+2
drivers/media/platform/vsp1/vsp1_entity.c
··· 122 122 unsigned int id; 123 123 unsigned int reg; 124 124 } routes[] = { 125 + { VI6_DPR_NODE_HSI, VI6_DPR_HSI_ROUTE }, 126 + { VI6_DPR_NODE_HST, VI6_DPR_HST_ROUTE }, 125 127 { VI6_DPR_NODE_LIF, 0 }, 126 128 { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) }, 127 129 { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) },
+2
drivers/media/platform/vsp1/vsp1_entity.h
··· 20 20 struct vsp1_device; 21 21 22 22 enum vsp1_entity_type { 23 + VSP1_ENTITY_HSI, 24 + VSP1_ENTITY_HST, 23 25 VSP1_ENTITY_LIF, 24 26 VSP1_ENTITY_RPF, 25 27 VSP1_ENTITY_UDS,
+222
drivers/media/platform/vsp1/vsp1_hsit.c
··· 1 + /* 2 + * vsp1_hsit.c -- R-Car VSP1 Hue Saturation value (Inverse) Transform 3 + * 4 + * Copyright (C) 2013 Renesas Corporation 5 + * 6 + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + 14 + #include <linux/device.h> 15 + #include <linux/gfp.h> 16 + 17 + #include <media/v4l2-subdev.h> 18 + 19 + #include "vsp1.h" 20 + #include "vsp1_hsit.h" 21 + 22 + #define HSIT_MIN_SIZE 4U 23 + #define HSIT_MAX_SIZE 8190U 24 + 25 + /* ----------------------------------------------------------------------------- 26 + * Device Access 27 + */ 28 + 29 + static inline u32 vsp1_hsit_read(struct vsp1_hsit *hsit, u32 reg) 30 + { 31 + return vsp1_read(hsit->entity.vsp1, reg); 32 + } 33 + 34 + static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) 35 + { 36 + vsp1_write(hsit->entity.vsp1, reg, data); 37 + } 38 + 39 + /* ----------------------------------------------------------------------------- 40 + * V4L2 Subdevice Core Operations 41 + */ 42 + 43 + static int hsit_s_stream(struct v4l2_subdev *subdev, int enable) 44 + { 45 + struct vsp1_hsit *hsit = to_hsit(subdev); 46 + 47 + if (!enable) 48 + return 0; 49 + 50 + if (hsit->inverse) 51 + vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); 52 + else 53 + vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN); 54 + 55 + return 0; 56 + } 57 + 58 + /* ----------------------------------------------------------------------------- 59 + * V4L2 Subdevice Pad Operations 60 + */ 61 + 62 + static int hsit_enum_mbus_code(struct v4l2_subdev *subdev, 63 + struct v4l2_subdev_fh *fh, 64 + struct v4l2_subdev_mbus_code_enum *code) 65 + { 66 + struct vsp1_hsit *hsit = to_hsit(subdev); 67 + 68 + if (code->index > 0) 69 + return -EINVAL; 70 + 71 + if ((code->pad == HSIT_PAD_SINK && !hsit->inverse) | 72 + (code->pad == HSIT_PAD_SOURCE && hsit->inverse)) 73 + code->code = V4L2_MBUS_FMT_ARGB8888_1X32; 74 + else 75 + code->code = V4L2_MBUS_FMT_AHSV8888_1X32; 76 + 77 + return 0; 78 + } 79 + 80 + static int hsit_enum_frame_size(struct v4l2_subdev *subdev, 81 + struct v4l2_subdev_fh *fh, 82 + struct v4l2_subdev_frame_size_enum *fse) 83 + { 84 + struct v4l2_mbus_framefmt *format; 85 + 86 + format = v4l2_subdev_get_try_format(fh, fse->pad); 87 + 88 + if (fse->index || fse->code != format->code) 89 + return -EINVAL; 90 + 91 + if (fse->pad == HSIT_PAD_SINK) { 92 + fse->min_width = HSIT_MIN_SIZE; 93 + fse->max_width = HSIT_MAX_SIZE; 94 + fse->min_height = HSIT_MIN_SIZE; 95 + fse->max_height = HSIT_MAX_SIZE; 96 + } else { 97 + /* The size on the source pad are fixed and always identical to 98 + * the size on the sink pad. 99 + */ 100 + fse->min_width = format->width; 101 + fse->max_width = format->width; 102 + fse->min_height = format->height; 103 + fse->max_height = format->height; 104 + } 105 + 106 + return 0; 107 + } 108 + 109 + static int hsit_get_format(struct v4l2_subdev *subdev, 110 + struct v4l2_subdev_fh *fh, 111 + struct v4l2_subdev_format *fmt) 112 + { 113 + struct vsp1_hsit *hsit = to_hsit(subdev); 114 + 115 + fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad, 116 + fmt->which); 117 + 118 + return 0; 119 + } 120 + 121 + static int hsit_set_format(struct v4l2_subdev *subdev, 122 + struct v4l2_subdev_fh *fh, 123 + struct v4l2_subdev_format *fmt) 124 + { 125 + struct vsp1_hsit *hsit = to_hsit(subdev); 126 + struct v4l2_mbus_framefmt *format; 127 + 128 + format = vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad, 129 + fmt->which); 130 + 131 + if (fmt->pad == HSIT_PAD_SOURCE) { 132 + /* The HST and HSI output format code and resolution can't be 133 + * modified. 134 + */ 135 + fmt->format = *format; 136 + return 0; 137 + } 138 + 139 + format->code = hsit->inverse ? V4L2_MBUS_FMT_AHSV8888_1X32 140 + : V4L2_MBUS_FMT_ARGB8888_1X32; 141 + format->width = clamp_t(unsigned int, fmt->format.width, 142 + HSIT_MIN_SIZE, HSIT_MAX_SIZE); 143 + format->height = clamp_t(unsigned int, fmt->format.height, 144 + HSIT_MIN_SIZE, HSIT_MAX_SIZE); 145 + format->field = V4L2_FIELD_NONE; 146 + format->colorspace = V4L2_COLORSPACE_SRGB; 147 + 148 + fmt->format = *format; 149 + 150 + /* Propagate the format to the source pad. */ 151 + format = vsp1_entity_get_pad_format(&hsit->entity, fh, HSIT_PAD_SOURCE, 152 + fmt->which); 153 + *format = fmt->format; 154 + format->code = hsit->inverse ? V4L2_MBUS_FMT_ARGB8888_1X32 155 + : V4L2_MBUS_FMT_AHSV8888_1X32; 156 + 157 + return 0; 158 + } 159 + 160 + /* ----------------------------------------------------------------------------- 161 + * V4L2 Subdevice Operations 162 + */ 163 + 164 + static struct v4l2_subdev_video_ops hsit_video_ops = { 165 + .s_stream = hsit_s_stream, 166 + }; 167 + 168 + static struct v4l2_subdev_pad_ops hsit_pad_ops = { 169 + .enum_mbus_code = hsit_enum_mbus_code, 170 + .enum_frame_size = hsit_enum_frame_size, 171 + .get_fmt = hsit_get_format, 172 + .set_fmt = hsit_set_format, 173 + }; 174 + 175 + static struct v4l2_subdev_ops hsit_ops = { 176 + .video = &hsit_video_ops, 177 + .pad = &hsit_pad_ops, 178 + }; 179 + 180 + /* ----------------------------------------------------------------------------- 181 + * Initialization and Cleanup 182 + */ 183 + 184 + struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) 185 + { 186 + struct v4l2_subdev *subdev; 187 + struct vsp1_hsit *hsit; 188 + int ret; 189 + 190 + hsit = devm_kzalloc(vsp1->dev, sizeof(*hsit), GFP_KERNEL); 191 + if (hsit == NULL) 192 + return ERR_PTR(-ENOMEM); 193 + 194 + hsit->inverse = inverse; 195 + 196 + if (inverse) { 197 + hsit->entity.type = VSP1_ENTITY_HSI; 198 + hsit->entity.id = VI6_DPR_NODE_HSI; 199 + } else { 200 + hsit->entity.type = VSP1_ENTITY_HST; 201 + hsit->entity.id = VI6_DPR_NODE_HST; 202 + } 203 + 204 + ret = vsp1_entity_init(vsp1, &hsit->entity, 2); 205 + if (ret < 0) 206 + return ERR_PTR(ret); 207 + 208 + /* Initialize the V4L2 subdev. */ 209 + subdev = &hsit->entity.subdev; 210 + v4l2_subdev_init(subdev, &hsit_ops); 211 + 212 + subdev->entity.ops = &vsp1_media_ops; 213 + subdev->internal_ops = &vsp1_subdev_internal_ops; 214 + snprintf(subdev->name, sizeof(subdev->name), "%s %s", 215 + dev_name(vsp1->dev), inverse ? "hsi" : "hst"); 216 + v4l2_set_subdevdata(subdev, hsit); 217 + subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 218 + 219 + vsp1_entity_init_formats(subdev, NULL); 220 + 221 + return hsit; 222 + }
+38
drivers/media/platform/vsp1/vsp1_hsit.h
··· 1 + /* 2 + * vsp1_hsit.h -- R-Car VSP1 Hue Saturation value (Inverse) Transform 3 + * 4 + * Copyright (C) 2013 Renesas Corporation 5 + * 6 + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + #ifndef __VSP1_HSIT_H__ 14 + #define __VSP1_HSIT_H__ 15 + 16 + #include <media/media-entity.h> 17 + #include <media/v4l2-subdev.h> 18 + 19 + #include "vsp1_entity.h" 20 + 21 + struct vsp1_device; 22 + 23 + #define HSIT_PAD_SINK 0 24 + #define HSIT_PAD_SOURCE 1 25 + 26 + struct vsp1_hsit { 27 + struct vsp1_entity entity; 28 + bool inverse; 29 + }; 30 + 31 + static inline struct vsp1_hsit *to_hsit(struct v4l2_subdev *subdev) 32 + { 33 + return container_of(subdev, struct vsp1_hsit, entity.subdev); 34 + } 35 + 36 + struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse); 37 + 38 + #endif /* __VSP1_HSIT_H__ */
+2
drivers/media/platform/vsp1/vsp1_regs.h
··· 424 424 */ 425 425 426 426 #define VI6_HST_CTRL 0x2a00 427 + #define VI6_HST_CTRL_EN (1 << 0) 427 428 428 429 /* ----------------------------------------------------------------------------- 429 430 * HSI Control Registers 430 431 */ 431 432 432 433 #define VI6_HSI_CTRL 0x2b00 434 + #define VI6_HSI_CTRL_EN (1 << 0) 433 435 434 436 /* ----------------------------------------------------------------------------- 435 437 * BRU Control Registers