media: rockchip: cif: let memory compact mode can be set from user space

Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
Change-Id: Id0e6bd0b9992215a8d1c4169b83e2c4765a697b1
This commit is contained in:
Allon Huang
2020-08-11 19:30:02 +08:00
committed by Tao Huang
parent 962eb1e143
commit 5452fec4f4
5 changed files with 114 additions and 28 deletions

View File

@@ -76,6 +76,7 @@ static const struct cif_output_fmt out_fmts[] = {
.fmt_val = YUV_OUTPUT_422 | UV_STORAGE_ORDER_UVUV,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV61,
.fmt_val = YUV_OUTPUT_422 | UV_STORAGE_ORDER_VUVU,
@@ -83,6 +84,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV12,
.fmt_val = YUV_OUTPUT_420 | UV_STORAGE_ORDER_UVUV,
@@ -90,6 +92,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420SP,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV21,
.fmt_val = YUV_OUTPUT_420 | UV_STORAGE_ORDER_VUVU,
@@ -97,46 +100,54 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420SP,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_YUYV,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_YVYU,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_UYVY,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_VYUY,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_RGB24,
.cplanes = 1,
.mplanes = 1,
.bpp = { 24 },
.csi_fmt_val = CSI_WRDDR_TYPE_RGB888,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_RGB565,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_BGR666,
.cplanes = 1,
.mplanes = 1,
.bpp = { 18 },
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB8,
.cplanes = 1,
@@ -144,6 +155,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG8,
.cplanes = 1,
@@ -151,6 +163,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG8,
.cplanes = 1,
@@ -158,6 +171,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR8,
.cplanes = 1,
@@ -165,6 +179,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB10,
.cplanes = 1,
@@ -172,6 +187,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG10,
.cplanes = 1,
@@ -179,6 +195,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG10,
.cplanes = 1,
@@ -186,6 +203,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.cplanes = 1,
@@ -193,6 +211,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB12,
.cplanes = 1,
@@ -200,6 +219,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG12,
.cplanes = 1,
@@ -207,6 +227,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG12,
.cplanes = 1,
@@ -214,6 +235,7 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR12,
.cplanes = 1,
@@ -221,17 +243,20 @@ static const struct cif_output_fmt out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_Y16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.fmt_type = CIF_FMT_TYPE_RAW,
}
/* TODO: We can support NV12M/NV21M/NV16M/NV61M too */
@@ -1324,18 +1349,11 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream,
* needs aligned with :ALIGN(bits_per_pixel * width / 8, 8), if enable 16bit mode
* needs aligned with :ALIGN(bits_per_pixel * width * 2, 8)
*/
if (dev->hdr.mode == NO_HDR &&
dev->chip_id != CHIP_RV1126_CIF &&
dev->chip_id != CHIP_RV1126_CIF_LITE) {
if (channel->fmt_val == CSI_WRDDR_TYPE_RAW10 ||
channel->fmt_val == CSI_WRDDR_TYPE_RAW12)
channel->virtual_width = ALIGN(channel->width * 2, 8);
else
channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact) {
channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 8);
} else {
if (channel->fmt_val == CSI_WRDDR_TYPE_RAW10 ||
channel->fmt_val == CSI_WRDDR_TYPE_RAW12)
channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 8);
if (fmt->fmt_type == CIF_FMT_TYPE_RAW)
channel->virtual_width = ALIGN(channel->width * 2, 8);
else
channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
}
@@ -1444,18 +1462,20 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream,
channel->cmd_mode_en << 4 | channel->crop_en << 5 |
channel->id << 8 | channel->data_type << 10;
if (dev->chip_id == CHIP_RV1126_CIF ||
dev->chip_id == CHIP_RV1126_CIF_LITE)
if (stream->is_compact)
val |= CSI_ENABLE_MIPI_COMPACT;
else
val &= ~CSI_ENABLE_MIPI_COMPACT;
} else if (mbus_type == V4L2_MBUS_CCP2) {
rkcif_csi_set_lvds_sav_eav(stream, channel);
val = LVDS_ENABLE_CAPTURE | LVDS_MODE(channel->lvds_cfg.mode) |
LVDS_MAIN_LANE(0) | LVDS_FID(0) |
LVDS_LANES_ENABLED(dev->active_sensor->lanes);
if (dev->chip_id == CHIP_RV1126_CIF ||
dev->chip_id == CHIP_RV1126_CIF_LITE)
if (stream->is_compact)
val |= LVDS_COMPACT;
else
val &= ~LVDS_COMPACT;
}
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
@@ -2357,12 +2377,14 @@ static void rkcif_set_fmt(struct rkcif_stream *stream,
}
}
if (dev->hdr.mode == NO_HDR) {
/* compact mode need bytesperline 4bytes align,
* align 8 to bring into correspondence with virtual width
*/
if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact) {
bpl = ALIGN(width * fmt->raw_bpp / 8, 8);
} else {
bpp = rkcif_align_bits_per_pixel(fmt, i);
bpl = width * bpp / CIF_YUV_STORED_BIT_WIDTH;
} else {
/* compact mode need bytesperline 4byte align */
bpl = ALIGN(width * fmt->raw_bpp / 8, 4);
}
size = bpl * height;
imagesize += size;
@@ -2427,6 +2449,10 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
stream->crop_enable = false;
stream->crop_mask = 0x0;
if (dev->chip_id >= CHIP_RV1126_CIF)
stream->is_compact = true;
else
stream->is_compact = false;
}
static int rkcif_fh_open(struct file *filp)
@@ -2786,6 +2812,51 @@ 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)
{
struct rkcif_stream *stream = video_drvdata(file);
struct rkcif_device *dev = stream->cifdev;
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)
stream->is_compact = true;
else
stream->is_compact = false;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct v4l2_ioctl_ops rkcif_v4l2_ioctl_ops = {
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
@@ -2808,6 +2879,8 @@ 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,
};
static void rkcif_unregister_stream_vdev(struct rkcif_stream *stream)

View File

@@ -1292,8 +1292,6 @@ static int rkcif_plat_probe(struct platform_device *pdev)
v4l2_dev = &cif_dev->v4l2_dev;
v4l2_dev->mdev = &cif_dev->media_dev;
strlcpy(v4l2_dev->name, name, sizeof(v4l2_dev->name));
v4l2_ctrl_handler_init(&cif_dev->ctrl_handler, 8);
v4l2_dev->ctrl_handler = &cif_dev->ctrl_handler;
ret = v4l2_device_register(cif_dev->dev, &cif_dev->v4l2_dev);
if (ret < 0)

View File

@@ -93,6 +93,7 @@ enum rkcif_state {
RKCIF_STATE_STREAMING
};
/* when add new chip id, add it in tail for increase */
enum rkcif_chip_id {
CHIP_PX30_CIF,
CHIP_RK1808_CIF,
@@ -181,6 +182,11 @@ struct rkcif_sensor_info {
int lanes;
};
enum cif_fmt_type {
CIF_FMT_TYPE_YUV = 0,
CIF_FMT_TYPE_RAW,
};
/*
* struct cif_output_fmt - The output format
*
@@ -191,6 +197,7 @@ struct rkcif_sensor_info {
* @cplanes: number of colour planes
* @mplanes: number of planes for format
* @raw_bpp: bits per pixel for raw format
* @fmt_type: image format, raw or yuv
*/
struct cif_output_fmt {
u8 bpp[VIDEO_MAX_PLANES];
@@ -200,11 +207,7 @@ struct cif_output_fmt {
u8 cplanes;
u8 mplanes;
u8 raw_bpp;
};
enum cif_fmt_type {
CIF_FMT_TYPE_YUV = 0,
CIF_FMT_TYPE_RAW,
enum cif_fmt_type fmt_type;
};
/*
@@ -213,6 +216,7 @@ enum cif_fmt_type {
* @mbus_code: mbus format
* @dvp_fmt_val: the fmt val corresponding to CIF_FOR register
* @csi_fmt_val: the fmt val corresponding to CIF_CSI_ID_CTRL
* @fmt_type: image format, raw or yuv
* @field: the field type of the input from sensor
*/
struct cif_input_fmt {
@@ -281,6 +285,7 @@ struct rkcif_stream {
enum rkcif_state state;
bool stopping;
bool crop_enable;
bool is_compact;
wait_queue_head_t wq_stopped;
int frame_idx;
int frame_phase;
@@ -364,7 +369,6 @@ struct rkcif_device {
struct v4l2_device v4l2_dev;
struct media_device media_dev;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_async_notifier notifier;
struct rkcif_sensor_info sensors[RKCIF_MAX_SENSOR];

View File

@@ -37,6 +37,9 @@
*2. fix compile error when config with module
*3. support mipi yuv
*4. support selection ioctl for cropping
*5. support cif compact mode(lvds & mipi) can be set from user space
*v0.1.6
*1. add cif self-defined ioctrl cmd:V4L2_CID_CIF_DATA_COMPACT
*/
#define RKCIF_DRIVER_VERSION RKCIF_API_VERSION

View File

@@ -9,6 +9,14 @@
#include <linux/types.h>
#include <linux/v4l2-controls.h>
#define RKCIF_API_VERSION KERNEL_VERSION(0, 1, 0x5)
#define RKCIF_API_VERSION KERNEL_VERSION(0, 1, 0x6)
#define V4L2_CID_CIF_DATA_COMPACT (V4L2_CID_PRIVATE_BASE + 0)
enum cif_csi_lvds_memory {
CSI_LVDS_MEM_16BITS = 0,
CSI_LVDS_MEM_COMPACT,
CSI_LVDS_MEM_MAX,
};
#endif