mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user