media: rockchip: cif support config memory mode

cif memory mode
 0: raw12/raw10/raw8 8bit memory compact
 1: raw12/raw10 16bit memory one pixel
    low align for rv1126/rv1109/rk356x
    |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
    | -| -| -| -|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
 2: raw12/raw10 16bit memory one pixel
    high align for rv1126/rv1109/rk356x
    |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
    |11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| -| -| -| -|

 note: rv1109/rv1126/rk356x dvp only support uncompact mode,
       and can be set low align or high align

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I59d619645650dfa10c9b2c168d8c741292f9f90f
This commit is contained in:
Zefa Chen
2021-10-09 17:23:28 +08:00
committed by Tao Huang
parent ecb04d26a3
commit 03d58d32a5
5 changed files with 160 additions and 43 deletions

View File

@@ -1826,7 +1826,9 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream,
channel->vc = stream->vc;
else
channel->vc = channel->id;
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
"%s: channel width %d, height %d, virtual_width %d, vc %d\n", __func__,
channel->width, channel->height, channel->virtual_width, channel->vc);
return 0;
}
@@ -1941,7 +1943,10 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream,
else
val &= ~LVDS_COMPACT;
}
if (stream->is_high_align)
val |= CSI_ENABLE_MIPI_HIGH_ALIGN;
else
val &= ~CSI_ENABLE_MIPI_HIGH_ALIGN;
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
return 0;
@@ -2944,12 +2949,21 @@ static int rkcif_stream_start(struct rkcif_stream *stream)
| stream->cif_fmt_in->dvp_fmt_val
| xfer_mode | yc_swap | multi_id_en
| multi_id_sel | multi_id_mode | bt1120_edge_mode;
if (stream->is_high_align)
val |= CIF_HIGH_ALIGN;
else
val &= ~CIF_HIGH_ALIGN;
rkcif_write_register(dev, CIF_REG_DVP_FOR, val);
val = stream->pixm.width;
if (stream->cif_fmt_in->fmt_type == CIF_FMT_TYPE_RAW) {
fmt = find_output_fmt(stream, stream->pixm.pixelformat);
val = stream->pixm.width * rkcif_cal_raw_vir_line_ratio(stream, fmt);
if (fmt->fmt_type == CIF_FMT_TYPE_RAW &&
fmt->csi_fmt_val == CSI_WRDDR_TYPE_RAW8)
val = ALIGN(stream->pixm.width * fmt->raw_bpp / 8, 256);
else
val = stream->pixm.width * rkcif_cal_raw_vir_line_ratio(stream, fmt);
}
rkcif_write_register(dev, CIF_REG_DVP_VIR_LINE_WIDTH, val);
rkcif_write_register(dev, CIF_REG_DVP_SET_SIZE,
@@ -3410,10 +3424,19 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
stream->crop_dyn_en = false;
stream->crop_mask = 0x0;
if (dev->chip_id >= CHIP_RV1126_CIF)
stream->is_compact = true;
else
stream->is_compact = false;
if (dev->inf_id == RKCIF_DVP) {
if (dev->chip_id <= CHIP_RK3568_CIF)
stream->is_compact = false;
else
stream->is_compact = true;
} else {
if (dev->chip_id >= CHIP_RV1126_CIF)
stream->is_compact = true;
else
stream->is_compact = false;
}
stream->is_high_align = false;
if (dev->chip_id == CHIP_RV1126_CIF ||
dev->chip_id == CHIP_RV1126_CIF_LITE)
@@ -3846,42 +3869,53 @@ err:
return -EINVAL;
}
static int rkcif_g_ctrl(struct file *file, void *fh,
struct v4l2_control *ctrl)
{
struct rkcif_stream *stream = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_CIF_DATA_COMPACT:
if (stream->is_compact)
ctrl->value = CSI_MEM_COMPACT;
else
ctrl->value = CSI_MEM_BYTE_LE;
break;
default:
return -EINVAL;
}
return 0;
}
static int rkcif_s_ctrl(struct file *file, void *fh,
struct v4l2_control *ctrl)
static long rkcif_ioctl_default(struct file *file, void *fh,
bool valid_prio, unsigned int cmd, void *arg)
{
struct rkcif_stream *stream = video_drvdata(file);
struct rkcif_device *dev = stream->cifdev;
const struct cif_input_fmt *in_fmt;
struct v4l2_rect rect;
int vc = 0;
if (stream->state == RKCIF_STATE_STREAMING) {
v4l2_err(&dev->v4l2_dev, "set failed, the stream is streaming\n");
return -EBUSY;
}
switch (ctrl->id) {
case V4L2_CID_CIF_DATA_COMPACT:
if (ctrl->value == CSI_LVDS_MEM_COMPACT)
switch (cmd) {
case RKCIF_CMD_GET_CSI_MEMORY_MODE:
if (stream->is_compact) {
*(int *)arg = CSI_LVDS_MEM_COMPACT;
} else {
if (stream->is_high_align)
*(int *)arg = CSI_LVDS_MEM_WORD_HIGH_ALIGN;
else
*(int *)arg = CSI_LVDS_MEM_WORD_LOW_ALIGN;
}
break;
case RKCIF_CMD_SET_CSI_MEMORY_MODE:
if (dev->terminal_sensor.sd) {
in_fmt = get_input_fmt(dev->terminal_sensor.sd, &rect, 0, &vc);
if (in_fmt == NULL) {
v4l2_err(&dev->v4l2_dev, "can't get sensor input format\n");
return -EINVAL;
}
} else {
v4l2_err(&dev->v4l2_dev, "can't get sensor device\n");
return -EINVAL;
}
if (*(int *)arg == CSI_LVDS_MEM_COMPACT) {
if (((dev->inf_id == RKCIF_DVP && dev->chip_id <= CHIP_RK3568_CIF) ||
(dev->inf_id == RKCIF_MIPI_LVDS && dev->chip_id < CHIP_RV1126_CIF)) &&
in_fmt->csi_fmt_val != CSI_WRDDR_TYPE_RAW8) {
v4l2_err(&dev->v4l2_dev, "device not support compact\n");
return -EINVAL;
}
stream->is_compact = true;
else
stream->is_high_align = false;
} else if (*(int *)arg == CSI_LVDS_MEM_WORD_HIGH_ALIGN) {
stream->is_compact = false;
stream->is_high_align = true;
} else {
stream->is_compact = false;
stream->is_high_align = false;
}
break;
default:
return -EINVAL;
@@ -3913,8 +3947,7 @@ static const struct v4l2_ioctl_ops rkcif_v4l2_ioctl_ops = {
.vidioc_g_selection = rkcif_g_selection,
.vidioc_enum_frameintervals = rkcif_enum_frameintervals,
.vidioc_enum_framesizes = rkcif_enum_framesizes,
.vidioc_g_ctrl = rkcif_g_ctrl,
.vidioc_s_ctrl = rkcif_s_ctrl,
.vidioc_default = rkcif_ioctl_default,
};
static void rkcif_unregister_stream_vdev(struct rkcif_stream *stream)

View File

@@ -152,6 +152,64 @@ static ssize_t rkcif_store_dummybuf_mode(struct device *dev,
return len;
}
/* show the compact mode of each stream in stream index order,
* 1 for compact, 0 for 16bit
*/
static ssize_t rkcif_show_memory_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE,
"stream[0~3] %d %d %d %d, 0(low align) 1(high align) 2(compact)\n",
cif_dev->stream[0].is_compact ? 2 : (cif_dev->stream[0].is_high_align ? 1 : 0),
cif_dev->stream[1].is_compact ? 2 : (cif_dev->stream[1].is_high_align ? 1 : 0),
cif_dev->stream[2].is_compact ? 2 : (cif_dev->stream[2].is_high_align ? 1 : 0),
cif_dev->stream[3].is_compact ? 2 : (cif_dev->stream[3].is_high_align ? 1 : 0));
return ret;
}
static ssize_t rkcif_store_memory_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4];
if (buf) {
index = 0;
for (i = 0; i < len; i++) {
if (buf[i] == ' ') {
continue;
} else if (buf[i] == '\0') {
break;
} else {
val[index] = buf[i];
index++;
if (index == 4)
break;
}
}
for (i = 0; i < index; i++) {
if (cif_dev->stream[i].is_compact) {
dev_info(cif_dev->dev, "stream[%d] set memory align fail, is compact mode\n",
i);
continue;
}
if (val[i] - '0' == 0)
cif_dev->stream[i].is_high_align = false;
else
cif_dev->stream[i].is_high_align = true;
}
}
return len;
}
static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR,
rkcif_show_compact_mode, rkcif_store_compact_mode);
@@ -161,11 +219,15 @@ static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR,
rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode);
static DEVICE_ATTR(is_high_align, S_IWUSR | S_IRUSR,
rkcif_show_memory_mode, rkcif_store_memory_mode);
static struct attribute *dev_attrs[] = {
&dev_attr_compact_test.attr,
&dev_attr_wait_line.attr,
&dev_attr_is_use_dummybuf.attr,
&dev_attr_is_high_align.attr,
NULL,
};

View File

@@ -447,6 +447,7 @@ struct rkcif_stream {
bool is_line_inten;
bool is_can_stop;
bool is_buf_active;
bool is_high_align;
};
struct rkcif_lvds_subdev {

View File

@@ -432,6 +432,7 @@ enum cif_reg_index {
#define BT656_1120_MULTI_ID_1_MASK ~(0x03 << 12)
#define BT656_1120_MULTI_ID_2_MASK ~(0x03 << 20)
#define BT656_1120_MULTI_ID_3_MASK ~(0x03 << 28)
#define CIF_HIGH_ALIGN (0x01 << 18)
/* CIF_SCL_CTRL */
#define ENABLE_SCL_DOWN (0x01 << 0)
@@ -515,6 +516,7 @@ enum cif_reg_index {
#define CSI_YUV_INPUT_ORDER_VYUY (0x1 << 16)
#define CSI_YUV_INPUT_ORDER_YUYV (0x2 << 16)
#define CSI_YUV_INPUT_ORDER_YVYU (0x3 << 16)
#define CSI_ENABLE_MIPI_HIGH_ALIGN (0x1 << 31)
#define LVDS_ENABLE_CAPTURE (0x1 << 16)
#define LVDS_MODE(mode) (((mode) & 0x7) << 17)

View File

@@ -11,12 +11,31 @@
#define RKCIF_API_VERSION KERNEL_VERSION(0, 1, 0xa)
#define V4L2_CID_CIF_DATA_COMPACT (V4L2_CID_PRIVATE_BASE + 0)
#define RKCIF_CMD_GET_CSI_MEMORY_MODE \
_IOR('V', BASE_VIDIOC_PRIVATE + 0, int)
#define RKCIF_CMD_SET_CSI_MEMORY_MODE \
_IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
/* cif memory mode
* 0: raw12/raw10/raw8 8bit memory compact
* 1: raw12/raw10 16bit memory one pixel
* low align for rv1126/rv1109/rk356x
* |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
* | -| -| -| -|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
* 2: raw12/raw10 16bit memory one pixel
* high align for rv1126/rv1109/rk356x
* |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
* |11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| -| -| -| -|
*
* note: rv1109/rv1126/rk356x dvp only support uncompact mode,
* and can be set low align or high align
*/
enum cif_csi_lvds_memory {
CSI_LVDS_MEM_16BITS = 0,
CSI_LVDS_MEM_COMPACT,
CSI_LVDS_MEM_MAX,
CSI_LVDS_MEM_COMPACT = 0,
CSI_LVDS_MEM_WORD_LOW_ALIGN = 1,
CSI_LVDS_MEM_WORD_HIGH_ALIGN = 2,
};
#endif