I was wondering if I could connect another camera at the same time.
I will not think of that again.
After modifying the device tree, …/…/module was created.
It is the test result after that.
# gst-launch-1.0 -v nvcamerasrc ! ‘video/x-raw(memory:NVMM),width=2304, height=1728, framerate=30/1, format=NV12’ ! nvoverlaysink -ev
Setting pipeline to PAUSED …
Thread 1 getting next capture
Thread 1 is waiting
Thread 2 getting next capture
Thread 2 is waiting
Thread 3 getting next capture
Thread 3 is waiting
Thread 4 getting next capture
Thread 4 is waiting
Thread 5 getting next capture
Thread 5 is waiting
Thread 6 getting next capture
Thread 6 is waiting
Thread 7 getting next capture
Thread 7 is waiting
Thread 8 getting next capture
Thread 8 is waiting
Thread 9 getting next capture
Thread 9 is waiting
Thread 10 getting next capture
Thread 10 is waiting
Thread 11 getting next capture
Thread 11 is waiting
Thread 12 getting next capture
Thread 12 is waiting
Starting services…
Worker thread IspHw statsComplete start
Worker thread IspHw frameComplete start
Worker thread CaptureScheduler checkFramePending start
Worker thread CaptureScheduler frameStart start
Worker thread V4L2CaptureScheduler checkCaptureComplete start
Worker thread V4L2CaptureScheduler issueCaptures start
Worker thread PS handleRequests start
getInstance: s_instance(0x7f94b92570)
getInstance: s_instance(0x7f94b92570)
subscribe: create SensorType(gyroscope) sensor(0x7f94b946f0)
subscribe: create SensorType(accelerometer) sensor(0x7f94b99b50)
AC plugin not present: dlopen “acplugin.so”, acplugin.so: cannot open shared object file: No such file or directory
Services are started
NvPclSetHotplugCallback: ++++++++++++++++++++++
---- Imager: Calibration blob file handling supported in this build ----
NvPclHwGetModuleList: OFParserListModules Succeeded
NvPclHwGetModuleList: WARNING: Could not map module to ISP config string
NvPclHwGetModuleList: No module data found
NvPclHwPrintModuleDefinition – Name: ov16825_hmns
NvPclHwPrintModuleDefinition – Position: 0
NvPclHwPrintModuleDefinition – CalibrationData Found: 1
NvPclHwPrintCameraSubModule – HwCamSubModule[0].Name: v4l2_sensor
NvPclHwPrintCameraSubModule – HwCamSubModule[0].DevName: hmns 2-0020
NvPclHwPrintCameraSubModule – HwCamSubModule[1].Name: v4l2_lens
NvPclHwPrintCameraSubModule – HwCamSubModule[1].DevName:
NvPclHwGetModuleList: OFParserListModules Succeeded
NvPclModuleListInitialize: NvPclModule list[0]: ov16825_hmns position0
NvPclHwScanExternalCameras – adding video2 to discover list
NvPclHwScanExternalCameras – adding video1 to discover list
NvPclHwScanExternalCameras – adding video0 to discover list
NvPclHwScanExternalCameras – adding video2 to discover list
NvPclHwScanExternalCameras – adding video1 to discover list
NvPclHwScanExternalCameras – adding video0 to discover list
initialize: /dev/video0
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
initialize: /dev/video1
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
initialize: /dev/video2
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
NvPclHwScanExternalCameras – adding video2 to discover list
NvPclHwScanExternalCameras – adding video1 to discover list
NvPclHwScanExternalCameras – adding video0 to discover list
initialize: /dev/video0
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
initialize: /dev/video1
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
initialize: /dev/video2
queryControls: 10100740 control HDR enable
queryControls: 10100836 control Bypass Mode
queryControls: 10100837 control Override Enable
queryControls: 10100838 control Height Align
queryControls: 10100839 control Size Align
queryControls: 10100840 control Write ISP format
Ioctl failed: Invalid argument
getHotplugMonitor: Getting hotplug monitor instance
initializeHotplug++
hotPlugfunc ++
addWatch: Watch added wd=‘1’
CheckProcDTExists: INFO: accessing /proc/device-tree/tegra-virtual-camera-platform/modules; No such file or directory
PCLHW_DTParser
setHotplugCallback: Registered new callback client
NvPclSetHotplugCallback: ----------------------
hotPlugfunc: reading from inotify FD, Thread waiting
NvPclOpen: ++++++++++++++++++++++
NvPclStateControllerOpen: Found GUID 0 match at index[0]
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bdf100
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bdf190
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bc3cd0
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bc3d60
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bc3df0
NvPclHwInitializeModule: allocate overrides pathname @ 0x7f94bc3e80
LoadOverridesFile: looking for override file [/Calib/camera_override.isp] 1/16CheckOverridesPermissions: cannot stat file [/Calib/camera_override.isp]
LoadOverridesFile: looking for override file [/data/nvcam/settings/camera_overrides.isp] 2/16CheckOverridesPermissions: cannot stat file [/data/nvcam/settings/camera_overrides.isp]
LoadOverridesFile: looking for override file [/opt/nvidia/nvcam/settings/camera_overrides.isp] 3/16CheckOverridesPermissions: cannot stat file [/opt/nvidia/nvcam/settings/camera_overrides.isp]
LoadOverridesFile: looking for override file [/var/nvidia/nvcam/settings/camera_overrides.isp] 4/16CheckOverridesPermissions: cannot stat file [/var/nvidia/nvcam/settings/camera_overrides.isp]
LoadOverridesFile: looking for override file [/data/nvcam/camera_overrides.isp] 5/16CheckOverridesPermissions: cannot stat file [/data/nvcam/camera_overrides.isp]
LoadOverridesFile: looking for override file [/data/nvcam/settings/ov16825_hmns.isp] 6/16CheckOverridesPermissions: cannot stat file [/data/nvcam/settings/ov16825_hmns.isp]
LoadOverridesFile: looking for override file [/opt/nvidia/nvcam/settings/ov16825_hmns.isp] 7/16CheckOverridesPermissions: cannot stat file [/opt/nvidia/nvcam/settings/ov16825_hmns.isp]
LoadOverridesFile: looking for override file [/var/nvidia/nvcam/settings/ov16825_hmns.isp] 8/16CheckOverridesPermissions: cannot stat file [/var/nvidia/nvcam/settings/ov16825_hmns.isp]
---- imager: No override file found. ----
Imager: looking for override file [/mnt/factory/camera/factory.bin] 1/16
Imager: looking for override file [/Calib/factory.bin] 2/16
Imager: looking for override file [/Calib/calibration.bin] 3/16
Imager: looking for override file [(null)] 4/16
Imager: looking for override file [(null)] 5/16
Imager: looking for override file [(null)] 6/16
Imager: looking for override file [(null)] 7/16
Imager: looking for override file [(null)] 8/16
Imager: looking for override file [(null)] 9/16
Imager: looking for override file [(null)] 10/16
Imager: looking for override file [(null)] 11/16
Imager: looking for override file [(null)] 12/16
Imager: looking for override file [(null)] 13/16
Imager: looking for override file [(null)] 14/16
Imager: looking for override file [(null)] 15/16
Imager: looking for override file [(null)] 16/16
Imager: looking for override file [/data/nvcam/settings/factory.bin] 1/16
Imager: looking for override file [/data/nvcam/settings/ov16825_hmns.bin] 2/16
Imager: looking for override file [/opt/nvidia/nvcam/settings/ov16825_hmns.bin] 3/16
Imager: looking for override file [/var/nvidia/nvcam/settings/ov16825_hmns.bin] 4/16
Imager: looking for override file [(null)] 5/16
Imager: looking for override file [(null)] 6/16
Imager: looking for override file [(null)] 7/16
Imager: looking for override file [(null)] 8/16
Imager: looking for override file [(null)] 9/16
Imager: looking for override file [(null)] 10/16
Imager: looking for override file [(null)] 11/16
Imager: looking for override file [(null)] 12/16
Imager: looking for override file [(null)] 13/16
Imager: looking for override file [(null)] 14/16
Imager: looking for override file [(null)] 15/16
Imager: looking for override file [(null)] 16/16
NvPclCreateDriver: Found NvPcl Driver Hal dev[ 396.020520] pgd = ffffffc1b7292000
_name match (v4l2_sensor)
NvPcl[ 396.027066] [00000000] *pgd=0000000250a86003CreateDriver: Found a Driver nam, *pud=0000000250a86003e match (v4l2_sensor)
NvPclCrea, *pmd=0000000000000000teDriver: Found NvPcl Driver Hal
dev_name match (v4l2_lens)
NvPclCreate[ 396.046903] Library at 0x402efc: 0x400000 /usr/sbin/nvcamera-daemon
Driver: Found a Driver name matc[ 396.056414] Library at 0x402ef8: 0x400000 /usr/sbin/nvcamera-daemon
h (v4l2_lens)
NvPclConnectDrive[ 396.065428] vdso base = 0x7f9e754000
rs: hImager was NULL, creating new imager
NvPclInitializeDrivers: v4l2_sensor ++++++++++++++++++
OFDPropertyGetString: could not read property [devnode-bus]
initialize: hmns 2-0020
(NvOdmDevice) Error ModuleNotPresent: V4L2Device not available (in dvs/git/dirty/git-master_linux/camera-partner/imager/src/V4L2Device.cpp, function findDevice(), line 231)
(NvOdmDevice) Error ModuleNotPresent: (propagating from dvs/git/dirty/git-master_linux/camera-partner/imager/src/V4L2Device.cpp, function initialize(), line 54)
(NvOdmDevice) Error ModuleNotPresent: (propagating from dvs/git/dirty/git-master_linux/camera-partner/imager/src/devices/V4L2SensorViCsi.cpp, function initialize(), line 97)
NvPclDriverInitializeData: Unable to initialize driver v4l2_sensor
NvPclInitializeDrivers: error: Failed to init camera sub module v4l2_sensor
NvPclStartPlatformDrivers: Failed to start module drivers
NvPclDriver_V4L2_Focuser_Stub_Close: Invalid NULL input pPclDriver
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bc3d60
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bc3df0
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bc3e80
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bdf100
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bdf190
NvPclCloseModuleDrivers: deallocate/free overrides pathname @ 0x7f94bc3cd0
NvPclStateControllerOpen: Failed ImagerGUID 0. (error 0xA000E)
NvPclStateControllerClose: Module ov16825_hmns closed
NvPclOpen: PCL Open Failed. Error: 0xf
NvPclClose: ++++++++++++++++++++++
NvPclClose: ----------------------
NvPclOpen: ----------------------
SCF: Error BadParameter: Sensor could not be opened. (in src/services/capture/CaptureServiceDeviceSensor.cpp, function getSourceFromGuid(), line 596)
SCF: Error BadParameter: (propagating from src/services/capture/CaptureService.cpp, function addSourceByGuid(), line 781)
SCF: Error BadParameter: (propagating from src/api/CameraDriver.cpp, function addSourceByIndex(), line 276)
SCF: Error BadParameter: (propagating from src/api/CameraDriver.cpp, function getSource(), line 439)
Socket read error. Camera Daemon stopped functioning…
gst_nvcamera_open() failed ret=0
ERROR: Pipeline doesn’t want to pause.
ERROR: from element /GstPipeline:pipeline0/GstNvCameraSrc:nvcamerasrc0: GStreamer error: state change failed and some element failed to post a proper error message with the reason for the failure.
Additional debug info:
gstbasesrc.c(3354): gst_base_src_start (): /GstPipeline:pipeline0/GstNvCameraSrc:nvcamerasrc0:
Failed to start
Setting pipeline to NULL …
Freeing pipeline …
[2]+ Segmentation fault (core dumped) nvcamera-daemon
Driver code attached.
We implemented the driver code simply because i2c initializes the camera separately in the application.
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <media/camera_common.h>
enum {
/* po3100k */
MNS0000_MODE_1280X720,
/* ov10635, ap0100 */
MNS0000_MODE_1280X800,
MNS0000_MODE_2560X800,
MNS0000_MODE_3840X800,
MNS0000_MODE_5120X800,
/* ar0231 drivepx */
MNS0000_MODE_1920X1208,
/* imx323 Kornix */
MNS0000_MODE_1920X1080,
MNS0000_MODE_3840X1080,
/* ov16825 */
MNS0000_MODE_2304X1728,
};
static const int hmns0000_30fps[] = {
30
};
static const struct camera_common_frmfmt hmns0000_frmfmt[] = {
/* po3100k */
{{1280, 720}, hmns0000_30fps, 1, 0, MNS0000_MODE_1280X720},
/* ov10635, ap0100 */
{{1280, 800}, hmns0000_30fps, 1, 0, MNS0000_MODE_1280X800},
{{2560, 800}, hmns0000_30fps, 1, 0, MNS0000_MODE_2560X800},
{{3840, 800}, hmns0000_30fps, 1, 0, MNS0000_MODE_3840X800},
{{5120, 800}, hmns0000_30fps, 1, 0, MNS0000_MODE_5120X800},
/* ar0231 drivepx */
{{1920, 1208}, hmns0000_30fps, 1, 0, MNS0000_MODE_1920X1208},
/* imx323 Kornix */
{{1920, 1080}, hmns0000_30fps, 1, 0, MNS0000_MODE_1920X1080},
{{3840, 1080}, hmns0000_30fps, 1, 0, MNS0000_MODE_3840X1080},
/* ov16825 */
{{2304, 1728}, hmns0000_30fps, 1, 0, MNS0000_MODE_2304X1728},
};
#if 0
#define MNS0000_DEFAULT_DATAFMT MEDIA_BUS_FMT_UYVY8_1X16
#define MNS0000_DEFAULT_MODE MNS0000_MODE_1280X800
#define MNS0000_DEFAULT_WIDTH 1280
#define MNS0000_DEFAULT_HEIGHT 800
#endif
#if 0 /* imx323 Kornix */
//#define MNS0000_DEFAULT_DATAFMT MEDIA_BUS_FMT_UYVY8_2X8
#define MNS0000_DEFAULT_DATAFMT MEDIA_BUS_FMT_UYVY8_1X16
#define MNS0000_DEFAULT_MODE MNS0000_MODE_3840X1080
#define MNS0000_DEFAULT_WIDTH 3840
#define MNS0000_DEFAULT_HEIGHT 1080
#endif
#define MNS0000_DEFAULT_DATAFMT MEDIA_BUS_FMT_SBGGR10_1X10
#define MNS0000_DEFAULT_MODE MNS0000_MODE_2304X1728
#define MNS0000_DEFAULT_WIDTH 2304
#define MNS0000_DEFAULT_HEIGHT 1728
#if 0 /* imx323 Kornix */
#define MNS0000_DEFAULT_DATAFMT MEDIA_BUS_FMT_UYVY8_1X16
#define MNS0000_DEFAULT_MODE MNS0000_MODE_1920X1080
#define MNS0000_DEFAULT_WIDTH 1920
#define MNS0000_DEFAULT_HEIGHT 1080
#endif
struct hmns0000 {
int numctrls;
struct v4l2_ctrl_handler ctrl_handler;
struct i2c_client * i2c_client;
struct v4l2_subdev * subdev;
struct media_pad pad;
struct camera_common_data * s_data;
struct camera_common_pdata * pdata;
struct v4l2_ctrl * ctrls[];
};
static struct v4l2_ctrl_config ctrl_config_list[] = {
/* Do not change the name field for the controls! */
{
.id = V4L2_CID_HDR_EN,
.name = "HDR enable",
.type = V4L2_CTRL_TYPE_INTEGER_MENU,
.min = 0,
.max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
.menu_skip_mask = 0,
.def = 0,
.qmenu_int = switch_ctrl_qmenu,
},
};
static int hmns0000_s_stream(struct v4l2_subdev *sd, int enable)
{
return 0;
}
static struct v4l2_subdev_video_ops hmns0000_subdev_video_ops = {
.s_stream = hmns0000_s_stream,
.g_mbus_config = camera_common_g_mbus_config,
};
static int hmns0000_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format)
{
return camera_common_g_fmt(sd, &format->format);
}
static int hmns0000_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format)
{
int ret;
ret = camera_common_s_fmt(sd, &format->format);
return ret;
}
static struct v4l2_subdev_pad_ops hmns0000_subdev_pad_ops = {
.set_fmt = hmns0000_set_fmt,
.get_fmt = hmns0000_get_fmt,
.enum_mbus_code = camera_common_enum_mbus_code,
.enum_frame_size = camera_common_enum_framesizes,
.enum_frame_interval = camera_common_enum_frameintervals,
};
static struct v4l2_subdev_ops hmns0000_subdev_ops = {
.video = &hmns0000_subdev_video_ops,
.pad = &hmns0000_subdev_pad_ops,
};
static struct of_device_id hmns0000_of_match[] = {
{ .compatible = "nvidia,hmns0000", },
{ },
};
static int hmns0000_ctrls_init(struct hmns0000 *priv, bool eeprom_ctrl)
{
struct i2c_client *client = priv->i2c_client;
struct v4l2_ctrl *ctrl;
int numctrls;
int err;
int i;
numctrls = ARRAY_SIZE(ctrl_config_list);
v4l2_ctrl_handler_init(&priv->ctrl_handler, numctrls);
for (i = 0; i < numctrls; i++) {
ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler,
&ctrl_config_list[i], NULL);
if (ctrl == NULL) {
printk("Failed to init %s ctrl\n", ctrl_config_list[i].name);
continue;
}
if (ctrl_config_list[i].type == V4L2_CTRL_TYPE_STRING &&
ctrl_config_list[i].flags & V4L2_CTRL_FLAG_READ_ONLY) {
ctrl->p_new.p_char = devm_kzalloc(&client->dev,
ctrl_config_list[i].max + 1, GFP_KERNEL);
if (!ctrl->p_new.p_char)
return -ENOMEM;
}
priv->ctrls[i] = ctrl;
}
priv->numctrls = numctrls;
priv->subdev->ctrl_handler = &priv->ctrl_handler;
if (priv->ctrl_handler.error) {
printk("Error %d adding controls\n", priv->ctrl_handler.error);
err = priv->ctrl_handler.error;
goto error;
}
err = v4l2_ctrl_handler_setup(&priv->ctrl_handler);
if (err) {
printk("Error %d setting default controls\n", err);
goto error;
}
return 0;
error:
v4l2_ctrl_handler_free(&priv->ctrl_handler);
return err;
}
MODULE_DEVICE_TABLE(of, hmns0000_of_match);
static struct camera_common_pdata *hmns0000_parse_dt(struct i2c_client *client)
{
struct device_node *node = client->dev.of_node;
struct camera_common_pdata *board_priv_pdata;
const struct of_device_id *match;
if (!node)
return NULL;
match = of_match_device(hmns0000_of_match, &client->dev);
if (!match) {
printk("Failed to find matching dt id\n");
return NULL;
}
board_priv_pdata = devm_kzalloc(&client->dev,
sizeof(*board_priv_pdata), GFP_KERNEL);
if (!board_priv_pdata)
return NULL;
return board_priv_pdata;
devm_kfree(&client->dev, board_priv_pdata);
return NULL;
}
static int hmns0000_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
return 0;
}
static const struct v4l2_subdev_internal_ops hmns0000_subdev_internal_ops = {
.open = hmns0000_open,
};
static const struct media_entity_operations hmns0000_media_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int hmns0000_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct camera_common_data *common_data;
struct device_node *node = client->dev.of_node;
struct hmns0000 *priv;
char debugfs_name[10];
int err;
pr_info("[MNS0000 @ %02X]: Probing V4L2 Sensor.\n", client->addr);
if (!IS_ENABLED(CONFIG_OF) || !node)
return -EINVAL;
common_data = devm_kzalloc(&client->dev, sizeof(struct camera_common_data), GFP_KERNEL);
if (!common_data)
return -ENOMEM;
priv = devm_kzalloc(&client->dev,
sizeof(struct hmns0000) + sizeof(struct v4l2_ctrl *) * ARRAY_SIZE(ctrl_config_list),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->pdata = hmns0000_parse_dt(client);
if (!priv->pdata) {
printk("unable to get platform data\n");
return -EFAULT;
}
common_data->ctrl_handler = &priv->ctrl_handler;
common_data->i2c_client = client;
common_data->frmfmt = hmns0000_frmfmt;
common_data->colorfmt = camera_common_find_datafmt(MNS0000_DEFAULT_DATAFMT);
common_data->ctrls = priv->ctrls;
common_data->priv = (void *)priv;
common_data->numctrls = ARRAY_SIZE(ctrl_config_list);
common_data->numfmts = ARRAY_SIZE(hmns0000_frmfmt);
common_data->def_mode = MNS0000_DEFAULT_MODE;
common_data->def_width = MNS0000_DEFAULT_WIDTH;
common_data->def_height = MNS0000_DEFAULT_HEIGHT;
common_data->fmt_width = common_data->def_width;
common_data->fmt_height = common_data->def_height;
priv->i2c_client = client;
priv->s_data = common_data;
priv->subdev = &common_data->subdev;
priv->subdev->dev = &client->dev;
priv->s_data->dev = &client->dev;
err = camera_common_parse_ports(client, common_data);
if (err) {
printk("Failed to find port info\n");
return err;
}
sprintf(debugfs_name, "hmns0000_%c", common_data->csi_port + 'a');
printk("%s: name %s\n", __func__, debugfs_name);
camera_common_create_debugfs(common_data, debugfs_name);
v4l2_i2c_subdev_init(priv->subdev, client, &hmns0000_subdev_ops);
err = hmns0000_ctrls_init(priv, !err);
if (err)
return err;
priv->subdev->internal_ops = &hmns0000_subdev_internal_ops;
priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
#if defined(CONFIG_MEDIA_CONTROLLER)
priv->pad.flags = MEDIA_PAD_FL_SOURCE;
priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
priv->subdev->entity.ops = &hmns0000_media_ops;
err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
if (err < 0) {
printk("unable to init media entity\n");
return err;
}
#endif
err = v4l2_async_register_subdev(priv->subdev);
if (err)
return err;
printk("Detected MNS0000 Sensor.\n");
return 0;
}
static int hmns0000_remove(struct i2c_client *client)
{
struct camera_common_data *s_data = to_camera_common_data(client);
struct hmns0000 *priv = (struct hmns0000 *)s_data->priv;
v4l2_async_unregister_subdev(priv->subdev);
#if defined(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&priv->subdev->entity);
#endif
v4l2_ctrl_handler_free(&priv->ctrl_handler);
camera_common_remove_debugfs(s_data);
return 0;
}
static const struct i2c_device_id hmns0000_id[] = {
{ "hmns0000", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, hmns0000_id);
static struct i2c_driver hmns0000_i2c_driver = {
.driver = {
.name = "hmns0000",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(hmns0000_of_match),
},
.probe = hmns0000_probe,
.remove = hmns0000_remove,
.id_table = hmns0000_id,
};
module_i2c_driver(hmns0000_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for HMNS0000");
MODULE_AUTHOR("Walter Kim <ys.kim@hyundai-mnsoft.com>");
MODULE_LICENSE("GPL v2");
The following is Device Tree.
/*
* Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/ {
host1x {
vi@15700000 {
num-channels = <3>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_vi_in0: endpoint {
csi-port = <0>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_out0>;
};
};
port@1 {
reg = <1>;
hmns0000_aggregate_vi_in1: endpoint {
csi-port = <2>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_out1>;
};
};
port@2 {
reg = <2>;
hmns0000_aggregate_vi_in2: endpoint {
csi-port = <4>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_out2>;
};
};
};
};
nvcsi@150c0000 {
num-channels = <3>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_csi_in0: endpoint@0 {
csi-port = <0>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_hmns0000_out0>;
};
};
port@1 {
reg = <1>;
hmns0000_aggregate_csi_out0: endpoint@1 {
remote-endpoint = <&hmns0000_aggregate_vi_in0>;
};
};
};
};
channel@1 {
reg = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_csi_in1: endpoint@2 {
csi-port = <2>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_hmns0000_out1>;
};
};
port@1 {
reg = <1>;
hmns0000_aggregate_csi_out1: endpoint@3 {
remote-endpoint = <&hmns0000_aggregate_vi_in1>;
};
};
};
};
channel@2 {
reg = <2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_csi_in2: endpoint@4 {
csi-port = <4>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_hmns0000_out2>;
};
};
port@1 {
reg = <1>;
hmns0000_aggregate_csi_out2: endpoint@5 {
remote-endpoint = <&hmns0000_aggregate_vi_in2>;
};
};
};
};
};
};
i2c@3180000 {
hmns0000@10 {
compatible = "nvidia,hmns0000";
/* I2C device address */
reg = <0x10>;
mode0 { //1280x720
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1280";
active_h = "720";
pixel_t = "uyvy";
line_length = "1280";
pix_clk_hz = "74000000";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "0";
};
mode1 { //1280x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1280";
active_h = "800";
pixel_t = "uyvy";
line_length = "1280";
};
mode2 { //2560x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "2560";
active_h = "800";
pixel_t = "uyvy";
line_length = "2560";
};
mode3 { //3840x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "800";
pixel_t = "uyvy";
line_length = "3840";
};
mode4 { //5120x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "5120";
active_h = "800";
pixel_t = "uyvy";
line_length = "5120";
};
mode5 { //HMNS0000_MODE_1920X1208
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1920";
active_h = "1208";
pixel_t = "bayer_rggb";
readout_orientation = "0";
line_length = "1354";
inherent_gain = "1";
mclk_multiplier = "25";
pix_clk_hz = "84000000";
gain_factor = "16";
framerate_factor = "1";
min_gain_val = "1";
max_gain_val = "256";
min_exp_time = "34";
max_exp_time = "999994";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "24";
};
mode6 { //1920x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1920";
active_h = "1080";
pixel_t = "uyvy";
line_length = "1920";
};
mode7 { //3840x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "1080";
pixel_t = "uyvy";
line_length = "3840";
};
mode8 { //OV5693_MODE_2304x1728
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "2304";
active_h = "1728";
pixel_t = "bayer_bggr";
readout_orientation = "0";
// line_length = "2711";
line_length = "2304";
mclk_multiplier = "8.5";
// pix_clk_hz = "160000000";
pix_clk_hz = "80000000";
// min_gain_val = "1.0";
// max_gain_val = "9";
// min_gain_val = "16";
// max_gain_val = "192";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "20";
max_exp_time = "327520";
};
/*
mode9 { //OV5693_MODE_4608x3456
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "4608";
active_h = "3456";
pixel_t = "bayer_bggr";
readout_orientation = "0";
line_length = "2711";
mclk_multiplier = "12.3";
// pix_clk_hz = "160000000";
pix_clk_hz = "80000000";
// min_gain_val = "1.0";
// max_gain_val = "9";
// min_gain_val = "16";
// max_gain_val = "192";
min_gain_val = "1";
max_gain_val = "16";
// min_hdr_ratio = "1";
// max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "20";
max_exp_time = "327520";
};
*/
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_hmns0000_out0: endpoint {
csi-port = <0>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_in0>;
};
};
};
};
hmns0000@20 {
compatible = "nvidia,hmns0000";
/* I2C device address */
reg = <0x20>;
// reg = <0x36>;
devnode = "video1";
physical_w = "6.239";
physical_h = "4.673";
sensor_model = "hmns0000";
mode0 { //1280x720
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1280";
active_h = "720";
pixel_t = "uyvy";
line_length = "1280";
pix_clk_hz = "74000000";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "0";
};
mode1 { //1280x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1280";
active_h = "800";
pixel_t = "uyvy";
line_length = "1280";
};
mode2 { //2560x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "2560";
active_h = "800";
pixel_t = "uyvy";
line_length = "2560";
};
mode3 { //3840x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "800";
pixel_t = "uyvy";
line_length = "3840";
};
mode4 { //5120x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "5120";
active_h = "800";
pixel_t = "uyvy";
line_length = "5120";
};
mode5 { //HMNS0000_MODE_1920X1208
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1920";
active_h = "1208";
pixel_t = "bayer_rggb";
readout_orientation = "0";
line_length = "1354";
inherent_gain = "1";
mclk_multiplier = "25";
pix_clk_hz = "84000000";
gain_factor = "16";
framerate_factor = "1";
min_gain_val = "1";
max_gain_val = "256";
min_exp_time = "34";
max_exp_time = "999994";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "24";
};
mode6 { //1920x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1920";
active_h = "1080";
pixel_t = "uyvy";
line_length = "1920";
};
mode7 { //3840x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "1080";
pixel_t = "uyvy";
line_length = "3840";
};
mode8 { //OV5693_MODE_2304x1728
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "2304";
active_h = "1728";
pixel_t = "bayer_bggr";
readout_orientation = "0";
// line_length = "2711";
line_length = "2304";
mclk_multiplier = "8.5";
// pix_clk_hz = "160000000";
pix_clk_hz = "80000000";
// min_gain_val = "1.0";
// max_gain_val = "9";
// min_gain_val = "16";
// max_gain_val = "192";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "20";
max_exp_time = "327520";
};
/*
mode9 { //OV5693_MODE_4608x3456
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_c";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "4608";
active_h = "3456";
pixel_t = "bayer_bggr";
readout_orientation = "0";
line_length = "2711";
mclk_multiplier = "12.3";
// pix_clk_hz = "160000000";
pix_clk_hz = "80000000";
// min_gain_val = "1.0";
// max_gain_val = "9";
// min_gain_val = "16";
// max_gain_val = "192";
min_gain_val = "1";
max_gain_val = "16";
// min_hdr_ratio = "1";
// max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "20";
max_exp_time = "327520";
};
*/
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_hmns0000_out1: endpoint {
csi-port = <2>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_in1>;
};
};
};
};
hmns0000@40 {
compatible = "nvidia,hmns0000";
/* I2C device address */
reg = <0x40>;
mode0 { //1280x720
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1280";
active_h = "720";
pixel_t = "uyvy";
line_length = "1280";
pix_clk_hz = "74000000";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "0";
};
mode1 { //1280x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1280";
active_h = "800";
pixel_t = "uyvy";
line_length = "1280";
};
mode2 { //2560x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "2560";
active_h = "800";
pixel_t = "uyvy";
line_length = "2560";
};
mode3 { //3840x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "800";
pixel_t = "uyvy";
line_length = "3840";
};
mode4 { //5120x800
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "5120";
active_h = "800";
pixel_t = "uyvy";
line_length = "5120";
};
mode5 { //HMNS0000_MODE_1920X1208
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1920";
active_h = "1208";
pixel_t = "bayer_rggb";
readout_orientation = "0";
line_length = "1354";
inherent_gain = "1";
mclk_multiplier = "25";
pix_clk_hz = "84000000";
gain_factor = "16";
framerate_factor = "1";
min_gain_val = "1";
max_gain_val = "256";
min_exp_time = "34";
max_exp_time = "999994";
min_framerate = "1";
max_framerate = "30";
embedded_metadata_height = "24";
};
mode6 { //1920x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "1920";
active_h = "1080";
pixel_t = "uyvy";
line_length = "1920";
};
mode7 { //3840x1080
mclk_khz = "24000";
num_lanes = "4";
tegra_sinterface = "serial_e";
discontinuous_clk = "no";
cil_settletime = "0";
active_w = "3840";
active_h = "1080";
pixel_t = "uyvy";
line_length = "3840";
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hmns0000_aggregate_hmns0000_out2: endpoint {
csi-port = <4>;
bus-width = <4>;
remote-endpoint = <&hmns0000_aggregate_csi_in2>;
};
};
};
};
};
hmns_ov16825@P5V27C {
min_focus_distance = "0.0";
hyper_focal = "0.0";
focal_length = "2.67";
f_number = "2.0";
aperture = "2.0";
};
tegra-camera-platform {
compatible = "nvidia, tegra-camera-platform";
/**
* Physical settings to calculate max ISO BW
*
* num_csi_lanes = <>;
* Total number of CSI lanes when all cameras are active
*
* max_lane_speed = <>;
* Max lane speed in Kbit/s
*
* min_bits_per_pixel = <>;
* Min bits per pixel
*
* vi_peak_byte_per_pixel = <>;
* Max byte per pixel for the VI ISO case
*
* vi_bw_margin_pct = <>;
* Vi bandwidth margin in percentage
*
* max_pixel_rate = <>;
* Max pixel rate in Kpixel/s for the ISP ISO case
*
* isp_peak_byte_per_pixel = <>;
* Max byte per pixel for the ISP ISO case
*
* isp_bw_margin_pct = <>;
* Isp bandwidth margin in percentage
*/
num_csi_lanes = <12>;
max_lane_speed = <1500000>;
min_bits_per_pixel = <10>;
vi_peak_byte_per_pixel = <2>;
vi_bw_margin_pct = <25>;
max_pixel_rate = <750000>;
isp_peak_byte_per_pixel = <5>;
isp_bw_margin_pct = <25>;
modules {
module0 {
badge = "ov16825_hmns";
position = "rear";
orientation = "1";
drivernode0 {
/* Declare PCL support driver (classically known as guid) */
pcl_id = "v4l2_sensor";
/* Driver v4l2 device name */
devname = "hmns 2-0020";
/* Declare the device-tree hierarchy to driver instance */
proc-device-tree = "/proc/device-tree/i2c@3180000/hmns0000@20";
};
drivernode1 {
/* Declare PCL support driver (classically known as guid) */
pcl_id = "v4l2_lens";
proc-device-tree = "/proc/device-tree/hmns_ov16825@P5V27C/";
};
};
};
};
};