162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Driver for the Conexant CX23885/7/8 PCIe bridge
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Various common ioctl() support functions
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "cx23885.h"
1162306a36Sopenharmony_ci#include "cx23885-ioctl.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG
1462306a36Sopenharmony_ciint cx23885_g_chip_info(struct file *file, void *fh,
1562306a36Sopenharmony_ci			 struct v4l2_dbg_chip_info *chip)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	struct cx23885_dev *dev = video_drvdata(file);
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (chip->match.addr > 1)
2062306a36Sopenharmony_ci		return -EINVAL;
2162306a36Sopenharmony_ci	if (chip->match.addr == 1) {
2262306a36Sopenharmony_ci		if (dev->v4l_device == NULL)
2362306a36Sopenharmony_ci			return -EINVAL;
2462306a36Sopenharmony_ci		strscpy(chip->name, "cx23417", sizeof(chip->name));
2562306a36Sopenharmony_ci	} else {
2662306a36Sopenharmony_ci		strscpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
2762306a36Sopenharmony_ci	}
2862306a36Sopenharmony_ci	return 0;
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic int cx23417_g_register(struct cx23885_dev *dev,
3262306a36Sopenharmony_ci			      struct v4l2_dbg_register *reg)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	u32 value;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (dev->v4l_device == NULL)
3762306a36Sopenharmony_ci		return -EINVAL;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
4062306a36Sopenharmony_ci		return -EINVAL;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (mc417_register_read(dev, (u16) reg->reg, &value))
4362306a36Sopenharmony_ci		return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	reg->size = 4;
4662306a36Sopenharmony_ci	reg->val = value;
4762306a36Sopenharmony_ci	return 0;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciint cx23885_g_register(struct file *file, void *fh,
5162306a36Sopenharmony_ci		       struct v4l2_dbg_register *reg)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct cx23885_dev *dev = video_drvdata(file);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (reg->match.addr > 1)
5662306a36Sopenharmony_ci		return -EINVAL;
5762306a36Sopenharmony_ci	if (reg->match.addr)
5862306a36Sopenharmony_ci		return cx23417_g_register(dev, reg);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
6162306a36Sopenharmony_ci		return -EINVAL;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	reg->size = 4;
6462306a36Sopenharmony_ci	reg->val = cx_read(reg->reg);
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic int cx23417_s_register(struct cx23885_dev *dev,
6962306a36Sopenharmony_ci			      const struct v4l2_dbg_register *reg)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	if (dev->v4l_device == NULL)
7262306a36Sopenharmony_ci		return -EINVAL;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
7562306a36Sopenharmony_ci		return -EINVAL;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
7862306a36Sopenharmony_ci		return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciint cx23885_s_register(struct file *file, void *fh,
8362306a36Sopenharmony_ci		       const struct v4l2_dbg_register *reg)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct cx23885_dev *dev = video_drvdata(file);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (reg->match.addr > 1)
8862306a36Sopenharmony_ci		return -EINVAL;
8962306a36Sopenharmony_ci	if (reg->match.addr)
9062306a36Sopenharmony_ci		return cx23417_s_register(dev, reg);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
9362306a36Sopenharmony_ci		return -EINVAL;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	cx_write(reg->reg, reg->val);
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci#endif
99