Skip to content

Commit

Permalink
DSO-18376 D4XX HWMC UVC LibRealSense compatibility
Browse files Browse the repository at this point in the history
- added new volatile CID (offset 32) for set/get HWMC
- Addressing https://rsjira.intel.com/browse/DSO-18376
  [D457][MIPI] Make HWMC work in USB-compatible manner

Signed-off-by: Dmitry Perchanov <dmitry.perchanov@intel.com>
  • Loading branch information
dmipx committed Jul 20, 2022
1 parent 254f5c4 commit fa3c4ed
Showing 1 changed file with 161 additions and 0 deletions.
161 changes: 161 additions & 0 deletions kernel/nvidia/0066-DSO-18376-D4XX-HWMC-UVC-LRS-compat.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
From bd5ffbcf99e977e55f6a8622ba41a1dacf43e7f1 Mon Sep 17 00:00:00 2001
From: Dmitry Perchanov <dmitry.perchanov@intel.com>
Date: Tue, 19 Jul 2022 16:39:06 +0300
Subject: [PATCH] D4XX: HWMC add separate Read/Write CID

Signed-off-by: Dmitry Perchanov <dmitry.perchanov@intel.com>
---
drivers/media/i2c/d4xx.c | 95 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/d4xx.c b/drivers/media/i2c/d4xx.c
index 7d5a319..43f149a 100644
--- a/drivers/media/i2c/d4xx.c
+++ b/drivers/media/i2c/d4xx.c
@@ -1299,6 +1299,9 @@ static int ds5_hw_set_exposure(struct ds5 *state, u32 base, s32 val)
#define DS5_CAMERA_CID_ERB (DS5_CAMERA_CID_BASE+13)
#define DS5_CAMERA_CID_EWB (DS5_CAMERA_CID_BASE+14)
#define DS5_CAMERA_CID_HWMC (DS5_CAMERA_CID_BASE+15)
+/* the HWMC will remain for legacy tools compatibility,
+ * HWMC_RW used for UVC compatibility*/
+#define DS5_CAMERA_CID_HWMC_RW (DS5_CAMERA_CID_BASE+32)

static int ds5_send_hwmc(struct ds5 *state, u16 cmdLen, struct hwm_cmd *cmd,
bool isRead, u16 *dataLen)
@@ -1348,6 +1351,69 @@ static int ds5_send_hwmc(struct ds5 *state, u16 cmdLen, struct hwm_cmd *cmd,
return 0;
}

+#define DS5_HWMC_DATA 0x4900
+#define DS5_HWMC_STATUS 0x4904
+#define DS5_HWMC_RESP_LEN 0x4908
+#define DS5_HWMC_EXEC 0x490C
+
+#define DS5_HWMC_STATUS_OK 0
+#define DS5_HWMC_STATUS_ERR 1
+#define DS5_HWMC_STATUS_WIP 2
+#define DS5_HWMC_BUFFER_SIZE 1024
+
+static int ds5_get_hwmc(struct ds5 *state, unsigned char *data)
+{
+ int ret = 0;
+ u16 status = DS5_HWMC_STATUS_WIP;
+ int retries = 100;
+ int errorCode;
+ u16 tmp_len = 0;
+
+ memset(data, 0, DS5_HWMC_BUFFER_SIZE);
+
+ do {
+ msleep_range(1);
+ ret = ds5_read(state, DS5_HWMC_STATUS, &status);
+ } while (!ret && retries-- && status != DS5_HWMC_STATUS_WIP);
+
+ if (ret || status != DS5_HWMC_STATUS_OK) {
+ if (status == DS5_HWMC_STATUS_ERR) {
+ ds5_raw_read(state, DS5_HWMC_DATA, &errorCode, sizeof(errorCode));
+ dev_err(&state->client->dev,
+ "%s(): HWMC failed, ret: %d, error code: %d\n",
+ __func__, ret, errorCode);
+ } else {
+ dev_err(&state->client->dev,
+ "%s(): HWMC failed because of timeout, ret: %d\n",
+ __func__, ret);
+ }
+ ret = -EAGAIN;
+ }
+
+ ret = regmap_raw_read(state->regmap, DS5_HWMC_RESP_LEN,
+ &tmp_len, sizeof(tmp_len));
+ if (ret)
+ return -EAGAIN;
+
+ if (tmp_len > DS5_HWMC_BUFFER_SIZE)
+ return -ENOBUFS;
+
+ dev_info(&state->client->dev,
+ "%s(): HWMC read len: %d\n",
+ __func__, tmp_len);
+
+ ds5_raw_read_with_check(state, DS5_HWMC_DATA, data, tmp_len);
+
+ /* This is needed for librealsense, to align there code with UVC,
+ * last word is length */
+ data[DS5_HWMC_BUFFER_SIZE - 4] = (unsigned char)(tmp_len & 0x00FF);
+ data[DS5_HWMC_BUFFER_SIZE - 3] = (unsigned char)((tmp_len & 0xFF00) >> 8);
+ data[DS5_HWMC_BUFFER_SIZE - 2] = 0;
+ data[DS5_HWMC_BUFFER_SIZE - 1] = 0;
+
+ return 0;
+}
+
static int ds5_set_calibration_data(struct ds5 *state, struct hwm_cmd *cmd, u16 length)
{
int ret;
@@ -1554,6 +1620,14 @@ static int ds5_s_ctrl(struct v4l2_ctrl *ctrl)
ret = ds5_send_hwmc(state, size + 4, (struct hwm_cmd *)ctrl->p_new.p_u8, true, &dataLen);
}
break;
+ case DS5_CAMERA_CID_HWMC_RW:
+ if (ctrl->p_new.p_u8) {
+ u16 size = *((u8*)ctrl->p_new.p_u8 + 1) << 8;
+ size |= *((u8*)ctrl->p_new.p_u8 + 0);
+ ret = ds5_send_hwmc(state, size + 4,
+ (struct hwm_cmd *)ctrl->p_new.p_u8, false, NULL);
+ }
+ break;
}

mutex_unlock(&state->lock);
@@ -1773,6 +1847,9 @@ static int ds5_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
devm_kfree(&state->client->dev, ae_setpoint_cmd);
}
break;
+ case DS5_CAMERA_CID_HWMC_RW:
+ ds5_get_hwmc(state, ctrl->p_new.p_u8);
+ break;
}

return ret;
@@ -1965,7 +2042,7 @@ static const struct v4l2_ctrl_config ds5_ctrl_hwmc = {
.id = DS5_CAMERA_CID_HWMC,
.name = "HWMC",
.type = V4L2_CTRL_TYPE_U8,
- .dims = {1028},
+ .dims = {DS5_HWMC_BUFFER_SIZE + 4},
.elem_size = sizeof(u8),
.min = 0,
.max = 0xFFFFFFFF,
@@ -1974,6 +2051,20 @@ static const struct v4l2_ctrl_config ds5_ctrl_hwmc = {
.step = 1,
};

+static const struct v4l2_ctrl_config ds5_ctrl_hwmc_rw = {
+ .ops = &ds5_ctrl_ops,
+ .id = DS5_CAMERA_CID_HWMC_RW,
+ .name = "HWMC_RW",
+ .type = V4L2_CTRL_TYPE_U8,
+ .dims = {DS5_HWMC_BUFFER_SIZE},
+ .elem_size = sizeof(u8),
+ .min = 0,
+ .max = 0xFFFFFFFF,
+ .def = 240,
+ .step = 1,
+ .flags = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
+};
+
static int ds5_mux_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct ds5 *state = v4l2_get_subdevdata(sd);
@@ -2100,7 +2191,7 @@ static int ds5_ctrl_init(struct ds5 *state)
ctrls->erb = v4l2_ctrl_new_custom(hdl, &ds5_ctrl_erb, NULL);
ctrls->ewb = v4l2_ctrl_new_custom(hdl, &ds5_ctrl_ewb, NULL);
ctrls->hwmc = v4l2_ctrl_new_custom(hdl, &ds5_ctrl_hwmc, NULL);
-
+ v4l2_ctrl_new_custom(hdl, &ds5_ctrl_hwmc_rw, NULL);
state->mux.sd.subdev.ctrl_handler = hdl;

return 0;
--
2.17.1

0 comments on commit fa3c4ed

Please sign in to comment.