summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2015-10-14 11:52:57 -0700
committerMatthew Pedro <mapedro@nvidia.com>2015-10-29 10:52:30 -0700
commitb15d976c0a2e6a3c512001a3be3feaf057655b8b (patch)
treef1669c0ab6c34d4ebdb909e882d6a6c22c5c2b09
parente46e60ceb990edf4e28db1685e28847e8dfca4b3 (diff)
media: tegra_camera: replace workqueue with kthread
Use kthread instead of workqueue, which will create a dedicated kernel thread for capture. Remove useless mutex and convert spin_lock_irq() to normal spin_lock(). Bug 1686911 Change-Id: Ib236a7ebbdd0359f2705774a979825f1f9e9d82a Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/819176 GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro <mapedro@nvidia.com>
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.c69
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.h4
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/vi2.c2
3 files changed, 38 insertions, 37 deletions
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.c b/drivers/media/platform/soc_camera/tegra_camera/common.c
index 2fa4d78a7add..888d0aed96d3 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.c
@@ -16,6 +16,8 @@
#include <linux/delay.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/nvhost.h>
@@ -247,7 +249,7 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
cam->ops->capture_setup(cam);
}
- spin_lock_irq(&cam->videobuf_queue_lock);
+ spin_lock(&cam->videobuf_queue_lock);
vb = cam->active;
do_gettimeofday(&vb->v4l2_buf.timestamp);
@@ -262,37 +264,41 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
cam->num_frames++;
- spin_unlock_irq(&cam->videobuf_queue_lock);
+ spin_unlock(&cam->videobuf_queue_lock);
return err;
}
-static void tegra_camera_work(struct work_struct *work)
+static int tegra_camera_kthread_capture(void *data)
{
- struct tegra_camera_dev *cam =
- container_of(work, struct tegra_camera_dev, work);
+ struct tegra_camera_dev *cam = data;
struct tegra_camera_buffer *buf;
while (1) {
- mutex_lock(&cam->work_mutex);
+ try_to_freeze();
- spin_lock_irq(&cam->videobuf_queue_lock);
+ wait_event_interruptible(cam->wait,
+ !list_empty(&cam->capture) ||
+ kthread_should_stop());
+ if (kthread_should_stop())
+ break;
+
+ spin_lock(&cam->videobuf_queue_lock);
if (list_empty(&cam->capture)) {
cam->active = NULL;
- spin_unlock_irq(&cam->videobuf_queue_lock);
- mutex_unlock(&cam->work_mutex);
- return;
+ spin_unlock(&cam->videobuf_queue_lock);
+ continue;
}
buf = list_entry(cam->capture.next, struct tegra_camera_buffer,
- queue);
+ queue);
cam->active = &buf->vb;
- spin_unlock_irq(&cam->videobuf_queue_lock);
+ spin_unlock(&cam->videobuf_queue_lock);
tegra_camera_capture_frame(cam);
-
- mutex_unlock(&cam->work_mutex);
}
+
+ return 0;
}
static int tegra_camera_init_buffer(struct tegra_camera_buffer *buf)
@@ -481,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_irq(&cam->videobuf_queue_lock);
+ spin_lock(&cam->videobuf_queue_lock);
list_add_tail(&buf->queue, &cam->capture);
- spin_unlock_irq(&cam->videobuf_queue_lock);
+ spin_unlock(&cam->videobuf_queue_lock);
- if (vb2_is_streaming(vb->vb2_queue))
- schedule_work(&cam->work);
+ /* Wait up kthread for capture */
+ wake_up_interruptible(&cam->wait);
}
static void tegra_camera_videobuf_release(struct vb2_buffer *vb)
@@ -498,9 +504,7 @@ 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;
- mutex_lock(&cam->work_mutex);
-
- spin_lock_irq(&cam->videobuf_queue_lock);
+ spin_lock(&cam->videobuf_queue_lock);
if (cam->active == vb)
cam->active = NULL;
@@ -512,9 +516,7 @@ static void tegra_camera_videobuf_release(struct vb2_buffer *vb)
if (buf->queue.next)
list_del_init(&buf->queue);
- spin_unlock_irq(&cam->videobuf_queue_lock);
-
- mutex_unlock(&cam->work_mutex);
+ spin_unlock(&cam->videobuf_queue_lock);
}
static int tegra_camera_videobuf_init(struct vb2_buffer *vb)
@@ -533,8 +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;
- schedule_work(&cam->work);
-
+ /* Start kthread to capture data to buffer */
+ cam->kthread_capture = kthread_run(tegra_camera_kthread_capture, cam,
+ dev_name(&cam->ndev->dev));
return 0;
}
@@ -547,11 +550,14 @@ 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;
- mutex_lock(&cam->work_mutex);
+ /* Stop the kthread for capture */
+ kthread_stop(cam->kthread_capture);
+ cam->kthread_capture = NULL;
+
cam->ops->capture_stop(cam, port);
- mutex_unlock(&cam->work_mutex);
return 0;
}
@@ -612,10 +618,8 @@ static void tegra_camera_remove_device(struct soc_camera_device *icd)
struct tegra_camera_dev *cam = ici->priv;
cam->enable_refcnt--;
- if (!cam->enable_refcnt) {
- cancel_work_sync(&cam->work);
+ if (!cam->enable_refcnt)
tegra_camera_deactivate(cam);
- }
}
static int tegra_camera_set_bus_param(struct soc_camera_device *icd)
@@ -909,9 +913,8 @@ static int tegra_camera_probe(struct platform_device *pdev)
cam->tpg_mode = tpg_mode;
INIT_LIST_HEAD(&cam->capture);
- INIT_WORK(&cam->work, tegra_camera_work);
spin_lock_init(&cam->videobuf_queue_lock);
- mutex_init(&cam->work_mutex);
+ 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 18da08cb6a86..c27c83cd4558 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.h
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.h
@@ -101,8 +101,8 @@ struct tegra_camera_dev {
int sequence_a;
int sequence_b;
- struct work_struct work;
- struct mutex work_mutex;
+ 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/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
index 4d17cda6046e..aaf6d2734ce3 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
@@ -1104,8 +1104,6 @@ static void vi2_sw_reset(struct tegra_camera_dev *cam)
udelay(10);
}
-
-
static int vi2_mipi_calibration(struct tegra_camera_dev *cam)
{
void __iomem *mipi_cal;