mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
In Linux v6.12 the definition 'no_llseek' was finally removed. Since Linux v6.0 it had been redefined as NULL. Add a test to conftest to determine if 'no_llseek' is present and if not then it is no longer necessary to populate this and we can leave as NULL. Bug 4876974 Change-Id: I051fdb285b32260b5913dad89cabe0be04253f67 Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3222106 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
146 lines
3.4 KiB
C
146 lines
3.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
// SPDX-FileCopyrightText: Copyright (c) 2014-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
/*
|
|
* NVCSI driver
|
|
*/
|
|
|
|
#include <nvidia/conftest.h>
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/export.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/fs.h>
|
|
#include <asm/ioctls.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_graph.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/platform_device.h>
|
|
#include <uapi/linux/nvhost_nvcsi_ioctl.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/nvhost.h>
|
|
|
|
#include <media/mc_common.h>
|
|
#include <media/csi.h>
|
|
#include <media/tegra_camera_platform.h>
|
|
|
|
//#include "camera/nvcsi/csi5_fops.h"
|
|
|
|
#include "deskew.h"
|
|
#include "nvcsi.h"
|
|
|
|
#define PG_CLK_RATE 102000000
|
|
/* width of interface between VI and CSI */
|
|
#define CSI_BUS_WIDTH 64
|
|
/* number of lanes per brick */
|
|
#define NUM_LANES 4
|
|
|
|
#define CSIA (1 << 20)
|
|
#define CSIF (1 << 25)
|
|
|
|
struct nvcsi {
|
|
struct platform_device *pdev;
|
|
struct regulator *regulator;
|
|
struct tegra_csi_device csi;
|
|
struct dentry *dir;
|
|
};
|
|
|
|
static struct tegra_csi_device *mc_csi;
|
|
|
|
struct nvcsi_private {
|
|
struct platform_device *pdev;
|
|
struct nvcsi_deskew_context deskew_ctx;
|
|
};
|
|
|
|
int nvcsi_cil_sw_reset(int lanes, int enable)
|
|
{
|
|
unsigned int phy_num = 0U;
|
|
unsigned int val = enable ? (SW_RESET1_EN | SW_RESET0_EN) : 0U;
|
|
unsigned int addr, i;
|
|
|
|
for (i = CSIA; i < CSIF; i = i << 2U) {
|
|
if (lanes & i) {
|
|
addr = CSI4_BASE_ADDRESS + NVCSI_CIL_A_SW_RESET +
|
|
(CSI4_PHY_OFFSET * phy_num);
|
|
host1x_writel(mc_csi->pdev, addr, val);
|
|
}
|
|
if (lanes & (i << 1U)) {
|
|
addr = CSI4_BASE_ADDRESS + NVCSI_CIL_B_SW_RESET +
|
|
(CSI4_PHY_OFFSET * phy_num);
|
|
host1x_writel(mc_csi->pdev, addr, val);
|
|
}
|
|
phy_num++;
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nvcsi_cil_sw_reset);
|
|
|
|
static long nvcsi_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
{
|
|
struct nvcsi_private *priv = file->private_data;
|
|
int ret;
|
|
|
|
switch (cmd) {
|
|
// sensor must be turned on before calling this ioctl, and streaming
|
|
// should be started shortly after.
|
|
case NVHOST_NVCSI_IOCTL_DESKEW_SETUP: {
|
|
unsigned int active_lanes;
|
|
|
|
dev_dbg(mc_csi->dev, "ioctl: deskew_setup\n");
|
|
priv->deskew_ctx.deskew_lanes = get_user(active_lanes,
|
|
(long __user *)arg);
|
|
ret = nvcsi_deskew_setup(&priv->deskew_ctx);
|
|
return ret;
|
|
}
|
|
case NVHOST_NVCSI_IOCTL_DESKEW_APPLY: {
|
|
dev_dbg(mc_csi->dev, "ioctl: deskew_apply\n");
|
|
ret = nvcsi_deskew_apply_check(&priv->deskew_ctx);
|
|
return ret;
|
|
}
|
|
}
|
|
return -ENOIOCTLCMD;
|
|
}
|
|
|
|
static int nvcsi_open(struct inode *inode, struct file *file)
|
|
{
|
|
struct nvhost_device_data *pdata = container_of(inode->i_cdev,
|
|
struct nvhost_device_data, ctrl_cdev);
|
|
struct platform_device *pdev = pdata->pdev;
|
|
struct nvcsi_private *priv;
|
|
|
|
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
|
|
if (unlikely(priv == NULL))
|
|
return -ENOMEM;
|
|
|
|
priv->pdev = pdev;
|
|
|
|
file->private_data = priv;
|
|
return nonseekable_open(inode, file);
|
|
}
|
|
|
|
static int nvcsi_release(struct inode *inode, struct file *file)
|
|
{
|
|
struct nvcsi_private *priv = file->private_data;
|
|
|
|
kfree(priv);
|
|
return 0;
|
|
}
|
|
|
|
const struct file_operations tegra_nvcsi_ctrl_ops = {
|
|
.owner = THIS_MODULE,
|
|
#if defined(NV_NO_LLSEEK_PRESENT)
|
|
.llseek = no_llseek,
|
|
#endif
|
|
.unlocked_ioctl = nvcsi_ioctl,
|
|
#ifdef CONFIG_COMPAT
|
|
.compat_ioctl = nvcsi_ioctl,
|
|
#endif
|
|
.open = nvcsi_open,
|
|
.release = nvcsi_release,
|
|
};
|
|
MODULE_LICENSE("GPL");
|