162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Xilinx Video IP Core
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013-2015 Ideas on Board
662306a36Sopenharmony_ci * Copyright (C) 2013-2015 Xilinx, Inc.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
962306a36Sopenharmony_ci *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef __XILINX_VIP_H__
1362306a36Sopenharmony_ci#define __XILINX_VIP_H__
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/bitops.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <media/v4l2-subdev.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct clk;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * Minimum and maximum width and height common to most video IP cores. IP
2362306a36Sopenharmony_ci * cores with different requirements must define their own values.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci#define XVIP_MIN_WIDTH			32
2662306a36Sopenharmony_ci#define XVIP_MAX_WIDTH			7680
2762306a36Sopenharmony_ci#define XVIP_MIN_HEIGHT			32
2862306a36Sopenharmony_ci#define XVIP_MAX_HEIGHT			7680
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * Pad IDs. IP cores with multiple inputs or outputs should define their own
3262306a36Sopenharmony_ci * values.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci#define XVIP_PAD_SINK			0
3562306a36Sopenharmony_ci#define XVIP_PAD_SOURCE			1
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* Xilinx Video IP Control Registers */
3862306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL			0x0000
3962306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_SW_ENABLE		BIT(0)
4062306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_REG_UPDATE		BIT(1)
4162306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_BYPASS		BIT(4)
4262306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_TEST_PATTERN		BIT(5)
4362306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_FRAME_SYNC_RESET	BIT(30)
4462306a36Sopenharmony_ci#define XVIP_CTRL_CONTROL_SW_RESET		BIT(31)
4562306a36Sopenharmony_ci#define XVIP_CTRL_STATUS			0x0004
4662306a36Sopenharmony_ci#define XVIP_CTRL_STATUS_PROC_STARTED		BIT(0)
4762306a36Sopenharmony_ci#define XVIP_CTRL_STATUS_EOF			BIT(1)
4862306a36Sopenharmony_ci#define XVIP_CTRL_ERROR				0x0008
4962306a36Sopenharmony_ci#define XVIP_CTRL_ERROR_SLAVE_EOL_EARLY		BIT(0)
5062306a36Sopenharmony_ci#define XVIP_CTRL_ERROR_SLAVE_EOL_LATE		BIT(1)
5162306a36Sopenharmony_ci#define XVIP_CTRL_ERROR_SLAVE_SOF_EARLY		BIT(2)
5262306a36Sopenharmony_ci#define XVIP_CTRL_ERROR_SLAVE_SOF_LATE		BIT(3)
5362306a36Sopenharmony_ci#define XVIP_CTRL_IRQ_ENABLE			0x000c
5462306a36Sopenharmony_ci#define XVIP_CTRL_IRQ_ENABLE_PROC_STARTED	BIT(0)
5562306a36Sopenharmony_ci#define XVIP_CTRL_IRQ_EOF			BIT(1)
5662306a36Sopenharmony_ci#define XVIP_CTRL_VERSION			0x0010
5762306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_MAJOR_MASK		(0xff << 24)
5862306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_MAJOR_SHIFT		24
5962306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_MINOR_MASK		(0xff << 16)
6062306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_MINOR_SHIFT		16
6162306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_REVISION_MASK		(0xf << 12)
6262306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_REVISION_SHIFT	12
6362306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_PATCH_MASK		(0xf << 8)
6462306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_PATCH_SHIFT		8
6562306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_INTERNAL_MASK		(0xff << 0)
6662306a36Sopenharmony_ci#define XVIP_CTRL_VERSION_INTERNAL_SHIFT	0
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Xilinx Video IP Timing Registers */
6962306a36Sopenharmony_ci#define XVIP_ACTIVE_SIZE			0x0020
7062306a36Sopenharmony_ci#define XVIP_ACTIVE_VSIZE_MASK			(0x7ff << 16)
7162306a36Sopenharmony_ci#define XVIP_ACTIVE_VSIZE_SHIFT			16
7262306a36Sopenharmony_ci#define XVIP_ACTIVE_HSIZE_MASK			(0x7ff << 0)
7362306a36Sopenharmony_ci#define XVIP_ACTIVE_HSIZE_SHIFT			0
7462306a36Sopenharmony_ci#define XVIP_ENCODING				0x0028
7562306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_8			(0 << 4)
7662306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_10			(1 << 4)
7762306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_12			(2 << 4)
7862306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_16			(3 << 4)
7962306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_MASK		(3 << 4)
8062306a36Sopenharmony_ci#define XVIP_ENCODING_NBITS_SHIFT		4
8162306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_YUV422	(0 << 0)
8262306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_YUV444	(1 << 0)
8362306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_RGB		(2 << 0)
8462306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_YUV420	(3 << 0)
8562306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_MASK		(3 << 0)
8662306a36Sopenharmony_ci#define XVIP_ENCODING_VIDEO_FORMAT_SHIFT	0
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/**
8962306a36Sopenharmony_ci * struct xvip_device - Xilinx Video IP device structure
9062306a36Sopenharmony_ci * @subdev: V4L2 subdevice
9162306a36Sopenharmony_ci * @dev: (OF) device
9262306a36Sopenharmony_ci * @iomem: device I/O register space remapped to kernel virtual memory
9362306a36Sopenharmony_ci * @clk: video core clock
9462306a36Sopenharmony_ci * @saved_ctrl: saved control register for resume / suspend
9562306a36Sopenharmony_ci */
9662306a36Sopenharmony_cistruct xvip_device {
9762306a36Sopenharmony_ci	struct v4l2_subdev subdev;
9862306a36Sopenharmony_ci	struct device *dev;
9962306a36Sopenharmony_ci	void __iomem *iomem;
10062306a36Sopenharmony_ci	struct clk *clk;
10162306a36Sopenharmony_ci	u32 saved_ctrl;
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/**
10562306a36Sopenharmony_ci * struct xvip_video_format - Xilinx Video IP video format description
10662306a36Sopenharmony_ci * @vf_code: AXI4 video format code
10762306a36Sopenharmony_ci * @width: AXI4 format width in bits per component
10862306a36Sopenharmony_ci * @pattern: CFA pattern for Mono/Sensor formats
10962306a36Sopenharmony_ci * @code: media bus format code
11062306a36Sopenharmony_ci * @bpp: bytes per pixel (when stored in memory)
11162306a36Sopenharmony_ci * @fourcc: V4L2 pixel format FCC identifier
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_cistruct xvip_video_format {
11462306a36Sopenharmony_ci	unsigned int vf_code;
11562306a36Sopenharmony_ci	unsigned int width;
11662306a36Sopenharmony_ci	const char *pattern;
11762306a36Sopenharmony_ci	unsigned int code;
11862306a36Sopenharmony_ci	unsigned int bpp;
11962306a36Sopenharmony_ci	u32 fourcc;
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciconst struct xvip_video_format *xvip_get_format_by_code(unsigned int code);
12362306a36Sopenharmony_ciconst struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc);
12462306a36Sopenharmony_ciconst struct xvip_video_format *xvip_of_get_format(struct device_node *node);
12562306a36Sopenharmony_civoid xvip_set_format_size(struct v4l2_mbus_framefmt *format,
12662306a36Sopenharmony_ci			  const struct v4l2_subdev_format *fmt);
12762306a36Sopenharmony_ciint xvip_enum_mbus_code(struct v4l2_subdev *subdev,
12862306a36Sopenharmony_ci			struct v4l2_subdev_state *sd_state,
12962306a36Sopenharmony_ci			struct v4l2_subdev_mbus_code_enum *code);
13062306a36Sopenharmony_ciint xvip_enum_frame_size(struct v4l2_subdev *subdev,
13162306a36Sopenharmony_ci			 struct v4l2_subdev_state *sd_state,
13262306a36Sopenharmony_ci			 struct v4l2_subdev_frame_size_enum *fse);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic inline u32 xvip_read(struct xvip_device *xvip, u32 addr)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	return ioread32(xvip->iomem + addr);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline void xvip_write(struct xvip_device *xvip, u32 addr, u32 value)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	iowrite32(value, xvip->iomem + addr);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline void xvip_clr(struct xvip_device *xvip, u32 addr, u32 clr)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	xvip_write(xvip, addr, xvip_read(xvip, addr) & ~clr);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline void xvip_set(struct xvip_device *xvip, u32 addr, u32 set)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	xvip_write(xvip, addr, xvip_read(xvip, addr) | set);
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_civoid xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set);
15562306a36Sopenharmony_civoid xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciint xvip_init_resources(struct xvip_device *xvip);
15862306a36Sopenharmony_civoid xvip_cleanup_resources(struct xvip_device *xvip);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic inline void xvip_reset(struct xvip_device *xvip)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	xvip_write(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_RESET);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic inline void xvip_start(struct xvip_device *xvip)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	xvip_set(xvip, XVIP_CTRL_CONTROL,
16862306a36Sopenharmony_ci		 XVIP_CTRL_CONTROL_SW_ENABLE | XVIP_CTRL_CONTROL_REG_UPDATE);
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic inline void xvip_stop(struct xvip_device *xvip)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_ENABLE);
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline void xvip_resume(struct xvip_device *xvip)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	xvip_write(xvip, XVIP_CTRL_CONTROL,
17962306a36Sopenharmony_ci		   xvip->saved_ctrl | XVIP_CTRL_CONTROL_SW_ENABLE);
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic inline void xvip_suspend(struct xvip_device *xvip)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	xvip->saved_ctrl = xvip_read(xvip, XVIP_CTRL_CONTROL);
18562306a36Sopenharmony_ci	xvip_write(xvip, XVIP_CTRL_CONTROL,
18662306a36Sopenharmony_ci		   xvip->saved_ctrl & ~XVIP_CTRL_CONTROL_SW_ENABLE);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic inline void xvip_set_frame_size(struct xvip_device *xvip,
19062306a36Sopenharmony_ci				       const struct v4l2_mbus_framefmt *format)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	xvip_write(xvip, XVIP_ACTIVE_SIZE,
19362306a36Sopenharmony_ci		   (format->height << XVIP_ACTIVE_VSIZE_SHIFT) |
19462306a36Sopenharmony_ci		   (format->width << XVIP_ACTIVE_HSIZE_SHIFT));
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline void xvip_get_frame_size(struct xvip_device *xvip,
19862306a36Sopenharmony_ci				       struct v4l2_mbus_framefmt *format)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	u32 reg;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	reg = xvip_read(xvip, XVIP_ACTIVE_SIZE);
20362306a36Sopenharmony_ci	format->width = (reg & XVIP_ACTIVE_HSIZE_MASK) >>
20462306a36Sopenharmony_ci			XVIP_ACTIVE_HSIZE_SHIFT;
20562306a36Sopenharmony_ci	format->height = (reg & XVIP_ACTIVE_VSIZE_MASK) >>
20662306a36Sopenharmony_ci			 XVIP_ACTIVE_VSIZE_SHIFT;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic inline void xvip_enable_reg_update(struct xvip_device *xvip)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	xvip_set(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic inline void xvip_disable_reg_update(struct xvip_device *xvip)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic inline void xvip_print_version(struct xvip_device *xvip)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	u32 version;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	version = xvip_read(xvip, XVIP_CTRL_VERSION);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	dev_info(xvip->dev, "device found, version %u.%02x%x\n",
22662306a36Sopenharmony_ci		 ((version & XVIP_CTRL_VERSION_MAJOR_MASK) >>
22762306a36Sopenharmony_ci		  XVIP_CTRL_VERSION_MAJOR_SHIFT),
22862306a36Sopenharmony_ci		 ((version & XVIP_CTRL_VERSION_MINOR_MASK) >>
22962306a36Sopenharmony_ci		  XVIP_CTRL_VERSION_MINOR_SHIFT),
23062306a36Sopenharmony_ci		 ((version & XVIP_CTRL_VERSION_REVISION_MASK) >>
23162306a36Sopenharmony_ci		  XVIP_CTRL_VERSION_REVISION_SHIFT));
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#endif /* __XILINX_VIP_H__ */
235