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_VYYUYY10_4X20,
35 1, 12, V4L2_PIX_FMT_XV15, 2, 1, 2, 2, "4:2:0, 10-bit 2-plane cont" },
36 { XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY10_4X20,
37 1, 12, V4L2_PIX_FMT_XV15M, 2, 2, 1, 2, "4:2:0, 10-bit 2-plane non-cont" },
38 { XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
39 1, 12, V4L2_PIX_FMT_X012, 2, 1, 2, 2, "4:2:0, 12-bit 2-plane cont" },
40 { XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
41 1, 12, V4L2_PIX_FMT_X012M, 2, 2, 1, 2, "4:2:0, 12-bit 2-plane non-cont" },
42 { XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
43 2, 12, V4L2_PIX_FMT_X016, 2, 1, 2, 2, "4:2:0, 16-bit 2-plane cont" },
44 { XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
45 2, 12, V4L2_PIX_FMT_X016M, 2, 2, 1, 2, "4:2:0, 16-bit 2-plane non-cont" },
46 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
47 2, 16, V4L2_PIX_FMT_YUYV, 1, 1, 2, 1, "4:2:2, packed, YUYV" },
48 { XVIP_VF_VUY_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
49 2, 16, V4L2_PIX_FMT_UYVY, 1, 1, 2, 1, "4:2:2, packed, UYVY" },
50 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
51 1, 16, V4L2_PIX_FMT_NV16, 2, 1, 1, 1, "4:2:2, semi-planar, YUV" },
52 { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
53 1, 16, V4L2_PIX_FMT_NV16M, 2, 2, 1, 1, "4:2:2, 2-plane non-contiguous" },
54 { XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
55 1, 16, V4L2_PIX_FMT_XV20, 2, 1, 2, 1, "4:2:2, 10-bit 2-plane cont" },
56 { XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
57 1, 16, V4L2_PIX_FMT_XV20M, 2, 2, 1, 1, "4:2:2, 10-bit 2-plane non-cont" },
58 { XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
59 1, 16, V4L2_PIX_FMT_X212, 2, 1, 2, 1, "4:2:2, 12-bit 2-plane cont" },
60 { XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
61 1, 16, V4L2_PIX_FMT_X212M, 2, 2, 1, 1, "4:2:2, 12-bit 2-plane non-cont" },
62 { XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
63 2, 16, V4L2_PIX_FMT_X216, 2, 1, 2, 1, "4:2:2, 16-bit 2-plane cont" },
64 { XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
65 2, 16, V4L2_PIX_FMT_X216M, 2, 2, 1, 1, "4:2:2, 16-bit 2-plane non-cont" },
66 { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
67 3, 24, V4L2_PIX_FMT_VUY24, 1, 1, 1, 1, "4:4:4, packed, YUYV" },
68 { XVIP_VF_YUVX, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
69 4, 32, V4L2_PIX_FMT_XVUY32, 1, 1, 1, 1, "X:4:4:4, packed, YUYV" },
70 { XVIP_VF_YUVX, 10, NULL, MEDIA_BUS_FMT_VUY10_1X30,
71 3, 32, V4L2_PIX_FMT_XVUY10, 1, 1, 1, 1, "2:10:10:10, packed, XVUY" },
72 { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
73 3, 24, V4L2_PIX_FMT_BGR24, 1, 1, 1, 1, "24-bit RGB" },
74 { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
75 3, 24, V4L2_PIX_FMT_RGB24, 1, 1, 1, 1, "24-bit RGB" },
76 { XVIP_VF_BGRX, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
77 4, 32, V4L2_PIX_FMT_BGRX32, 1, 1, 1, 1, "x:8:8:8 RGB w/8 bits padding" },
78 { XVIP_VF_XRGB, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
79 4, 32, V4L2_PIX_FMT_XBGR32, 1, 1, 1, 1, "8:8:8:x RGBx w/8 bits padding" },
80 { XVIP_VF_XBGR, 10, NULL, MEDIA_BUS_FMT_RBG101010_1X30,
81 3, 32, V4L2_PIX_FMT_XBGR30, 1, 1, 1, 1, "2:10:10:10, packed, XBGR" },
82 { XVIP_VF_XBGR, 12, NULL, MEDIA_BUS_FMT_RBG121212_1X36,
83 3, 40, V4L2_PIX_FMT_XBGR40, 1, 1, 1, 1, "4:12:12:12, packed, XBGR" },
84 { XVIP_VF_RBG, 16, NULL, MEDIA_BUS_FMT_RBG161616_1X48,
85 6, 48, V4L2_PIX_FMT_BGR48, 1, 1, 1, 1, "48-bit RGB" },
86 { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
87 1, 8, V4L2_PIX_FMT_GREY, 1, 1, 1, 1, "Greyscale 8-bit" },
88 { XVIP_VF_Y_GREY, 10, NULL, MEDIA_BUS_FMT_Y10_1X10,
89 4, 32, V4L2_PIX_FMT_XY10, 1, 1, 1, 1, "2:10:10:10, Grey, xY1Y2Y3Y4" },
90 { XVIP_VF_Y_GREY, 12, NULL, MEDIA_BUS_FMT_Y12_1X12,
91 1, 12, V4L2_PIX_FMT_XY12, 1, 1, 1, 1, "4:12:12:12, packed, xY1Y2Y3" },
92 { XVIP_VF_Y_GREY, 16, NULL, MEDIA_BUS_FMT_Y16_1X16,
93 2, 16, V4L2_PIX_FMT_Y16, 1, 1, 1, 1, "Greyscale 16-bit" },
94 { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
95 1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit RGGB" },
96 { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
97 1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit GRBG" },
98 { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
99 1, 8, V4L2_PIX_FMT_SGBRG8, 1, 1, 1, 1, "Bayer 8-bit GBRG" },
100 { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
101 1, 8, V4L2_PIX_FMT_SBGGR8, 1, 1, 1, 1, "Bayer 8-bit BGGR" },
102 { XVIP_VF_MONO_SENSOR, 12, "rggb", MEDIA_BUS_FMT_SRGGB12_1X12,
103 1, 12, V4L2_PIX_FMT_SRGGB12, 1, 1, 1, 1, "Bayer 12-bit RGGB" },
104 { XVIP_VF_MONO_SENSOR, 12, "grbg", MEDIA_BUS_FMT_SGRBG12_1X12,
105 1, 12, V4L2_PIX_FMT_SGRBG12, 1, 1, 1, 1, "Bayer 12-bit GRBG" },
106 { XVIP_VF_MONO_SENSOR, 12, "gbrg", MEDIA_BUS_FMT_SGBRG12_1X12,
107 1, 12, V4L2_PIX_FMT_SGBRG12, 1, 1, 1, 1, "Bayer 12-bit GBRG" },
108 { XVIP_VF_MONO_SENSOR, 12, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
109 1, 12, V4L2_PIX_FMT_SBGGR12, 1, 1, 1, 1, "Bayer 12-bit BGGR" },
110 { XVIP_VF_MONO_SENSOR, 16, "rggb", MEDIA_BUS_FMT_SRGGB16_1X16,
111 1, 16, V4L2_PIX_FMT_SRGGB16, 1, 1, 1, 1, "Bayer 16-bit RGGB" },
112 { XVIP_VF_MONO_SENSOR, 16, "grbg", MEDIA_BUS_FMT_SGRBG16_1X16,
113 1, 12, V4L2_PIX_FMT_SGRBG16, 1, 1, 1, 1, "Bayer 16-bit GRBG" },
114 { XVIP_VF_MONO_SENSOR, 16, "gbrg", MEDIA_BUS_FMT_SGBRG16_1X16,
115 1, 12, V4L2_PIX_FMT_SGBRG16, 1, 1, 1, 1, "Bayer 16-bit GBRG" },
116 { XVIP_VF_MONO_SENSOR, 16, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
117 1, 12, V4L2_PIX_FMT_SBGGR16, 1, 1, 1, 1, "Bayer 16-bit BGGR" },
121 * xvip_get_format_by_code - Retrieve format information for a media bus code
122 * @code: the format media bus code
124 * Return: a pointer to the format information structure corresponding to the
125 * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can
128 const struct xvip_video_format *xvip_get_format_by_code(unsigned int code)
132 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
133 const struct xvip_video_format *format = &xvip_video_formats[i];
135 if (format->code == code)
139 return ERR_PTR(-EINVAL);
141 EXPORT_SYMBOL_GPL(xvip_get_format_by_code);
144 * xvip_get_format_by_fourcc - Retrieve format information for a 4CC
145 * @fourcc: the format 4CC
147 * Return: a pointer to the format information structure corresponding to the
148 * given V4L2 format @fourcc, or ERR_PTR if no corresponding format can be
151 const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc)
155 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
156 const struct xvip_video_format *format = &xvip_video_formats[i];
158 if (format->fourcc == fourcc)
162 return ERR_PTR(-EINVAL);
164 EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
167 * xvip_bpl_scaling_factor - Retrieve bpl scaling factor for a 4CC
168 * @fourcc: the format 4CC
169 * @numerator: returning numerator of scaling factor
170 * @denominator: returning denominator of scaling factor
172 * Return: Return numerator and denominator values by address
174 void xvip_bpl_scaling_factor(u32 fourcc, u32 *numerator, u32 *denominator)
177 case V4L2_PIX_FMT_XY10:
178 case V4L2_PIX_FMT_XV15:
179 case V4L2_PIX_FMT_XV20:
180 case V4L2_PIX_FMT_XV15M:
181 case V4L2_PIX_FMT_XV20M:
182 case V4L2_PIX_FMT_XBGR30:
183 case V4L2_PIX_FMT_XVUY10:
187 case V4L2_PIX_FMT_XBGR40:
188 case V4L2_PIX_FMT_XY12:
189 case V4L2_PIX_FMT_X012:
190 case V4L2_PIX_FMT_X012M:
191 case V4L2_PIX_FMT_X212:
192 case V4L2_PIX_FMT_X212M:
202 EXPORT_SYMBOL_GPL(xvip_bpl_scaling_factor);
205 * xvip_width_padding_factor - Retrieve width's padding factor for a 4CC
206 * @fourcc: the format 4CC
207 * @numerator: returning numerator of padding factor
208 * @denominator: returning denominator of padding factor
210 * Return: Return numerator and denominator values by address
212 void xvip_width_padding_factor(u32 fourcc, u32 *numerator, u32 *denominator)
215 case V4L2_PIX_FMT_XY10:
216 case V4L2_PIX_FMT_XV15:
217 case V4L2_PIX_FMT_XV20:
218 case V4L2_PIX_FMT_XV15M:
219 case V4L2_PIX_FMT_XV20M:
220 case V4L2_PIX_FMT_XBGR30:
221 case V4L2_PIX_FMT_XVUY10:
222 /* 32 bits are required per 30 bits of data */
226 case V4L2_PIX_FMT_XBGR40:
227 case V4L2_PIX_FMT_XY12:
228 case V4L2_PIX_FMT_X012:
229 case V4L2_PIX_FMT_X012M:
230 case V4L2_PIX_FMT_X212:
231 case V4L2_PIX_FMT_X212M:
241 EXPORT_SYMBOL_GPL(xvip_width_padding_factor);
244 * xvip_of_get_format - Parse a device tree node and return format information
245 * @node: the device tree node
247 * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties
248 * from the device tree @node passed as an argument and return the corresponding
249 * format information.
251 * Return: a pointer to the format information structure corresponding to the
252 * format name and width, or ERR_PTR if no corresponding format can be found.
254 const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
256 const char *pattern = "mono";
257 unsigned int vf_code;
262 ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
266 ret = of_property_read_u32(node, "xlnx,video-width", &width);
270 if (vf_code == XVIP_VF_MONO_SENSOR)
271 of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
273 for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
274 const struct xvip_video_format *format = &xvip_video_formats[i];
276 if (format->vf_code != vf_code || format->width != width)
279 if (vf_code == XVIP_VF_MONO_SENSOR &&
280 strcmp(pattern, format->pattern))
286 return ERR_PTR(-EINVAL);
288 EXPORT_SYMBOL_GPL(xvip_of_get_format);
291 * xvip_set_format_size - Set the media bus frame format size
292 * @format: V4L2 frame format on media bus
293 * @fmt: media bus format
295 * Set the media bus frame format size. The width / height from the subdevice
296 * format are set to the given media bus format. The new format size is stored
297 * in @format. The width and height are clamped using default min / max values.
299 void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
300 const struct v4l2_subdev_format *fmt)
302 format->width = clamp_t(unsigned int, fmt->format.width,
303 XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
304 format->height = clamp_t(unsigned int, fmt->format.height,
305 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
307 EXPORT_SYMBOL_GPL(xvip_set_format_size);
310 * xvip_clr_or_set - Clear or set the register with a bitmask
311 * @xvip: Xilinx Video IP device
312 * @addr: address of register
313 * @mask: bitmask to be set or cleared
314 * @set: boolean flag indicating whether to set or clear
316 * Clear or set the register at address @addr with a bitmask @mask depending on
317 * the boolean flag @set. When the flag @set is true, the bitmask is set in
318 * the register, otherwise the bitmask is cleared from the register
319 * when the flag @set is false.
321 * Fox eample, this function can be used to set a control with a boolean value
322 * requested by users. If the caller knows whether to set or clear in the first
323 * place, the caller should call xvip_clr() or xvip_set() directly instead of
324 * using this function.
326 void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set)
330 reg = xvip_read(xvip, addr);
331 reg = set ? reg | mask : reg & ~mask;
332 xvip_write(xvip, addr, reg);
334 EXPORT_SYMBOL_GPL(xvip_clr_or_set);
337 * xvip_clr_and_set - Clear and set the register with a bitmask
338 * @xvip: Xilinx Video IP device
339 * @addr: address of register
340 * @clr: bitmask to be cleared
341 * @set: bitmask to be set
343 * Clear a bit(s) of mask @clr in the register at address @addr, then set
344 * a bit(s) of mask @set in the register after.
346 void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set)
350 reg = xvip_read(xvip, addr);
353 xvip_write(xvip, addr, reg);
355 EXPORT_SYMBOL_GPL(xvip_clr_and_set);
357 int xvip_init_resources(struct xvip_device *xvip)
359 struct platform_device *pdev = to_platform_device(xvip->dev);
360 struct resource *res;
362 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
363 xvip->iomem = devm_ioremap_resource(xvip->dev, res);
364 if (IS_ERR(xvip->iomem))
365 return PTR_ERR(xvip->iomem);
367 xvip->clk = devm_clk_get(xvip->dev, NULL);
368 if (IS_ERR(xvip->clk))
369 return PTR_ERR(xvip->clk);
371 clk_prepare_enable(xvip->clk);
374 EXPORT_SYMBOL_GPL(xvip_init_resources);
376 void xvip_cleanup_resources(struct xvip_device *xvip)
378 clk_disable_unprepare(xvip->clk);
380 EXPORT_SYMBOL_GPL(xvip_cleanup_resources);
382 /* -----------------------------------------------------------------------------
383 * Subdev operations handlers
387 * xvip_enum_mbus_code - Enumerate the media format code
388 * @subdev: V4L2 subdevice
389 * @cfg: V4L2 subdev pad configuration
390 * @code: returning media bus code
392 * Enumerate the media bus code of the subdevice. Return the corresponding
393 * pad format code. This function only works for subdevices with fixed format
394 * on all pads. Subdevices with multiple format should have their own
395 * function to enumerate mbus codes.
397 * Return: 0 if the media bus code is found, or -EINVAL if the format index
400 int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
401 struct v4l2_subdev_pad_config *cfg,
402 struct v4l2_subdev_mbus_code_enum *code)
404 struct v4l2_mbus_framefmt *format;
406 /* Enumerating frame sizes based on the active configuration isn't
409 if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE)
415 format = v4l2_subdev_get_try_format(subdev, cfg, code->pad);
417 code->code = format->code;
421 EXPORT_SYMBOL_GPL(xvip_enum_mbus_code);
424 * xvip_enum_frame_size - Enumerate the media bus frame size
425 * @subdev: V4L2 subdevice
426 * @cfg: V4L2 subdev pad configuration
427 * @fse: returning media bus frame size
429 * This function is a drop-in implementation of the subdev enum_frame_size pad
430 * operation. It assumes that the subdevice has one sink pad and one source
431 * pad, and that the format on the source pad is always identical to the
432 * format on the sink pad. Entities with different requirements need to
433 * implement their own enum_frame_size handlers.
435 * Return: 0 if the media bus frame size is found, or -EINVAL
436 * if the index or the code is not valid.
438 int xvip_enum_frame_size(struct v4l2_subdev *subdev,
439 struct v4l2_subdev_pad_config *cfg,
440 struct v4l2_subdev_frame_size_enum *fse)
442 struct v4l2_mbus_framefmt *format;
444 /* Enumerating frame sizes based on the active configuration isn't
447 if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE)
450 format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
452 if (fse->index || fse->code != format->code)
455 if (fse->pad == XVIP_PAD_SINK) {
456 fse->min_width = XVIP_MIN_WIDTH;
457 fse->max_width = XVIP_MAX_WIDTH;
458 fse->min_height = XVIP_MIN_HEIGHT;
459 fse->max_height = XVIP_MAX_HEIGHT;
461 /* The size on the source pad is fixed and always identical to
462 * the size on the sink pad.
464 fse->min_width = format->width;
465 fse->max_width = format->width;
466 fse->min_height = format->height;
467 fse->max_height = format->height;
472 EXPORT_SYMBOL_GPL(xvip_enum_frame_size);