Commit 56e3b29f authored by Helen Koike's avatar Helen Koike Committed by Mauro Carvalho Chehab

media: staging: rkisp1: add streaming paths

Add v4l2 capture device interface to rkisp1 driver, allowing users to
get frames from ISP1.
ISP1 has two major streaming paths, mainpah and selfpah, with different
capabilities.
Each one has an independent crop and resizer, thus add a capture video
device and a resizer subdevice for each of the paths.
Signed-off-by: default avatarJacob Chen <jacob2.chen@rock-chips.com>
Signed-off-by: default avatarShunqian Zheng <zhengsq@rock-chips.com>
Signed-off-by: default avatarYichong Zhong <zyc@rock-chips.com>
Signed-off-by: default avatarJacob Chen <cc@rock-chips.com>
Signed-off-by: default avatarEddie Cai <eddie.cai.linux@gmail.com>
Signed-off-by: default avatarJeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: default avatarAllon Huang <allon.huang@rock-chips.com>
Signed-off-by: default avatarTomasz Figa <tfiga@chromium.org>
Signed-off-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarHelen Koike <helen.koike@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent d65dd852
obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip-isp1.o obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip-isp1.o
rockchip-isp1-objs += rkisp1-common.o \ rockchip-isp1-objs += rkisp1-capture.o \
rkisp1-common.o \
rkisp1-dev.o \ rkisp1-dev.o \
rkisp1-isp.o rkisp1-isp.o \
rkisp1-resizer.o
This diff is collapsed.
...@@ -41,6 +41,16 @@ ...@@ -41,6 +41,16 @@
#define RKISP1_MAX_BUS_CLK 8 #define RKISP1_MAX_BUS_CLK 8
enum rkisp1_rsz_pad {
RKISP1_RSZ_PAD_SINK,
RKISP1_RSZ_PAD_SRC,
};
enum rkisp1_stream_id {
RKISP1_MAINPATH,
RKISP1_SELFPATH,
};
enum rkisp1_fmt_pix_type { enum rkisp1_fmt_pix_type {
RKISP1_FMT_YUV, RKISP1_FMT_YUV,
RKISP1_FMT_RGB, RKISP1_FMT_RGB,
...@@ -124,11 +134,63 @@ struct rkisp1_dummy_buffer { ...@@ -124,11 +134,63 @@ struct rkisp1_dummy_buffer {
struct rkisp1_device; struct rkisp1_device;
/*
* struct rkisp1_capture - ISP capture video device
*
* @pix.fmt: buffer format
* @pix.info: pixel information
* @pix.cfg: pixel configuration
*
* @buf.lock: lock to protect buf_queue
* @buf.queue: queued buffer list
* @buf.dummy: dummy space to store dropped data
*
* rkisp1 use shadowsock registers, so it need two buffer at a time
* @buf.curr: the buffer used for current frame
* @buf.next: the buffer used for next frame
*/
struct rkisp1_capture {
struct rkisp1_vdev_node vnode;
struct rkisp1_device *rkisp1;
enum rkisp1_stream_id id;
struct rkisp1_capture_ops *ops;
const struct rkisp1_capture_config *config;
bool is_streaming;
bool is_stopping;
wait_queue_head_t done;
unsigned int sp_y_stride;
struct {
/* protects queue, curr and next */
spinlock_t lock;
struct list_head queue;
struct rkisp1_dummy_buffer dummy;
struct rkisp1_buffer *curr;
struct rkisp1_buffer *next;
} buf;
struct {
const struct rkisp1_capture_fmt_cfg *cfg;
const struct v4l2_format_info *info;
struct v4l2_pix_format_mplane fmt;
} pix;
};
struct rkisp1_resizer {
struct v4l2_subdev sd;
enum rkisp1_stream_id id;
struct rkisp1_device *rkisp1;
struct media_pad pads[RKISP1_ISP_PAD_MAX];
struct v4l2_subdev_pad_config pad_cfg[RKISP1_ISP_PAD_MAX];
const struct rkisp1_rsz_config *config;
enum rkisp1_fmt_pix_type fmt_type;
};
struct rkisp1_debug { struct rkisp1_debug {
struct dentry *debugfs_dir; struct dentry *debugfs_dir;
unsigned long data_loss; unsigned long data_loss;
unsigned long pic_size_error; unsigned long pic_size_error;
unsigned long mipi_error; unsigned long mipi_error;
unsigned long stop_timeout[2];
unsigned long frame_drop[2];
}; };
/* /*
...@@ -136,6 +198,7 @@ struct rkisp1_debug { ...@@ -136,6 +198,7 @@ struct rkisp1_debug {
* @base_addr: base register address * @base_addr: base register address
* @active_sensor: sensor in-use, set when streaming on * @active_sensor: sensor in-use, set when streaming on
* @isp: ISP sub-device * @isp: ISP sub-device
* @rkisp1_capture: capture video device
*/ */
struct rkisp1_device { struct rkisp1_device {
void __iomem *base_addr; void __iomem *base_addr;
...@@ -149,6 +212,8 @@ struct rkisp1_device { ...@@ -149,6 +212,8 @@ struct rkisp1_device {
struct v4l2_async_notifier notifier; struct v4l2_async_notifier notifier;
struct rkisp1_sensor_async *active_sensor; struct rkisp1_sensor_async *active_sensor;
struct rkisp1_isp isp; struct rkisp1_isp isp;
struct rkisp1_resizer resizer_devs[2];
struct rkisp1_capture capture_devs[2];
struct media_pipeline pipe; struct media_pipeline pipe;
struct vb2_alloc_ctx *alloc_ctx; struct vb2_alloc_ctx *alloc_ctx;
struct rkisp1_debug debug; struct rkisp1_debug debug;
...@@ -196,5 +261,12 @@ const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code); ...@@ -196,5 +261,12 @@ const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code);
void rkisp1_isp_isr(struct rkisp1_device *rkisp1); void rkisp1_isp_isr(struct rkisp1_device *rkisp1);
void rkisp1_mipi_isr(struct rkisp1_device *rkisp1); void rkisp1_mipi_isr(struct rkisp1_device *rkisp1);
void rkisp1_capture_isr(struct rkisp1_device *rkisp1);
int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1);
void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1);
int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1);
void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1);
#endif /* _RKISP1_COMMON_H */ #endif /* _RKISP1_COMMON_H */
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
* *
* ISP Block Diagram * ISP Block Diagram
* ----------------- * -----------------
* rkisp1-resizer.c rkisp1-capture.c
* |====================| |=======================|
* rkisp1-isp.c Main Picture Path * rkisp1-isp.c Main Picture Path
* |==========================| |===============================================| * |==========================| |===============================================|
* +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+ * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+
...@@ -72,8 +74,23 @@ ...@@ -72,8 +74,23 @@
* +----------+ |------+------| * +----------+ |------+------|
* | ISP | * | ISP |
* |------+------| * |------+------|
* | 2 | 3 | * +-------------| 2 | 3 |
* +------+------+ * | +------+------+
* | |
* v v
* +- ---------+ +-----------+
* | 0 | | 0 |
* ------------- -------------
* | Resizer | | Resizer |
* ------------| ------------|
* | 1 | | 1 |
* +-----------+ +-----------+
* | |
* v v
* +-----------+ +-----------+
* | selfpath | | mainpath |
* | (capture) | | (capture) |
* +-----------+ +-----------+
*/ */
struct rkisp1_match_data { struct rkisp1_match_data {
...@@ -87,14 +104,18 @@ struct rkisp1_match_data { ...@@ -87,14 +104,18 @@ struct rkisp1_match_data {
static int rkisp1_create_links(struct rkisp1_device *rkisp1) static int rkisp1_create_links(struct rkisp1_device *rkisp1)
{ {
struct media_entity *source, *sink;
unsigned int flags, source_pad; unsigned int flags, source_pad;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
unsigned int i;
int ret; int ret;
/* sensor links */ /* sensor links */
flags = MEDIA_LNK_FL_ENABLED; flags = MEDIA_LNK_FL_ENABLED;
list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) { list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) {
if (sd == &rkisp1->isp.sd) if (sd == &rkisp1->isp.sd ||
sd == &rkisp1->resizer_devs[RKISP1_MAINPATH].sd ||
sd == &rkisp1->resizer_devs[RKISP1_SELFPATH].sd)
continue; continue;
ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode, ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode,
...@@ -116,6 +137,25 @@ static int rkisp1_create_links(struct rkisp1_device *rkisp1) ...@@ -116,6 +137,25 @@ static int rkisp1_create_links(struct rkisp1_device *rkisp1)
flags = 0; flags = 0;
} }
flags = MEDIA_LNK_FL_ENABLED;
/* create ISP->RSZ->CAP links */
for (i = 0; i < 2; i++) {
source = &rkisp1->isp.sd.entity;
sink = &rkisp1->resizer_devs[i].sd.entity;
ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_VIDEO,
sink, RKISP1_RSZ_PAD_SINK, flags);
if (ret)
return ret;
source = sink;
sink = &rkisp1->capture_devs[i].vnode.vdev.entity;
ret = media_create_pad_link(source, RKISP1_RSZ_PAD_SRC,
sink, 0, flags);
if (ret)
return ret;
}
return 0; return 0;
} }
...@@ -288,15 +328,29 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1) ...@@ -288,15 +328,29 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
if (ret) if (ret)
return ret; return ret;
ret = rkisp1_resizer_devs_register(rkisp1);
if (ret)
goto err_unreg_isp_subdev;
ret = rkisp1_capture_devs_register(rkisp1);
if (ret)
goto err_unreg_resizer_devs;
ret = rkisp1_subdev_notifier(rkisp1); ret = rkisp1_subdev_notifier(rkisp1);
if (ret) { if (ret) {
dev_err(rkisp1->dev, dev_err(rkisp1->dev,
"Failed to register subdev notifier(%d)\n", ret); "Failed to register subdev notifier(%d)\n", ret);
rkisp1_isp_unregister(rkisp1); goto err_unreg_capture_devs;
return ret;
} }
return 0; return 0;
err_unreg_capture_devs:
rkisp1_capture_devs_unregister(rkisp1);
err_unreg_resizer_devs:
rkisp1_resizer_devs_unregister(rkisp1);
err_unreg_isp_subdev:
rkisp1_isp_unregister(rkisp1);
return ret;
} }
static irqreturn_t rkisp1_isr(int irq, void *ctx) static irqreturn_t rkisp1_isr(int irq, void *ctx)
...@@ -304,6 +358,13 @@ static irqreturn_t rkisp1_isr(int irq, void *ctx) ...@@ -304,6 +358,13 @@ static irqreturn_t rkisp1_isr(int irq, void *ctx)
struct device *dev = ctx; struct device *dev = ctx;
struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
/*
* Call rkisp1_capture_isr() first to handle the frame that
* potentially completed using the current frame_sequence number before
* it is potentially incremented by rkisp1_isp_isr() in the vertical
* sync.
*/
rkisp1_capture_isr(rkisp1);
rkisp1_isp_isr(rkisp1); rkisp1_isp_isr(rkisp1);
rkisp1_mipi_isr(rkisp1); rkisp1_mipi_isr(rkisp1);
...@@ -347,6 +408,14 @@ static void rkisp1_debug_init(struct rkisp1_device *rkisp1) ...@@ -347,6 +408,14 @@ static void rkisp1_debug_init(struct rkisp1_device *rkisp1)
&debug->pic_size_error); &debug->pic_size_error);
debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir, debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
&debug->mipi_error); &debug->mipi_error);
debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir,
&debug->stop_timeout[RKISP1_MAINPATH]);
debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir,
&debug->stop_timeout[RKISP1_SELFPATH]);
debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir,
&debug->frame_drop[RKISP1_MAINPATH]);
debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir,
&debug->frame_drop[RKISP1_SELFPATH]);
} }
static int rkisp1_probe(struct platform_device *pdev) static int rkisp1_probe(struct platform_device *pdev)
...@@ -440,6 +509,8 @@ static int rkisp1_remove(struct platform_device *pdev) ...@@ -440,6 +509,8 @@ static int rkisp1_remove(struct platform_device *pdev)
v4l2_async_notifier_unregister(&rkisp1->notifier); v4l2_async_notifier_unregister(&rkisp1->notifier);
v4l2_async_notifier_cleanup(&rkisp1->notifier); v4l2_async_notifier_cleanup(&rkisp1->notifier);
rkisp1_capture_devs_unregister(rkisp1);
rkisp1_resizer_devs_unregister(rkisp1);
rkisp1_isp_unregister(rkisp1); rkisp1_isp_unregister(rkisp1);
media_device_unregister(&rkisp1->media_dev); media_device_unregister(&rkisp1->media_dev);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment