1 /* 2 * Xilinx Video IP Core 3 * 4 * Copyright (C) 2013-2015 Ideas on Board 5 * Copyright (C) 2013-2015 Xilinx, Inc. 6 * 7 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com> 8 * Laurent Pinchart <laurent.pinchart@ideasonboard.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/clk.h> 16 #include <linux/export.h> 17 #include <linux/kernel.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 21 #include <dt-bindings/media/xilinx-vip.h> 22 23 #include "xilinx-vip.h" 24 25 /* ----------------------------------------------------------------------------- 26 * Helper functions 27 */ 28 29 static const struct xvip_video_format xvip_video_formats[] = { 30 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16, 31 2, V4L2_PIX_FMT_YUYV, "4:2:2, packed, YUYV" }, 32 { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24, 33 3, V4L2_PIX_FMT_YUV444, "4:4:4, packed, YUYV" }, 34 { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24, 35 3, 0, NULL }, 36 { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8, 37 1, V4L2_PIX_FMT_GREY, "Greyscale 8-bit" }, 38 { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8, 39 1, V4L2_PIX_FMT_SGRBG8, "Bayer 8-bit RGGB" }, 40 { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8, 41 1, V4L2_PIX_FMT_SGRBG8, "Bayer 8-bit GRBG" }, 42 { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8, 43 1, V4L2_PIX_FMT_SGBRG8, "Bayer 8-bit GBRG" }, 44 { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8, 45 1, V4L2_PIX_FMT_SBGGR8, "Bayer 8-bit BGGR" }, 46 }; 47 48 /** 49 * xvip_get_format_by_code - Retrieve format information for a media bus code 50 * @code: the format media bus code 51 * 52 * Return: a pointer to the format information structure corresponding to the 53 * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can 54 * be found. 55 */ 56 const struct xvip_video_format *xvip_get_format_by_code(unsigned int code) 57 { 58 unsigned int i; 59 60 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) { 61 const struct xvip_video_format *format = &xvip_video_formats[i]; 62 63 if (format->code == code) 64 return format; 65 } 66 67 return ERR_PTR(-EINVAL); 68 } 69 EXPORT_SYMBOL_GPL(xvip_get_format_by_code); 70 71 /** 72 * xvip_get_format_by_fourcc - Retrieve format information for a 4CC 73 * @fourcc: the format 4CC 74 * 75 * Return: a pointer to the format information structure corresponding to the 76 * given V4L2 format @fourcc, or ERR_PTR if no corresponding format can be 77 * found. 78 */ 79 const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc) 80 { 81 unsigned int i; 82 83 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) { 84 const struct xvip_video_format *format = &xvip_video_formats[i]; 85 86 if (format->fourcc == fourcc) 87 return format; 88 } 89 90 return ERR_PTR(-EINVAL); 91 } 92 EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc); 93 94 /** 95 * xvip_of_get_format - Parse a device tree node and return format information 96 * @node: the device tree node 97 * 98 * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties 99 * from the device tree @node passed as an argument and return the corresponding 100 * format information. 101 * 102 * Return: a pointer to the format information structure corresponding to the 103 * format name and width, or ERR_PTR if no corresponding format can be found. 104 */ 105 const struct xvip_video_format *xvip_of_get_format(struct device_node *node) 106 { 107 const char *pattern = "mono"; 108 unsigned int vf_code; 109 unsigned int i; 110 u32 width; 111 int ret; 112 113 ret = of_property_read_u32(node, "xlnx,video-format", &vf_code); 114 if (ret < 0) 115 return ERR_PTR(ret); 116 117 ret = of_property_read_u32(node, "xlnx,video-width", &width); 118 if (ret < 0) 119 return ERR_PTR(ret); 120 121 if (vf_code == XVIP_VF_MONO_SENSOR) 122 of_property_read_string(node, "xlnx,cfa-pattern", &pattern); 123 124 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) { 125 const struct xvip_video_format *format = &xvip_video_formats[i]; 126 127 if (format->vf_code != vf_code || format->width != width) 128 continue; 129 130 if (vf_code == XVIP_VF_MONO_SENSOR && 131 strcmp(pattern, format->pattern)) 132 continue; 133 134 return format; 135 } 136 137 return ERR_PTR(-EINVAL); 138 } 139 EXPORT_SYMBOL_GPL(xvip_of_get_format); 140 141 /** 142 * xvip_set_format_size - Set the media bus frame format size 143 * @format: V4L2 frame format on media bus 144 * @fmt: media bus format 145 * 146 * Set the media bus frame format size. The width / height from the subdevice 147 * format are set to the given media bus format. The new format size is stored 148 * in @format. The width and height are clamped using default min / max values. 149 */ 150 void xvip_set_format_size(struct v4l2_mbus_framefmt *format, 151 const struct v4l2_subdev_format *fmt) 152 { 153 format->width = clamp_t(unsigned int, fmt->format.width, 154 XVIP_MIN_WIDTH, XVIP_MAX_WIDTH); 155 format->height = clamp_t(unsigned int, fmt->format.height, 156 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT); 157 } 158 EXPORT_SYMBOL_GPL(xvip_set_format_size); 159 160 /** 161 * xvip_clr_or_set - Clear or set the register with a bitmask 162 * @xvip: Xilinx Video IP device 163 * @addr: address of register 164 * @mask: bitmask to be set or cleared 165 * @set: boolean flag indicating whether to set or clear 166 * 167 * Clear or set the register at address @addr with a bitmask @mask depending on 168 * the boolean flag @set. When the flag @set is true, the bitmask is set in 169 * the register, otherwise the bitmask is cleared from the register 170 * when the flag @set is false. 171 * 172 * Fox eample, this function can be used to set a control with a boolean value 173 * requested by users. If the caller knows whether to set or clear in the first 174 * place, the caller should call xvip_clr() or xvip_set() directly instead of 175 * using this function. 176 */ 177 void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set) 178 { 179 u32 reg; 180 181 reg = xvip_read(xvip, addr); 182 reg = set ? reg | mask : reg & ~mask; 183 xvip_write(xvip, addr, reg); 184 } 185 EXPORT_SYMBOL_GPL(xvip_clr_or_set); 186 187 /** 188 * xvip_clr_and_set - Clear and set the register with a bitmask 189 * @xvip: Xilinx Video IP device 190 * @addr: address of register 191 * @clr: bitmask to be cleared 192 * @set: bitmask to be set 193 * 194 * Clear a bit(s) of mask @clr in the register at address @addr, then set 195 * a bit(s) of mask @set in the register after. 196 */ 197 void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set) 198 { 199 u32 reg; 200 201 reg = xvip_read(xvip, addr); 202 reg &= ~clr; 203 reg |= set; 204 xvip_write(xvip, addr, reg); 205 } 206 EXPORT_SYMBOL_GPL(xvip_clr_and_set); 207 208 int xvip_init_resources(struct xvip_device *xvip) 209 { 210 struct platform_device *pdev = to_platform_device(xvip->dev); 211 struct resource *res; 212 213 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 214 xvip->iomem = devm_ioremap_resource(xvip->dev, res); 215 if (IS_ERR(xvip->iomem)) 216 return PTR_ERR(xvip->iomem); 217 218 xvip->clk = devm_clk_get(xvip->dev, NULL); 219 if (IS_ERR(xvip->clk)) 220 return PTR_ERR(xvip->clk); 221 222 clk_prepare_enable(xvip->clk); 223 return 0; 224 } 225 EXPORT_SYMBOL_GPL(xvip_init_resources); 226 227 void xvip_cleanup_resources(struct xvip_device *xvip) 228 { 229 clk_disable_unprepare(xvip->clk); 230 } 231 EXPORT_SYMBOL_GPL(xvip_cleanup_resources); 232 233 /* ----------------------------------------------------------------------------- 234 * Subdev operations handlers 235 */ 236 237 /** 238 * xvip_enum_mbus_code - Enumerate the media format code 239 * @subdev: V4L2 subdevice 240 * @cfg: V4L2 subdev pad configuration 241 * @code: returning media bus code 242 * 243 * Enumerate the media bus code of the subdevice. Return the corresponding 244 * pad format code. This function only works for subdevices with fixed format 245 * on all pads. Subdevices with multiple format should have their own 246 * function to enumerate mbus codes. 247 * 248 * Return: 0 if the media bus code is found, or -EINVAL if the format index 249 * is not valid. 250 */ 251 int xvip_enum_mbus_code(struct v4l2_subdev *subdev, 252 struct v4l2_subdev_pad_config *cfg, 253 struct v4l2_subdev_mbus_code_enum *code) 254 { 255 struct v4l2_mbus_framefmt *format; 256 257 /* Enumerating frame sizes based on the active configuration isn't 258 * supported yet. 259 */ 260 if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE) 261 return -EINVAL; 262 263 if (code->index) 264 return -EINVAL; 265 266 format = v4l2_subdev_get_try_format(subdev, cfg, code->pad); 267 268 code->code = format->code; 269 270 return 0; 271 } 272 EXPORT_SYMBOL_GPL(xvip_enum_mbus_code); 273 274 /** 275 * xvip_enum_frame_size - Enumerate the media bus frame size 276 * @subdev: V4L2 subdevice 277 * @cfg: V4L2 subdev pad configuration 278 * @fse: returning media bus frame size 279 * 280 * This function is a drop-in implementation of the subdev enum_frame_size pad 281 * operation. It assumes that the subdevice has one sink pad and one source 282 * pad, and that the format on the source pad is always identical to the 283 * format on the sink pad. Entities with different requirements need to 284 * implement their own enum_frame_size handlers. 285 * 286 * Return: 0 if the media bus frame size is found, or -EINVAL 287 * if the index or the code is not valid. 288 */ 289 int xvip_enum_frame_size(struct v4l2_subdev *subdev, 290 struct v4l2_subdev_pad_config *cfg, 291 struct v4l2_subdev_frame_size_enum *fse) 292 { 293 struct v4l2_mbus_framefmt *format; 294 295 /* Enumerating frame sizes based on the active configuration isn't 296 * supported yet. 297 */ 298 if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE) 299 return -EINVAL; 300 301 format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad); 302 303 if (fse->index || fse->code != format->code) 304 return -EINVAL; 305 306 if (fse->pad == XVIP_PAD_SINK) { 307 fse->min_width = XVIP_MIN_WIDTH; 308 fse->max_width = XVIP_MAX_WIDTH; 309 fse->min_height = XVIP_MIN_HEIGHT; 310 fse->max_height = XVIP_MAX_HEIGHT; 311 } else { 312 /* The size on the source pad is fixed and always identical to 313 * the size on the sink pad. 314 */ 315 fse->min_width = format->width; 316 fse->max_width = format->width; 317 fse->min_height = format->height; 318 fse->max_height = format->height; 319 } 320 321 return 0; 322 } 323 EXPORT_SYMBOL_GPL(xvip_enum_frame_size); 324