cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xilinx-tpg.c (24759B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Xilinx Test Pattern Generator
      4 *
      5 * Copyright (C) 2013-2015 Ideas on Board
      6 * Copyright (C) 2013-2015 Xilinx, Inc.
      7 *
      8 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
      9 *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
     10 */
     11
     12#include <linux/device.h>
     13#include <linux/gpio/consumer.h>
     14#include <linux/module.h>
     15#include <linux/of.h>
     16#include <linux/platform_device.h>
     17#include <linux/xilinx-v4l2-controls.h>
     18
     19#include <media/v4l2-async.h>
     20#include <media/v4l2-ctrls.h>
     21#include <media/v4l2-subdev.h>
     22
     23#include "xilinx-vip.h"
     24#include "xilinx-vtc.h"
     25
     26#define XTPG_CTRL_STATUS_SLAVE_ERROR		(1 << 16)
     27#define XTPG_CTRL_IRQ_SLAVE_ERROR		(1 << 16)
     28
     29#define XTPG_PATTERN_CONTROL			0x0100
     30#define XTPG_PATTERN_MASK			(0xf << 0)
     31#define XTPG_PATTERN_CONTROL_CROSS_HAIRS	(1 << 4)
     32#define XTPG_PATTERN_CONTROL_MOVING_BOX		(1 << 5)
     33#define XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT	6
     34#define XTPG_PATTERN_CONTROL_COLOR_MASK_MASK	(0xf << 6)
     35#define XTPG_PATTERN_CONTROL_STUCK_PIXEL	(1 << 9)
     36#define XTPG_PATTERN_CONTROL_NOISE		(1 << 10)
     37#define XTPG_PATTERN_CONTROL_MOTION		(1 << 12)
     38#define XTPG_MOTION_SPEED			0x0104
     39#define XTPG_CROSS_HAIRS			0x0108
     40#define XTPG_CROSS_HAIRS_ROW_SHIFT		0
     41#define XTPG_CROSS_HAIRS_ROW_MASK		(0xfff << 0)
     42#define XTPG_CROSS_HAIRS_COLUMN_SHIFT		16
     43#define XTPG_CROSS_HAIRS_COLUMN_MASK		(0xfff << 16)
     44#define XTPG_ZPLATE_HOR_CONTROL			0x010c
     45#define XTPG_ZPLATE_VER_CONTROL			0x0110
     46#define XTPG_ZPLATE_START_SHIFT			0
     47#define XTPG_ZPLATE_START_MASK			(0xffff << 0)
     48#define XTPG_ZPLATE_SPEED_SHIFT			16
     49#define XTPG_ZPLATE_SPEED_MASK			(0xffff << 16)
     50#define XTPG_BOX_SIZE				0x0114
     51#define XTPG_BOX_COLOR				0x0118
     52#define XTPG_STUCK_PIXEL_THRESH			0x011c
     53#define XTPG_NOISE_GAIN				0x0120
     54#define XTPG_BAYER_PHASE			0x0124
     55#define XTPG_BAYER_PHASE_RGGB			0
     56#define XTPG_BAYER_PHASE_GRBG			1
     57#define XTPG_BAYER_PHASE_GBRG			2
     58#define XTPG_BAYER_PHASE_BGGR			3
     59#define XTPG_BAYER_PHASE_OFF			4
     60
     61/*
     62 * The minimum blanking value is one clock cycle for the front porch, one clock
     63 * cycle for the sync pulse and one clock cycle for the back porch.
     64 */
     65#define XTPG_MIN_HBLANK			3
     66#define XTPG_MAX_HBLANK			(XVTC_MAX_HSIZE - XVIP_MIN_WIDTH)
     67#define XTPG_MIN_VBLANK			3
     68#define XTPG_MAX_VBLANK			(XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT)
     69
     70/**
     71 * struct xtpg_device - Xilinx Test Pattern Generator device structure
     72 * @xvip: Xilinx Video IP device
     73 * @pads: media pads
     74 * @npads: number of pads (1 or 2)
     75 * @has_input: whether an input is connected to the sink pad
     76 * @formats: active V4L2 media bus format for each pad
     77 * @default_format: default V4L2 media bus format
     78 * @vip_format: format information corresponding to the active format
     79 * @bayer: boolean flag if TPG is set to any bayer format
     80 * @ctrl_handler: control handler
     81 * @hblank: horizontal blanking control
     82 * @vblank: vertical blanking control
     83 * @pattern: test pattern control
     84 * @streaming: is the video stream active
     85 * @vtc: video timing controller
     86 * @vtmux_gpio: video timing mux GPIO
     87 */
     88struct xtpg_device {
     89	struct xvip_device xvip;
     90
     91	struct media_pad pads[2];
     92	unsigned int npads;
     93	bool has_input;
     94
     95	struct v4l2_mbus_framefmt formats[2];
     96	struct v4l2_mbus_framefmt default_format;
     97	const struct xvip_video_format *vip_format;
     98	bool bayer;
     99
    100	struct v4l2_ctrl_handler ctrl_handler;
    101	struct v4l2_ctrl *hblank;
    102	struct v4l2_ctrl *vblank;
    103	struct v4l2_ctrl *pattern;
    104	bool streaming;
    105
    106	struct xvtc_device *vtc;
    107	struct gpio_desc *vtmux_gpio;
    108};
    109
    110static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
    111{
    112	return container_of(subdev, struct xtpg_device, xvip.subdev);
    113}
    114
    115static u32 xtpg_get_bayer_phase(unsigned int code)
    116{
    117	switch (code) {
    118	case MEDIA_BUS_FMT_SRGGB8_1X8:
    119		return XTPG_BAYER_PHASE_RGGB;
    120	case MEDIA_BUS_FMT_SGRBG8_1X8:
    121		return XTPG_BAYER_PHASE_GRBG;
    122	case MEDIA_BUS_FMT_SGBRG8_1X8:
    123		return XTPG_BAYER_PHASE_GBRG;
    124	case MEDIA_BUS_FMT_SBGGR8_1X8:
    125		return XTPG_BAYER_PHASE_BGGR;
    126	default:
    127		return XTPG_BAYER_PHASE_OFF;
    128	}
    129}
    130
    131static void __xtpg_update_pattern_control(struct xtpg_device *xtpg,
    132					  bool passthrough, bool pattern)
    133{
    134	u32 pattern_mask = (1 << (xtpg->pattern->maximum + 1)) - 1;
    135
    136	/*
    137	 * If the TPG has no sink pad or no input connected to its sink pad
    138	 * passthrough mode can't be enabled.
    139	 */
    140	if (xtpg->npads == 1 || !xtpg->has_input)
    141		passthrough = false;
    142
    143	/* If passthrough mode is allowed unmask bit 0. */
    144	if (passthrough)
    145		pattern_mask &= ~1;
    146
    147	/* If test pattern mode is allowed unmask all other bits. */
    148	if (pattern)
    149		pattern_mask &= 1;
    150
    151	__v4l2_ctrl_modify_range(xtpg->pattern, 0, xtpg->pattern->maximum,
    152				 pattern_mask, pattern ? 9 : 0);
    153}
    154
    155static void xtpg_update_pattern_control(struct xtpg_device *xtpg,
    156					bool passthrough, bool pattern)
    157{
    158	mutex_lock(xtpg->ctrl_handler.lock);
    159	__xtpg_update_pattern_control(xtpg, passthrough, pattern);
    160	mutex_unlock(xtpg->ctrl_handler.lock);
    161}
    162
    163/* -----------------------------------------------------------------------------
    164 * V4L2 Subdevice Video Operations
    165 */
    166
    167static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable)
    168{
    169	struct xtpg_device *xtpg = to_tpg(subdev);
    170	unsigned int width = xtpg->formats[0].width;
    171	unsigned int height = xtpg->formats[0].height;
    172	bool passthrough;
    173	u32 bayer_phase;
    174
    175	if (!enable) {
    176		xvip_stop(&xtpg->xvip);
    177		if (xtpg->vtc)
    178			xvtc_generator_stop(xtpg->vtc);
    179
    180		xtpg_update_pattern_control(xtpg, true, true);
    181		xtpg->streaming = false;
    182		return 0;
    183	}
    184
    185	xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
    186
    187	if (xtpg->vtc) {
    188		struct xvtc_config config = {
    189			.hblank_start = width,
    190			.hsync_start = width + 1,
    191			.vblank_start = height,
    192			.vsync_start = height + 1,
    193		};
    194		unsigned int htotal;
    195		unsigned int vtotal;
    196
    197		htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
    198			       v4l2_ctrl_g_ctrl(xtpg->hblank) + width);
    199		vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
    200			       v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
    201
    202		config.hsync_end = htotal - 1;
    203		config.hsize = htotal;
    204		config.vsync_end = vtotal - 1;
    205		config.vsize = vtotal;
    206
    207		xvtc_generator_start(xtpg->vtc, &config);
    208	}
    209
    210	/*
    211	 * Configure the bayer phase and video timing mux based on the
    212	 * operation mode (passthrough or test pattern generation). The test
    213	 * pattern can be modified by the control set handler, we thus need to
    214	 * take the control lock here to avoid races.
    215	 */
    216	mutex_lock(xtpg->ctrl_handler.lock);
    217
    218	xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    219			 XTPG_PATTERN_MASK, xtpg->pattern->cur.val);
    220
    221	/*
    222	 * Switching between passthrough and test pattern generation modes isn't
    223	 * allowed during streaming, update the control range accordingly.
    224	 */
    225	passthrough = xtpg->pattern->cur.val == 0;
    226	__xtpg_update_pattern_control(xtpg, passthrough, !passthrough);
    227
    228	xtpg->streaming = true;
    229
    230	mutex_unlock(xtpg->ctrl_handler.lock);
    231
    232	/*
    233	 * For TPG v5.0, the bayer phase needs to be off for the pass through
    234	 * mode, otherwise the external input would be subsampled.
    235	 */
    236	bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
    237		    : xtpg_get_bayer_phase(xtpg->formats[0].code);
    238	xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
    239
    240	if (xtpg->vtmux_gpio)
    241		gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
    242
    243	xvip_start(&xtpg->xvip);
    244
    245	return 0;
    246}
    247
    248/* -----------------------------------------------------------------------------
    249 * V4L2 Subdevice Pad Operations
    250 */
    251
    252static struct v4l2_mbus_framefmt *
    253__xtpg_get_pad_format(struct xtpg_device *xtpg,
    254		      struct v4l2_subdev_state *sd_state,
    255		      unsigned int pad, u32 which)
    256{
    257	switch (which) {
    258	case V4L2_SUBDEV_FORMAT_TRY:
    259		return v4l2_subdev_get_try_format(&xtpg->xvip.subdev,
    260						  sd_state, pad);
    261	case V4L2_SUBDEV_FORMAT_ACTIVE:
    262		return &xtpg->formats[pad];
    263	default:
    264		return NULL;
    265	}
    266}
    267
    268static int xtpg_get_format(struct v4l2_subdev *subdev,
    269			   struct v4l2_subdev_state *sd_state,
    270			   struct v4l2_subdev_format *fmt)
    271{
    272	struct xtpg_device *xtpg = to_tpg(subdev);
    273
    274	fmt->format = *__xtpg_get_pad_format(xtpg, sd_state, fmt->pad,
    275					     fmt->which);
    276
    277	return 0;
    278}
    279
    280static int xtpg_set_format(struct v4l2_subdev *subdev,
    281			   struct v4l2_subdev_state *sd_state,
    282			   struct v4l2_subdev_format *fmt)
    283{
    284	struct xtpg_device *xtpg = to_tpg(subdev);
    285	struct v4l2_mbus_framefmt *__format;
    286	u32 bayer_phase;
    287
    288	__format = __xtpg_get_pad_format(xtpg, sd_state, fmt->pad, fmt->which);
    289
    290	/* In two pads mode the source pad format is always identical to the
    291	 * sink pad format.
    292	 */
    293	if (xtpg->npads == 2 && fmt->pad == 1) {
    294		fmt->format = *__format;
    295		return 0;
    296	}
    297
    298	/* Bayer phase is configurable at runtime */
    299	if (xtpg->bayer) {
    300		bayer_phase = xtpg_get_bayer_phase(fmt->format.code);
    301		if (bayer_phase != XTPG_BAYER_PHASE_OFF)
    302			__format->code = fmt->format.code;
    303	}
    304
    305	xvip_set_format_size(__format, fmt);
    306
    307	fmt->format = *__format;
    308
    309	/* Propagate the format to the source pad. */
    310	if (xtpg->npads == 2) {
    311		__format = __xtpg_get_pad_format(xtpg, sd_state, 1,
    312						 fmt->which);
    313		*__format = fmt->format;
    314	}
    315
    316	return 0;
    317}
    318
    319/* -----------------------------------------------------------------------------
    320 * V4L2 Subdevice Operations
    321 */
    322
    323static int xtpg_enum_frame_size(struct v4l2_subdev *subdev,
    324				struct v4l2_subdev_state *sd_state,
    325				struct v4l2_subdev_frame_size_enum *fse)
    326{
    327	struct v4l2_mbus_framefmt *format;
    328
    329	format = v4l2_subdev_get_try_format(subdev, sd_state, fse->pad);
    330
    331	if (fse->index || fse->code != format->code)
    332		return -EINVAL;
    333
    334	/* Min / max values for pad 0 is always fixed in both one and two pads
    335	 * modes. In two pads mode, the source pad(= 1) size is identical to
    336	 * the sink pad size */
    337	if (fse->pad == 0) {
    338		fse->min_width = XVIP_MIN_WIDTH;
    339		fse->max_width = XVIP_MAX_WIDTH;
    340		fse->min_height = XVIP_MIN_HEIGHT;
    341		fse->max_height = XVIP_MAX_HEIGHT;
    342	} else {
    343		fse->min_width = format->width;
    344		fse->max_width = format->width;
    345		fse->min_height = format->height;
    346		fse->max_height = format->height;
    347	}
    348
    349	return 0;
    350}
    351
    352static int xtpg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
    353{
    354	struct xtpg_device *xtpg = to_tpg(subdev);
    355	struct v4l2_mbus_framefmt *format;
    356
    357	format = v4l2_subdev_get_try_format(subdev, fh->state, 0);
    358	*format = xtpg->default_format;
    359
    360	if (xtpg->npads == 2) {
    361		format = v4l2_subdev_get_try_format(subdev, fh->state, 1);
    362		*format = xtpg->default_format;
    363	}
    364
    365	return 0;
    366}
    367
    368static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
    369{
    370	return 0;
    371}
    372
    373static int xtpg_s_ctrl(struct v4l2_ctrl *ctrl)
    374{
    375	struct xtpg_device *xtpg = container_of(ctrl->handler,
    376						struct xtpg_device,
    377						ctrl_handler);
    378	switch (ctrl->id) {
    379	case V4L2_CID_TEST_PATTERN:
    380		xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    381				 XTPG_PATTERN_MASK, ctrl->val);
    382		return 0;
    383	case V4L2_CID_XILINX_TPG_CROSS_HAIRS:
    384		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    385				XTPG_PATTERN_CONTROL_CROSS_HAIRS, ctrl->val);
    386		return 0;
    387	case V4L2_CID_XILINX_TPG_MOVING_BOX:
    388		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    389				XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val);
    390		return 0;
    391	case V4L2_CID_XILINX_TPG_COLOR_MASK:
    392		xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    393				 XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
    394				 ctrl->val <<
    395				 XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
    396		return 0;
    397	case V4L2_CID_XILINX_TPG_STUCK_PIXEL:
    398		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    399				XTPG_PATTERN_CONTROL_STUCK_PIXEL, ctrl->val);
    400		return 0;
    401	case V4L2_CID_XILINX_TPG_NOISE:
    402		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    403				XTPG_PATTERN_CONTROL_NOISE, ctrl->val);
    404		return 0;
    405	case V4L2_CID_XILINX_TPG_MOTION:
    406		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
    407				XTPG_PATTERN_CONTROL_MOTION, ctrl->val);
    408		return 0;
    409	case V4L2_CID_XILINX_TPG_MOTION_SPEED:
    410		xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
    411		return 0;
    412	case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW:
    413		xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
    414				 XTPG_CROSS_HAIRS_ROW_MASK,
    415				 ctrl->val << XTPG_CROSS_HAIRS_ROW_SHIFT);
    416		return 0;
    417	case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN:
    418		xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
    419				 XTPG_CROSS_HAIRS_COLUMN_MASK,
    420				 ctrl->val << XTPG_CROSS_HAIRS_COLUMN_SHIFT);
    421		return 0;
    422	case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START:
    423		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
    424				 XTPG_ZPLATE_START_MASK,
    425				 ctrl->val << XTPG_ZPLATE_START_SHIFT);
    426		return 0;
    427	case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED:
    428		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
    429				 XTPG_ZPLATE_SPEED_MASK,
    430				 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
    431		return 0;
    432	case V4L2_CID_XILINX_TPG_ZPLATE_VER_START:
    433		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
    434				 XTPG_ZPLATE_START_MASK,
    435				 ctrl->val << XTPG_ZPLATE_START_SHIFT);
    436		return 0;
    437	case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED:
    438		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
    439				 XTPG_ZPLATE_SPEED_MASK,
    440				 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
    441		return 0;
    442	case V4L2_CID_XILINX_TPG_BOX_SIZE:
    443		xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
    444		return 0;
    445	case V4L2_CID_XILINX_TPG_BOX_COLOR:
    446		xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
    447		return 0;
    448	case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH:
    449		xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val);
    450		return 0;
    451	case V4L2_CID_XILINX_TPG_NOISE_GAIN:
    452		xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val);
    453		return 0;
    454	}
    455
    456	return 0;
    457}
    458
    459static const struct v4l2_ctrl_ops xtpg_ctrl_ops = {
    460	.s_ctrl	= xtpg_s_ctrl,
    461};
    462
    463static const struct v4l2_subdev_core_ops xtpg_core_ops = {
    464};
    465
    466static const struct v4l2_subdev_video_ops xtpg_video_ops = {
    467	.s_stream = xtpg_s_stream,
    468};
    469
    470static const struct v4l2_subdev_pad_ops xtpg_pad_ops = {
    471	.enum_mbus_code		= xvip_enum_mbus_code,
    472	.enum_frame_size	= xtpg_enum_frame_size,
    473	.get_fmt		= xtpg_get_format,
    474	.set_fmt		= xtpg_set_format,
    475};
    476
    477static const struct v4l2_subdev_ops xtpg_ops = {
    478	.core   = &xtpg_core_ops,
    479	.video  = &xtpg_video_ops,
    480	.pad    = &xtpg_pad_ops,
    481};
    482
    483static const struct v4l2_subdev_internal_ops xtpg_internal_ops = {
    484	.open	= xtpg_open,
    485	.close	= xtpg_close,
    486};
    487
    488/*
    489 * Control Config
    490 */
    491
    492static const char *const xtpg_pattern_strings[] = {
    493	"Passthrough",
    494	"Horizontal Ramp",
    495	"Vertical Ramp",
    496	"Temporal Ramp",
    497	"Solid Red",
    498	"Solid Green",
    499	"Solid Blue",
    500	"Solid Black",
    501	"Solid White",
    502	"Color Bars",
    503	"Zone Plate",
    504	"Tartan Color Bars",
    505	"Cross Hatch",
    506	"None",
    507	"Vertical/Horizontal Ramps",
    508	"Black/White Checker Board",
    509};
    510
    511static struct v4l2_ctrl_config xtpg_ctrls[] = {
    512	{
    513		.ops	= &xtpg_ctrl_ops,
    514		.id	= V4L2_CID_XILINX_TPG_CROSS_HAIRS,
    515		.name	= "Test Pattern: Cross Hairs",
    516		.type	= V4L2_CTRL_TYPE_BOOLEAN,
    517		.min	= false,
    518		.max	= true,
    519		.step	= 1,
    520		.def	= 0,
    521	}, {
    522		.ops	= &xtpg_ctrl_ops,
    523		.id	= V4L2_CID_XILINX_TPG_MOVING_BOX,
    524		.name	= "Test Pattern: Moving Box",
    525		.type	= V4L2_CTRL_TYPE_BOOLEAN,
    526		.min	= false,
    527		.max	= true,
    528		.step	= 1,
    529		.def	= 0,
    530	}, {
    531		.ops	= &xtpg_ctrl_ops,
    532		.id	= V4L2_CID_XILINX_TPG_COLOR_MASK,
    533		.name	= "Test Pattern: Color Mask",
    534		.type	= V4L2_CTRL_TYPE_BITMASK,
    535		.min	= 0,
    536		.max	= 0xf,
    537		.def	= 0,
    538	}, {
    539		.ops	= &xtpg_ctrl_ops,
    540		.id	= V4L2_CID_XILINX_TPG_STUCK_PIXEL,
    541		.name	= "Test Pattern: Stuck Pixel",
    542		.type	= V4L2_CTRL_TYPE_BOOLEAN,
    543		.min	= false,
    544		.max	= true,
    545		.step	= 1,
    546		.def	= 0,
    547	}, {
    548		.ops	= &xtpg_ctrl_ops,
    549		.id	= V4L2_CID_XILINX_TPG_NOISE,
    550		.name	= "Test Pattern: Noise",
    551		.type	= V4L2_CTRL_TYPE_BOOLEAN,
    552		.min	= false,
    553		.max	= true,
    554		.step	= 1,
    555		.def	= 0,
    556	}, {
    557		.ops	= &xtpg_ctrl_ops,
    558		.id	= V4L2_CID_XILINX_TPG_MOTION,
    559		.name	= "Test Pattern: Motion",
    560		.type	= V4L2_CTRL_TYPE_BOOLEAN,
    561		.min	= false,
    562		.max	= true,
    563		.step	= 1,
    564		.def	= 0,
    565	}, {
    566		.ops	= &xtpg_ctrl_ops,
    567		.id	= V4L2_CID_XILINX_TPG_MOTION_SPEED,
    568		.name	= "Test Pattern: Motion Speed",
    569		.type	= V4L2_CTRL_TYPE_INTEGER,
    570		.min	= 0,
    571		.max	= (1 << 8) - 1,
    572		.step	= 1,
    573		.def	= 4,
    574		.flags	= V4L2_CTRL_FLAG_SLIDER,
    575	}, {
    576		.ops	= &xtpg_ctrl_ops,
    577		.id	= V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW,
    578		.name	= "Test Pattern: Cross Hairs Row",
    579		.type	= V4L2_CTRL_TYPE_INTEGER,
    580		.min	= 0,
    581		.max	= (1 << 12) - 1,
    582		.step	= 1,
    583		.def	= 0x64,
    584		.flags	= V4L2_CTRL_FLAG_SLIDER,
    585	}, {
    586		.ops	= &xtpg_ctrl_ops,
    587		.id	= V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN,
    588		.name	= "Test Pattern: Cross Hairs Column",
    589		.type	= V4L2_CTRL_TYPE_INTEGER,
    590		.min	= 0,
    591		.max	= (1 << 12) - 1,
    592		.step	= 1,
    593		.def	= 0x64,
    594		.flags	= V4L2_CTRL_FLAG_SLIDER,
    595	}, {
    596		.ops	= &xtpg_ctrl_ops,
    597		.id	= V4L2_CID_XILINX_TPG_ZPLATE_HOR_START,
    598		.name	= "Test Pattern: Zplate Horizontal Start Pos",
    599		.type	= V4L2_CTRL_TYPE_INTEGER,
    600		.min	= 0,
    601		.max	= (1 << 16) - 1,
    602		.step	= 1,
    603		.def	= 0x1e,
    604		.flags	= V4L2_CTRL_FLAG_SLIDER,
    605	}, {
    606		.ops	= &xtpg_ctrl_ops,
    607		.id	= V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED,
    608		.name	= "Test Pattern: Zplate Horizontal Speed",
    609		.type	= V4L2_CTRL_TYPE_INTEGER,
    610		.min	= 0,
    611		.max	= (1 << 16) - 1,
    612		.step	= 1,
    613		.def	= 0,
    614		.flags	= V4L2_CTRL_FLAG_SLIDER,
    615	}, {
    616		.ops	= &xtpg_ctrl_ops,
    617		.id	= V4L2_CID_XILINX_TPG_ZPLATE_VER_START,
    618		.name	= "Test Pattern: Zplate Vertical Start Pos",
    619		.type	= V4L2_CTRL_TYPE_INTEGER,
    620		.min	= 0,
    621		.max	= (1 << 16) - 1,
    622		.step	= 1,
    623		.def	= 1,
    624		.flags	= V4L2_CTRL_FLAG_SLIDER,
    625	}, {
    626		.ops	= &xtpg_ctrl_ops,
    627		.id	= V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED,
    628		.name	= "Test Pattern: Zplate Vertical Speed",
    629		.type	= V4L2_CTRL_TYPE_INTEGER,
    630		.min	= 0,
    631		.max	= (1 << 16) - 1,
    632		.step	= 1,
    633		.def	= 0,
    634		.flags	= V4L2_CTRL_FLAG_SLIDER,
    635	}, {
    636		.ops	= &xtpg_ctrl_ops,
    637		.id	= V4L2_CID_XILINX_TPG_BOX_SIZE,
    638		.name	= "Test Pattern: Box Size",
    639		.type	= V4L2_CTRL_TYPE_INTEGER,
    640		.min	= 0,
    641		.max	= (1 << 12) - 1,
    642		.step	= 1,
    643		.def	= 0x32,
    644		.flags	= V4L2_CTRL_FLAG_SLIDER,
    645	}, {
    646		.ops	= &xtpg_ctrl_ops,
    647		.id	= V4L2_CID_XILINX_TPG_BOX_COLOR,
    648		.name	= "Test Pattern: Box Color(RGB)",
    649		.type	= V4L2_CTRL_TYPE_INTEGER,
    650		.min	= 0,
    651		.max	= (1 << 24) - 1,
    652		.step	= 1,
    653		.def	= 0,
    654	}, {
    655		.ops	= &xtpg_ctrl_ops,
    656		.id	= V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH,
    657		.name	= "Test Pattern: Stuck Pixel threshold",
    658		.type	= V4L2_CTRL_TYPE_INTEGER,
    659		.min	= 0,
    660		.max	= (1 << 16) - 1,
    661		.step	= 1,
    662		.def	= 0,
    663		.flags	= V4L2_CTRL_FLAG_SLIDER,
    664	}, {
    665		.ops	= &xtpg_ctrl_ops,
    666		.id	= V4L2_CID_XILINX_TPG_NOISE_GAIN,
    667		.name	= "Test Pattern: Noise Gain",
    668		.type	= V4L2_CTRL_TYPE_INTEGER,
    669		.min	= 0,
    670		.max	= (1 << 8) - 1,
    671		.step	= 1,
    672		.def	= 0,
    673		.flags	= V4L2_CTRL_FLAG_SLIDER,
    674	},
    675};
    676
    677/* -----------------------------------------------------------------------------
    678 * Media Operations
    679 */
    680
    681static const struct media_entity_operations xtpg_media_ops = {
    682	.link_validate = v4l2_subdev_link_validate,
    683};
    684
    685/* -----------------------------------------------------------------------------
    686 * Power Management
    687 */
    688
    689static int __maybe_unused xtpg_pm_suspend(struct device *dev)
    690{
    691	struct xtpg_device *xtpg = dev_get_drvdata(dev);
    692
    693	xvip_suspend(&xtpg->xvip);
    694
    695	return 0;
    696}
    697
    698static int __maybe_unused xtpg_pm_resume(struct device *dev)
    699{
    700	struct xtpg_device *xtpg = dev_get_drvdata(dev);
    701
    702	xvip_resume(&xtpg->xvip);
    703
    704	return 0;
    705}
    706
    707/* -----------------------------------------------------------------------------
    708 * Platform Device Driver
    709 */
    710
    711static int xtpg_parse_of(struct xtpg_device *xtpg)
    712{
    713	struct device *dev = xtpg->xvip.dev;
    714	struct device_node *node = xtpg->xvip.dev->of_node;
    715	struct device_node *ports;
    716	struct device_node *port;
    717	unsigned int nports = 0;
    718	bool has_endpoint = false;
    719
    720	ports = of_get_child_by_name(node, "ports");
    721	if (ports == NULL)
    722		ports = node;
    723
    724	for_each_child_of_node(ports, port) {
    725		const struct xvip_video_format *format;
    726		struct device_node *endpoint;
    727
    728		if (!of_node_name_eq(port, "port"))
    729			continue;
    730
    731		format = xvip_of_get_format(port);
    732		if (IS_ERR(format)) {
    733			dev_err(dev, "invalid format in DT");
    734			of_node_put(port);
    735			return PTR_ERR(format);
    736		}
    737
    738		/* Get and check the format description */
    739		if (!xtpg->vip_format) {
    740			xtpg->vip_format = format;
    741		} else if (xtpg->vip_format != format) {
    742			dev_err(dev, "in/out format mismatch in DT");
    743			of_node_put(port);
    744			return -EINVAL;
    745		}
    746
    747		if (nports == 0) {
    748			endpoint = of_get_next_child(port, NULL);
    749			if (endpoint)
    750				has_endpoint = true;
    751			of_node_put(endpoint);
    752		}
    753
    754		/* Count the number of ports. */
    755		nports++;
    756	}
    757
    758	if (nports != 1 && nports != 2) {
    759		dev_err(dev, "invalid number of ports %u\n", nports);
    760		return -EINVAL;
    761	}
    762
    763	xtpg->npads = nports;
    764	if (nports == 2 && has_endpoint)
    765		xtpg->has_input = true;
    766
    767	return 0;
    768}
    769
    770static int xtpg_probe(struct platform_device *pdev)
    771{
    772	struct v4l2_subdev *subdev;
    773	struct xtpg_device *xtpg;
    774	u32 i, bayer_phase;
    775	int ret;
    776
    777	xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
    778	if (!xtpg)
    779		return -ENOMEM;
    780
    781	xtpg->xvip.dev = &pdev->dev;
    782
    783	ret = xtpg_parse_of(xtpg);
    784	if (ret < 0)
    785		return ret;
    786
    787	ret = xvip_init_resources(&xtpg->xvip);
    788	if (ret < 0)
    789		return ret;
    790
    791	xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing",
    792						   GPIOD_OUT_HIGH);
    793	if (IS_ERR(xtpg->vtmux_gpio)) {
    794		ret = PTR_ERR(xtpg->vtmux_gpio);
    795		goto error_resource;
    796	}
    797
    798	xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
    799	if (IS_ERR(xtpg->vtc)) {
    800		ret = PTR_ERR(xtpg->vtc);
    801		goto error_resource;
    802	}
    803
    804	/* Reset and initialize the core */
    805	xvip_reset(&xtpg->xvip);
    806
    807	/* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
    808	 * number of pads.
    809	 */
    810	if (xtpg->npads == 2) {
    811		xtpg->pads[0].flags = MEDIA_PAD_FL_SINK;
    812		xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE;
    813	} else {
    814		xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE;
    815	}
    816
    817	/* Initialize the default format */
    818	xtpg->default_format.code = xtpg->vip_format->code;
    819	xtpg->default_format.field = V4L2_FIELD_NONE;
    820	xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
    821	xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
    822
    823	bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
    824	if (bayer_phase != XTPG_BAYER_PHASE_OFF)
    825		xtpg->bayer = true;
    826
    827	xtpg->formats[0] = xtpg->default_format;
    828	if (xtpg->npads == 2)
    829		xtpg->formats[1] = xtpg->default_format;
    830
    831	/* Initialize V4L2 subdevice and media entity */
    832	subdev = &xtpg->xvip.subdev;
    833	v4l2_subdev_init(subdev, &xtpg_ops);
    834	subdev->dev = &pdev->dev;
    835	subdev->internal_ops = &xtpg_internal_ops;
    836	strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
    837	v4l2_set_subdevdata(subdev, xtpg);
    838	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
    839	subdev->entity.ops = &xtpg_media_ops;
    840
    841	ret = media_entity_pads_init(&subdev->entity, xtpg->npads, xtpg->pads);
    842	if (ret < 0)
    843		goto error;
    844
    845	v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls));
    846
    847	xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
    848					 V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
    849					 XTPG_MAX_VBLANK, 1, 100);
    850	xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
    851					 V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
    852					 XTPG_MAX_HBLANK, 1, 100);
    853	xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
    854					&xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN,
    855					ARRAY_SIZE(xtpg_pattern_strings) - 1,
    856					1, 9, xtpg_pattern_strings);
    857
    858	for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
    859		v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL);
    860
    861	if (xtpg->ctrl_handler.error) {
    862		dev_err(&pdev->dev, "failed to add controls\n");
    863		ret = xtpg->ctrl_handler.error;
    864		goto error;
    865	}
    866	subdev->ctrl_handler = &xtpg->ctrl_handler;
    867
    868	xtpg_update_pattern_control(xtpg, true, true);
    869
    870	ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
    871	if (ret < 0) {
    872		dev_err(&pdev->dev, "failed to set controls\n");
    873		goto error;
    874	}
    875
    876	platform_set_drvdata(pdev, xtpg);
    877
    878	xvip_print_version(&xtpg->xvip);
    879
    880	ret = v4l2_async_register_subdev(subdev);
    881	if (ret < 0) {
    882		dev_err(&pdev->dev, "failed to register subdev\n");
    883		goto error;
    884	}
    885
    886	return 0;
    887
    888error:
    889	v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
    890	media_entity_cleanup(&subdev->entity);
    891	xvtc_put(xtpg->vtc);
    892error_resource:
    893	xvip_cleanup_resources(&xtpg->xvip);
    894	return ret;
    895}
    896
    897static int xtpg_remove(struct platform_device *pdev)
    898{
    899	struct xtpg_device *xtpg = platform_get_drvdata(pdev);
    900	struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
    901
    902	v4l2_async_unregister_subdev(subdev);
    903	v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
    904	media_entity_cleanup(&subdev->entity);
    905
    906	xvip_cleanup_resources(&xtpg->xvip);
    907
    908	return 0;
    909}
    910
    911static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
    912
    913static const struct of_device_id xtpg_of_id_table[] = {
    914	{ .compatible = "xlnx,v-tpg-5.0" },
    915	{ }
    916};
    917MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
    918
    919static struct platform_driver xtpg_driver = {
    920	.driver = {
    921		.name		= "xilinx-tpg",
    922		.pm		= &xtpg_pm_ops,
    923		.of_match_table	= xtpg_of_id_table,
    924	},
    925	.probe			= xtpg_probe,
    926	.remove			= xtpg_remove,
    927};
    928
    929module_platform_driver(xtpg_driver);
    930
    931MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
    932MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver");
    933MODULE_LICENSE("GPL v2");