From b2f6b2abc791802631ff1c85488cdf3c1f0a97e2 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Mon, 7 Nov 2016 12:59:07 +0100 Subject: Revert "media: tegra_camera: introduce 2 kthreads for capture" This reverts commit ff5bccb61c1f8da1f63451fda88bd1f65dbee5b2. This makes Antmicro's OV5640 camera module work again as described on their blog here: http://antmicro.com/Blog/2015/09/jetson-tk1-cameras/ Further investigation pending. Acked-by: Marcel Ziswiler Acked-by: Dominik Sliwa --- .../platform/soc_camera/tegra_camera/common.c | 153 +++++++++------------ .../platform/soc_camera/tegra_camera/common.h | 19 +-- .../media/platform/soc_camera/tegra_camera/vi.c | 22 ++- .../media/platform/soc_camera/tegra_camera/vi2.c | 60 +++----- 4 files changed, 104 insertions(+), 150 deletions(-) diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.c b/drivers/media/platform/soc_camera/tegra_camera/common.c index 17129d507d88..888d0aed96d3 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/common.c +++ b/drivers/media/platform/soc_camera/tegra_camera/common.c @@ -46,6 +46,8 @@ module_param(tpg_mode, int, 0644); #define TEGRA_CAM_DRV_NAME "vi" #define TEGRA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define TEGRA_SYNCPT_RETRY_COUNT 10 + static const struct soc_mbus_pixelfmt tegra_camera_yuv_formats[] = { { .fourcc = V4L2_PIX_FMT_UYVY, @@ -201,96 +203,73 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *cam) cam->cal_done = 0; } -static int tegra_camera_capture_frame(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) +static int tegra_camera_capture_frame(struct tegra_camera_dev *cam) { + struct vb2_buffer *vb = cam->active; + struct tegra_camera_buffer *buf = to_tegra_vb(vb); + struct soc_camera_device *icd = buf->icd; + struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; + struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; + int port = pdata->port; + int retry = TEGRA_SYNCPT_RETRY_COUNT; int err; /* Setup capture registers */ - cam->ops->capture_setup(cam, buf); + cam->ops->capture_setup(cam); cam->ops->incr_syncpts(cam); /* MIPI CSI pads calibration after starting capture */ if (cam->ops->mipi_calibration && !cam->cal_done) { - err = cam->ops->mipi_calibration(cam, buf); + err = cam->ops->mipi_calibration(cam); if (!err) cam->cal_done = 1; } - /* Issue start capture */ - cam->ops->capture_start(cam, buf); - - /* Move buffer to capture done queue */ - spin_lock(&cam->done_lock); - list_add_tail(&buf->queue, &cam->done); - spin_unlock(&cam->done_lock); + while (retry) { + err = cam->ops->capture_start(cam, buf); + if (err) { + retry--; - /* Wait up kthread for capture done */ - wake_up_interruptible(&cam->capture_done_wait); - - /* Wait for next frame start */ - return cam->ops->capture_wait(cam, buf); -} - -static int tegra_camera_kthread_capture_start(void *data) -{ - struct tegra_camera_dev *cam = data; - struct tegra_camera_buffer *buf; + cam->ops->incr_syncpts(cam); + if (cam->ops->save_syncpts) + cam->ops->save_syncpts(cam); - while (1) { - try_to_freeze(); - - wait_event_interruptible(cam->capture_start_wait, - !list_empty(&cam->capture) || - kthread_should_stop()); - if (kthread_should_stop()) - break; - - spin_lock(&cam->capture_lock); - if (list_empty(&cam->capture)) { - spin_unlock(&cam->capture_lock); continue; } - - buf = list_entry(cam->capture.next, struct tegra_camera_buffer, - queue); - list_del_init(&buf->queue); - spin_unlock(&cam->capture_lock); - - tegra_camera_capture_frame(cam, buf); + break; } - return 0; -} - -static int tegra_camera_capture_done(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) -{ - struct vb2_buffer *vb = &buf->vb; - struct soc_camera_device *icd = buf->icd; - struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; - struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; - int port = pdata->port; - int err; + /* Reset hardware for too many errors */ + if (!retry) { + tegra_camera_deactivate(cam); + mdelay(5); + tegra_camera_activate(cam, icd); + if (cam->active) + cam->ops->capture_setup(cam); + } - /* Wait for buffer is output to memeory */ - err = cam->ops->capture_done(cam, port); + spin_lock(&cam->videobuf_queue_lock); - /* Buffer is done */ + vb = cam->active; do_gettimeofday(&vb->v4l2_buf.timestamp); vb->v4l2_buf.field = cam->field; if (port == TEGRA_CAMERA_PORT_CSI_A) vb->v4l2_buf.sequence = cam->sequence_a++; else if (port == TEGRA_CAMERA_PORT_CSI_B) vb->v4l2_buf.sequence = cam->sequence_b++; + vb2_buffer_done(vb, err < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + list_del_init(&buf->queue); + cam->num_frames++; + spin_unlock(&cam->videobuf_queue_lock); + return err; } -static int tegra_camera_kthread_capture_done(void *data) +static int tegra_camera_kthread_capture(void *data) { struct tegra_camera_dev *cam = data; struct tegra_camera_buffer *buf; @@ -298,24 +277,25 @@ static int tegra_camera_kthread_capture_done(void *data) while (1) { try_to_freeze(); - wait_event_interruptible(cam->capture_done_wait, - !list_empty(&cam->done) || + wait_event_interruptible(cam->wait, + !list_empty(&cam->capture) || kthread_should_stop()); - if (kthread_should_stop() && list_empty(&cam->done)) + if (kthread_should_stop()) break; - spin_lock(&cam->done_lock); - if (list_empty(&cam->done)) { - spin_unlock(&cam->done_lock); + spin_lock(&cam->videobuf_queue_lock); + if (list_empty(&cam->capture)) { + cam->active = NULL; + spin_unlock(&cam->videobuf_queue_lock); continue; } - buf = list_entry(cam->done.next, struct tegra_camera_buffer, + buf = list_entry(cam->capture.next, struct tegra_camera_buffer, queue); - list_del_init(&buf->queue); - spin_unlock(&cam->done_lock); + cam->active = &buf->vb; + spin_unlock(&cam->videobuf_queue_lock); - tegra_camera_capture_done(cam, buf); + tegra_camera_capture_frame(cam); } return 0; @@ -507,12 +487,12 @@ static void tegra_camera_videobuf_queue(struct vb2_buffer *vb) struct tegra_camera_dev *cam = ici->priv; struct tegra_camera_buffer *buf = to_tegra_vb(vb); - spin_lock(&cam->capture_lock); + spin_lock(&cam->videobuf_queue_lock); list_add_tail(&buf->queue, &cam->capture); - spin_unlock(&cam->capture_lock); + spin_unlock(&cam->videobuf_queue_lock); /* Wait up kthread for capture */ - wake_up_interruptible(&cam->capture_start_wait); + wake_up_interruptible(&cam->wait); } static void tegra_camera_videobuf_release(struct vb2_buffer *vb) @@ -524,7 +504,10 @@ static void tegra_camera_videobuf_release(struct vb2_buffer *vb) struct tegra_camera_buffer *buf = to_tegra_vb(vb); struct tegra_camera_dev *cam = ici->priv; - spin_lock(&cam->done_lock); + spin_lock(&cam->videobuf_queue_lock); + + if (cam->active == vb) + cam->active = NULL; /* * Doesn't hurt also if the list is empty, but it hurts, if queuing the @@ -533,7 +516,7 @@ static void tegra_camera_videobuf_release(struct vb2_buffer *vb) if (buf->queue.next) list_del_init(&buf->queue); - spin_unlock(&cam->done_lock); + spin_unlock(&cam->videobuf_queue_lock); } static int tegra_camera_videobuf_init(struct vb2_buffer *vb) @@ -552,15 +535,9 @@ static int tegra_camera_start_streaming(struct vb2_queue *q, unsigned int count) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct tegra_camera_dev *cam = ici->priv; - /* Start kthread to capture frame */ - cam->kthread_capture_start = kthread_run( - tegra_camera_kthread_capture_start, cam, - "tegra-vi/capture-start"); - - /* Start kthread to wait data output to buffer */ - cam->kthread_capture_done = kthread_run( - tegra_camera_kthread_capture_done, cam, - "tegra-vi/capture-done"); + /* Start kthread to capture data to buffer */ + cam->kthread_capture = kthread_run(tegra_camera_kthread_capture, cam, + dev_name(&cam->ndev->dev)); return 0; } @@ -573,13 +550,12 @@ static int tegra_camera_stop_streaming(struct vb2_queue *q) struct tegra_camera_dev *cam = ici->priv; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; + struct tegra_camera_buffer *buf, *nbuf; int port = pdata->port; /* Stop the kthread for capture */ - kthread_stop(cam->kthread_capture_start); - cam->kthread_capture_start = NULL; - kthread_stop(cam->kthread_capture_done); - cam->kthread_capture_done = NULL; + kthread_stop(cam->kthread_capture); + cam->kthread_capture = NULL; cam->ops->capture_stop(cam, port); @@ -937,11 +913,8 @@ static int tegra_camera_probe(struct platform_device *pdev) cam->tpg_mode = tpg_mode; INIT_LIST_HEAD(&cam->capture); - INIT_LIST_HEAD(&cam->done); - spin_lock_init(&cam->capture_lock); - spin_lock_init(&cam->done_lock); - init_waitqueue_head(&cam->capture_start_wait); - init_waitqueue_head(&cam->capture_done_wait); + spin_lock_init(&cam->videobuf_queue_lock); + init_waitqueue_head(&cam->wait); if (pdev->dev.of_node) { int cplen; diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.h b/drivers/media/platform/soc_camera/tegra_camera/common.h index 1d71c2ba39f5..c27c83cd4558 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/common.h +++ b/drivers/media/platform/soc_camera/tegra_camera/common.h @@ -62,13 +62,9 @@ struct tegra_camera_ops { void (*clks_disable)(struct tegra_camera_dev *cam); void (*capture_clean)(struct tegra_camera_dev *vi2_cam); - int (*capture_setup)(struct tegra_camera_dev *vi2_cam, - struct tegra_camera_buffer *buf); + int (*capture_setup)(struct tegra_camera_dev *vi2_cam); int (*capture_start)(struct tegra_camera_dev *vi2_cam, struct tegra_camera_buffer *buf); - int (*capture_wait)(struct tegra_camera_dev *vi2_cam, - struct tegra_camera_buffer *buf); - int (*capture_done)(struct tegra_camera_dev *vi2_cam, int port); int (*capture_stop)(struct tegra_camera_dev *vi2_cam, int port); void (*init_syncpts)(struct tegra_camera_dev *vi2_cam); @@ -80,8 +76,7 @@ struct tegra_camera_ops { void (*deactivate)(struct tegra_camera_dev *vi2_cam); int (*port_is_valid)(int port); - int (*mipi_calibration)(struct tegra_camera_dev *vi2_cam, - struct tegra_camera_buffer *buf); + int (*mipi_calibration)(struct tegra_camera_dev *vi2_cam); }; struct tegra_camera_dev { @@ -98,20 +93,16 @@ struct tegra_camera_dev { struct tegra_camera_ops *ops; void __iomem *reg_base; + spinlock_t videobuf_queue_lock; struct list_head capture; - spinlock_t capture_lock; - struct list_head done; - spinlock_t done_lock; struct vb2_buffer *active; struct vb2_alloc_ctx *alloc_ctx; enum v4l2_field field; int sequence_a; int sequence_b; - struct task_struct *kthread_capture_start; - struct task_struct *kthread_capture_done; - wait_queue_head_t capture_start_wait; - wait_queue_head_t capture_done_wait; + struct task_struct *kthread_capture; + wait_queue_head_t wait; /* syncpt ids */ u32 syncpt_id_csi_a; diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi.c b/drivers/media/platform/soc_camera/tegra_camera/vi.c index fe4ea6dcda8a..1fa0d098a88a 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/vi.c +++ b/drivers/media/platform/soc_camera/tegra_camera/vi.c @@ -773,9 +773,10 @@ static int vi_capture_output_channel_setup( } -static int vi_capture_setup(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) +static int vi_capture_setup(struct tegra_camera_dev *cam) { + struct vb2_buffer *vb = cam->active; + struct tegra_camera_buffer *buf = to_tegra_vb(vb); struct soc_camera_device *icd = buf->icd; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; @@ -984,7 +985,8 @@ static int vi_capture_start(struct tegra_camera_dev *cam, static int vi_capture_stop(struct tegra_camera_dev *cam, int port) { - int err = 0; + struct tegra_camera_buffer *buf = to_tegra_vb(cam->active); + int err; if (vi_port_is_csi(port)) err = nvhost_syncpt_wait_timeout_ext(cam->ndev, @@ -993,6 +995,8 @@ static int vi_capture_stop(struct tegra_camera_dev *cam, int port) TEGRA_SYNCPT_VI_WAIT_TIMEOUT, NULL, NULL); + else + err = 0; if (err) { u32 buffer_addr; @@ -1001,8 +1005,18 @@ static int vi_capture_stop(struct tegra_camera_dev *cam, int port) dev_warn(&cam->ndev->dev, "Timeout on VI syncpt\n"); - buffer_addr = TC_VI_REG_RD(cam, + if (buf->output_channel == 0) + buffer_addr = TC_VI_REG_RD(cam, TEGRA_VI_VB0_BASE_ADDRESS_FIRST); + else if (buf->output_channel == 1) + buffer_addr = TC_VI_REG_RD(cam, + TEGRA_VI_VB0_BASE_ADDRESS_SECOND); + else { + dev_err(&cam->ndev->dev, "Wrong output channel %d\n", + buf->output_channel); + return -EINVAL; + } + dev_warn(&cam->ndev->dev, "buffer_addr = 0x%08x\n", buffer_addr); diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c index 99bef12e1b7f..56659fe6bb3a 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c +++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c @@ -787,9 +787,10 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam, return 0; } -static int vi2_capture_setup(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) +static int vi2_capture_setup(struct tegra_camera_dev *cam) { + struct vb2_buffer *vb = cam->active; + struct tegra_camera_buffer *buf = to_tegra_vb(vb); struct soc_camera_device *icd = buf->icd; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; @@ -959,7 +960,7 @@ static void vi2_capture_error_status(struct tegra_camera_dev *cam) } static int vi2_capture_start(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) + struct tegra_camera_buffer *buf) { struct soc_camera_device *icd = buf->icd; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; @@ -972,6 +973,7 @@ static int vi2_capture_start(struct tegra_camera_dev *cam, if (err < 0) return err; + /* Only wait on CSI frame end syncpt if we're using CSI. */ if (port == TEGRA_CAMERA_PORT_CSI_A) { if (!nvhost_syncpt_read_ext_check(cam->ndev, cam->syncpt_id_csi_a, &val)) @@ -982,6 +984,13 @@ static int vi2_capture_start(struct tegra_camera_dev *cam, TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT, VI_CSI_PPA_FRAME_START | cam->syncpt_id_csi_a); TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SINGLE_SHOT, 0x1); + + err = nvhost_syncpt_wait_timeout_ext(cam->ndev, + cam->syncpt_id_csi_a, + cam->syncpt_csi_a, + TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, + NULL, + NULL); } else if (port == TEGRA_CAMERA_PORT_CSI_B || port == TEGRA_CAMERA_PORT_CSI_C) { if (!nvhost_syncpt_read_ext_check(cam->ndev, @@ -993,30 +1002,7 @@ static int vi2_capture_start(struct tegra_camera_dev *cam, TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT, VI_CSI_PPB_FRAME_START | cam->syncpt_id_csi_b); TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_SINGLE_SHOT, 0x1); - } - - return err; -} - -static int vi2_capture_wait(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) -{ - struct soc_camera_device *icd = buf->icd; - struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; - struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; - int port = pdata->port; - int err = 0; - /* Only wait on CSI frame end syncpt if we're using CSI. */ - if (port == TEGRA_CAMERA_PORT_CSI_A) { - err = nvhost_syncpt_wait_timeout_ext(cam->ndev, - cam->syncpt_id_csi_a, - cam->syncpt_csi_a, - TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, - NULL, - NULL); - } else if (port == TEGRA_CAMERA_PORT_CSI_B || - port == TEGRA_CAMERA_PORT_CSI_C) { err = nvhost_syncpt_wait_timeout_ext(cam->ndev, cam->syncpt_id_csi_b, cam->syncpt_csi_b, @@ -1046,7 +1032,7 @@ static int vi2_capture_wait(struct tegra_camera_dev *cam, return err; } -static int vi2_capture_done(struct tegra_camera_dev *cam, int port) +static int vi2_capture_stop(struct tegra_camera_dev *cam, int port) { u32 val; int err = 0; @@ -1076,6 +1062,7 @@ static int vi2_capture_done(struct tegra_camera_dev *cam, int port) TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, NULL, NULL); + TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf002); } else if (port == TEGRA_CAMERA_PORT_CSI_B || port == TEGRA_CAMERA_PORT_CSI_C) { if (!nvhost_syncpt_read_ext_check(cam->ndev, @@ -1102,22 +1089,12 @@ static int vi2_capture_done(struct tegra_camera_dev *cam, int port) TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, NULL, NULL); + TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf002); } return err; } -static int vi2_capture_stop(struct tegra_camera_dev *cam, int port) -{ - u32 reg = (port == TEGRA_CAMERA_PORT_CSI_A) ? - TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND : - TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND; - - TC_VI_REG_WT(cam, reg, 0xf002); - - return 0; -} - /* Reset VI2/CSI2 when activating, no sepecial ops for deactiving */ static void vi2_sw_reset(struct tegra_camera_dev *cam) { @@ -1130,12 +1107,13 @@ static void vi2_sw_reset(struct tegra_camera_dev *cam) } -static int vi2_mipi_calibration(struct tegra_camera_dev *cam, - struct tegra_camera_buffer *buf) +static int vi2_mipi_calibration(struct tegra_camera_dev *cam) { void __iomem *mipi_cal; struct regmap *regs; struct platform_device *pdev = cam->ndev; + struct vb2_buffer *vb = cam->active; + struct tegra_camera_buffer *buf = to_tegra_vb(vb); struct soc_camera_device *icd = buf->icd; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; @@ -1278,8 +1256,6 @@ struct tegra_camera_ops vi2_ops = { .capture_clean = vi2_capture_clean, .capture_setup = vi2_capture_setup, .capture_start = vi2_capture_start, - .capture_wait = vi2_capture_wait, - .capture_done = vi2_capture_done, .capture_stop = vi2_capture_stop, .activate = vi2_sw_reset, -- cgit v1.2.3