media: i2c: maxim: driver version v3.06.00

Signed-off-by: Cai Wenzhong <cwz@rock-chips.com>
Change-Id: If0c75766e3a8eaf6ad6921931c526454ca8b0511
This commit is contained in:
Cai Wenzhong
2024-06-11 19:38:58 +08:00
parent b7fa365e98
commit 1138b37041
6 changed files with 257 additions and 2 deletions

View File

@@ -47,6 +47,11 @@
* 1. unified use __v4l2_ctrl_handler_setup in the xxx_start_stream
* 2. support subscribe hot plug detect v4l2 event
*
* V3.06.00
* 1. support multi-channel information configuration
* 2. mode vc initialization when vc-array isn't configured
* 3. fix the issue of mutex deadlock during hot plug
*
*/
#include <linux/clk.h>
#include <linux/i2c.h>
@@ -74,7 +79,7 @@
#include "maxim2c_api.h"
#define DRIVER_VERSION KERNEL_VERSION(3, 0x05, 0x00)
#define DRIVER_VERSION KERNEL_VERSION(3, 0x06, 0x00)
#define MAXIM2C_NAME "maxim2c"

View File

@@ -49,6 +49,21 @@ struct maxim2c_hot_plug_work {
u32 hot_plug_state;
};
struct maxim2c_vc_info {
u32 enable; // 0: disable, !0: enable
u32 width;
u32 height;
u32 bus_fmt;
/*
* the following are optional parameters, user-defined data types
* default 0: invalid parameter
*/
u32 data_type;
u32 data_bit;
};
struct maxim2c_mode {
u32 width;
u32 height;
@@ -61,6 +76,7 @@ struct maxim2c_mode {
u32 bpp;
const struct regval *reg_list;
u32 vc[PAD_MAX];
struct maxim2c_vc_info vc_info[PAD_MAX];
struct v4l2_rect crop_rect;
};

View File

@@ -103,6 +103,7 @@ static int maxim2c_support_mode_init(maxim2c_t *maxim2c)
struct device_node *node = NULL;
struct maxim2c_mode *mode = NULL;
u32 value = 0, vc_array[PAD_MAX], crop_array[4];
struct maxim2c_vc_info vc_info[PAD_MAX];
int ret = 0, i = 0, array_size = 0;
dev_info(dev, "=== maxim2c support mode init ===\n");
@@ -239,6 +240,41 @@ static int maxim2c_support_mode_init(maxim2c_t *maxim2c)
for (i = 0; i < PAD_MAX; i++)
dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]);
/* vc info */
array_size = of_property_count_u32_elems(node, "vc-info");
if ((array_size > 0) &&
(array_size % sizeof(struct maxim2c_vc_info) == 0) &&
(array_size <= sizeof(struct maxim2c_vc_info) * PAD_MAX)) {
memset((char *)vc_info, 0, sizeof(vc_info));
ret = of_property_read_u32_array(node, "vc-info", (u32 *)vc_info, array_size);
if (ret == 0) {
/* <enable width height bus_fmt data_type data_bit> */
for (i = 0; i < PAD_MAX; i++) {
dev_info(dev, "vc-info[%d] property:\n", i);
dev_info(dev, " vc-info[%d].enable = %d:\n", i, vc_info[i].enable);
dev_info(dev, " vc-info[%d].width = %d:\n", i, vc_info[i].width);
dev_info(dev, " vc-info[%d].height = %d:\n", i, vc_info[i].height);
dev_info(dev, " vc-info[%d].bus_fmt = %d:\n", i, vc_info[i].bus_fmt);
dev_info(dev, " vc-info[%d].data_type = %d:\n", i, vc_info[i].data_type);
dev_info(dev, " vc-info[%d].data_bit = %d:\n", i, vc_info[i].data_bit);
mode->vc_info[i].enable = vc_info[i].enable;
mode->vc_info[i].width = vc_info[i].width;
mode->vc_info[i].height = vc_info[i].height;
mode->vc_info[i].bus_fmt = vc_info[i].bus_fmt;
mode->vc_info[i].data_type = vc_info[i].data_type;
mode->vc_info[i].data_bit = vc_info[i].data_bit;
}
}
}
/* crop rect */
array_size = of_property_read_variable_u32_array(node,
"crop-rect", crop_array, 1, 4);
@@ -354,11 +390,52 @@ static void maxim2c_set_vicap_rst_inf(maxim2c_t *maxim2c,
maxim2c->is_reset = rst_info.is_reset;
}
static int maxim2c_get_channel_info(maxim2c_t *maxim2c, struct rkmodule_channel_info *ch_info)
{
const struct maxim2c_mode *mode = maxim2c->cur_mode;
struct device *dev = &maxim2c->client->dev;
if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
return -EINVAL;
if (mode->vc_info[ch_info->index].enable) {
ch_info->vc = mode->vc[ch_info->index];
ch_info->width = mode->vc_info[ch_info->index].width;
ch_info->height = mode->vc_info[ch_info->index].height;
ch_info->bus_fmt = mode->vc_info[ch_info->index].bus_fmt;
/* optional parameters, default 0: invalid parameter */
ch_info->data_type = mode->vc_info[ch_info->index].data_type;
ch_info->data_bit = mode->vc_info[ch_info->index].data_bit;
} else {
ch_info->vc = mode->vc[ch_info->index];
ch_info->width = mode->width;
ch_info->height = mode->height;
ch_info->bus_fmt = mode->bus_fmt;
}
dev_info(dev, "get channel info, ch_info->index = %d\n", ch_info->index);
dev_info(dev, " ch_info->vc = 0x%x\n", ch_info->vc);
dev_info(dev, " ch_info->width = %d\n", ch_info->width);
dev_info(dev, " ch_info->height = %d\n", ch_info->height);
dev_info(dev, " ch_info->bus_fmt = 0x%x\n", ch_info->bus_fmt);
dev_info(dev, " ch_info->data_type = 0x%x:\n", ch_info->data_type);
dev_info(dev, " ch_info->data_bit = %d\n", ch_info->data_bit);
return 0;
}
static long maxim2c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
maxim2c_t *maxim2c = v4l2_get_subdevdata(sd);
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_capture_info *capture_info;
struct rkmodule_channel_info *ch_info;
long ret = 0;
dev_dbg(&maxim2c->client->dev, "ioctl cmd = 0x%08x\n", cmd);
@@ -392,6 +469,10 @@ static long maxim2c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
else
capture_info->mode = RKMODULE_CAPTURE_MODE_NONE;
break;
case RKMODULE_GET_CHANNEL_INFO:
ch_info = (struct rkmodule_channel_info *)arg;
ret = maxim2c_get_channel_info(maxim2c, ch_info);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -409,6 +490,7 @@ static long maxim2c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
struct rkmodule_vicap_reset_info *vicap_rst_inf;
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_capture_info *capture_info;
struct rkmodule_channel_info *ch_info;
long ret = 0;
switch (cmd) {
@@ -501,6 +583,21 @@ static long maxim2c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
}
kfree(capture_info);
break;
case RKMODULE_GET_CHANNEL_INFO:
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
if (!ch_info) {
ret = -ENOMEM;
return ret;
}
ret = maxim2c_ioctl(sd, cmd, ch_info);
if (!ret) {
ret = copy_to_user(up, ch_info, sizeof(*ch_info));
if (ret)
ret = -EFAULT;
}
kfree(ch_info);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -914,8 +1011,17 @@ static int maxim2c_get_selection(struct v4l2_subdev *sd,
#endif
{
maxim2c_t *maxim2c = v4l2_get_subdevdata(sd);
int i = 0;
if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {
/* if multiple channel info enable, get_selection isn't support */
for (i = 0; i < PAD_MAX; i++) {
if (maxim2c->cur_mode->vc_info[i].enable) {
v4l2_warn(sd, "Multi-channel enable, get_selection isn't support\n");
return -EINVAL;
}
}
sel->r.left = maxim2c->cur_mode->crop_rect.left;
sel->r.width = maxim2c->cur_mode->crop_rect.width;
sel->r.top = maxim2c->cur_mode->crop_rect.top;

View File

@@ -70,6 +70,11 @@
* 1. unified use __v4l2_ctrl_handler_setup in the xxx_start_stream
* 2. support subscribe hot plug detect v4l2 event
*
* V3.06.00
* 1. support multi-channel information configuration
* 2. mode vc initialization when vc-array isn't configured
* 3. fix the issue of mutex deadlock during hot plug
*
*/
#include <linux/clk.h>
#include <linux/i2c.h>
@@ -97,7 +102,7 @@
#include "maxim4c_api.h"
#define DRIVER_VERSION KERNEL_VERSION(3, 0x05, 0x00)
#define DRIVER_VERSION KERNEL_VERSION(3, 0x06, 0x00)
#define MAXIM4C_NAME "maxim4c"

View File

@@ -49,6 +49,21 @@ struct maxim4c_hot_plug_work {
u32 hot_plug_state;
};
struct maxim4c_vc_info {
u32 enable; // 0: disable, !0: enable
u32 width;
u32 height;
u32 bus_fmt;
/*
* the following are optional parameters, user-defined data types
* default 0: invalid parameter
*/
u32 data_type;
u32 data_bit;
};
struct maxim4c_mode {
u32 width;
u32 height;
@@ -61,6 +76,7 @@ struct maxim4c_mode {
u32 bpp;
const struct regval *reg_list;
u32 vc[PAD_MAX];
struct maxim4c_vc_info vc_info[PAD_MAX];
struct v4l2_rect crop_rect;
};

View File

@@ -103,6 +103,7 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c)
struct device_node *node = NULL;
struct maxim4c_mode *mode = NULL;
u32 value = 0, vc_array[PAD_MAX], crop_array[4];
struct maxim4c_vc_info vc_info[PAD_MAX];
int ret = 0, i = 0, array_size = 0;
dev_info(dev, "=== maxim4c support mode init ===\n");
@@ -239,6 +240,41 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c)
for (i = 0; i < PAD_MAX; i++)
dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]);
/* vc info */
array_size = of_property_count_u32_elems(node, "vc-info");
if ((array_size > 0) &&
(array_size % sizeof(struct maxim4c_vc_info) == 0) &&
(array_size <= sizeof(struct maxim4c_vc_info) * PAD_MAX)) {
memset((char *)vc_info, 0, sizeof(vc_info));
ret = of_property_read_u32_array(node, "vc-info", (u32 *)vc_info, array_size);
if (ret == 0) {
/* <enable width height bus_fmt data_type data_bit> */
for (i = 0; i < PAD_MAX; i++) {
dev_info(dev, "vc-info[%d] property:\n", i);
dev_info(dev, " vc-info[%d].enable = %d:\n", i, vc_info[i].enable);
dev_info(dev, " vc-info[%d].width = %d:\n", i, vc_info[i].width);
dev_info(dev, " vc-info[%d].height = %d:\n", i, vc_info[i].height);
dev_info(dev, " vc-info[%d].bus_fmt = %d:\n", i, vc_info[i].bus_fmt);
dev_info(dev, " vc-info[%d].data_type = %d:\n", i, vc_info[i].data_type);
dev_info(dev, " vc-info[%d].data_bit = %d:\n", i, vc_info[i].data_bit);
mode->vc_info[i].enable = vc_info[i].enable;
mode->vc_info[i].width = vc_info[i].width;
mode->vc_info[i].height = vc_info[i].height;
mode->vc_info[i].bus_fmt = vc_info[i].bus_fmt;
mode->vc_info[i].data_type = vc_info[i].data_type;
mode->vc_info[i].data_bit = vc_info[i].data_bit;
}
}
}
/* crop rect */
array_size = of_property_read_variable_u32_array(node,
"crop-rect", crop_array, 1, 4);
@@ -354,11 +390,52 @@ static void maxim4c_set_vicap_rst_inf(maxim4c_t *maxim4c,
maxim4c->is_reset = rst_info.is_reset;
}
static int maxim4c_get_channel_info(maxim4c_t *maxim4c, struct rkmodule_channel_info *ch_info)
{
const struct maxim4c_mode *mode = maxim4c->cur_mode;
struct device *dev = &maxim4c->client->dev;
if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
return -EINVAL;
if (mode->vc_info[ch_info->index].enable) {
ch_info->vc = mode->vc[ch_info->index];
ch_info->width = mode->vc_info[ch_info->index].width;
ch_info->height = mode->vc_info[ch_info->index].height;
ch_info->bus_fmt = mode->vc_info[ch_info->index].bus_fmt;
/* optional parameters, default 0: invalid parameter */
ch_info->data_type = mode->vc_info[ch_info->index].data_type;
ch_info->data_bit = mode->vc_info[ch_info->index].data_bit;
} else {
ch_info->vc = mode->vc[ch_info->index];
ch_info->width = mode->width;
ch_info->height = mode->height;
ch_info->bus_fmt = mode->bus_fmt;
}
dev_info(dev, "get channel info, ch_info->index = %d\n", ch_info->index);
dev_info(dev, " ch_info->vc = 0x%x\n", ch_info->vc);
dev_info(dev, " ch_info->width = %d\n", ch_info->width);
dev_info(dev, " ch_info->height = %d\n", ch_info->height);
dev_info(dev, " ch_info->bus_fmt = 0x%x\n", ch_info->bus_fmt);
dev_info(dev, " ch_info->data_type = 0x%x:\n", ch_info->data_type);
dev_info(dev, " ch_info->data_bit = %d\n", ch_info->data_bit);
return 0;
}
static long maxim4c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
maxim4c_t *maxim4c = v4l2_get_subdevdata(sd);
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_capture_info *capture_info;
struct rkmodule_channel_info *ch_info;
long ret = 0;
dev_dbg(&maxim4c->client->dev, "ioctl cmd = 0x%08x\n", cmd);
@@ -392,6 +469,10 @@ static long maxim4c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
else
capture_info->mode = RKMODULE_CAPTURE_MODE_NONE;
break;
case RKMODULE_GET_CHANNEL_INFO:
ch_info = (struct rkmodule_channel_info *)arg;
ret = maxim4c_get_channel_info(maxim4c, ch_info);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -409,6 +490,7 @@ static long maxim4c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
struct rkmodule_vicap_reset_info *vicap_rst_inf;
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_capture_info *capture_info;
struct rkmodule_channel_info *ch_info;
long ret = 0;
switch (cmd) {
@@ -501,6 +583,21 @@ static long maxim4c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
}
kfree(capture_info);
break;
case RKMODULE_GET_CHANNEL_INFO:
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
if (!ch_info) {
ret = -ENOMEM;
return ret;
}
ret = maxim4c_ioctl(sd, cmd, ch_info);
if (!ret) {
ret = copy_to_user(up, ch_info, sizeof(*ch_info));
if (ret)
ret = -EFAULT;
}
kfree(ch_info);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -914,8 +1011,18 @@ static int maxim4c_get_selection(struct v4l2_subdev *sd,
#endif
{
maxim4c_t *maxim4c = v4l2_get_subdevdata(sd);
int i = 0;
if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {
/* if multiple channel info enable, get_selection isn't support */
for (i = 0; i < PAD_MAX; i++) {
if (maxim4c->cur_mode->vc_info[i].enable) {
v4l2_warn(sd,
"Multi-channel enable, get_selection isn't support\n");
return -EINVAL;
}
}
sel->r.left = maxim4c->cur_mode->crop_rect.left;
sel->r.width = maxim4c->cur_mode->crop_rect.width;
sel->r.top = maxim4c->cur_mode->crop_rect.top;