4 * Copyright (C) 2013-2015 Ideas on Board
5 * Copyright (C) 2013-2015 Xilinx, Inc.
7 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
8 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
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.
15 #include <linux/clk.h>
16 #include <linux/export.h>
17 #include <linux/kernel.h>
19 #include <linux/platform_device.h>
21 #include <dt-bindings/media/xilinx-vip.h>
23 #include "xilinx-vip.h"
25 /* -----------------------------------------------------------------------------
29 static const struct xvip_video_format xvip_video_formats[] = {
30 { XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
31 1, 12, V4L2_PIX_FMT_NV12, 2, 1, 1, 2, "4:2:0, semi-planar, YUV" },
32 { XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
33 1, 12, V4L2_PIX_FMT_NV12M, 2, 2, 1, 2, "4:2:0, 2-plane non-cont" },
34 { XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
35 1, 15, V4L2_PIX_FMT_XV15M, 2, 2, 1, 2, "4:2:0, 10-bit 2-plane non-cont" },
36 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
37 2, 16, V4L2_PIX_FMT_YUYV, 1, 1, 2, 1, "4:2:2, packed, YUYV" },
38 { XVIP_VF_VUY_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
39 2, 16, V4L2_PIX_FMT_UYVY, 1, 1, 2, 1, "4:2:2, packed, UYVY" },
40 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
41 1, 16, V4L2_PIX_FMT_NV16, 2, 1, 1, 1, "4:2:2, semi-planar, YUV" },
42 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
43 1, 16, V4L2_PIX_FMT_NV16M, 2, 2, 1, 1, "4:2:2, 2-plane non-contiguous" },
44 { XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
45 1, 20, V4L2_PIX_FMT_XV20M, 2, 2, 1, 1, "4:2:2, 10-bit 2-plane non-cont" },
46 { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
47 3, 24, V4L2_PIX_FMT_VUY24, 1, 1, 1, 1, "4:4:4, packed, YUYV" },
48 { XVIP_VF_YUVX, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
49 4, 32, V4L2_PIX_FMT_XVUY32, 1, 1, 1, 1, "X:4:4:4, packed, YUYV" },
50 { XVIP_VF_YUVX, 10, NULL, MEDIA_BUS_FMT_VUY8_1X24,
51 4, 32, V4L2_PIX_FMT_XVUY10, 1, 1, 1, 1, "2:10:10:10, packed, XVUY" },
52 { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
53 3, 24, V4L2_PIX_FMT_RGB24, 1, 1, 1, 1, "24-bit RGB" },
54 { XVIP_VF_BGRX, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
55 4, 32, V4L2_PIX_FMT_BGRX32, 1, 1, 1, 1, "x:8:8:8 RGB w/8 bits padding" },
56 { XVIP_VF_XRGB, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
57 4, 32, V4L2_PIX_FMT_XRGB32, 1, 1, 1, 1, "8:8:8:x RGBx w/8 bits padding" },
58 { XVIP_VF_XBGR, 10, NULL, MEDIA_BUS_FMT_RBG888_1X24,
59 4, 32, V4L2_PIX_FMT_XBGR30, 1, 1, 1, 1, "2:10:10:10, packed, XBGR" },
60 { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
61 1, 8, V4L2_PIX_FMT_GREY, 1, 1, 1, 1, "Greyscale 8-bit" },
62 { XVIP_VF_Y_GREY, 10, NULL, MEDIA_BUS_FMT_Y10_1X10,
63 4, 32, V4L2_PIX_FMT_Y10, 1, 1, 1, 1, "2:10:10:10, Grey, xY1Y2Y3Y4" },
64 { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
65 1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit RGGB" },
66 { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
67 1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit GRBG" },
68 { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
69 1, 8, V4L2_PIX_FMT_SGBRG8, 1, 1, 1, 1, "Bayer 8-bit GBRG" },
70 { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
71 1, 8, V4L2_PIX_FMT_SBGGR8, 1, 1, 1, 1, "Bayer 8-bit BGGR" },
75 * xvip_get_format_by_code - Retrieve format information for a media bus code
76 * @code: the format media bus code
78 * Return: a pointer to the format information structure corresponding to the
79 * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can
82 const struct xvip_video_format *xvip_get_format_by_code(unsigned int code)
86 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
87 const struct xvip_video_format *format = &xvip_video_formats[i];
89 if (format->code == code)
93 return ERR_PTR(-EINVAL);
95 EXPORT_SYMBOL_GPL(xvip_get_format_by_code);
98 * xvip_get_format_by_fourcc - Retrieve format information for a 4CC
99 * @fourcc: the format 4CC
101 * Return: a pointer to the format information structure corresponding to the
102 * given V4L2 format @fourcc, or ERR_PTR if no corresponding format can be
105 const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc)
109 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
110 const struct xvip_video_format *format = &xvip_video_formats[i];
112 if (format->fourcc == fourcc)
116 return ERR_PTR(-EINVAL);
118 EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
121 * xvip_bpl_scaling_factor - Retrieve bpl scaling factor for a 4CC
122 * @fourcc: the format 4CC
123 * @numerator: returning numerator of scaling factor
124 * @denominator: returning denominator of scaling factor
126 * Return: Return numerator and denominator values by address
128 void xvip_bpl_scaling_factor(u32 fourcc, u32 *numerator, u32 *denominator)
131 case V4L2_PIX_FMT_XV15M:
132 case V4L2_PIX_FMT_XV20M:
142 EXPORT_SYMBOL_GPL(xvip_bpl_scaling_factor);
145 * xvip_width_padding_factor - Retrieve width's padding factor for a 4CC
146 * @fourcc: the format 4CC
147 * @numerator: returning numerator of padding factor
148 * @denominator: returning denominator of padding factor
150 * Return: Return numerator and denominator values by address
152 void xvip_width_padding_factor(u32 fourcc, u32 *numerator, u32 *denominator)
155 case V4L2_PIX_FMT_XV15M:
156 case V4L2_PIX_FMT_XV20M:
157 /* 32 bits are required per 30 bits of data */
167 EXPORT_SYMBOL_GPL(xvip_width_padding_factor);
170 * xvip_of_get_format - Parse a device tree node and return format information
171 * @node: the device tree node
173 * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties
174 * from the device tree @node passed as an argument and return the corresponding
175 * format information.
177 * Return: a pointer to the format information structure corresponding to the
178 * format name and width, or ERR_PTR if no corresponding format can be found.
180 const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
182 const char *pattern = "mono";
183 unsigned int vf_code;
188 ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
192 ret = of_property_read_u32(node, "xlnx,video-width", &width);
196 if (vf_code == XVIP_VF_MONO_SENSOR)
197 of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
199 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
200 const struct xvip_video_format *format = &xvip_video_formats[i];
202 if (format->vf_code != vf_code || format->width != width)
205 if (vf_code == XVIP_VF_MONO_SENSOR &&
206 strcmp(pattern, format->pattern))
212 return ERR_PTR(-EINVAL);
214 EXPORT_SYMBOL_GPL(xvip_of_get_format);
217 * xvip_set_format_size - Set the media bus frame format size
218 * @format: V4L2 frame format on media bus
219 * @fmt: media bus format
221 * Set the media bus frame format size. The width / height from the subdevice
222 * format are set to the given media bus format. The new format size is stored
223 * in @format. The width and height are clamped using default min / max values.
225 void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
226 const struct v4l2_subdev_format *fmt)
228 format->width = clamp_t(unsigned int, fmt->format.width,
229 XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
230 format->height = clamp_t(unsigned int, fmt->format.height,
231 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
233 EXPORT_SYMBOL_GPL(xvip_set_format_size);
236 * xvip_clr_or_set - Clear or set the register with a bitmask
237 * @xvip: Xilinx Video IP device
238 * @addr: address of register
239 * @mask: bitmask to be set or cleared
240 * @set: boolean flag indicating whether to set or clear
242 * Clear or set the register at address @addr with a bitmask @mask depending on
243 * the boolean flag @set. When the flag @set is true, the bitmask is set in
244 * the register, otherwise the bitmask is cleared from the register
245 * when the flag @set is false.
247 * Fox eample, this function can be used to set a control with a boolean value
248 * requested by users. If the caller knows whether to set or clear in the first
249 * place, the caller should call xvip_clr() or xvip_set() directly instead of
250 * using this function.
252 void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set)
256 reg = xvip_read(xvip, addr);
257 reg = set ? reg | mask : reg & ~mask;
258 xvip_write(xvip, addr, reg);
260 EXPORT_SYMBOL_GPL(xvip_clr_or_set);
263 * xvip_clr_and_set - Clear and set the register with a bitmask
264 * @xvip: Xilinx Video IP device
265 * @addr: address of register
266 * @clr: bitmask to be cleared
267 * @set: bitmask to be set
269 * Clear a bit(s) of mask @clr in the register at address @addr, then set
270 * a bit(s) of mask @set in the register after.
272 void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set)
276 reg = xvip_read(xvip, addr);
279 xvip_write(xvip, addr, reg);
281 EXPORT_SYMBOL_GPL(xvip_clr_and_set);
283 int xvip_init_resources(struct xvip_device *xvip)
285 struct platform_device *pdev = to_platform_device(xvip->dev);
286 struct resource *res;
288 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
289 xvip->iomem = devm_ioremap_resource(xvip->dev, res);
290 if (IS_ERR(xvip->iomem))
291 return PTR_ERR(xvip->iomem);
293 xvip->clk = devm_clk_get(xvip->dev, NULL);
294 if (IS_ERR(xvip->clk))
295 return PTR_ERR(xvip->clk);
297 clk_prepare_enable(xvip->clk);
300 EXPORT_SYMBOL_GPL(xvip_init_resources);
302 void xvip_cleanup_resources(struct xvip_device *xvip)
304 clk_disable_unprepare(xvip->clk);
306 EXPORT_SYMBOL_GPL(xvip_cleanup_resources);
308 /* -----------------------------------------------------------------------------
309 * Subdev operations handlers
313 * xvip_enum_mbus_code - Enumerate the media format code
314 * @subdev: V4L2 subdevice
315 * @cfg: V4L2 subdev pad configuration
316 * @code: returning media bus code
318 * Enumerate the media bus code of the subdevice. Return the corresponding
319 * pad format code. This function only works for subdevices with fixed format
320 * on all pads. Subdevices with multiple format should have their own
321 * function to enumerate mbus codes.
323 * Return: 0 if the media bus code is found, or -EINVAL if the format index
326 int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
327 struct v4l2_subdev_pad_config *cfg,
328 struct v4l2_subdev_mbus_code_enum *code)
330 struct v4l2_mbus_framefmt *format;
332 /* Enumerating frame sizes based on the active configuration isn't
335 if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE)
341 format = v4l2_subdev_get_try_format(subdev, cfg, code->pad);
343 code->code = format->code;
347 EXPORT_SYMBOL_GPL(xvip_enum_mbus_code);
350 * xvip_enum_frame_size - Enumerate the media bus frame size
351 * @subdev: V4L2 subdevice
352 * @cfg: V4L2 subdev pad configuration
353 * @fse: returning media bus frame size
355 * This function is a drop-in implementation of the subdev enum_frame_size pad
356 * operation. It assumes that the subdevice has one sink pad and one source
357 * pad, and that the format on the source pad is always identical to the
358 * format on the sink pad. Entities with different requirements need to
359 * implement their own enum_frame_size handlers.
361 * Return: 0 if the media bus frame size is found, or -EINVAL
362 * if the index or the code is not valid.
364 int xvip_enum_frame_size(struct v4l2_subdev *subdev,
365 struct v4l2_subdev_pad_config *cfg,
366 struct v4l2_subdev_frame_size_enum *fse)
368 struct v4l2_mbus_framefmt *format;
370 /* Enumerating frame sizes based on the active configuration isn't
373 if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE)
376 format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
378 if (fse->index || fse->code != format->code)
381 if (fse->pad == XVIP_PAD_SINK) {
382 fse->min_width = XVIP_MIN_WIDTH;
383 fse->max_width = XVIP_MAX_WIDTH;
384 fse->min_height = XVIP_MIN_HEIGHT;
385 fse->max_height = XVIP_MAX_HEIGHT;
387 /* The size on the source pad is fixed and always identical to
388 * the size on the sink pad.
390 fse->min_width = format->width;
391 fse->max_width = format->width;
392 fse->min_height = format->height;
393 fse->max_height = format->height;
398 EXPORT_SYMBOL_GPL(xvip_enum_frame_size);