cron job: media_tree daily build: ERRORS

2018-03-09 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Sat Mar 10 05:00:13 CET 2018
media-tree git hash:e68854a2588a923b31eebce348f8020374843f8e
media_build git hash:   992168cb60d578dfaf4859a70184fc71780e503d
v4l-utils git hash: 14ce03c18ef67aa7a3d5781f015be855fd43839c
gcc version:i686-linux-gcc (GCC) 7.3.0
sparse version: v0.5.0-3994-g45eb2282
smatch version: v0.5.0-3994-g45eb2282
host hardware:  x86_64
host os:4.14.0-3-amd64

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-multi: WARNINGS
linux-git-arm-pxa: OK
linux-git-arm-stm32: OK
linux-git-arm64: OK
linux-git-blackfin-bf561: OK
linux-git-i686: OK
linux-git-m32r: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
linux-2.6.36.4-i686: ERRORS
linux-2.6.36.4-x86_64: ERRORS
linux-2.6.37.6-i686: ERRORS
linux-2.6.37.6-x86_64: ERRORS
linux-2.6.38.8-i686: ERRORS
linux-2.6.38.8-x86_64: ERRORS
linux-2.6.39.4-i686: ERRORS
linux-2.6.39.4-x86_64: ERRORS
linux-3.0.60-i686: ERRORS
linux-3.0.60-x86_64: ERRORS
linux-3.1.10-i686: ERRORS
linux-3.1.10-x86_64: ERRORS
linux-3.2.98-i686: ERRORS
linux-3.2.98-x86_64: ERRORS
linux-3.3.8-i686: ERRORS
linux-3.3.8-x86_64: ERRORS
linux-3.4.27-i686: ERRORS
linux-3.4.27-x86_64: ERRORS
linux-3.5.7-i686: ERRORS
linux-3.5.7-x86_64: ERRORS
linux-3.6.11-i686: ERRORS
linux-3.6.11-x86_64: ERRORS
linux-3.7.4-i686: ERRORS
linux-3.7.4-x86_64: ERRORS
linux-3.8-i686: ERRORS
linux-3.8-x86_64: ERRORS
linux-3.9.2-i686: WARNINGS
linux-3.9.2-x86_64: WARNINGS
linux-3.10.1-i686: WARNINGS
linux-3.10.1-x86_64: WARNINGS
linux-3.11.1-i686: WARNINGS
linux-3.11.1-x86_64: WARNINGS
linux-3.12.67-i686: WARNINGS
linux-3.12.67-x86_64: WARNINGS
linux-3.13.11-i686: WARNINGS
linux-3.13.11-x86_64: WARNINGS
linux-3.14.9-i686: WARNINGS
linux-3.14.9-x86_64: WARNINGS
linux-3.15.2-i686: WARNINGS
linux-3.15.2-x86_64: WARNINGS
linux-3.16.53-i686: WARNINGS
linux-3.16.53-x86_64: WARNINGS
linux-3.17.8-i686: WARNINGS
linux-3.17.8-x86_64: WARNINGS
linux-3.18.93-i686: WARNINGS
linux-3.18.93-x86_64: WARNINGS
linux-3.19-i686: WARNINGS
linux-3.19-x86_64: WARNINGS
linux-4.0.9-i686: WARNINGS
linux-4.0.9-x86_64: WARNINGS
linux-4.1.49-i686: WARNINGS
linux-4.1.49-x86_64: WARNINGS
linux-4.2.8-i686: WARNINGS
linux-4.2.8-x86_64: WARNINGS
linux-4.3.6-i686: WARNINGS
linux-4.3.6-x86_64: WARNINGS
linux-4.4.115-i686: WARNINGS
linux-4.4.115-x86_64: WARNINGS
linux-4.5.7-i686: WARNINGS
linux-4.5.7-x86_64: WARNINGS
linux-4.6.7-i686: WARNINGS
linux-4.6.7-x86_64: WARNINGS
linux-4.7.5-i686: WARNINGS
linux-4.7.5-x86_64: WARNINGS
linux-4.8-i686: WARNINGS
linux-4.8-x86_64: WARNINGS
linux-4.9.80-i686: WARNINGS
linux-4.9.80-x86_64: WARNINGS
linux-4.10.14-i686: WARNINGS
linux-4.10.14-x86_64: WARNINGS
linux-4.11-i686: WARNINGS
linux-4.11-x86_64: WARNINGS
linux-4.12.1-i686: WARNINGS
linux-4.12.1-x86_64: WARNINGS
linux-4.13-i686: WARNINGS
linux-4.13-x86_64: WARNINGS
linux-4.14.17-i686: WARNINGS
linux-4.14.17-x86_64: WARNINGS
linux-4.15.2-i686: WARNINGS
linux-4.15.2-x86_64: WARNINGS
linux-4.16-rc1-i686: WARNINGS
linux-4.16-rc1-x86_64: WARNINGS
apps: WARNINGS
spec-git: OK
sparse: WARNINGS
smatch: OK

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Saturday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Saturday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/index.html


[PATCH 0/3] rcar-vin: always run in continues mode

2018-03-09 Thread Niklas Söderlund
Hi,

This series reworks the R-Car VIN driver to only run using its continues 
capture mode. This improves performance a lot when userspace struggles 
to keep up and queue buffers as fast as the VIN driver consumes them.  
The solution to always be able to run in continues is to introduce a 
scratch buffer inside the VIN driver which it can pad the hardware 
capture buffer ring with if it have no buffer from userspace. Using this 
scratch buffer allows the driver to not need to stop capturing when it 
run out of buffers and then restart it once it have more buffers.

Patch 1/3 removes a duplicated check in the VIN interrupt handler. Patch 
2/3 adds the allocation of the scratch buffer. And finally 3/3 drops the 
single capture mode in favor of always running in continues capture mode 
and the scratch buffer.

The series is based on top of the latest media-tree master branch and 
can be fetched from.

git://git.ragnatech.se/linux v4l2/next/vin/mode-v1

It is tested on R-Car Koelsch Gen2 board using the onboard HDMI and CVBS 
inputs. The test application v4l2-compliance pass for both inputs 
without issues or warnings. A slight adaption of these patches to the 
pending VIN Gen3 patches have been tested with great improvement in 
capture speed for buffer strained situations and no regressions in the 
vin-tests suite.

Niklas Söderlund (3):
  rcar-vin: remove duplicated check of state in irq handler
  rcar-vin: allocate a scratch buffer at stream start
  rcar-vin: use scratch buffer and always run in continuous mode

 drivers/media/platform/rcar-vin/rcar-dma.c | 212 ++---
 drivers/media/platform/rcar-vin/rcar-vin.h |  10 +-
 2 files changed, 75 insertions(+), 147 deletions(-)

-- 
2.16.2



[PATCH 3/3] rcar-vin: use scratch buffer and always run in continuous mode

2018-03-09 Thread Niklas Söderlund
Instead of switching capture mode depending on how many buffers are
available use a scratch buffer and always run in continuous mode. By
using a scratch buffer the responsiveness of the capture loop is
increased as it can keep running even if there are no buffers available
from userspace.

As soon as a userspace queues a buffer it is inserted into the capture
loop and returned as soon as it is filled. This is a improvement on the
previous logic where the whole capture loop was stopped and switched to
single capture mode if userspace did not feed the VIN driver buffers at
the same time it consumed them. To make matters worse it was difficult
for the driver to reenter continues mode if it entered single mode even
if userspace started to queue buffers faster. This resulted in
suboptimal performance where if userspace where delayed for a short
period the ongoing capture would be slowed down and run in single mode
until the capturing process where restarted.

An additional effect of this change is that the capture logic can be
made much simple as we know that continues mode will always be used.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 187 -
 drivers/media/platform/rcar-vin/rcar-vin.h |   6 +-
 2 files changed, 52 insertions(+), 141 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
b/drivers/media/platform/rcar-vin/rcar-dma.c
index 8ea73cdc9a720abe..208cf8a0ea77002d 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -168,12 +168,8 @@ static int rvin_setup(struct rvin_dev *vin)
break;
case V4L2_FIELD_ALTERNATE:
case V4L2_FIELD_NONE:
-   if (vin->continuous) {
-   vnmc = VNMC_IM_ODD_EVEN;
-   progressive = true;
-   } else {
-   vnmc = VNMC_IM_ODD;
-   }
+   vnmc = VNMC_IM_ODD_EVEN;
+   progressive = true;
break;
default:
vnmc = VNMC_IM_ODD;
@@ -298,14 +294,6 @@ static bool rvin_capture_active(struct rvin_dev *vin)
return rvin_read(vin, VNMS_REG) & VNMS_CA;
 }
 
-static int rvin_get_active_slot(struct rvin_dev *vin, u32 vnms)
-{
-   if (vin->continuous)
-   return (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
-
-   return 0;
-}
-
 static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
 {
if (vin->format.field == V4L2_FIELD_ALTERNATE) {
@@ -344,76 +332,47 @@ static void rvin_set_slot_addr(struct rvin_dev *vin, int 
slot, dma_addr_t addr)
rvin_write(vin, offset, VNMB_REG(slot));
 }
 
-/* Moves a buffer from the queue to the HW slots */
-static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
+/*
+ * Moves a buffer from the queue to the HW slot. If no buffer is
+ * available use the scratch buffer. The scratch buffer is never
+ * returned to userspace, its only function is to enable the capture
+ * loop to keep running.
+ */
+static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
 {
struct rvin_buffer *buf;
struct vb2_v4l2_buffer *vbuf;
-   dma_addr_t phys_addr_top;
-
-   if (vin->queue_buf[slot] != NULL)
-   return true;
+   dma_addr_t phys_addr;
 
-   if (list_empty(>buf_list))
-   return false;
+   /* A already populated slot shall never be overwritten. */
+   if (WARN_ON(vin->queue_buf[slot] != NULL))
+   return;
 
vin_dbg(vin, "Filling HW slot: %d\n", slot);
 
-   /* Keep track of buffer we give to HW */
-   buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
-   vbuf = >vb;
-   list_del_init(to_buf_list(vbuf));
-   vin->queue_buf[slot] = vbuf;
-
-   /* Setup DMA */
-   phys_addr_top = vb2_dma_contig_plane_dma_addr(>vb2_buf, 0);
-   rvin_set_slot_addr(vin, slot, phys_addr_top);
-
-   return true;
-}
-
-static bool rvin_fill_hw(struct rvin_dev *vin)
-{
-   int slot, limit;
-
-   limit = vin->continuous ? HW_BUFFER_NUM : 1;
-
-   for (slot = 0; slot < limit; slot++)
-   if (!rvin_fill_hw_slot(vin, slot))
-   return false;
-   return true;
-}
-
-static void rvin_capture_on(struct rvin_dev *vin)
-{
-   vin_dbg(vin, "Capture on in %s mode\n",
-   vin->continuous ? "continuous" : "single");
+   if (list_empty(>buf_list)) {
+   vin->queue_buf[slot] = NULL;
+   phys_addr = vin->scratch_phys;
+   } else {
+   /* Keep track of buffer we give to HW */
+   buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
+   vbuf = >vb;
+   list_del_init(to_buf_list(vbuf));
+   vin->queue_buf[slot] = vbuf;
+
+   /* Setup DMA */
+   phys_addr = 

[PATCH 1/3] rcar-vin: remove duplicated check of state in irq handler

2018-03-09 Thread Niklas Söderlund
This is an error from when the driver where converted from soc-camera.
There is absolutely no gain to check the state variable two times to be
extra sure if the hardware is stopped.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
b/drivers/media/platform/rcar-vin/rcar-dma.c
index 23fdff7a7370842e..b4be75d5009080f7 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -916,12 +916,6 @@ static irqreturn_t rvin_irq(int irq, void *data)
rvin_ack_interrupt(vin);
handled = 1;
 
-   /* Nothing to do if capture status is 'STOPPED' */
-   if (vin->state == STOPPED) {
-   vin_dbg(vin, "IRQ while state stopped\n");
-   goto done;
-   }
-
/* Nothing to do if capture status is 'STOPPING' */
if (vin->state == STOPPING) {
vin_dbg(vin, "IRQ while state stopping\n");
-- 
2.16.2



[PATCH 2/3] rcar-vin: allocate a scratch buffer at stream start

2018-03-09 Thread Niklas Söderlund
Before starting capturing allocate a scratch buffer which can be used by
the driver to give to the hardware if no buffers are available from
userspace. The buffer is not used in this patch but prepares for future
refactoring where the scratch buffer can be used to avoid the need to
fallback on single capture mode if userspace don't queue buffers as fast
as the VIN driver consumes them.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 19 +++
 drivers/media/platform/rcar-vin/rcar-vin.h |  4 
 2 files changed, 23 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
b/drivers/media/platform/rcar-vin/rcar-dma.c
index b4be75d5009080f7..8ea73cdc9a720abe 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -1070,6 +1070,17 @@ static int rvin_start_streaming(struct vb2_queue *vq, 
unsigned int count)
unsigned long flags;
int ret;
 
+   /* Allocate scratch buffer. */
+   vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
+ >scratch_phys, GFP_KERNEL);
+   if (!vin->scratch) {
+   spin_lock_irqsave(>qlock, flags);
+   return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
+   spin_unlock_irqrestore(>qlock, flags);
+   vin_err(vin, "Failed to allocate scratch buffer\n");
+   return -ENOMEM;
+   }
+
sd = vin_to_source(vin);
v4l2_subdev_call(sd, video, s_stream, 1);
 
@@ -1085,6 +1096,10 @@ static int rvin_start_streaming(struct vb2_queue *vq, 
unsigned int count)
 
spin_unlock_irqrestore(>qlock, flags);
 
+   if (ret)
+   dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
+ vin->scratch_phys);
+
return ret;
 }
 
@@ -1135,6 +1150,10 @@ static void rvin_stop_streaming(struct vb2_queue *vq)
 
/* disable interrupts */
rvin_disable_interrupts(vin);
+
+   /* Free scratch buffer. */
+   dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
+ vin->scratch_phys);
 }
 
 static const struct vb2_ops rvin_qops = {
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h 
b/drivers/media/platform/rcar-vin/rcar-vin.h
index 5382078143fb3869..11a981d707c7ca47 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -102,6 +102,8 @@ struct rvin_graph_entity {
  *
  * @lock:  protects @queue
  * @queue: vb2 buffers queue
+ * @scratch:   cpu address for scratch buffer
+ * @scratch_phys:  pysical address of the scratch buffer
  *
  * @qlock: protects @queue_buf, @buf_list, @continuous, @sequence
  * @state
@@ -130,6 +132,8 @@ struct rvin_dev {
 
struct mutex lock;
struct vb2_queue queue;
+   void *scratch;
+   dma_addr_t scratch_phys;
 
spinlock_t qlock;
struct vb2_v4l2_buffer *queue_buf[HW_BUFFER_NUM];
-- 
2.16.2



[RFC 2/8] media: Add request API

2018-03-09 Thread Sakari Ailus
From: Laurent Pinchart 

The request API allows bundling media device parameters with request
objects and applying them atomically, either synchronously or
asynchronously.

Signed-off-by: Laurent Pinchart 
Signed-off-by: Sakari Ailus 
---
 drivers/media/media-device.c | 366 ++-
 include/media/media-device.h |  71 -
 include/uapi/linux/media.h   |  10 ++
 3 files changed, 441 insertions(+), 6 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index da63da1..41ec5ac 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -19,11 +19,13 @@
 /* We need to access legacy defines from linux/media.h */
 #define __NEED_MEDIA_LEGACY_API
 
+#include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -35,6 +37,349 @@
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 
+static const char *__request_state[] = {
+   "IDLE",
+   "QUEUED",
+   "COMPLETED",
+};
+
+const char *
+media_device_request_state_str(enum media_device_request_state state)
+{
+   if (state < ARRAY_SIZE(__request_state))
+   return __request_state[state];
+
+   return "UNKNOWN";
+}
+
+/* 
-
+ * Requests
+ */
+
+void media_device_request_get(struct media_device_request *req)
+{
+   kref_get(>kref);
+}
+EXPORT_SYMBOL_GPL(media_device_request_get);
+
+static void media_device_request_release(struct kref *kref)
+{
+   struct media_device_request *req =
+   container_of(kref, struct media_device_request, kref);
+   struct media_device *mdev = req->mdev;
+   unsigned long flags;
+
+   dev_dbg(mdev->dev, "request: release %s\n", req->debug_str);
+
+   spin_lock_irqsave(>req_lock, flags);
+   list_del(>list);
+   spin_unlock_irqrestore(>req_lock, flags);
+
+   mdev->ops->req_free(mdev, req);
+}
+
+void media_device_request_put(struct media_device_request *req)
+{
+   kref_put(>kref, media_device_request_release);
+}
+EXPORT_SYMBOL_GPL(media_device_request_put);
+
+static int media_device_request_close(struct inode *inode, struct file *filp)
+{
+   struct media_device_request *req = filp->private_data;
+
+   media_device_request_put(req);
+
+   return 0;
+}
+
+static const struct file_operations request_fops = {
+   .owner = THIS_MODULE,
+   .release = media_device_request_close,
+};
+
+/**
+ * media_device_request_find - Find a request based on the file descriptor
+ * @mdev: The media device
+ * @request: The request file handle
+ *
+ * Find and return the request associated with the given file descriptor, or
+ * an error if no such request exists.
+ *
+ * When the function returns a request it increases its reference count. The
+ * caller is responsible for releasing the reference by calling
+ * media_device_request_put() on the request.
+ */
+struct media_device_request *
+media_device_request_find(struct media_device *mdev, int request)
+{
+   struct file *filp;
+   struct media_device_request *req;
+
+   filp = fget(request);
+   if (!filp)
+   return ERR_PTR(-ENOENT);
+
+   if (filp->f_op != _fops)
+   goto err_fput;
+   req = filp->private_data;
+   media_device_request_get(req);
+
+   if (req->mdev != mdev)
+   goto err_kref_put;
+
+   fput(filp);
+
+   return req;
+
+err_kref_put:
+   media_device_request_put(req);
+
+err_fput:
+   fput(filp);
+
+   return ERR_PTR(-EBADF);
+}
+EXPORT_SYMBOL_GPL(media_device_request_find);
+
+static int media_device_request_alloc(struct media_device *mdev,
+ struct file *filp,
+ struct media_request_cmd *cmd)
+{
+   struct media_device_request *req;
+#ifdef CONFIG_DYNAMIC_DEBUG
+   char comm[TASK_COMM_LEN];
+#endif
+   unsigned long flags;
+   int fd;
+   int ret;
+
+   fd = get_unused_fd_flags(O_CLOEXEC);
+   if (fd < 0)
+   return fd;
+
+   filp = anon_inode_getfile("request", _fops, NULL, O_CLOEXEC);
+   if (IS_ERR(filp)) {
+   ret = PTR_ERR(filp);
+   goto err_put_fd;
+   }
+
+   req = mdev->ops->req_alloc(mdev);
+   if (!req) {
+   ret = -ENOMEM;
+   goto err_fput;
+   }
+
+   filp->private_data = req;
+   req->mdev = mdev;
+   req->state = MEDIA_DEVICE_REQUEST_STATE_IDLE;
+   kref_init(>kref);
+
+   spin_lock_irqsave(>req_lock, flags);
+   list_add_tail(>req_list, >req_idle);
+   spin_unlock_irqrestore(>req_lock, flags);
+
+   cmd->request = fd;
+
+#ifdef CONFIG_DYNAMIC_DEBUG
+   get_task_comm(comm, current);
+   snprintf(req->debug_str, sizeof(req->debug_str), 

[RFC 3/8] media: Support polling for completed requests

2018-03-09 Thread Sakari Ailus
Implement poll for events. POLLPRI is used to notify the user an event is
complete.

Signed-off-by: Sakari Ailus 
---
 drivers/media/media-device.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 41ec5ac..a4d3884 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -84,6 +84,34 @@ void media_device_request_put(struct media_device_request 
*req)
 }
 EXPORT_SYMBOL_GPL(media_device_request_put);
 
+static unsigned int media_device_request_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+   struct media_device_request *req = filp->private_data;
+   struct media_device *mdev = req->mdev;
+   unsigned int poll_events = poll_requested_events(wait);
+   int ret = 0;
+
+   if (poll_events & (POLLIN | POLLOUT))
+   return POLLERR;
+
+   if (poll_events & POLLPRI) {
+   unsigned long flags;
+   bool complete;
+
+   spin_lock_irqsave(>req_lock, flags);
+   complete = req->state == MEDIA_DEVICE_REQUEST_STATE_COMPLETE;
+   spin_unlock_irqrestore(>req_lock, flags);
+
+   if (complete)
+   poll_wait(filp, >poll_wait, wait);
+   else
+   ret |= POLLPRI;
+   }
+
+   return ret;
+}
+
 static int media_device_request_close(struct inode *inode, struct file *filp)
 {
struct media_device_request *req = filp->private_data;
@@ -95,6 +123,7 @@ static int media_device_request_close(struct inode *inode, 
struct file *filp)
 
 static const struct file_operations request_fops = {
.owner = THIS_MODULE,
+   .poll = media_device_request_poll,
.release = media_device_request_close,
 };
 
-- 
2.7.4



[RFC 1/8] media: Support variable size IOCTL arguments

2018-03-09 Thread Sakari Ailus
Maintain a list of supported IOCTL argument sizes and allow only those in
the list.

As an additional bonus, IOCTL handlers will be able to check whether the
caller actually set (using the argument size) the field vs. assigning it
to zero. Separate macro can be provided for that.

This will be easier for applications as well since there is no longer the
problem of setting the reserved fields zero, or at least it is a lesser
problem.

Signed-off-by: Sakari Ailus 
Acked-by: Hans Verkuil 
---
 drivers/media/media-device.c | 65 
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 35e81f7..da63da1 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -387,22 +387,36 @@ static long copy_arg_to_user(void __user *uarg, void 
*karg, unsigned int cmd)
 /* Do acquire the graph mutex */
 #define MEDIA_IOC_FL_GRAPH_MUTEX   BIT(0)
 
-#define MEDIA_IOC_ARG(__cmd, func, fl, from_user, to_user) \
+#define MEDIA_IOC_SZ_ARG(__cmd, func, fl, alt_sz, from_user, to_user)  \
[_IOC_NR(MEDIA_IOC_##__cmd)] = {\
.cmd = MEDIA_IOC_##__cmd,   \
.fn = (long (*)(struct media_device *, void *))func,\
.flags = fl,\
+   .alt_arg_sizes = alt_sz,\
.arg_from_user = from_user, \
.arg_to_user = to_user, \
}
 
-#define MEDIA_IOC(__cmd, func, fl) \
-   MEDIA_IOC_ARG(__cmd, func, fl, copy_arg_from_user, copy_arg_to_user)
+#define MEDIA_IOC_ARG(__cmd, func, fl, from_user, to_user) \
+   MEDIA_IOC_SZ_ARG(__cmd, func, fl, NULL, from_user, to_user)
+
+#define MEDIA_IOC_SZ(__cmd, func, fl, alt_sz)  \
+   MEDIA_IOC_SZ_ARG(__cmd, func, fl, alt_sz,   \
+copy_arg_from_user, copy_arg_to_user)
+
+#define MEDIA_IOC(__cmd, func, fl) \
+   MEDIA_IOC_ARG(__cmd, func, fl,  \
+ copy_arg_from_user, copy_arg_to_user)
 
 /* the table is indexed by _IOC_NR(cmd) */
 struct media_ioctl_info {
unsigned int cmd;
unsigned short flags;
+   /*
+* Sizes of the alternative arguments. If there are none, this
+* pointer is NULL.
+*/
+   const unsigned short *alt_arg_sizes;
long (*fn)(struct media_device *dev, void *arg);
long (*arg_from_user)(void *karg, void __user *uarg, unsigned int cmd);
long (*arg_to_user)(void __user *uarg, void *karg, unsigned int cmd);
@@ -416,6 +430,42 @@ static const struct media_ioctl_info ioctl_info[] = {
MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, 
MEDIA_IOC_FL_GRAPH_MUTEX),
 };
 
+#define MASK_IOC_SIZE(cmd) \
+   ((cmd) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
+
+static inline long is_valid_ioctl(unsigned int cmd)
+{
+   const struct media_ioctl_info *info = ioctl_info;
+   const unsigned short *alt_arg_sizes;
+
+   if (_IOC_NR(cmd) >= ARRAY_SIZE(ioctl_info))
+   return -ENOIOCTLCMD;
+
+   info += _IOC_NR(cmd);
+
+   if (info->cmd == cmd)
+   return 0;
+
+   /*
+* Verify that the size-dependent patch of the IOCTL command
+* matches and that the size does not exceed the principal
+* argument size.
+*/
+   if (MASK_IOC_SIZE(info->cmd) != MASK_IOC_SIZE(cmd)
+   || _IOC_SIZE(info->cmd) < _IOC_SIZE(cmd))
+   return -ENOIOCTLCMD;
+
+   alt_arg_sizes = info->alt_arg_sizes;
+   if (!alt_arg_sizes)
+   return -ENOIOCTLCMD;
+
+   for (; *alt_arg_sizes; alt_arg_sizes++)
+   if (_IOC_SIZE(cmd) == *alt_arg_sizes)
+   return 0;
+
+   return -ENOIOCTLCMD;
+}
+
 static long media_device_ioctl(struct file *filp, unsigned int cmd,
   unsigned long __arg)
 {
@@ -426,9 +476,9 @@ static long media_device_ioctl(struct file *filp, unsigned 
int cmd,
char __karg[256], *karg = __karg;
long ret;
 
-   if (_IOC_NR(cmd) >= ARRAY_SIZE(ioctl_info)
-   || ioctl_info[_IOC_NR(cmd)].cmd != cmd)
-   return -ENOIOCTLCMD;
+   ret = is_valid_ioctl(cmd);
+   if (ret)
+   return ret;
 
info = _info[_IOC_NR(cmd)];
 
@@ -444,6 +494,9 @@ static long media_device_ioctl(struct file *filp, unsigned 
int cmd,
goto out_free;
}
 
+   /* Set the rest of the argument struct to zero */
+   memset(karg + _IOC_SIZE(cmd), 0, _IOC_SIZE(info->cmd) - _IOC_SIZE(cmd));
+
if (info->flags & MEDIA_IOC_FL_GRAPH_MUTEX)
   

[RFC 5/8] videodev2.h: Add request_fd field to v4l2_buffer

2018-03-09 Thread Sakari Ailus
From: Hans Verkuil 

When queuing buffers allow for passing the request that should
be associated with this buffer.

Signed-off-by: Hans Verkuil 
[acour...@chromium.org: make request ID 32-bit]
Signed-off-by: Alexandre Courbot 
[Sakari Ailus: requests fds are int; use assign_in_user in get_v4l2_buffer]
Signed-off-by: Sakari Ailus 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 2 +-
 drivers/media/usb/cpia2/cpia2_v4l.c | 2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   | 7 ---
 drivers/media/v4l2-core/v4l2-ioctl.c| 4 ++--
 include/uapi/linux/videodev2.h  | 3 ++-
 5 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 886a2d8..6d4d184 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -203,7 +203,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
-   b->reserved2 = 0;
+   b->request_fd = 0;
b->reserved = 0;
 
if (q->is_multiplanar) {
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c 
b/drivers/media/usb/cpia2/cpia2_v4l.c
index 99f106b..af42ce3 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -948,7 +948,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct 
v4l2_buffer *buf)
buf->sequence = cam->buffers[buf->index].seq;
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
buf->length = cam->frame_size;
-   buf->reserved2 = 0;
+   buf->request_fd = 0;
buf->reserved = 0;
memset(>timecode, 0, sizeof(buf->timecode));
 
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 5198c9e..61a8bd4 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -386,7 +386,7 @@ struct v4l2_buffer32 {
__s32   fd;
} m;
__u32   length;
-   __u32   reserved2;
+   __s32   request_fd;
__u32   reserved;
 };
 
@@ -500,7 +500,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
get_user(memory, >memory) ||
put_user(memory, >memory) ||
get_user(length, >length) ||
-   put_user(length, >length))
+   put_user(length, >length) ||
+   assign_in_user(>request_fd, >request_fd))
return -EFAULT;
 
if (V4L2_TYPE_IS_OUTPUT(type))
@@ -604,7 +605,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
assign_in_user(>timestamp.tv_usec, >timestamp.tv_usec) ||
copy_in_user(>timecode, >timecode, sizeof(kp->timecode)) ||
assign_in_user(>sequence, >sequence) ||
-   assign_in_user(>reserved2, >reserved2) ||
+   assign_in_user(>request_fd, >request_fd) ||
assign_in_user(>reserved, >reserved) ||
get_user(length, >length) ||
put_user(length, >length))
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index f697c23..6c623e5 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -437,13 +437,13 @@ static void v4l_print_buffer(const void *arg, bool 
write_only)
const struct v4l2_plane *plane;
int i;
 
-   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, 
field=%s, sequence=%d, memory=%s",
+   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request_fd=%d, 
flags=0x%08x, field=%s, sequence=%d, memory=%s",
p->timestamp.tv_sec / 3600,
(int)(p->timestamp.tv_sec / 60) % 60,
(int)(p->timestamp.tv_sec % 60),
(long)p->timestamp.tv_usec,
p->index,
-   prt_names(p->type, v4l2_type_names),
+   prt_names(p->type, v4l2_type_names), p->request_fd,
p->flags, prt_names(p->field, v4l2_field_names),
p->sequence, prt_names(p->memory, v4l2_memory_names));
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 9827189..4fd46ae 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -909,6 +909,7 @@ struct v4l2_plane {
  * @length:size in bytes of the buffer (NOT its payload) for single-plane
  * buffers (when type != *_MPLANE); number of elements in the
  * planes array for multi-plane buffers
+ * @request_fd: fd of the request that this 

[RFC 0/8] Preparing the request API

2018-03-09 Thread Sakari Ailus
Hi folks,

This preliminary RFC patchset prepares for the request API. What's new
here is support for binding arbitrary configuration or resources to
requests.

There are a few new concepts here:

Class --- a type of configuration or resource a driver (or e.g. the V4L2
framework) can attach to a resource. E.g. a video buffer queue would be a
class.

Object --- an instance of the class. This may be either configuration (in
which case the setting will stay until changed, e.g. V4L2 format on a
video node) or a resource (such as a video buffer).

Reference --- a reference to an object. If a configuration is not changed
in a request, instead of allocating a new object, a reference to an
existing object is used. This saves time and memory.

I expect Laurent to comment on aligning the concept names between the
request API and DRM. As far as I understand, the respective DRM names
would be "object" and "state".

The drivers will need to interact with the requests in three ways:

- Allocate new configurations or resources. Drivers are free to store
  their own data into request objects as well. These callbacks are
  specific to classes.

- Validate and queue callbacks. These callbacks are used to try requests
  (validate only) as well as queue them (validate and queue). These
  callbacks are media device wide, at least for now.

The lifetime of the objects related to requests is based on refcounting
both requests and request objects. This fits well for existing use cases
whether or not based on refcounting; what still needs most of the
attention is likely that the number of gets and puts matches once the
object is no longer needed.

Configuration can be bound to the request the usual way (V4L2 IOCTLs with
the request_fd field set to the request). Once queued, request completion
is signalled through polling the request file handle (POLLPRI).

I'm posting this as an RFC because it's not complete yet; I'll continue
working on it next week.

Todo list:

- Better separation of request support between media-device.c and
  media-request.c. The intent is that mostly IOCTL handling would be in
  media-device.c.

- Request support in a few drivers as well as the control framework.

- Request support for V4L2 formats.

- Provide means to iterate over references in a request. This would be
  useful for drivers. The exact needs will be clearer once support for a
  few drivers has been added.

- Reinit support.

In the future, support for changing e.g. Media controller link state or
V4L2 sub-device formats will need to be added. Those are not in my
immediate plans though.

Comments and questions are welcome.


Open questions:

- How to tell at complete time whether a request failed? Return error code
  on release? What's the behaviour with reinit then --- fail on error? Add
  another request command to ask for status?


Alexandre Courbot (1):
  videodev2.h: add request_fd field to v4l2_ext_controls

Hans Verkuil (1):
  videodev2.h: Add request_fd field to v4l2_buffer

Laurent Pinchart (1):
  media: Add request API

Sakari Ailus (5):
  media: Support variable size IOCTL arguments
  media: Support polling for completed requests
  media: Add support for request classes and objects
  staging: media: atomisp: Remove v4l2_buffer.reserved2 field hack
  vb2: Add support for requests

 drivers/media/Makefile |   3 +-
 drivers/media/common/videobuf2/videobuf2-core.c|  43 +-
 drivers/media/common/videobuf2/videobuf2-v4l2.c|  24 +-
 drivers/media/media-device.c   | 483 -
 drivers/media/media-request.c  | 287 
 drivers/media/usb/cpia2/cpia2_v4l.c|   2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c  |  16 +-
 drivers/media/v4l2-core/v4l2-ioctl.c   |   6 +-
 .../media/atomisp/pci/atomisp2/atomisp_ioctl.c |  17 +-
 include/media/media-device.h   |  80 +++-
 include/media/media-request.h  | 229 ++
 include/media/videobuf2-core.h |  19 +
 include/media/videobuf2-v4l2.h |   2 +
 include/uapi/linux/media.h |  10 +
 include/uapi/linux/videodev2.h |   6 +-
 15 files changed, 1186 insertions(+), 41 deletions(-)
 create mode 100644 drivers/media/media-request.c
 create mode 100644 include/media/media-request.h

-- 
2.7.4



[RFC 4/8] media: Add support for request classes and objects

2018-03-09 Thread Sakari Ailus
Media requests may contain multiple objects (e.g. V4L2 format or video
buffers). The media request objects support managing these in a generic
way. The classes are effectively a helper for managing certain kinds of
objects.

Objects may be sticky (the previous configuration matters, e.g. V4L2
format) or non-sticky (whatever was before is irrelevant, e.g. video
buffers).

The drivers are responsible for initialising the classes for types of
objects they support with requests. Some of this could possibly be
implemented in the media and V4L2 frameworks.

Signed-off-by: Sakari Ailus 
---
 drivers/media/Makefile|   3 +-
 drivers/media/media-device.c  |  27 +++-
 drivers/media/media-request.c | 287 ++
 include/media/media-device.h  |  13 +-
 include/media/media-request.h | 229 +
 5 files changed, 554 insertions(+), 5 deletions(-)
 create mode 100644 drivers/media/media-request.c
 create mode 100644 include/media/media-request.h

diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 594b462..985d35e 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -3,7 +3,8 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-media-objs := media-device.o media-devnode.o media-entity.o
+media-objs := media-device.o media-devnode.o media-entity.o \
+  media-request.o
 
 #
 # I2C drivers should come before other drivers, otherwise they'll fail
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index a4d3884..873d83c 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 
@@ -66,15 +67,21 @@ static void media_device_request_release(struct kref *kref)
 {
struct media_device_request *req =
container_of(kref, struct media_device_request, kref);
+   struct media_request_ref *ref, *ref_safe;
struct media_device *mdev = req->mdev;
unsigned long flags;
 
dev_dbg(mdev->dev, "request: release %s\n", req->debug_str);
 
spin_lock_irqsave(>req_lock, flags);
-   list_del(>list);
+   list_del(>req_list);
spin_unlock_irqrestore(>req_lock, flags);
 
+   list_for_each_entry_safe(ref, ref_safe, >obj_refs, req_list) {
+   __media_request_ref_put(ref);
+   kfree(ref);
+   }
+
mdev->ops->req_free(mdev, req);
 }
 
@@ -203,6 +210,7 @@ static int media_device_request_alloc(struct media_device 
*mdev,
req->mdev = mdev;
req->state = MEDIA_DEVICE_REQUEST_STATE_IDLE;
kref_init(>kref);
+   INIT_LIST_HEAD(>obj_refs);
 
spin_lock_irqsave(>req_lock, flags);
list_add_tail(>req_list, >req_idle);
@@ -237,6 +245,13 @@ void media_device_request_complete(struct media_device 
*mdev,
 
spin_lock_irqsave(>req_lock, flags);
 
+   if (!media_request_is_complete(req)) {
+   spin_unlock_irqrestore(>req_lock, flags);
+   dev_dbg(mdev->dev, "request: %s is not complete yet\n",
+   req->debug_str);
+   return;
+   }
+
if (req->state == MEDIA_DEVICE_REQUEST_STATE_IDLE) {
dev_dbg(mdev->dev,
"request: not completing an idle request %s\n",
@@ -285,7 +300,9 @@ static int media_device_request_queue(
media_device_request_state_str(req->state));
} else {
req->state = MEDIA_DEVICE_REQUEST_STATE_QUEUED;
+   media_request_sticky_to_old(req);
}
+
spin_unlock_irqrestore(>req_lock, flags);
 
if (ret)
@@ -306,7 +323,7 @@ static int media_device_request_queue(
 */
media_device_request_get(req);
spin_lock_irqsave(>req_lock, flags);
-   list_move(>list, >req_queued);
+   list_move(>req_list, >req_queued);
spin_unlock_irqrestore(>req_lock, flags);
 
ret = mdev->ops->req_queue(mdev, req);
@@ -316,6 +333,10 @@ static int media_device_request_queue(
goto err_put;
}
 
+   spin_lock_irqsave(>req_lock, flags);
+   media_request_new_to_sticky(req);
+   spin_unlock_irqrestore(>req_lock, flags);
+
mutex_unlock(>req_queue_mutex);
 
return 0;
@@ -325,6 +346,7 @@ static int media_device_request_queue(
 
 err_set_idle:
spin_lock_irqsave(>req_lock, flags);
+   media_request_detach_old(req);
req->state = MEDIA_DEVICE_REQUEST_STATE_IDLE;
spin_unlock_irqrestore(>req_lock, flags);
 
@@ -1149,6 +1171,7 @@ int __must_check __media_device_register(struct 
media_device *mdev,
spin_lock_init(>req_lock);
INIT_LIST_HEAD(>req_idle);
INIT_LIST_HEAD(>req_queued);
+   INIT_LIST_HEAD(>classes);
 
/* Register the device node. */
mdev->devnode = devnode;
diff --git 

[RFC 6/8] videodev2.h: add request_fd field to v4l2_ext_controls

2018-03-09 Thread Sakari Ailus
From: Alexandre Courbot 

Allow to specify a request to be used with the S_EXT_CTRLS and
G_EXT_CTRLS operations.

Signed-off-by: Alexandre Courbot 
[Sakari Ailus: reserved no longer an array, add compat32 code]
Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 9 ++---
 drivers/media/v4l2-core/v4l2-ioctl.c  | 2 +-
 include/uapi/linux/videodev2.h| 3 ++-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 61a8bd4..9adb367 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -733,7 +733,8 @@ struct v4l2_ext_controls32 {
__u32 which;
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved;
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
@@ -808,7 +809,8 @@ static int get_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
-   copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+   assign_in_user(>request_fd, >request_fd) ||
+   assign_in_user(>reserved, >reserved))
return -EFAULT;
 
if (count == 0)
@@ -866,7 +868,8 @@ static int put_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
-   copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
+   assign_in_user(>request_fd, >request_fd) ||
+   assign_in_user(>reserved, >reserved) ||
get_user(kcontrols, >controls))
return -EFAULT;
 
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 6c623e5..b58018b 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -870,7 +870,7 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int 
allow_priv)
__u32 i;
 
/* zero the reserved fields */
-   c->reserved[0] = c->reserved[1] = 0;
+   c->reserved = 0;
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4fd46ae..ac502ad 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1592,7 +1592,8 @@ struct v4l2_ext_controls {
};
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved;
struct v4l2_ext_control *controls;
 };
 
-- 
2.7.4



[RFC 7/8] staging: media: atomisp: Remove v4l2_buffer.reserved2 field hack

2018-03-09 Thread Sakari Ailus
The atomisp driver used to use the reserved2 field in struct v4l2_buffer
for picking a particular ISP configuration for the buffer. As reserved2
field will have new use soon, remove this hack.

Signed-off-by: Sakari Ailus 
---
 .../staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c  | 17 +++--
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c 
b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
index 5c84dd6..182bb70 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
@@ -1283,16 +1283,7 @@ static int atomisp_qbuf(struct file *file, void *fh, 
struct v4l2_buffer *buf)
if (!((buf->flags & NOFLUSH_FLAGS) == NOFLUSH_FLAGS))
wbinvd();
 
-   if (!atomisp_is_vf_pipe(pipe) &&
-   (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING)) {
-   /* this buffer will have a per-frame parameter */
-   pipe->frame_request_config_id[buf->index] = buf->reserved2 &
-   ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING;
-   dev_dbg(isp->dev, "This buffer requires per_frame setting which 
has isp_config_id %d\n",
-   pipe->frame_request_config_id[buf->index]);
-   } else {
-   pipe->frame_request_config_id[buf->index] = 0;
-   }
+   pipe->frame_request_config_id[buf->index] = 0;
 
pipe->frame_params[buf->index] = NULL;
 
@@ -1470,12 +1461,10 @@ static int atomisp_dqbuf(struct file *file, void *fh, 
struct v4l2_buffer *buf)
buf->reserved &= 0x;
if (!(buf->flags & V4L2_BUF_FLAG_ERROR))
buf->reserved |= __get_frame_exp_id(pipe, buf) << 16;
-   buf->reserved2 = pipe->frame_config_id[buf->index];
rt_mutex_unlock(>mutex);
 
-   dev_dbg(isp->dev, "dqbuf buffer %d (%s) for asd%d with exp_id %d, 
isp_config_id %d\n",
-   buf->index, vdev->name, asd->index, buf->reserved >> 16,
-   buf->reserved2);
+   dev_dbg(isp->dev, "dqbuf buffer %d (%s) for asd%d with exp_id %d\n",
+   buf->index, vdev->name, asd->index, buf->reserved >> 16);
return 0;
 }
 
-- 
2.7.4



[RFC 8/8] vb2: Add support for requests

2018-03-09 Thread Sakari Ailus
Associate a buffer to a request when it is queued and disassociate when it
is done.

Signed-off-by: Sakari Ailus 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 43 -
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 24 +-
 include/media/videobuf2-core.h  | 19 +++
 include/media/videobuf2-v4l2.h  |  2 ++
 4 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index d3f7bb3..0e8d555 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -346,6 +346,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
break;
}
 
+   if (q->class)
+   media_request_object_init(q->class, >req_obj);
+
vb->state = VB2_BUF_STATE_DEQUEUED;
vb->vb2_queue = q;
vb->num_planes = num_planes;
@@ -520,7 +523,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned 
int buffers)
/* Free videobuf buffers */
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 ++buffer) {
-   kfree(q->bufs[buffer]);
+   if (q->class)
+   media_request_object_put(>bufs[buffer]->req_obj);
+   else
+   kfree(q->bufs[buffer]);
q->bufs[buffer] = NULL;
}
 
@@ -944,6 +950,10 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
default:
/* Inform any processes that may be waiting for buffers */
wake_up(>done_wq);
+   if (vb->req_ref) {
+   media_request_ref_complete(vb->req_ref);
+   vb->req_ref = NULL;
+   }
break;
}
 }
@@ -1249,6 +1259,32 @@ static int __buf_prepare(struct vb2_buffer *vb, const 
void *pb)
return -EIO;
}
 
+   if (vb->request_fd) {
+   struct media_device_request *req;
+   struct media_request_ref *ref;
+
+   if (!q->class) {
+   dprintk(1, "requests not enabled for the queue\n");
+   return -EINVAL;
+   }
+
+   req = media_device_request_find(q->class->mdev, vb->request_fd);
+   if (IS_ERR(req)) {
+   dprintk(1, "no request found for fd %d (%ld)\n",
+   vb->request_fd, PTR_ERR(req));
+   return PTR_ERR(req);
+   }
+
+   ref = media_request_object_bind(req,
+   >bufs[vb->index]->req_obj);
+   media_device_request_put(req);
+
+   if (IS_ERR(ref))
+   return PTR_ERR(ref);
+
+   vb->req_ref = ref;
+   }
+
vb->state = VB2_BUF_STATE_PREPARING;
 
switch (q->memory) {
@@ -1269,6 +1305,8 @@ static int __buf_prepare(struct vb2_buffer *vb, const 
void *pb)
if (ret) {
dprintk(1, "buffer preparation failed: %d\n", ret);
vb->state = VB2_BUF_STATE_DEQUEUED;
+   media_request_ref_unbind(vb->req_ref);
+   vb->req_ref = NULL;
return ret;
}
 
@@ -2037,6 +2075,9 @@ void vb2_core_queue_release(struct vb2_queue *q)
mutex_lock(>mmap_lock);
__vb2_queue_free(q, q->num_buffers);
mutex_unlock(>mmap_lock);
+   media_request_class_unregister(q->class);
+   kfree(q->class);
+   q->class = NULL;
 }
 EXPORT_SYMBOL_GPL(vb2_core_queue_release);
 
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 6d4d184..ca36109 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -196,6 +196,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->index = vb->index;
b->type = vb->type;
b->memory = vb->memory;
+   b->request_fd = vb->request_fd;
b->bytesused = 0;
 
b->flags = vbuf->flags;
@@ -203,7 +204,6 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
-   b->request_fd = 0;
b->reserved = 0;
 
if (q->is_multiplanar) {
@@ -319,6 +319,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
return -EINVAL;
}
vb->timestamp = 0;
+   vb->request_fd = b->request_fd;
vbuf->sequence = 0;
 
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
@@ -667,6 +668,27 @@ int vb2_queue_init(struct vb2_queue *q)
 }
 

[PATCH 02/11] media: vsp1: use kernel __packed for structures

2018-03-09 Thread Kieran Bingham
The kernel provides a __packed definition to abstract away from the
compiler specific attributes tag.

Convert all packed structures in VSP1 to use it.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 37e2c984fbf3..382e45c2054e 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -29,19 +29,19 @@
 struct vsp1_dl_header_list {
u32 num_bytes;
u32 addr;
-} __attribute__((__packed__));
+} __packed;
 
 struct vsp1_dl_header {
u32 num_lists;
struct vsp1_dl_header_list lists[8];
u32 next_header;
u32 flags;
-} __attribute__((__packed__));
+} __packed;
 
 struct vsp1_dl_entry {
u32 addr;
u32 data;
-} __attribute__((__packed__));
+} __packed;
 
 /**
  * struct vsp1_dl_body - Display list body
-- 
git-series 0.9.1


[PATCH 03/11] media: vsp1: Rename dl_child to dl_next

2018-03-09 Thread Kieran Bingham
Both vsp1_dl_list_commit() and __vsp1_dl_list_put() walk the display
list chain referencing the nodes as children, when in reality they are
siblings.

Update the terminology to 'dl_next' to be consistent with the
vsp1_video_pipeline_run() usage.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 382e45c2054e..057f0f093222 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -400,7 +400,7 @@ struct vsp1_dl_list *vsp1_dl_list_get(struct 
vsp1_dl_manager *dlm)
 /* This function must be called with the display list manager lock held.*/
 static void __vsp1_dl_list_put(struct vsp1_dl_list *dl)
 {
-   struct vsp1_dl_list *dl_child;
+   struct vsp1_dl_list *dl_next;
 
if (!dl)
return;
@@ -410,8 +410,8 @@ static void __vsp1_dl_list_put(struct vsp1_dl_list *dl)
 * hardware operation.
 */
if (dl->has_chain) {
-   list_for_each_entry(dl_child, >chain, chain)
-   __vsp1_dl_list_put(dl_child);
+   list_for_each_entry(dl_next, >chain, chain)
+   __vsp1_dl_list_put(dl_next);
}
 
dl->has_chain = false;
@@ -667,17 +667,17 @@ static void vsp1_dl_list_commit_singleshot(struct 
vsp1_dl_list *dl)
 void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
 {
struct vsp1_dl_manager *dlm = dl->dlm;
-   struct vsp1_dl_list *dl_child;
+   struct vsp1_dl_list *dl_next;
unsigned long flags;
 
if (dlm->mode == VSP1_DL_MODE_HEADER) {
/* Fill the header for the head and chained display lists. */
vsp1_dl_list_fill_header(dl, list_empty(>chain));
 
-   list_for_each_entry(dl_child, >chain, chain) {
-   bool last = list_is_last(_child->chain, >chain);
+   list_for_each_entry(dl_next, >chain, chain) {
+   bool last = list_is_last(_next->chain, >chain);
 
-   vsp1_dl_list_fill_header(dl_child, last);
+   vsp1_dl_list_fill_header(dl_next, last);
}
}
 
-- 
git-series 0.9.1


[PATCH 01/11] media: vsp1: drm: Fix minor grammar error

2018-03-09 Thread Kieran Bingham
The pixel format is 'unsupported'. Fix the small debug message which
incorrectly declares this.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_drm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c 
b/drivers/media/platform/vsp1/vsp1_drm.c
index 3c8b1952799d..0459b970e9da 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -363,7 +363,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int 
pipe_index,
 */
fmtinfo = vsp1_get_format_info(vsp1, cfg->pixelformat);
if (!fmtinfo) {
-   dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n",
+   dev_dbg(vsp1->dev, "Unsupported pixel format %08x for RPF\n",
cfg->pixelformat);
return -EINVAL;
}
-- 
git-series 0.9.1


[PATCH 06/11] media: vsp1: Provide VSP1 feature helper macro

2018-03-09 Thread Kieran Bingham
The VSP1 devices define their specific capabilities through features
marked in their device info structure. Various parts of the code read
this info structure to infer if the features are available.

Wrap this into a more readable vsp1_feature(vsp1, f) macro to ensure
that usage is consistent throughout the driver.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1.h |  2 ++
 drivers/media/platform/vsp1/vsp1_drv.c | 16 
 drivers/media/platform/vsp1/vsp1_wpf.c |  6 +++---
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h 
b/drivers/media/platform/vsp1/vsp1.h
index 78ef838416b3..1c080538c993 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -69,6 +69,8 @@ struct vsp1_device_info {
bool uapi;
 };
 
+#define vsp1_feature(vsp1, f) ((vsp1)->info->features & (f))
+
 struct vsp1_device {
struct device *dev;
const struct vsp1_device_info *info;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c 
b/drivers/media/platform/vsp1/vsp1_drv.c
index eed9516e25e1..6fa0019ffc6e 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -268,7 +268,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
 
/* Instantiate all the entities. */
-   if (vsp1->info->features & VSP1_HAS_BRS) {
+   if (vsp1_feature(vsp1, VSP1_HAS_BRS)) {
vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
if (IS_ERR(vsp1->brs)) {
ret = PTR_ERR(vsp1->brs);
@@ -278,7 +278,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(>brs->entity.list_dev, >entities);
}
 
-   if (vsp1->info->features & VSP1_HAS_BRU) {
+   if (vsp1_feature(vsp1, VSP1_HAS_BRU)) {
vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
if (IS_ERR(vsp1->bru)) {
ret = PTR_ERR(vsp1->bru);
@@ -288,7 +288,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(>bru->entity.list_dev, >entities);
}
 
-   if (vsp1->info->features & VSP1_HAS_CLU) {
+   if (vsp1_feature(vsp1, VSP1_HAS_CLU)) {
vsp1->clu = vsp1_clu_create(vsp1);
if (IS_ERR(vsp1->clu)) {
ret = PTR_ERR(vsp1->clu);
@@ -314,7 +314,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
list_add_tail(>hst->entity.list_dev, >entities);
 
-   if (vsp1->info->features & VSP1_HAS_HGO && vsp1->info->uapi) {
+   if (vsp1_feature(vsp1, VSP1_HAS_HGO) && vsp1->info->uapi) {
vsp1->hgo = vsp1_hgo_create(vsp1);
if (IS_ERR(vsp1->hgo)) {
ret = PTR_ERR(vsp1->hgo);
@@ -325,7 +325,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
  >entities);
}
 
-   if (vsp1->info->features & VSP1_HAS_HGT && vsp1->info->uapi) {
+   if (vsp1_feature(vsp1, VSP1_HAS_HGT) && vsp1->info->uapi) {
vsp1->hgt = vsp1_hgt_create(vsp1);
if (IS_ERR(vsp1->hgt)) {
ret = PTR_ERR(vsp1->hgt);
@@ -356,7 +356,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
}
 
-   if (vsp1->info->features & VSP1_HAS_LUT) {
+   if (vsp1_feature(vsp1, VSP1_HAS_LUT)) {
vsp1->lut = vsp1_lut_create(vsp1);
if (IS_ERR(vsp1->lut)) {
ret = PTR_ERR(vsp1->lut);
@@ -390,7 +390,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
}
 
-   if (vsp1->info->features & VSP1_HAS_SRU) {
+   if (vsp1_feature(vsp1, VSP1_HAS_SRU)) {
vsp1->sru = vsp1_sru_create(vsp1);
if (IS_ERR(vsp1->sru)) {
ret = PTR_ERR(vsp1->sru);
@@ -524,7 +524,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED);
vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED);
 
-   if (vsp1->info->features & VSP1_HAS_BRS)
+   if (vsp1_feature(vsp1, VSP1_HAS_BRS))
vsp1_write(vsp1, VI6_DPR_ILV_BRS_ROUTE, VI6_DPR_NODE_UNUSED);
 
vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c 
b/drivers/media/platform/vsp1/vsp1_wpf.c
index 68218625549e..f90e474cf2cc 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -146,13 +146,13 @@ static int wpf_init_controls(struct vsp1_rwpf *wpf)
if (wpf->entity.index != 0) {
/* Only WPF0 supports flipping. */
num_flip_ctrls = 0;
-   } else if (vsp1->info->features & VSP1_HAS_WPF_HFLIP) {
+   } else if (vsp1_feature(vsp1, 

[PATCH 07/11] media: vsp1: Use header display lists for all WPF outputs linked to the DU

2018-03-09 Thread Kieran Bingham
Header mode display lists are now supported on all WPF outputs. To
support extended headers and auto-fld capabilities for interlaced mode
handling only header mode display lists can be used.

Disable the headerless display list configuration, and remove the dead
code.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c | 107 ++-
 1 file changed, 27 insertions(+), 80 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 6271bea5e831..dc273e3b4753 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -98,7 +98,7 @@ struct vsp1_dl_body_pool {
  * struct vsp1_dl_list - Display list
  * @list: entry in the display list manager lists
  * @dlm: the display list manager
- * @header: display list header, NULL for headerless lists
+ * @header: display list header
  * @dma: DMA address for the header
  * @body0: first display list body
  * @bodies: list of extra display list bodies
@@ -119,15 +119,9 @@ struct vsp1_dl_list {
struct list_head chain;
 };
 
-enum vsp1_dl_mode {
-   VSP1_DL_MODE_HEADER,
-   VSP1_DL_MODE_HEADERLESS,
-};
-
 /**
  * struct vsp1_dl_manager - Display List manager
  * @index: index of the related WPF
- * @mode: display list operation mode (header or headerless)
  * @singleshot: execute the display list in single-shot mode
  * @vsp1: the VSP1 device
  * @lock: protects the free, active, queued, pending and gc_bodies lists
@@ -139,7 +133,6 @@ enum vsp1_dl_mode {
  */
 struct vsp1_dl_manager {
unsigned int index;
-   enum vsp1_dl_mode mode;
bool singleshot;
struct vsp1_device *vsp1;
 
@@ -320,6 +313,7 @@ static struct vsp1_dl_list *vsp1_dl_list_alloc(struct 
vsp1_dl_manager *dlm,
   struct vsp1_dl_body_pool *pool)
 {
struct vsp1_dl_list *dl;
+   size_t header_offset;
 
dl = kzalloc(sizeof(*dl), GFP_KERNEL);
if (!dl)
@@ -332,16 +326,15 @@ static struct vsp1_dl_list *vsp1_dl_list_alloc(struct 
vsp1_dl_manager *dlm,
dl->body0 = vsp1_dl_body_get(pool);
if (!dl->body0)
return NULL;
-   if (dlm->mode == VSP1_DL_MODE_HEADER) {
-   size_t header_offset = dl->body0->max_entries
-* sizeof(*dl->body0->entries);
 
-   dl->header = ((void *)dl->body0->entries) + header_offset;
-   dl->dma = dl->body0->dma + header_offset;
+   header_offset = dl->body0->max_entries
+* sizeof(*dl->body0->entries);
 
-   memset(dl->header, 0, sizeof(*dl->header));
-   dl->header->lists[0].addr = dl->body0->dma;
-   }
+   dl->header = ((void *)dl->body0->entries) + header_offset;
+   dl->dma = dl->body0->dma + header_offset;
+
+   memset(dl->header, 0, sizeof(*dl->header));
+   dl->header->lists[0].addr = dl->body0->dma;
 
return dl;
 }
@@ -473,16 +466,9 @@ struct vsp1_dl_body *vsp1_dl_list_get_body0(struct 
vsp1_dl_list *dl)
  *
  * The reference must be explicitly released by a call to vsp1_dl_body_put()
  * when the body isn't needed anymore.
- *
- * Additional bodies are only usable for display lists in header mode.
- * Attempting to add a body to a header-less display list will return an error.
  */
 int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb)
 {
-   /* Multi-body lists are only available in header mode. */
-   if (dl->dlm->mode != VSP1_DL_MODE_HEADER)
-   return -EINVAL;
-
refcount_inc(>refcnt);
 
list_add_tail(>list, >bodies);
@@ -503,17 +489,10 @@ int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct 
vsp1_dl_body *dlb)
  * Adding a display list to a chain passes ownership of the display list to
  * the head display list item. The chain is released when the head dl item is
  * put back with __vsp1_dl_list_put().
- *
- * Chained display lists are only usable in header mode. Attempts to add a
- * display list to a chain in header-less mode will return an error.
  */
 int vsp1_dl_list_add_chain(struct vsp1_dl_list *head,
   struct vsp1_dl_list *dl)
 {
-   /* Chained lists are only available in header mode. */
-   if (head->dlm->mode != VSP1_DL_MODE_HEADER)
-   return -EINVAL;
-
head->has_chain = true;
list_add_tail(>chain, >chain);
return 0;
@@ -581,17 +560,10 @@ static bool vsp1_dl_list_hw_update_pending(struct 
vsp1_dl_manager *dlm)
return false;
 
/*
-* Check whether the VSP1 has taken the update. In headerless mode the
-* hardware indicates this by clearing the UPD bit in the DL_BODY_SIZE
-* register, and in header mode by clearing the UPDHDR bit in the CMD
-* register.
+* Check whether the VSP1 has taken the update. In header mode 

[PATCH 08/11] media: vsp1: Add support for extended display list headers

2018-03-09 Thread Kieran Bingham
Extended display list headers allow pre and post command lists to be
executed by the VSP pipeline. This provides the base support for
features such as AUTO_FLD (for interlaced support) and AUTO_DISP (for
supporting continuous camera preview pipelines.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1.h  |  1 +-
 drivers/media/platform/vsp1/vsp1_dl.c   | 83 +-
 drivers/media/platform/vsp1/vsp1_dl.h   | 29 -
 drivers/media/platform/vsp1/vsp1_drv.c  |  7 +-
 drivers/media/platform/vsp1/vsp1_regs.h |  5 +-
 5 files changed, 116 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h 
b/drivers/media/platform/vsp1/vsp1.h
index 1c080538c993..bb3b32795206 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -55,6 +55,7 @@ struct vsp1_uds;
 #define VSP1_HAS_HGO   (1 << 7)
 #define VSP1_HAS_HGT   (1 << 8)
 #define VSP1_HAS_BRS   (1 << 9)
+#define VSP1_HAS_EXT_DL(1 << 10)
 
 struct vsp1_device_info {
u32 version;
diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index dc273e3b4753..36440a2a2c8b 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -26,6 +26,9 @@
 #define VSP1_DLH_INT_ENABLE(1 << 1)
 #define VSP1_DLH_AUTO_START(1 << 0)
 
+#define VSP1_DLH_EXT_PRE_CMD_EXEC  (1 << 9)
+#define VSP1_DLH_EXT_POST_CMD_EXEC (1 << 8)
+
 struct vsp1_dl_header_list {
u32 num_bytes;
u32 addr;
@@ -38,11 +41,34 @@ struct vsp1_dl_header {
u32 flags;
 } __packed;
 
+struct vsp1_dl_ext_header {
+   u32 reserved0;  /* alignment padding */
+
+   u16 pre_ext_cmd_qty;
+   u16 flags;
+   u32 pre_ext_cmd_plist;
+
+   u32 post_ext_cmd_qty;
+   u32 post_ext_cmd_plist;
+} __packed;
+
+struct vsp1_dl_header_extended {
+   struct vsp1_dl_header header;
+   struct vsp1_dl_ext_header ext;
+} __packed;
+
 struct vsp1_dl_entry {
u32 addr;
u32 data;
 } __packed;
 
+struct vsp1_dl_ext_cmd_header {
+   u32 cmd;
+   u32 flags;
+   u32 data;
+   u32 reserved;
+} __packed;
+
 /**
  * struct vsp1_dl_body - Display list body
  * @list: entry in the display list list of bodies
@@ -99,9 +125,12 @@ struct vsp1_dl_body_pool {
  * @list: entry in the display list manager lists
  * @dlm: the display list manager
  * @header: display list header
+ * @extended: extended display list header. NULL for normal lists
  * @dma: DMA address for the header
  * @body0: first display list body
  * @bodies: list of extra display list bodies
+ * @pre_cmd: pre cmd to be issued through extended dl header
+ * @post_cmd: post cmd to be issued through extended dl header
  * @has_chain: if true, indicates that there's a partition chain
  * @chain: entry in the display list partition chain
  */
@@ -110,11 +139,15 @@ struct vsp1_dl_list {
struct vsp1_dl_manager *dlm;
 
struct vsp1_dl_header *header;
+   struct vsp1_dl_ext_header *extended;
dma_addr_t dma;
 
struct vsp1_dl_body *body0;
struct list_head bodies;
 
+   struct vsp1_dl_ext_cmd *pre_cmd;
+   struct vsp1_dl_ext_cmd *post_cmd;
+
bool has_chain;
struct list_head chain;
 };
@@ -498,6 +531,14 @@ int vsp1_dl_list_add_chain(struct vsp1_dl_list *head,
return 0;
 }
 
+static void vsp1_dl_ext_cmd_fill_header(struct vsp1_dl_ext_cmd *cmd)
+{
+   cmd->cmds[0].cmd = cmd->cmd_opcode;
+   cmd->cmds[0].flags = cmd->flags;
+   cmd->cmds[0].data = cmd->data_dma;
+   cmd->cmds[0].reserved = 0;
+}
+
 static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last)
 {
struct vsp1_dl_manager *dlm = dl->dlm;
@@ -550,6 +591,27 @@ static void vsp1_dl_list_fill_header(struct vsp1_dl_list 
*dl, bool is_last)
 */
dl->header->flags = VSP1_DLH_INT_ENABLE;
}
+
+   if (!dl->extended)
+   return;
+
+   dl->extended->flags = 0;
+
+   if (dl->pre_cmd) {
+   dl->extended->pre_ext_cmd_plist = dl->pre_cmd->cmd_dma;
+   dl->extended->pre_ext_cmd_qty = dl->pre_cmd->num_cmds;
+   dl->extended->flags |= VSP1_DLH_EXT_PRE_CMD_EXEC;
+
+   vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
+   }
+
+   if (dl->post_cmd) {
+   dl->extended->pre_ext_cmd_plist = dl->post_cmd->cmd_dma;
+   dl->extended->pre_ext_cmd_qty = dl->post_cmd->num_cmds;
+   dl->extended->flags |= VSP1_DLH_EXT_POST_CMD_EXEC;
+
+   vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
+   }
 }
 
 static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
@@ -715,14 +777,20 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
 }
 
 /* Hardware Setup */
-void vsp1_dlm_setup(struct vsp1_device *vsp1)
+void 

[PATCH 04/11] media: vsp1: Remove unused display list structure field

2018-03-09 Thread Kieran Bingham
The vsp1 reference in the vsp1_dl_body structure is not used.
Remove it.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 057f0f093222..16a2d3c93655 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -48,7 +48,6 @@ struct vsp1_dl_entry {
  * @list: entry in the display list list of bodies
  * @free: entry in the pool free body list
  * @pool: pool to which this body belongs
- * @vsp1: the VSP1 device
  * @entries: array of entries
  * @dma: DMA address of the entries
  * @size: size of the DMA memory in bytes
@@ -62,7 +61,6 @@ struct vsp1_dl_body {
refcount_t refcnt;
 
struct vsp1_dl_body_pool *pool;
-   struct vsp1_device *vsp1;
 
struct vsp1_dl_entry *entries;
dma_addr_t dma;
-- 
git-series 0.9.1


[PATCH 11/11] drm: rcar-du: Support interlaced video output through vsp1

2018-03-09 Thread Kieran Bingham
Use the newly exposed VSP1 interface to enable interlaced frame support
through the VSP1 lif pipelines.

Signed-off-by: Kieran Bingham 
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 1 +
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 
b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 5685d5af6998..9854d9deb944 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -248,6 +248,7 @@ static void rcar_du_crtc_set_display_timing(struct 
rcar_du_crtc *rcrtc)
/* Signal polarities */
value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
  | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
+ | ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? DSMR_ODEV : 0)
  | DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, value);
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c 
b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 2c260c33840b..5e47daef8bd2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -178,6 +178,9 @@ static void rcar_du_vsp_plane_setup(struct 
rcar_du_vsp_plane *plane)
};
unsigned int i;
 
+   cfg.interlaced = !!(plane->plane.state->crtc->mode.flags
+   & DRM_MODE_FLAG_INTERLACE);
+
cfg.src.left = state->state.src.x1 >> 16;
cfg.src.top = state->state.src.y1 >> 16;
cfg.src.width = drm_rect_width(>state.src) >> 16;
-- 
git-series 0.9.1


[PATCH 09/11] media: vsp1: Provide support for extended command pools

2018-03-09 Thread Kieran Bingham
VSPD and VSP-DL devices can provide extended display lists supporting
extended command display list objects.

These extended commands require their own dma memory areas for a header
and body specific to the command type.

Implement a command pool to allocate all necessary memory in a single
DMA allocation to reduce pressure on the TLB, and provide convenvient
re-usable command objects for the entities to utilise.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c | 189 +++-
 drivers/media/platform/vsp1/vsp1_dl.h |   3 +-
 2 files changed, 192 insertions(+)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 36440a2a2c8b..6d17b8bfa21c 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -121,6 +121,30 @@ struct vsp1_dl_body_pool {
 };
 
 /**
+ * struct vsp1_cmd_pool - display list body pool
+ * @dma: DMA address of the entries
+ * @size: size of the full DMA memory pool in bytes
+ * @mem: CPU memory pointer for the pool
+ * @bodies: Array of DLB structures for the pool
+ * @free: List of free DLB entries
+ * @lock: Protects the pool and free list
+ * @vsp1: the VSP1 device
+ */
+struct vsp1_dl_cmd_pool {
+   /* DMA allocation */
+   dma_addr_t dma;
+   size_t size;
+   void *mem;
+
+   struct vsp1_dl_ext_cmd *cmds;
+   struct list_head free;
+
+   spinlock_t lock;
+
+   struct vsp1_device *vsp1;
+};
+
+/**
  * struct vsp1_dl_list - Display list
  * @list: entry in the display list manager lists
  * @dlm: the display list manager
@@ -176,6 +200,7 @@ struct vsp1_dl_manager {
struct vsp1_dl_list *pending;
 
struct vsp1_dl_body_pool *pool;
+   struct vsp1_dl_cmd_pool *autfld_cmds;
 };
 
 /* 
-
@@ -339,6 +364,139 @@ void vsp1_dl_body_write(struct vsp1_dl_body *dlb, u32 
reg, u32 data)
 }
 
 /* 
-
+ * Display List Extended Command Management
+ */
+
+enum vsp1_extcmd_type {
+   VSP1_EXTCMD_AUTODISP,
+   VSP1_EXTCMD_AUTOFLD,
+};
+
+struct vsp1_extended_command_info {
+   u16 opcode;
+   size_t body_size;
+} vsp1_extended_commands[] = {
+   [VSP1_EXTCMD_AUTODISP] = { 0x02, 96 },
+   [VSP1_EXTCMD_AUTOFLD]  = { 0x03, 160 },
+};
+
+/**
+ * vsp1_dl_cmd_pool_create - Create a pool of commands from a single allocation
+ * @vsp1: The VSP1 device
+ * @type: The command pool type
+ * @num_commands: The quantity of commands to allocate
+ *
+ * Allocate a pool of commands each with enough memory to contain the private
+ * data of each command. The allocation sizes are dependent upon the command
+ * type.
+ *
+ * Return a pointer to a pool on success or NULL if memory can't be allocated.
+ */
+struct vsp1_dl_cmd_pool *
+vsp1_dl_cmd_pool_create(struct vsp1_device *vsp1, enum vsp1_extcmd_type type,
+   unsigned int num_cmds)
+{
+   struct vsp1_dl_cmd_pool *pool;
+   unsigned int i;
+   size_t cmd_size;
+
+   pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+   if (!pool)
+   return NULL;
+
+   pool->cmds = kcalloc(num_cmds, sizeof(*pool->cmds), GFP_KERNEL);
+   if (!pool->cmds) {
+   kfree(pool);
+   return NULL;
+   }
+
+   cmd_size = sizeof(struct vsp1_dl_ext_cmd_header) +
+  vsp1_extended_commands[type].body_size;
+   cmd_size = ALIGN(cmd_size, 16);
+
+   pool->size = cmd_size * num_cmds;
+   pool->mem = dma_alloc_wc(vsp1->bus_master, pool->size, >dma,
+GFP_KERNEL);
+   if (!pool->mem) {
+   kfree(pool->cmds);
+   kfree(pool);
+   return NULL;
+   }
+
+   spin_lock_init(>lock);
+   INIT_LIST_HEAD(>free);
+
+   for (i = 0; i < num_cmds; ++i) {
+   struct vsp1_dl_ext_cmd *cmd = >cmds[i];
+   size_t cmd_offset = i * cmd_size;
+   size_t data_offset = sizeof(struct vsp1_dl_ext_cmd_header) +
+cmd_offset;
+
+   cmd->pool = pool;
+   cmd->cmd_opcode = vsp1_extended_commands[type].opcode;
+
+   /* TODO: Auto-disp can utilise more than one command per cmd */
+   cmd->num_cmds = 1;
+   cmd->cmds = pool->mem + cmd_offset;
+   cmd->cmd_dma = pool->dma + cmd_offset;
+
+   cmd->data = pool->mem + data_offset;
+   cmd->data_dma = pool->dma + data_offset;
+   cmd->data_size = vsp1_extended_commands[type].body_size;
+
+   list_add_tail(>free, >free);
+   }
+
+   return pool;
+}
+
+struct vsp1_dl_ext_cmd *vsp1_dl_ext_cmd_get(struct vsp1_dl_cmd_pool *pool)
+{
+   struct vsp1_dl_ext_cmd *cmd = NULL;
+   unsigned long flags;
+
+   

[PATCH 10/11] media: vsp1: Support Interlaced display pipelines

2018-03-09 Thread Kieran Bingham
Calculate the top and bottom fields for the interlaced frames and
utilise the extended display list command feature to implement the
auto-field operations. This allows the DU to update the VSP2 registers
dynamically based upon the currently processing field.

Signed-off-by: Kieran Bingham 
---
 drivers/media/platform/vsp1/vsp1_dl.c   | 10 +++-
 drivers/media/platform/vsp1/vsp1_dl.h   |  2 +-
 drivers/media/platform/vsp1/vsp1_drm.c  | 12 -
 drivers/media/platform/vsp1/vsp1_pipe.c |  3 +-
 drivers/media/platform/vsp1/vsp1_regs.h |  1 +-
 drivers/media/platform/vsp1/vsp1_rpf.c  | 72 --
 drivers/media/platform/vsp1/vsp1_rwpf.h |  1 +-
 include/media/vsp1.h|  1 +-
 8 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c 
b/drivers/media/platform/vsp1/vsp1_dl.c
index 6d17b8bfa21c..4a079060864b 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -886,8 +886,9 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
  * with the frame end interrupt. The function always returns true in header 
mode
  * as display list processing is then not continuous and races never occur.
  */
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool interlaced)
 {
+   struct vsp1_device *vsp1 = dlm->vsp1;
bool completed = false;
 
spin_lock(>lock);
@@ -912,6 +913,13 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
if (vsp1_dl_list_hw_update_pending(dlm))
goto done;
 
+   if (interlaced) {
+   u32 status = vsp1_read(vsp1, VI6_STATUS);
+
+   if (!(status & VI6_STATUS_FLD_STD(dlm->index)))
+   goto done;
+   }
+
/*
 * The device starts processing the queued display list right after the
 * frame end interrupt. The display list thus becomes active.
diff --git a/drivers/media/platform/vsp1/vsp1_dl.h 
b/drivers/media/platform/vsp1/vsp1_dl.h
index 3009912ddefb..24a9fb53223a 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.h
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -57,7 +57,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device 
*vsp1,
unsigned int prealloc);
 void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
 void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool interlaced);
 struct vsp1_dl_ext_cmd *vsp1_dlm_get_autofld_cmd(struct vsp1_dl_list *dl);
 
 struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c 
b/drivers/media/platform/vsp1/vsp1_drm.c
index 0459b970e9da..d7028de053ae 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -329,6 +329,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int 
pipe_index,
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
struct vsp1_drm_pipeline *drm_pipe = >drm->pipe[pipe_index];
const struct vsp1_format_info *fmtinfo;
+   struct vsp1_rwpf *output = drm_pipe->pipe.output;
struct vsp1_rwpf *rpf;
 
if (rpf_index >= vsp1->info->rpf_count)
@@ -368,6 +369,17 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int 
pipe_index,
return -EINVAL;
}
 
+   if (!(vsp1_feature(vsp1, VSP1_HAS_EXT_DL)) && cfg->interlaced) {
+   /*
+* Interlaced support requires extended display lists to
+* provide the auto-fld feature with the DU.
+*/
+   dev_dbg(vsp1->dev, "Interlaced unsupported on this output\n");
+   return -EINVAL;
+   }
+
+   rpf->interlaced = output->interlaced = cfg->interlaced;
+
rpf->fmtinfo = fmtinfo;
rpf->format.num_planes = fmtinfo->planes;
rpf->format.plane_fmt[0].bytesperline = cfg->pitch;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c 
b/drivers/media/platform/vsp1/vsp1_pipe.c
index fa445b1a2e38..df674b3bb9a0 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -341,7 +341,8 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 * up being postponed by one frame. @completed represents whether the
 * active frame was finished or postponed.
 */
-   completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
+   completed = vsp1_dlm_irq_frame_end(pipe->output->dlm,
+  pipe->output->interlaced);
 
if (pipe->hgo)
vsp1_hgo_frame_end(pipe->hgo);
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h 
b/drivers/media/platform/vsp1/vsp1_regs.h
index 43ad68ff3167..e2dffbe82809 100644
--- 

[PATCH 00/11] R-Car DU Interlaced support through VSP1

2018-03-09 Thread Kieran Bingham
The Gen3 R-Car DU devices make use of the VSP to handle frame
processing.

In this series we implement support for handling interlaced pipelines
by using the auto-fld feature of the VSP hardware.

The implementation is preceded by some cleanup work and refactoring, through
patches 1 to 6. These are trivial and could be collected earlier and
independently if this series requires further revisions.

Patch 7 makes a key distinctive change to remove all existing support for
headerless display lists throughout the VSP1 driver, and ensures that all
pipelines use the same code path. This simplifies the code and reduces
opportunity for untested code paths to exist.

Patches 8, 9 and 10 implement the relevant support in the VSP1 driver, before
patch 11 finally enables the feature through the drm R-Car DU driver.

This series is based upon my previous TLB optimise and body rework, and is
available from the following URL: 

  git://git.kernel.org/pub/scm/linux/kernel/git/kbingham/rcar.git
  tags/vsp1/du/interlaced/v1

Kieran Bingham (11):
  media: vsp1: drm: Fix minor grammar error
  media: vsp1: use kernel __packed for structures
  media: vsp1: Rename dl_child to dl_next
  media: vsp1: Remove unused display list structure field
  media: vsp1: Clean up DLM objects on error
  media: vsp1: Provide VSP1 feature helper macro
  media: vsp1: Use header display lists for all WPF outputs linked to the DU
  media: vsp1: Add support for extended display list headers
  media: vsp1: Provide support for extended command pools
  media: vsp1: Support Interlaced display pipelines
  drm: rcar-du: Support interlaced video output through vsp1

 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |   1 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c   |   3 +-
 drivers/media/platform/vsp1/vsp1.h  |   3 +-
 drivers/media/platform/vsp1/vsp1_dl.c   | 405 +++--
 drivers/media/platform/vsp1/vsp1_dl.h   |  34 +-
 drivers/media/platform/vsp1/vsp1_drm.c  |  14 +-
 drivers/media/platform/vsp1/vsp1_drv.c  |  23 +-
 drivers/media/platform/vsp1/vsp1_pipe.c |   3 +-
 drivers/media/platform/vsp1/vsp1_regs.h |   6 +-
 drivers/media/platform/vsp1/vsp1_rpf.c  |  72 +++-
 drivers/media/platform/vsp1/vsp1_rwpf.h |   1 +-
 drivers/media/platform/vsp1/vsp1_wpf.c  |   6 +-
 include/media/vsp1.h|   1 +-
 13 files changed, 457 insertions(+), 115 deletions(-)

base-commit: 397eb3811ec096d0ceefa1dbea2d0ae68feb0587
-- 
git-series 0.9.1


[PATCH v3] [media] Use common error handling code in 19 functions

2018-03-09 Thread SF Markus Elfring
From: Markus Elfring 
Date: Fri, 9 Mar 2018 21:00:12 +0100

Adjust jump targets so that a bit of exception handling can be better
reused at the end of these functions.

This issue was partly detected by using the Coccinelle software.

Signed-off-by: Markus Elfring 
---

v3:
Laurent Pinchart and Todor Tomov requested a few adjustments.
Updates were rebased on source files from Linux next-20180308.

v2:
Hans Verkuil insisted on patch squashing. Thus several changes
were recombined based on source files from Linux next-20180216.

The implementation of the function "tda8261_set_params" was improved
after a notification by Christoph Böhmwalder on 2017-09-26.

 drivers/media/dvb-core/dmxdev.c| 16 
 drivers/media/dvb-frontends/tda1004x.c | 20 ++
 drivers/media/dvb-frontends/tda8261.c  | 19 ++
 drivers/media/pci/bt8xx/dst.c  | 19 ++
 drivers/media/pci/bt8xx/dst_ca.c   | 30 +++
 drivers/media/pci/cx88/cx88-input.c| 17 +
 drivers/media/platform/omap3isp/ispvideo.c | 28 ++
 .../media/platform/qcom/camss-8x16/camss-csid.c| 19 +-
 drivers/media/tuners/tuner-xc2028.c| 30 +++
 drivers/media/usb/cpia2/cpia2_usb.c| 13 ---
 drivers/media/usb/gspca/gspca.c| 17 +
 drivers/media/usb/gspca/sn9c20x.c  | 17 +
 drivers/media/usb/pvrusb2/pvrusb2-ioread.c | 10 +++--
 drivers/media/usb/tm6000/tm6000-cards.c|  7 ++--
 drivers/media/usb/tm6000/tm6000-dvb.c  | 11 --
 drivers/media/usb/tm6000/tm6000-video.c| 13 ---
 drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c  | 13 +++
 drivers/media/usb/ttusb-dec/ttusb_dec.c| 43 --
 18 files changed, 171 insertions(+), 171 deletions(-)

diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index 61a750fae465..17d05b05fa9d 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -656,18 +656,18 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
tsfeed->priv = filter;
 
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout);
-   if (ret < 0) {
-   dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
-   return ret;
-   }
+   if (ret < 0)
+   goto release_feed;
 
ret = tsfeed->start_filtering(tsfeed);
-   if (ret < 0) {
-   dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
-   return ret;
-   }
+   if (ret < 0)
+   goto release_feed;
 
return 0;
+
+release_feed:
+   dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
+   return ret;
 }
 
 static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
diff --git a/drivers/media/dvb-frontends/tda1004x.c 
b/drivers/media/dvb-frontends/tda1004x.c
index 58e3beff5adc..85ca111fc8c4 100644
--- a/drivers/media/dvb-frontends/tda1004x.c
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -1299,20 +1299,22 @@ struct dvb_frontend* tda10045_attach(const struct 
tda1004x_config* config,
id = tda1004x_read_byte(state, TDA1004X_CHIPID);
if (id < 0) {
printk(KERN_ERR "tda10045: chip is not answering. Giving 
up.\n");
-   kfree(state);
-   return NULL;
+   goto free_state;
}
 
if (id != 0x25) {
printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't 
proceed\n", id);
-   kfree(state);
-   return NULL;
+   goto free_state;
}
 
/* create dvb_frontend */
memcpy(>frontend.ops, _ops, sizeof(struct 
dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return >frontend;
+
+free_state:
+   kfree(state);
+   return NULL;
 }
 
 static const struct dvb_frontend_ops tda10046_ops = {
@@ -1369,19 +1371,21 @@ struct dvb_frontend* tda10046_attach(const struct 
tda1004x_config* config,
id = tda1004x_read_byte(state, TDA1004X_CHIPID);
if (id < 0) {
printk(KERN_ERR "tda10046: chip is not answering. Giving 
up.\n");
-   kfree(state);
-   return NULL;
+   goto free_state;
}
if (id != 0x46) {
printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't 
proceed\n", id);
-   kfree(state);
-   return NULL;
+   goto free_state;
}
 
/* create dvb_frontend */
memcpy(>frontend.ops, _ops, sizeof(struct 
dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return >frontend;
+
+free_state:
+   kfree(state);
+   return NULL;
 }
 
 module_param(debug, int, 0644);
diff --git 

[PATCH 1/4] dma-buf: add optional invalidate_mappings callback

2018-03-09 Thread Christian König
Each importer can now provide an invalidate_mappings callback.

This allows the exporter to provide the mappings without the need to pin
the backing store.

Signed-off-by: Christian König 
---
 drivers/dma-buf/dma-buf.c | 25 +
 include/linux/dma-buf.h   | 36 
 2 files changed, 61 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d78d5fc173dc..ed8d5844ae74 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -629,6 +629,9 @@ struct sg_table *dma_buf_map_attachment(struct 
dma_buf_attachment *attach,
 
might_sleep();
 
+   if (attach->invalidate_mappings)
+   reservation_object_assert_held(attach->dmabuf->resv);
+
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);
 
@@ -656,6 +659,9 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment 
*attach,
 {
might_sleep();
 
+   if (attach->invalidate_mappings)
+   reservation_object_assert_held(attach->dmabuf->resv);
+
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
 
@@ -664,6 +670,25 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment 
*attach,
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
 
+/**
+ * dma_buf_invalidate_mappings - invalidate all mappings of this dma_buf
+ *
+ * @dmabuf:[in]buffer which mappings should be invalidated
+ *
+ * Informs all attachmenst that they need to destroy and recreated all their
+ * mappings.
+ */
+void dma_buf_invalidate_mappings(struct dma_buf *dmabuf)
+{
+   struct dma_buf_attachment *attach;
+
+   reservation_object_assert_held(dmabuf->resv);
+
+   list_for_each_entry(attach, >attachments, node)
+   attach->invalidate_mappings(attach);
+}
+EXPORT_SYMBOL_GPL(dma_buf_invalidate_mappings);
+
 /**
  * DOC: cpu access
  *
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 085db2fee2d7..c1e2f7d93509 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -91,6 +91,18 @@ struct dma_buf_ops {
 */
void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
 
+   /**
+* @supports_mapping_invalidation:
+*
+* True for exporters which supports unpinned DMA-buf operation using
+* the reservation lock.
+*
+* When attachment->invalidate_mappings is set the @map_dma_buf and
+* @unmap_dma_buf callbacks can be called with the reservation lock
+* held.
+*/
+   bool supports_mapping_invalidation;
+
/**
 * @map_dma_buf:
 *
@@ -326,6 +338,29 @@ struct dma_buf_attachment {
struct device *dev;
struct list_head node;
void *priv;
+
+   /**
+* @invalidate_mappings:
+*
+* Optional callback provided by the importer of the attachment which
+* must be set before mappings are created.
+*
+* If provided the exporter can avoid pinning the backing store while
+* mappings exists.
+*
+* The function is called with the lock of the reservation object
+* associated with the dma_buf held and the mapping function must be
+* called with this lock held as well. This makes sure that no mapping
+* is created concurrently with an ongoing invalidation.
+*
+* After the callback all existing mappings are still valid until all
+* fences in the dma_bufs reservation object are signaled, but should be
+* destroyed by the importer as soon as possible.
+*
+* New mappings can be created immediately, but can't be used before the
+* exclusive fence in the dma_bufs reservation object is signaled.
+*/
+   void (*invalidate_mappings)(struct dma_buf_attachment *attach);
 };
 
 /**
@@ -391,6 +426,7 @@ struct sg_table *dma_buf_map_attachment(struct 
dma_buf_attachment *,
enum dma_data_direction);
 void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
enum dma_data_direction);
+void dma_buf_invalidate_mappings(struct dma_buf *dma_buf);
 int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 enum dma_data_direction dir);
 int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
-- 
2.14.1



[PATCH 3/4] drm/amdgpu: add independent DMA-buf export

2018-03-09 Thread Christian König
Instead of relying on the DRM functions just implement our own export
functions. This adds support for taking care of unpinned DMA-buf.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h|   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c|   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c |   4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c  | 117 ++---
 4 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 96bcdb97e7e2..909dc9764a22 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -371,7 +371,6 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
 void amdgpu_gem_object_close(struct drm_gem_object *obj,
struct drm_file *file_priv);
 unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
-struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *
 amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
 struct dma_buf_attachment *attach,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index e6709362994a..e32dcdf8d3db 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -886,7 +886,6 @@ static struct drm_driver kms_driver = {
.gem_prime_export = amdgpu_gem_prime_export,
.gem_prime_import = amdgpu_gem_prime_import,
.gem_prime_res_obj = amdgpu_gem_prime_res_obj,
-   .gem_prime_get_sg_table = amdgpu_gem_prime_get_sg_table,
.gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table,
.gem_prime_vmap = amdgpu_gem_prime_vmap,
.gem_prime_vunmap = amdgpu_gem_prime_vunmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 48e0115d4f76..d5db5955a70a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -31,6 +31,7 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -931,6 +932,9 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
 
amdgpu_bo_kunmap(abo);
 
+   if (abo->gem_base.dma_buf)
+   dma_buf_invalidate_mappings(abo->gem_base.dma_buf);
+
/* remember the eviction */
if (evict)
atomic64_inc(>num_evictions);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 1c9991738477..f575fb46d7a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -32,13 +32,9 @@
 
 static const struct dma_buf_ops amdgpu_dmabuf_ops;
 
-struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-   struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-   int npages = bo->tbo.num_pages;
-
-   return drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages);
-}
+static void amdgpu_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
+struct sg_table *sgt,
+enum dma_data_direction dir);
 
 void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj)
 {
@@ -126,22 +122,21 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret);
 }
 
-static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
-struct device *target_dev,
-struct dma_buf_attachment *attach)
+static struct sg_table *
+amdgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
+  enum dma_data_direction dir)
 {
+   struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+   struct sg_table *sgt;
long r;
 
-   r = drm_gem_map_attach(dma_buf, target_dev, attach);
-   if (r)
-   return r;
-
-   r = amdgpu_bo_reserve(bo, false);
-   if (unlikely(r != 0))
-   goto error_detach;
-
+   if (!attach->invalidate_mappings) {
+   r = amdgpu_bo_reserve(bo, false);
+   if (unlikely(r != 0))
+   return ERR_PTR(r);
+   }
 
if (dma_buf->ops != _dmabuf_ops) {
/*
@@ -157,41 +152,80 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
}
}
 
-   /* pin buffer into GTT */
-   r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
-   if (r)
-   goto error_unreserve;
+   if (!attach->invalidate_mappings || true) {
+   /* pin buffer into GTT */
+   r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
+   if (r)
+   goto error_unreserve;
+
+   } else {
+   /* move buffer into GTT */
+  

[PATCH 4/4] drm/amdgpu: add independent DMA-buf import

2018-03-09 Thread Christian König
Instead of relying on the DRM functions just implement our own import
functions. This adds support for taking care of unpinned DMA-buf.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 64 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c   | 32 +---
 2 files changed, 80 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index f575fb46d7a8..7963ce329519 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -298,22 +298,64 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device 
*dev,
return buf;
 }
 
+static void
+amdgpu_gem_prime_invalidate_mappings(struct dma_buf_attachment *attach)
+{
+   struct ttm_operation_ctx ctx = { false, false };
+   struct drm_gem_object *obj = attach->priv;
+   struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+   int r;
+
+   amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
+   r = ttm_bo_validate(>tbo, >placement, );
+   if (r)
+   DRM_ERROR("Failed to unmap DMA-buf import (%d))\n", r);
+}
+
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
 {
+   struct dma_buf_attachment *attach;
struct drm_gem_object *obj;
+   int ret;
 
-   if (dma_buf->ops == _dmabuf_ops) {
-   obj = dma_buf->priv;
-   if (obj->dev == dev) {
-   /*
-* Importing dmabuf exported from out own gem increases
-* refcount on gem itself instead of f_count of dmabuf.
-*/
-   drm_gem_object_get(obj);
-   return obj;
-   }
+   if (dma_buf->ops != _dmabuf_ops)
+   return drm_gem_prime_import(dev, dma_buf);
+
+   obj = dma_buf->priv;
+   if (obj->dev == dev) {
+   /*
+* Importing dmabuf exported from out own gem increases
+* refcount on gem itself instead of f_count of dmabuf.
+*/
+   drm_gem_object_get(obj);
+   return obj;
+   }
+
+   /*
+* Attach, but don't map other amdgpu BOs
+*/
+   attach = dma_buf_attach(dma_buf, dev->dev);
+   if (IS_ERR(attach))
+   return ERR_CAST(attach);
+
+   get_dma_buf(dma_buf);
+
+   obj = amdgpu_gem_prime_import_sg_table(dev, attach, NULL);
+   if (IS_ERR(obj)) {
+   ret = PTR_ERR(obj);
+   goto fail_detach;
}
 
-   return drm_gem_prime_import(dev, dma_buf);
+   obj->import_attach = attach;
+   attach->invalidate_mappings = amdgpu_gem_prime_invalidate_mappings;
+   attach->priv = obj;
+
+   return obj;
+
+fail_detach:
+   dma_buf_detach(dma_buf, attach);
+   dma_buf_put(dma_buf);
+
+   return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 291dd3d600cd..aeead0281e92 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "amdgpu.h"
 #include "amdgpu_object.h"
 #include "amdgpu_trace.h"
@@ -685,6 +686,7 @@ struct amdgpu_ttm_gup_task_list {
 
 struct amdgpu_ttm_tt {
struct ttm_dma_tt   ttm;
+   struct amdgpu_bo*bo;
u64 offset;
uint64_tuserptr;
struct mm_struct*usermm;
@@ -993,6 +995,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct 
ttm_buffer_object *bo,
return NULL;
}
gtt->ttm.ttm.func = _backend_func;
+   gtt->bo = ttm_to_amdgpu_bo(bo);
if (ttm_sg_tt_init(>ttm, bo, page_flags)) {
kfree(gtt);
return NULL;
@@ -1005,7 +1008,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
 {
struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
-   bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
 
if (gtt && gtt->userptr) {
ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
@@ -1017,7 +1019,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
return 0;
}
 
-   if (slave && ttm->sg) {
+   if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
+   if (!ttm->sg) {
+   struct dma_buf_attachment *attach;
+   struct sg_table *sgt;
+
+   attach = gtt->bo->gem_base.import_attach;
+   sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR(sgt))
+   return PTR_ERR(sgt);
+
+  

RFC: unpinned DMA-buf exporting

2018-03-09 Thread Christian König
This set of patches adds an option invalidate_mappings callback to each DMA-buf 
attachment which can be filled in by the importer.

This callback allows the exporter to provided the DMA-buf content without 
pinning it. The reservation objects lock acts as synchronization point for 
buffer moves and creating mappings.

This set includes an implementation for amdgpu which should be rather easily 
portable to other DRM drivers.

Please comment,
Christian.



[PATCH 2/4] drm/ttm: keep a reference to transfer pipelined BOs

2018-03-09 Thread Christian König
Make sure the transfered BO is never destroy before the transfer BO.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/ttm/ttm_bo_util.c | 50 +++
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 1f730b3f18e5..1ee20558ee31 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -39,6 +39,11 @@
 #include 
 #include 
 
+struct ttm_transfer_obj {
+   struct ttm_buffer_object base;
+   struct ttm_buffer_object *bo;
+};
+
 void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
 {
ttm_bo_mem_put(bo, >mem);
@@ -435,7 +440,11 @@ EXPORT_SYMBOL(ttm_bo_move_memcpy);
 
 static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
 {
-   kfree(bo);
+   struct ttm_transfer_obj *fbo;
+
+   fbo = container_of(bo, struct ttm_transfer_obj, base);
+   ttm_bo_unref(>bo);
+   kfree(fbo);
 }
 
 /**
@@ -456,14 +465,15 @@ static void ttm_transfered_destroy(struct 
ttm_buffer_object *bo)
 static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
  struct ttm_buffer_object **new_obj)
 {
-   struct ttm_buffer_object *fbo;
+   struct ttm_transfer_obj *fbo;
int ret;
 
fbo = kmalloc(sizeof(*fbo), GFP_KERNEL);
if (!fbo)
return -ENOMEM;
 
-   *fbo = *bo;
+   fbo->base = *bo;
+   fbo->bo = ttm_bo_reference(bo);
 
/**
 * Fix up members that we shouldn't copy directly:
@@ -471,25 +481,25 @@ static int ttm_buffer_object_transfer(struct 
ttm_buffer_object *bo,
 */
 
atomic_inc(>bdev->glob->bo_count);
-   INIT_LIST_HEAD(>ddestroy);
-   INIT_LIST_HEAD(>lru);
-   INIT_LIST_HEAD(>swap);
-   INIT_LIST_HEAD(>io_reserve_lru);
-   mutex_init(>wu_mutex);
-   fbo->moving = NULL;
-   drm_vma_node_reset(>vma_node);
-   atomic_set(>cpu_writers, 0);
-
-   kref_init(>list_kref);
-   kref_init(>kref);
-   fbo->destroy = _transfered_destroy;
-   fbo->acc_size = 0;
-   fbo->resv = >ttm_resv;
-   reservation_object_init(fbo->resv);
-   ret = reservation_object_trylock(fbo->resv);
+   INIT_LIST_HEAD(>base.ddestroy);
+   INIT_LIST_HEAD(>base.lru);
+   INIT_LIST_HEAD(>base.swap);
+   INIT_LIST_HEAD(>base.io_reserve_lru);
+   mutex_init(>base.wu_mutex);
+   fbo->base.moving = NULL;
+   drm_vma_node_reset(>base.vma_node);
+   atomic_set(>base.cpu_writers, 0);
+
+   kref_init(>base.list_kref);
+   kref_init(>base.kref);
+   fbo->base.destroy = _transfered_destroy;
+   fbo->base.acc_size = 0;
+   fbo->base.resv = >base.ttm_resv;
+   reservation_object_init(fbo->base.resv);
+   ret = reservation_object_trylock(fbo->base.resv);
WARN_ON(!ret);
 
-   *new_obj = fbo;
+   *new_obj = >base;
return 0;
 }
 
-- 
2.14.1



[PATCH 1/4] dma-buf: add optional invalidate_mappings callback

2018-03-09 Thread Christian König
Each importer can now provide an invalidate_mappings callback.

This allows the exporter to provide the mappings without the need to pin
the backing store.

Signed-off-by: Christian König 
---
 drivers/dma-buf/dma-buf.c | 25 +
 include/linux/dma-buf.h   | 36 
 2 files changed, 61 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d78d5fc173dc..ed8d5844ae74 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -629,6 +629,9 @@ struct sg_table *dma_buf_map_attachment(struct 
dma_buf_attachment *attach,
 
might_sleep();
 
+   if (attach->invalidate_mappings)
+   reservation_object_assert_held(attach->dmabuf->resv);
+
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);
 
@@ -656,6 +659,9 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment 
*attach,
 {
might_sleep();
 
+   if (attach->invalidate_mappings)
+   reservation_object_assert_held(attach->dmabuf->resv);
+
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
 
@@ -664,6 +670,25 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment 
*attach,
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
 
+/**
+ * dma_buf_invalidate_mappings - invalidate all mappings of this dma_buf
+ *
+ * @dmabuf:[in]buffer which mappings should be invalidated
+ *
+ * Informs all attachmenst that they need to destroy and recreated all their
+ * mappings.
+ */
+void dma_buf_invalidate_mappings(struct dma_buf *dmabuf)
+{
+   struct dma_buf_attachment *attach;
+
+   reservation_object_assert_held(dmabuf->resv);
+
+   list_for_each_entry(attach, >attachments, node)
+   attach->invalidate_mappings(attach);
+}
+EXPORT_SYMBOL_GPL(dma_buf_invalidate_mappings);
+
 /**
  * DOC: cpu access
  *
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 085db2fee2d7..c1e2f7d93509 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -91,6 +91,18 @@ struct dma_buf_ops {
 */
void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
 
+   /**
+* @supports_mapping_invalidation:
+*
+* True for exporters which supports unpinned DMA-buf operation using
+* the reservation lock.
+*
+* When attachment->invalidate_mappings is set the @map_dma_buf and
+* @unmap_dma_buf callbacks can be called with the reservation lock
+* held.
+*/
+   bool supports_mapping_invalidation;
+
/**
 * @map_dma_buf:
 *
@@ -326,6 +338,29 @@ struct dma_buf_attachment {
struct device *dev;
struct list_head node;
void *priv;
+
+   /**
+* @invalidate_mappings:
+*
+* Optional callback provided by the importer of the attachment which
+* must be set before mappings are created.
+*
+* If provided the exporter can avoid pinning the backing store while
+* mappings exists.
+*
+* The function is called with the lock of the reservation object
+* associated with the dma_buf held and the mapping function must be
+* called with this lock held as well. This makes sure that no mapping
+* is created concurrently with an ongoing invalidation.
+*
+* After the callback all existing mappings are still valid until all
+* fences in the dma_bufs reservation object are signaled, but should be
+* destroyed by the importer as soon as possible.
+*
+* New mappings can be created immediately, but can't be used before the
+* exclusive fence in the dma_bufs reservation object is signaled.
+*/
+   void (*invalidate_mappings)(struct dma_buf_attachment *attach);
 };
 
 /**
@@ -391,6 +426,7 @@ struct sg_table *dma_buf_map_attachment(struct 
dma_buf_attachment *,
enum dma_data_direction);
 void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
enum dma_data_direction);
+void dma_buf_invalidate_mappings(struct dma_buf *dma_buf);
 int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 enum dma_data_direction dir);
 int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
-- 
2.14.1



Re: [PATCH v8 07/13] [media] vb2: mark codec drivers as unordered

2018-03-09 Thread Nicolas Dufresne
Le vendredi 09 mars 2018 à 14:49 -0300, Gustavo Padovan a écrit :
> From: Gustavo Padovan 
> 
> In preparation to have full support to explicit fence we are
> marking codec as non-ordered preventively. It is easier and safer from an

The usage of "codec" is soso 

> uAPI point of view to move from unordered to ordered than the opposite.
> 
> Signed-off-by: Gustavo Padovan 
> ---
>  drivers/media/platform/coda/coda-common.c  | 1 +
>  drivers/media/platform/exynos-gsc/gsc-m2m.c| 1 +
>  drivers/media/platform/exynos4-is/fimc-m2m.c   | 1 +
>  drivers/media/platform/m2m-deinterlace.c   | 1 +

... these tree are not codecs. Did you just set all M2M drivers are
unordered ?

>  drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c| 1 +
>  drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c   | 1 +
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1 +
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1 +
>  drivers/media/platform/mx2_emmaprp.c   | 1 +
>  drivers/media/platform/qcom/venus/vdec.c   | 1 +
>  drivers/media/platform/qcom/venus/venc.c   | 1 +
>  drivers/media/platform/rcar_fdp1.c | 1 +
>  drivers/media/platform/rcar_jpu.c  | 1 +
>  drivers/media/platform/rockchip/rga/rga-buf.c  | 1 +
>  drivers/media/platform/s5p-g2d/g2d.c   | 1 +

If this 2D blitter driver picks input buffers in random order, we have
a serious problem.

>  drivers/media/platform/s5p-jpeg/jpeg-core.c| 1 +
>  drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   | 1 +
>  drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   | 1 +
>  drivers/media/platform/sh_veu.c| 1 +
>  drivers/media/platform/sti/bdisp/bdisp-v4l2.c  | 1 +
>  drivers/media/platform/ti-vpe/vpe.c| 1 +
>  drivers/media/platform/vim2m.c | 1 +
>  22 files changed, 22 insertions(+)
> 
> diff --git a/drivers/media/platform/coda/coda-common.c 
> b/drivers/media/platform/coda/coda-common.c
> index 04e35d70ce2e..6deb29fe6eb7 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -1649,6 +1649,7 @@ static const struct vb2_ops coda_qops = {
>   .stop_streaming = coda_stop_streaming,
>   .wait_prepare   = vb2_ops_wait_prepare,
>   .wait_finish= vb2_ops_wait_finish,
> + .is_unordered   = vb2_ops_set_unordered,
>  };
>  
>  static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
> diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c 
> b/drivers/media/platform/exynos-gsc/gsc-m2m.c
> index e9ff27949a91..10c3e4659d38 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
> +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
> @@ -286,6 +286,7 @@ static const struct vb2_ops gsc_m2m_qops = {
>   .wait_finish = vb2_ops_wait_finish,
>   .stop_streaming  = gsc_m2m_stop_streaming,
>   .start_streaming = gsc_m2m_start_streaming,
> + .is_unordered= vb2_ops_set_unordered,
>  };
>  
>  static int gsc_m2m_querycap(struct file *file, void *fh,
> diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c 
> b/drivers/media/platform/exynos4-is/fimc-m2m.c
> index a19f8b164a47..dfc487a582c0 100644
> --- a/drivers/media/platform/exynos4-is/fimc-m2m.c
> +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
> @@ -227,6 +227,7 @@ static const struct vb2_ops fimc_qops = {
>   .wait_finish = vb2_ops_wait_finish,
>   .stop_streaming  = stop_streaming,
>   .start_streaming = start_streaming,
> + .is_unordered= vb2_ops_set_unordered,
>  };
>  
>  /*
> diff --git a/drivers/media/platform/m2m-deinterlace.c 
> b/drivers/media/platform/m2m-deinterlace.c
> index 1e4195144f39..35a0f45d2a51 100644
> --- a/drivers/media/platform/m2m-deinterlace.c
> +++ b/drivers/media/platform/m2m-deinterlace.c
> @@ -856,6 +856,7 @@ static const struct vb2_ops deinterlace_qops = {
>   .queue_setup = deinterlace_queue_setup,
>   .buf_prepare = deinterlace_buf_prepare,
>   .buf_queue   = deinterlace_buf_queue,
> + .is_unordered= vb2_ops_set_unordered,
>  };
>  
>  static int queue_init(void *priv, struct vb2_queue *src_vq,
> diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
> b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> index 226f90886484..34a4b5b2e1b5 100644
> --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> @@ -764,6 +764,7 @@ static const struct vb2_ops mtk_jpeg_qops = {
>   .wait_finish= vb2_ops_wait_finish,
>   .start_streaming= mtk_jpeg_start_streaming,
>   .stop_streaming = mtk_jpeg_stop_streaming,
> + .is_unordered   = vb2_ops_set_unordered,
>  };
>  
>  static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
> diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c 
> 

Re: [PATCH v5 0/2] media: video-i2c: add video-i2c driver support

2018-03-09 Thread Matt Ranostay
On Fri, Mar 9, 2018 at 4:45 AM, Hans Verkuil  wrote:
> Hi Matt,
>
> This is looking good. One request before I merge: please run the
> 'v4l2-compliance -s -f' utility and post the result here.
>
> I don't think I've asked you to do that before (or if I did, I couldn't
> find it in my mail archive).
>
> It should run without failures.
>
> Use the latest version from the git repo: 
> https://git.linuxtv.org/v4l-utils.git/
>
> ./bootstrap.sh; ./configure; make; sudo make install

Heh so not exactly no failures. Suspect a lot of these are due to the
weird small 8x8 pixel input, and the fact it doesn't
support modes a typical video capture device would.

v4l2-compliance SHA   : 14ce03c18ef67aa7a3d5781f015be855fd43839c

Compliance test for device /dev/video0:

Driver Info:
Driver name  : video-i2c
Card type: I2C 2-105 Transport Video
Bus info : I2C:2-105
Driver version   : 4.14.11
Capabilities : 0x8521
Video Capture
Read/Write
Streaming
Extended Pix Format
Device Capabilities
Device Caps  : 0x0521
Video Capture
Read/Write
Streaming
Extended Pix Format

Required ioctls:
test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
test second /dev/video0 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK

Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 1 Audio Inputs: 0 Tuners: 0

Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)

Control ioctls (Input 0):
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0

Format ioctls (Input 0):
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)

Codec ioctls (Input 0):
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

Buffer ioctls (Input 0):
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK (Not Supported)

Test input 0:

Streaming ioctls:
test read/write: OK
fail: v4l2-test-buffers.cpp(248): g_field() == V4L2_FIELD_ANY
fail: v4l2-test-buffers.cpp(658): buf.check(q, last_seq)
fail: v4l2-test-buffers.cpp(928): captureBufs(node, q, m2m_q,
frame_count, false)
test MMAP: FAIL
fail: v4l2-test-buffers.cpp(1028): can_stream && ret != EINVAL
test USERPTR: FAIL
test DMABUF: Cannot test, specify --expbuf-device

Stream using all formats:
test MMAP for Format Y12 , Frame Size 8x8@10.00 Hz:
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field None: FAIL
fail: v4l2-test-buffers.cpp(1472): fmt.g_sizeimage() <= size
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 80, Field None: FAIL
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field Top: FAIL
fail: v4l2-test-buffers.cpp(1472): fmt.g_sizeimage() <= size
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 80, Field None: FAIL
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field Bottom: FAIL
fail: v4l2-test-buffers.cpp(1472): fmt.g_sizeimage() <= size
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 80, Field None: FAIL
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field Interlaced: FAIL
fail: v4l2-test-buffers.cpp(1472): fmt.g_sizeimage() <= size
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 80, Field None: FAIL
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field Sequential Top-Bottom: FAIL
fail: v4l2-test-buffers.cpp(1472): fmt.g_sizeimage() <= size
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 80, Field None: FAIL
fail: v4l2-test-buffers.cpp(1268): q.reqbufs(node, 3)
Stride 0, Field Sequential Bottom-Top: FAIL
fail: 

[PATCH v8 00/13] V4L2 Explicit Synchronization

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Hi,

So v8 is finally out addressing the comments from the previous version[1].
For more info see v5 cover letter[2]. The most important points I address
here is the handling of fences that signal with error to follow Hans
suggestion. I also added V4L2_CAP_FENCES to all vb2 drivers and marked all
codec and cobalt as unordered. More specific changelog are noted on the
patches itself.

The first 3 patches are just clean ups in preparation to add the new cap flag
and can go upstream earlier. Then there are patches to add unordered info,
the actual fences implementation and later the V4L2_CAP_FENCES flag.
The last patch contains the Documentation.

You can find the code at:

https://gitlab.collabora.com/padovan/linux/tree/v4l2-fences

The test tools I've been using are:
https://gitlab.collabora.com/padovan/drm-v4l2-test
https://gitlab.collabora.com/padovan/v4l2-fences-test

Please review,

Gustavo

[1] https://lkml.org/lkml/2018/1/10/644
[2] https://lkml.org/lkml/2017/11/15/550

Gustavo Padovan (13):
  [media] xilinx: regroup caps on querycap
  [media] hackrf: group device capabilities
  [media] omap3isp: group device capabilities
  [media] vb2: add is_unordered callback for drivers
  [media] v4l: add 'unordered' flag to format description ioctl
  [media] cobalt: add .is_unordered() for cobalt
  [media] vb2: mark codec drivers as unordered
  [media] vb2: add explicit fence user API
  [media] vb2: add in-fence support to QBUF
  [media] vb2: add out-fence support to QBUF
  [media] v4l: introduce the fences capability
  [media] v4l: Add V4L2_CAP_FENCES to drivers
  [media] v4l: Document explicit synchronization behavior

 Documentation/media/uapi/v4l/buffer.rst|  45 +++-
 Documentation/media/uapi/v4l/vidioc-enum-fmt.rst   |   7 +
 Documentation/media/uapi/v4l/vidioc-qbuf.rst   |  55 +++-
 Documentation/media/uapi/v4l/vidioc-querybuf.rst   |  12 +-
 Documentation/media/uapi/v4l/vidioc-querycap.rst   |   3 +
 drivers/media/common/videobuf2/videobuf2-core.c| 289 ++---
 drivers/media/common/videobuf2/videobuf2-v4l2.c|  58 -
 drivers/media/pci/cobalt/cobalt-v4l2.c |   4 +-
 drivers/media/pci/cx23885/cx23885-417.c|   2 +-
 drivers/media/pci/cx23885/cx23885-video.c  |   3 +-
 drivers/media/pci/cx88/cx88-video.c|   3 +-
 drivers/media/pci/dt3155/dt3155.c  |   2 +-
 drivers/media/pci/saa7134/saa7134-video.c  |   2 +
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c |   3 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2.c |   3 +-
 drivers/media/pci/sta2x11/sta2x11_vip.c|   2 +-
 drivers/media/pci/tw68/tw68-video.c|   3 +-
 drivers/media/pci/tw686x/tw686x-video.c|   2 +-
 drivers/media/platform/am437x/am437x-vpfe.c|   2 +-
 drivers/media/platform/blackfin/bfin_capture.c |   3 +-
 drivers/media/platform/coda/coda-common.c  |   4 +-
 drivers/media/platform/davinci/vpbe_display.c  |   3 +-
 drivers/media/platform/davinci/vpfe_capture.c  |   3 +-
 drivers/media/platform/davinci/vpif_capture.c  |   3 +-
 drivers/media/platform/davinci/vpif_display.c  |   3 +-
 drivers/media/platform/exynos-gsc/gsc-m2m.c|   4 +-
 drivers/media/platform/exynos4-is/fimc-capture.c   |   3 +-
 drivers/media/platform/exynos4-is/fimc-isp-video.c |   3 +-
 drivers/media/platform/exynos4-is/fimc-lite.c  |   2 +-
 drivers/media/platform/exynos4-is/fimc-m2m.c   |   4 +-
 drivers/media/platform/m2m-deinterlace.c   |   4 +-
 drivers/media/platform/marvell-ccic/mcam-core.c|   2 +-
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c|   1 +
 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c   |   1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c |   1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c |   1 +
 drivers/media/platform/mx2_emmaprp.c   |   4 +-
 drivers/media/platform/omap3isp/ispvideo.c |   9 +-
 drivers/media/platform/pxa_camera.c|   3 +-
 drivers/media/platform/qcom/venus/vdec.c   |   1 +
 drivers/media/platform/qcom/venus/venc.c   |   1 +
 drivers/media/platform/rcar_fdp1.c |   1 +
 drivers/media/platform/rcar_jpu.c  |   4 +-
 drivers/media/platform/rockchip/rga/rga-buf.c  |   1 +
 drivers/media/platform/s3c-camif/camif-capture.c   |   3 +-
 drivers/media/platform/s5p-g2d/g2d.c   |   4 +-
 drivers/media/platform/s5p-jpeg/jpeg-core.c|   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   |   4 +-
 drivers/media/platform/sh_veu.c|   4 +-
 drivers/media/platform/sh_vou.c|   2 +-
 drivers/media/platform/sti/bdisp/bdisp-v4l2.c  |   4 +-
 drivers/media/platform/ti-vpe/cal.c|   2 +-
 drivers/media/platform/ti-vpe/vpe.c| 

[PATCH v8 01/13] [media] xilinx: regroup caps on querycap

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

To better organize the code we concentrate the setting of
V4L2_CAP_STREAMING in one place.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/platform/xilinx/xilinx-dma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/xilinx/xilinx-dma.c 
b/drivers/media/platform/xilinx/xilinx-dma.c
index 522cdfdd3345..565e466ba4fa 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -494,13 +494,14 @@ xvip_dma_querycap(struct file *file, void *fh, struct 
v4l2_capability *cap)
struct v4l2_fh *vfh = file->private_data;
struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
 
-   cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+   cap->device_caps = V4L2_CAP_STREAMING;
+   cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS
  | dma->xdev->v4l2_caps;
 
if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-   cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
else
-   cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
 
strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
strlcpy(cap->card, dma->video.name, sizeof(cap->card));
-- 
2.14.3



[PATCH v8 03/13] [media] omap3isp: group device capabilities

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Instead of putting V4L2_CAP_STREAMING everywhere, set device_caps
earlier with this value.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/platform/omap3isp/ispvideo.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index a751c89a3ea8..b4d4ef926749 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -658,13 +658,14 @@ isp_video_querycap(struct file *file, void *fh, struct 
v4l2_capability *cap)
strlcpy(cap->card, video->video.name, sizeof(cap->card));
strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
 
-   cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-   | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
+   cap->device_caps = V4L2_CAP_STREAMING;
+   cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
+   V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_DEVICE_CAPS;
 
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-   cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
else
-   cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
 
return 0;
 }
-- 
2.14.3



[PATCH v8 04/13] [media] vb2: add is_unordered callback for drivers

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Explicit synchronization benefits a lot from ordered queues, they fit
better in a pipeline with DRM for example so create a opt-in way for
drivers notify videobuf2 that the queue is unordered.

Drivers don't need implement it if the queue is ordered.

v2: - improve comments for is_unordered flag (Hans)

v3: - make it bool (Hans)
- create vb2_ops_set_unordered() helper

Signed-off-by: Gustavo Padovan 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h  |  6 ++
 include/media/videobuf2-v4l2.h  | 10 ++
 3 files changed, 22 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 886a2d8d5c6c..68291ba8632d 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -961,6 +961,12 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
 }
 EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
 
+bool vb2_ops_set_unordered(struct vb2_queue *q)
+{
+   return true;
+}
+EXPORT_SYMBOL_GPL(vb2_ops_set_unordered);
+
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 5b6c541e4e1b..46a9e674f7e1 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -370,6 +370,10 @@ struct vb2_buffer {
  * callback by calling vb2_buffer_done() with either
  * %VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use
  * vb2_wait_for_all_buffers() function
+ * @is_unordered:  tell if the queue is unordered, i.e. buffers can be
+ * dequeued in a different order from how they were queued.
+ * The default is assumed to be ordered and this function
+ * only needs to be implemented for unordered queues.
  * @buf_queue: passes buffer vb to the driver; driver may start
  * hardware operation on this buffer; driver should give
  * the buffer back by calling vb2_buffer_done() function;
@@ -393,6 +397,7 @@ struct vb2_ops {
 
int (*start_streaming)(struct vb2_queue *q, unsigned int count);
void (*stop_streaming)(struct vb2_queue *q);
+   bool (*is_unordered)(struct vb2_queue *q);
 
void (*buf_queue)(struct vb2_buffer *vb);
 };
@@ -566,6 +571,7 @@ struct vb2_queue {
u32 cnt_wait_finish;
u32 cnt_start_streaming;
u32 cnt_stop_streaming;
+   u32 cnt_is_unordered;
 #endif
 };
 
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 3d5e2d739f05..9de3c887c875 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -291,4 +291,14 @@ void vb2_ops_wait_prepare(struct vb2_queue *vq);
  */
 void vb2_ops_wait_finish(struct vb2_queue *vq);
 
+/**
+ * vb2_ops_set_unordered - helper function to mark queue as unordered
+ *
+ * @vq: pointer to  vb2_queue
+ *
+ * This helper just return true to notify that the driver can't deal with
+ * ordered queues.
+ */
+bool vb2_ops_set_unordered(struct vb2_queue *q);
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
2.14.3



[PATCH v8 02/13] [media] hackrf: group device capabilities

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Instead of putting V4L2_CAP_STREAMING and V4L2_CAP_READWRITE
everywhere, set device_caps earlier with these values.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/usb/hackrf/hackrf.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/media/usb/hackrf/hackrf.c 
b/drivers/media/usb/hackrf/hackrf.c
index 7eb53517a82f..6d692fb3e8dd 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -909,18 +909,15 @@ static int hackrf_querycap(struct file *file, void *fh,
 
dev_dbg(>dev, "\n");
 
+   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
if (vdev->vfl_dir == VFL_DIR_RX)
-   cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
-  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
-
+   cap->device_caps |= V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER;
else
-   cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
-  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+   cap->device_caps |= V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR;
 
cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
-   V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
-   V4L2_CAP_DEVICE_CAPS;
+   V4L2_CAP_DEVICE_CAPS | cap->device_caps;
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-- 
2.14.3



[PATCH v8 07/13] [media] vb2: mark codec drivers as unordered

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

In preparation to have full support to explicit fence we are
marking codec as non-ordered preventively. It is easier and safer from an
uAPI point of view to move from unordered to ordered than the opposite.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/platform/coda/coda-common.c  | 1 +
 drivers/media/platform/exynos-gsc/gsc-m2m.c| 1 +
 drivers/media/platform/exynos4-is/fimc-m2m.c   | 1 +
 drivers/media/platform/m2m-deinterlace.c   | 1 +
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c| 1 +
 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c   | 1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1 +
 drivers/media/platform/mx2_emmaprp.c   | 1 +
 drivers/media/platform/qcom/venus/vdec.c   | 1 +
 drivers/media/platform/qcom/venus/venc.c   | 1 +
 drivers/media/platform/rcar_fdp1.c | 1 +
 drivers/media/platform/rcar_jpu.c  | 1 +
 drivers/media/platform/rockchip/rga/rga-buf.c  | 1 +
 drivers/media/platform/s5p-g2d/g2d.c   | 1 +
 drivers/media/platform/s5p-jpeg/jpeg-core.c| 1 +
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   | 1 +
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   | 1 +
 drivers/media/platform/sh_veu.c| 1 +
 drivers/media/platform/sti/bdisp/bdisp-v4l2.c  | 1 +
 drivers/media/platform/ti-vpe/vpe.c| 1 +
 drivers/media/platform/vim2m.c | 1 +
 22 files changed, 22 insertions(+)

diff --git a/drivers/media/platform/coda/coda-common.c 
b/drivers/media/platform/coda/coda-common.c
index 04e35d70ce2e..6deb29fe6eb7 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1649,6 +1649,7 @@ static const struct vb2_ops coda_qops = {
.stop_streaming = coda_stop_streaming,
.wait_prepare   = vb2_ops_wait_prepare,
.wait_finish= vb2_ops_wait_finish,
+   .is_unordered   = vb2_ops_set_unordered,
 };
 
 static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c 
b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index e9ff27949a91..10c3e4659d38 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -286,6 +286,7 @@ static const struct vb2_ops gsc_m2m_qops = {
.wait_finish = vb2_ops_wait_finish,
.stop_streaming  = gsc_m2m_stop_streaming,
.start_streaming = gsc_m2m_start_streaming,
+   .is_unordered= vb2_ops_set_unordered,
 };
 
 static int gsc_m2m_querycap(struct file *file, void *fh,
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c 
b/drivers/media/platform/exynos4-is/fimc-m2m.c
index a19f8b164a47..dfc487a582c0 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -227,6 +227,7 @@ static const struct vb2_ops fimc_qops = {
.wait_finish = vb2_ops_wait_finish,
.stop_streaming  = stop_streaming,
.start_streaming = start_streaming,
+   .is_unordered= vb2_ops_set_unordered,
 };
 
 /*
diff --git a/drivers/media/platform/m2m-deinterlace.c 
b/drivers/media/platform/m2m-deinterlace.c
index 1e4195144f39..35a0f45d2a51 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -856,6 +856,7 @@ static const struct vb2_ops deinterlace_qops = {
.queue_setup = deinterlace_queue_setup,
.buf_prepare = deinterlace_buf_prepare,
.buf_queue   = deinterlace_buf_queue,
+   .is_unordered= vb2_ops_set_unordered,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq,
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 226f90886484..34a4b5b2e1b5 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -764,6 +764,7 @@ static const struct vb2_ops mtk_jpeg_qops = {
.wait_finish= vb2_ops_wait_finish,
.start_streaming= mtk_jpeg_start_streaming,
.stop_streaming = mtk_jpeg_stop_streaming,
+   .is_unordered   = vb2_ops_set_unordered,
 };
 
 static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
index 583d47724ee8..f3bb9f277f55 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -629,6 +629,7 @@ static const struct vb2_ops mtk_mdp_m2m_qops = {
.wait_finish = mtk_mdp_ctx_lock,
.stop_streaming  = mtk_mdp_m2m_stop_streaming,
.start_streaming = mtk_mdp_m2m_start_streaming,
+   .is_unordered= 

[PATCH v8 05/13] [media] v4l: add 'unordered' flag to format description ioctl

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

For explicit synchronization it important for userspace to know if the
format being used by the driver can deliver the buffers back to userspace
in the same order they were queued with QBUF.

Ordered streams fits nicely in a pipeline with DRM for example, where
ordered buffer are expected.

v2  - Improve documentation (Hans)

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/vidioc-enum-fmt.rst | 7 +++
 include/uapi/linux/videodev2.h   | 1 +
 2 files changed, 8 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst 
b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
index 019c513df217..df8e039b9ac2 100644
--- a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
+++ b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
@@ -116,6 +116,13 @@ one until ``EINVAL`` is returned.
   - This format is not native to the device but emulated through
software (usually libv4l2), where possible try to use a native
format instead for better performance.
+* - ``V4L2_FMT_FLAG_UNORDERED``
+  - 0x0004
+  - This format doesn't guarantee ordered buffer handling. I.e. the order
+   in which buffers are dequeued with
+   :ref:`VIDIOC_DQBUF ` may be different
+   from the order in which they were queued with
+   :ref:`VIDIOC_QBUF `.
 
 
 Return Value
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 982718965180..58894cfe9479 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -716,6 +716,7 @@ struct v4l2_fmtdesc {
 
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 #define V4L2_FMT_FLAG_EMULATED   0x0002
+#define V4L2_FMT_FLAG_UNORDERED  0x0004
 
/* Frame Size and frame rate enumeration */
 /*
-- 
2.14.3



[PATCH v8 08/13] [media] vb2: add explicit fence user API

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Turn the reserved2 field into fence_fd that we will use to send
an in-fence to the kernel or return an out-fence from the kernel to
userspace.

Two new flags were added, V4L2_BUF_FLAG_IN_FENCE, that should be used
when sending a fence to the kernel to be waited on, and
V4L2_BUF_FLAG_OUT_FENCE, to ask the kernel to give back an out-fence.

v6: - big improvement on doc (Hans Verkuil)

v5:
- keep using reserved2 field for cpia2
- set fence_fd to 0 for now, for compat with userspace(Mauro)

v4:
- make it a union with reserved2 and fence_fd (Hans Verkuil)

v3:
- make the out_fence refer to the current buffer (Hans Verkuil)

v2: add documentation

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/buffer.rst | 45 +++--
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  4 +--
 include/uapi/linux/videodev2.h  |  7 +++-
 4 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/Documentation/media/uapi/v4l/buffer.rst 
b/Documentation/media/uapi/v4l/buffer.rst
index e2c85ddc990b..49273026740f 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -301,10 +301,22 @@ struct v4l2_buffer
elements in the ``planes`` array. The driver will fill in the
actual number of valid elements in that array.
 * - __u32
-  - ``reserved2``
+  - ``fence_fd``
   -
-  - A place holder for future extensions. Drivers and applications
-   must set this to 0.
+  - Used to communicate fences file descriptors from userspace to kernel
+   and vice-versa. On :ref:`VIDIOC_QBUF ` when sending
+   an in-fence for V4L2 to wait on, the ``V4L2_BUF_FLAG_IN_FENCE`` flag 
must
+   be used and this field set to the fence file descriptor of the in-fence
+   If the in-fence is not valid ` VIDIOC_QBUF`` returns an error.
+
+To get an out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE``
+   must be set, the kernel will return the out-fence file descriptor on
+   this field. If it fails to create the out-fence ``VIDIOC_QBUF` returns
+an error.
+
+   In all other ioctls V4L2 sets this field to -1 if
+   ``V4L2_BUF_FLAG_IN_FENCE`` and/or ``V4L2_BUF_FLAG_OUT_FENCE`` are set,
+   otherwise this field is set to 0 for backward compatibility.
 * - __u32
   - ``reserved``
   -
@@ -648,6 +660,33 @@ Buffer Flags
   - Start Of Exposure. The buffer timestamp has been taken when the
exposure of the frame has begun. This is only valid for the
``V4L2_BUF_TYPE_VIDEO_CAPTURE`` buffer type.
+* .. _`V4L2-BUF-FLAG-IN-FENCE`:
+
+  - ``V4L2_BUF_FLAG_IN_FENCE``
+  - 0x0020
+  - Ask V4L2 to wait on the fence passed in the ``fence_fd`` field. The
+   buffer won't be queued to the driver until the fence signals. The order
+   in which buffers are queued is guaranteed to be preserved, so any
+   buffers queued after this buffer will also be blocked until this fence
+   signals. This flag must be set before calling ``VIDIOC_QBUF``. For
+   other ioctls the driver just report the value of the flag.
+
+If the fence signals the flag is cleared and not reported anymore.
+   If the fence is not valid ``VIDIOC_QBUF`` returns an error.
+
+
+* .. _`V4L2-BUF-FLAG-OUT-FENCE`:
+
+  - ``V4L2_BUF_FLAG_OUT_FENCE``
+  - 0x0040
+  - Request for a fence to be attached to the buffer. The driver will fill
+   in the out-fence fd in the ``fence_fd`` field when :ref:`VIDIOC_QBUF
+   ` returns. This flag must be set before calling
+   ``VIDIOC_QBUF``. For other ioctls the driver just report the value of
+   the flag.
+
+If the creation of the  out-fence  fails ``VIDIOC_QBUF`` returns an
+   error.
 
 
 
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 68291ba8632d..ad1e032c3bf5 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -203,7 +203,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
-   b->reserved2 = 0;
+   b->fence_fd = 0;
b->reserved = 0;
 
if (q->is_multiplanar) {
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 5198c9eeb348..3de2252e3632 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -386,7 +386,7 @@ struct v4l2_buffer32 {
__s32   fd;
} m;
__u32   length;
-   __u32   reserved2;

[PATCH v8 11/13] [media] v4l: introduce the fences capability

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Drivers capable of using fences (vb2 drivers) should report the
V4L2_CAP_FENCES to userspace, so add this flag to the uapi.

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/vidioc-querycap.rst | 3 +++
 include/uapi/linux/videodev2.h   | 1 +
 2 files changed, 4 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst 
b/Documentation/media/uapi/v4l/vidioc-querycap.rst
index 66fb1b3d6e6e..414016065309 100644
--- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
+++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
@@ -254,6 +254,9 @@ specification the ioctl returns an ``EINVAL`` error code.
 * - ``V4L2_CAP_TOUCH``
   - 0x1000
   - This is a touch device.
+* - ``V4L2_CAP_FENCES``
+  - 0x2000
+  - The device support explicit synchronization.
 * - ``V4L2_CAP_DEVICE_CAPS``
   - 0x8000
   - The driver fills the ``device_caps`` field. This capability can
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 2d424aebdd1e..db58204e346e 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -460,6 +460,7 @@ struct v4l2_capability {
 #define V4L2_CAP_STREAMING  0x0400  /* streaming I/O ioctls */
 
 #define V4L2_CAP_TOUCH  0x1000  /* Is a touch device */
+#define V4L2_CAP_FENCES 0x2000  /* Supports explicit 
synchronization */
 
 #define V4L2_CAP_DEVICE_CAPS0x8000  /* sets device 
capabilities field */
 
-- 
2.14.3



[PATCH v8 09/13] [media] vb2: add in-fence support to QBUF

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Receive in-fence from userspace and add support for waiting on them
before queueing the buffer to the driver. Buffers can't be queued to the
driver before its fences signal. And a buffer can't be queue to the driver
out of the order they were queued from userspace. That means that even if
it fence signal it must wait all other buffers, ahead of it in the queue,
to signal first.

If the fence for some buffer fails we do not queue it to the driver,
instead we mark it as error and wait until the previous buffer is done
to notify userspace of the error. We wait here to deliver the buffers back
to userspace in order.

v9: - rename fence to in_fence in many places
- handle fences signalling with error better (Hans Verkuil)

v8: - improve comments and docs (Hans Verkuil)
- fix unlocking of vb->fence_cb_lock on vb2_core_qbuf (Hans Verkuil)
- move in-fences code that was in the out-fences patch here (Alex)

v8: - improve comments about fences with errors

v7:
- get rid of the fence array stuff for ordering and just use
get_num_buffers_ready() (Hans)
- fix issue of queuing the buffer twice (Hans)
- avoid the dma_fence_wait() in core_qbuf() (Alex)
- merge preparation commit in

v6:
- With fences always keep the order userspace queues the buffers.
- Protect in_fence manipulation with a lock (Brian Starkey)
- check if fences have the same context before adding a fence array
- Fix last_fence ref unbalance in __set_in_fence() (Brian Starkey)
- Clean up fence if __set_in_fence() fails (Brian Starkey)
- treat -EINVAL from dma_fence_add_callback() (Brian Starkey)

v5: - use fence_array to keep buffers ordered in vb2 core when
needed (Brian Starkey)
- keep backward compat on the reserved2 field (Brian Starkey)
- protect fence callback removal with lock (Brian Starkey)

v4:
- Add a comment about dma_fence_add_callback() not returning a
error (Hans)
- Call dma_fence_put(vb->in_fence) if fence signaled (Hans)
- select SYNC_FILE under config VIDEOBUF2_CORE (Hans)
- Move dma_fence_is_signaled() check to __enqueue_in_driver() (Hans)
- Remove list_for_each_entry() in __vb2_core_qbuf() (Hans)
-  Remove if (vb->state != VB2_BUF_STATE_QUEUED) from
vb2_start_streaming() (Hans)
- set IN_FENCE flags on __fill_v4l2_buffer (Hans)
- Queue buffers to the driver as soon as they are ready (Hans)
- call fill_user_buffer() after queuing the buffer (Hans)
- add err: label to clean up fence
- add dma_fence_wait() before calling vb2_start_streaming()

v3: - document fence parameter
- remove ternary if at vb2_qbuf() return (Mauro)
- do not change if conditions behaviour (Mauro)

v2:
- fix vb2_queue_or_prepare_buf() ret check
- remove check for VB2_MEMORY_DMABUF only (Javier)
- check num of ready buffers to start streaming
- when queueing, start from the first ready buffer
- handle queue cancel

Signed-off-by: Gustavo Padovan 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 197 
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  34 +++-
 drivers/media/v4l2-core/Kconfig |  33 
 include/media/videobuf2-core.h  |  14 +-
 4 files changed, 248 insertions(+), 30 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index d3f7bb33a54d..5de5e35cfc40 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -352,6 +352,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->index = q->num_buffers + buffer;
vb->type = q->type;
vb->memory = memory;
+   spin_lock_init(>fence_cb_lock);
for (plane = 0; plane < num_planes; ++plane) {
vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane];
@@ -891,20 +892,12 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned 
int plane_no)
 }
 EXPORT_SYMBOL_GPL(vb2_plane_cookie);
 
-void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
+static void vb2_process_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
 {
struct vb2_queue *q = vb->vb2_queue;
unsigned long flags;
unsigned int plane;
 
-   if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
-   return;
-
-   if (WARN_ON(state != VB2_BUF_STATE_DONE &&
-   state != VB2_BUF_STATE_ERROR &&
-   state != VB2_BUF_STATE_QUEUED &&
-   state != VB2_BUF_STATE_REQUEUEING))
-

[PATCH v8 12/13] [media] v4l: Add V4L2_CAP_FENCES to drivers

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Drivers that use videobuf2 are capable of using fences and
should report that to userspace.

The coding style is following what each drivers was already
doing.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/pci/cobalt/cobalt-v4l2.c | 3 ++-
 drivers/media/pci/cx23885/cx23885-417.c| 2 +-
 drivers/media/pci/cx23885/cx23885-video.c  | 3 ++-
 drivers/media/pci/cx88/cx88-video.c| 3 ++-
 drivers/media/pci/dt3155/dt3155.c  | 2 +-
 drivers/media/pci/saa7134/saa7134-video.c  | 2 ++
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c | 3 ++-
 drivers/media/pci/solo6x10/solo6x10-v4l2.c | 3 ++-
 drivers/media/pci/sta2x11/sta2x11_vip.c| 2 +-
 drivers/media/pci/tw68/tw68-video.c| 3 ++-
 drivers/media/pci/tw686x/tw686x-video.c| 2 +-
 drivers/media/platform/am437x/am437x-vpfe.c| 2 +-
 drivers/media/platform/blackfin/bfin_capture.c | 3 ++-
 drivers/media/platform/coda/coda-common.c  | 3 ++-
 drivers/media/platform/davinci/vpbe_display.c  | 3 ++-
 drivers/media/platform/davinci/vpfe_capture.c  | 3 ++-
 drivers/media/platform/davinci/vpif_capture.c  | 3 ++-
 drivers/media/platform/davinci/vpif_display.c  | 3 ++-
 drivers/media/platform/exynos-gsc/gsc-m2m.c| 3 ++-
 drivers/media/platform/exynos4-is/fimc-capture.c   | 3 ++-
 drivers/media/platform/exynos4-is/fimc-isp-video.c | 3 ++-
 drivers/media/platform/exynos4-is/fimc-lite.c  | 2 +-
 drivers/media/platform/exynos4-is/fimc-m2m.c   | 3 ++-
 drivers/media/platform/m2m-deinterlace.c   | 3 ++-
 drivers/media/platform/marvell-ccic/mcam-core.c| 2 +-
 drivers/media/platform/mx2_emmaprp.c   | 3 ++-
 drivers/media/platform/omap3isp/ispvideo.c | 2 +-
 drivers/media/platform/pxa_camera.c| 3 ++-
 drivers/media/platform/rcar_jpu.c  | 3 ++-
 drivers/media/platform/s3c-camif/camif-capture.c   | 3 ++-
 drivers/media/platform/s5p-g2d/g2d.c   | 3 ++-
 drivers/media/platform/s5p-jpeg/jpeg-core.c| 3 ++-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   | 3 ++-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   | 3 ++-
 drivers/media/platform/sh_veu.c| 3 ++-
 drivers/media/platform/sh_vou.c| 2 +-
 drivers/media/platform/sti/bdisp/bdisp-v4l2.c  | 3 ++-
 drivers/media/platform/ti-vpe/cal.c| 2 +-
 drivers/media/platform/ti-vpe/vpe.c| 3 ++-
 drivers/media/platform/vim2m.c | 3 ++-
 drivers/media/platform/vivid/vivid-core.c  | 2 +-
 drivers/media/platform/vsp1/vsp1_histo.c   | 2 +-
 drivers/media/platform/vsp1/vsp1_video.c   | 2 +-
 drivers/media/platform/xilinx/xilinx-dma.c | 2 +-
 drivers/media/usb/airspy/airspy.c  | 2 +-
 drivers/media/usb/au0828/au0828-video.c| 3 ++-
 drivers/media/usb/em28xx/em28xx-video.c| 1 +
 drivers/media/usb/go7007/go7007-v4l2.c | 2 +-
 drivers/media/usb/hackrf/hackrf.c  | 3 ++-
 drivers/media/usb/msi2500/msi2500.c| 2 +-
 drivers/media/usb/pwc/pwc-v4l.c| 2 +-
 drivers/media/usb/s2255/s2255drv.c | 2 +-
 drivers/media/usb/stk1160/stk1160-v4l.c| 3 ++-
 drivers/media/usb/usbtv/usbtv-video.c  | 3 ++-
 drivers/media/usb/uvc/uvc_driver.c | 1 +
 55 files changed, 89 insertions(+), 52 deletions(-)

diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c 
b/drivers/media/pci/cobalt/cobalt-v4l2.c
index 6b6611a0e190..ef1014b5d4a7 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -484,7 +484,8 @@ static int cobalt_querycap(struct file *file, void *priv_fh,
strlcpy(vcap->card, "cobalt", sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
 "PCIe:%s", pci_name(cobalt->pci_dev));
-   vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+   vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
+   V4L2_CAP_FENCES;
if (s->is_output)
vcap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
else
diff --git a/drivers/media/pci/cx23885/cx23885-417.c 
b/drivers/media/pci/cx23885/cx23885-417.c
index a71f3c7569ce..56bf7ec4e25f 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1334,7 +1334,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-  V4L2_CAP_STREAMING;
+  V4L2_CAP_STREAMING | V4L2_CAP_FENCES;
if (dev->tuner_type != TUNER_ABSENT)

[PATCH v8 10/13] [media] vb2: add out-fence support to QBUF

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

If V4L2_BUF_FLAG_OUT_FENCE flag is present on the QBUF call we create
an out_fence and send its fd to userspace on the fence_fd field as a
return arg for the QBUF call.

The fence is signaled on buffer_done(), when the job on the buffer is
finished.

v9: - remove in-fences changes from this patch (Alex Courbot)
- improve fence context creation (Hans Verkuil)
- clean up out fences if vb2_core_qbuf() fails (Hans Verkuil)

v8:
- return 0 as fence_fd if OUT_FENCE flag not used (Mauro)
- fix crash when checking not using fences in vb2_buffer_done()

v7:
- merge patch that add the infrastructure to out-fences into
this one (Alex Courbot)
- Do not install the fd if there is no fence. (Alex Courbot)
- do not report error on requeueing, just WARN_ON_ONCE() (Hans)

v6
- get rid of the V4L2_EVENT_OUT_FENCE event. We always keep the
ordering in vb2 for queueing in the driver, so the event is not
necessary anymore and the out_fence_fd is sent back to userspace
on QBUF call return arg
- do not allow requeueing with out-fences, instead mark the buffer
with an error and wake up to userspace.
- send the out_fence_fd back to userspace on the fence_fd field

v5:
- delay fd_install to DQ_EVENT (Hans)
- if queue is fully ordered send OUT_FENCE event right away
(Brian)
- rename 'q->ordered' to 'q->ordered_in_driver'
- merge change to implement OUT_FENCE event here

v4:
- return the out_fence_fd in the BUF_QUEUED event(Hans)

v3: - add WARN_ON_ONCE(q->ordered) on requeueing (Hans)
- set the OUT_FENCE flag if there is a fence pending (Hans)
- call fd_install() after vb2_core_qbuf() (Hans)
- clean up fence if vb2_core_qbuf() fails (Hans)
- add list to store sync_file and fence for the next queued buffer

v2: check if the queue is ordered.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 88 +
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 20 +-
 include/media/videobuf2-core.h  | 25 +++
 3 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 5de5e35cfc40..dd18a9f345c7 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -357,6 +358,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane];
}
+   vb->out_fence_fd = -1;
q->bufs[vb->index] = vb;
 
/* Allocate video buffer memory for the MMAP type */
@@ -934,10 +936,22 @@ static void vb2_process_buffer_done(struct vb2_buffer 
*vb, enum vb2_buffer_state
case VB2_BUF_STATE_QUEUED:
return;
case VB2_BUF_STATE_REQUEUEING:
+   /* Requeuing with explicit synchronization, spit warning */
+   WARN_ON_ONCE(vb->out_fence);
+
if (q->start_streaming_called)
__enqueue_in_driver(vb);
return;
default:
+   if (vb->out_fence) {
+   if (state == VB2_BUF_STATE_ERROR)
+   dma_fence_set_error(vb->out_fence, -EFAULT);
+   dma_fence_signal(vb->out_fence);
+   dma_fence_put(vb->out_fence);
+   vb->out_fence = NULL;
+   vb->out_fence_fd = -1;
+   }
+
/* Inform any processes that may be waiting for buffers */
wake_up(>done_wq);
break;
@@ -1353,6 +1367,62 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+static inline const char *vb2_fence_get_driver_name(struct dma_fence *fence)
+{
+   return "vb2_fence";
+}
+
+static inline const char *vb2_fence_get_timeline_name(struct dma_fence *fence)
+{
+   return "vb2_fence_timeline";
+}
+
+static inline bool vb2_fence_enable_signaling(struct dma_fence *fence)
+{
+   return true;
+}
+
+static const struct dma_fence_ops vb2_fence_ops = {
+   .get_driver_name = vb2_fence_get_driver_name,
+   .get_timeline_name = vb2_fence_get_timeline_name,
+   .enable_signaling = vb2_fence_enable_signaling,
+   .wait = dma_fence_default_wait,
+};
+
+int vb2_setup_out_fence(struct vb2_queue *q, unsigned int index)
+{
+   struct vb2_buffer *vb;
+
+   vb = q->bufs[index];
+
+   vb->out_fence_fd = 

[PATCH v8 13/13] [media] v4l: Document explicit synchronization behavior

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

Add section to VIDIOC_QBUF and VIDIOC_QUERY_BUF about it

v6: - Close some gaps in the docs (Hans)

v5:
- Remove V4L2_CAP_ORDERED
- Add doc about V4L2_FMT_FLAG_UNORDERED

v4:
- Document ordering behavior for in-fences
- Document V4L2_CAP_ORDERED capability
- Remove doc about OUT_FENCE event
- Document immediate return of out-fence in QBUF

v3:
- make the out_fence refer to the current buffer (Hans)
- Note what happens when the IN_FENCE is not set (Hans)

v2:
- mention that fences are files (Hans)
- rework for the new API

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/vidioc-qbuf.rst | 55 +++-
 Documentation/media/uapi/v4l/vidioc-querybuf.rst | 12 --
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
index 9e448a4aa3aa..371d84966e34 100644
--- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
+++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
@@ -54,7 +54,7 @@ When the buffer is intended for output (``type`` is
 or ``V4L2_BUF_TYPE_VBI_OUTPUT``) applications must also initialize the
 ``bytesused``, ``field`` and ``timestamp`` fields, see :ref:`buffer`
 for details. Applications must also set ``flags`` to 0. The
-``reserved2`` and ``reserved`` fields must be set to 0. When using the
+``reserved`` field must be set to 0. When using the
 :ref:`multi-planar API `, the ``m.planes`` field must
 contain a userspace pointer to a filled-in array of struct
 :c:type:`v4l2_plane` and the ``length`` field must be set
@@ -118,6 +118,59 @@ immediately with an ``EAGAIN`` error code when no buffer 
is available.
 The struct :c:type:`v4l2_buffer` structure is specified in
 :ref:`buffer`.
 
+Explicit Synchronization
+
+
+Explicit Synchronization allows us to control the synchronization of
+shared buffers from userspace by passing fences to the kernel and/or
+receiving them from it. Fences passed to the kernel are named in-fences and
+the kernel should wait on them to signal before using the buffer. On the other
+side, the kernel can create out-fences for the buffers it queues to the
+drivers. Out-fences signal when the driver is finished with buffer, i.e., the
+buffer is ready. The fences are represented as a file and passed as a file
+descriptor to userspace.
+
+The in-fences are communicated to the kernel at the ``VIDIOC_QBUF`` ioctl
+using the ``V4L2_BUF_FLAG_IN_FENCE`` buffer flag and the `fence_fd` field. If
+an in-fence needs to be passed to the kernel, `fence_fd` should be set to the
+fence file descriptor number and the ``V4L2_BUF_FLAG_IN_FENCE`` should be set
+as well. Setting one but not the other will cause ``VIDIOC_QBUF`` to return
+with an error. The fence_fd field will be ignored if the
+``V4L2_BUF_FLAG_IN_FENCE`` is not set.
+
+The videobuf2-core will guarantee that all buffers queued with an in-fence will
+be queued to the drivers in the same order. Fences may signal out of order, so
+this guarantee at videobuf2 is necessary to not change ordering. So when
+waiting on a fence to signal all buffers queued after will be also block until
+that fence signal.
+
+If the in-fence signals with an error the buffer will be marked with
+``V4L2_BUF_FLAG_ERROR`` when returned to userspace at ``VIDIOC_DQBUF``.
+Even with the error the order of dequeueing the buffers are preserved.
+
+To get an out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
+be set to ask for a fence to be attached to the buffer. The out-fence fd is
+sent to userspace as a ``VIDIOC_QBUF`` return argument on the `fence_fd` field.
+
+Note the the same `fence_fd` field is used for both sending the in-fence as
+input argument to receive the out-fence as a return argument. A buffer can
+have both in-fence ond out-fence.
+
+At streamoff the out-fences will either signal normally if the driver waits
+for the operations on the buffers to finish or signal with an error if the
+driver cancels the pending operations. Buffers with in-fences won't be queued
+to the driver if their fences signal. They will be cleaned up.
+
+The ``V4L2_FMT_FLAG_UNORDERED`` flag in ``VIDIOC_ENUM_FMT`` tells userspace
+that the  when using this format the order in which buffers are dequeued can
+be different from the order in which they were queued.
+
+Ordering is important to fences because it can optimize the pipeline with
+other drivers like a DRM/KMS display driver. For example, if a capture from the
+camera is happening in an orderly manner one can send the capture buffer
+out-fence to the DRM/KMS driver and rest sure that the buffers will be shown on
+the screen at the correct order. If an ordered queue can not be set then such
+arrangements with other drivers may not be possible.
 
 Return Value
 
diff --git 

[PATCH v8 06/13] [media] cobalt: add .is_unordered() for cobalt

2018-03-09 Thread Gustavo Padovan
From: Gustavo Padovan 

The cobalt driver may reorder the capture buffers so we need to report
it as such.

v2: - use vb2_ops_set_unordered() helper

Signed-off-by: Gustavo Padovan 
---
 drivers/media/pci/cobalt/cobalt-v4l2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c 
b/drivers/media/pci/cobalt/cobalt-v4l2.c
index e2a4c705d353..6b6611a0e190 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -430,6 +430,7 @@ static const struct vb2_ops cobalt_qops = {
.stop_streaming = cobalt_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+   .is_unordered = vb2_ops_set_unordered,
 };
 
 /* V4L2 ioctls */
-- 
2.14.3



Re: [PATCH 00/13] media: imx: Switch to subdev notifiers

2018-03-09 Thread Steve Longerbeam

Hi Hans,


On 03/09/2018 04:57 AM, Hans Verkuil wrote:

Hi Steve,

I understand there will be a v2 of this series?


Yes. I'm mulling what to do about the empty endpoints issue.
My initial thought was to modify the i.mx6 DTS to remove the
empty endpoints in the video-mux input ports, which would also
require a change to the video-mux driver. But that would also
introduce a kernel incompatibility with previously built / existing
DTBs.

But it sounds like there is agreement between Laurent, Philipp, and
Sakari that it would be acceptable for media/v4l2 core to ignore empty
endpoints, as long as that is done consistently throughout, and that
the binding docs are updated to be more explicitly clear that the
remote-endpoint property is optional (but recommended).
Is that correct?

I prefer this approach, since it doesn't introduce an incompatibility
with existing DTBs.

So I am leaning towards modifying only the first patch in this
series ("media: v4l2-fwnode: Let parse_endpoint callback decide
if no remote is error"), to simply ignore empty endpoints in
v4l2_async_notifier_fwnode_parse_endpoint() and return success.



  If so, then I can mark this
series as 'Changes Requested' in patchwork.


Yep, that's fine.

Steve






On 22/02/18 02:39, Steve Longerbeam wrote:

This patchset converts the imx-media driver and its dependent
subdevs to use subdev notifiers.

There are a couple shortcomings in v4l2-core that prevented
subdev notifiers from working correctly in imx-media:

1. v4l2_async_notifier_fwnode_parse_endpoint() treats a fwnode
endpoint that is not connected to a remote device as an error.
But in the case of the video-mux subdev, this is not an error, it's
ok if some of the muxes inputs have no connection. So the first
patch is a small modification to allow the parse_endpoint callback
to decide whether an unconnected endpoint is an error.

2. In the imx-media graph, multiple subdevs will encounter the same
upstream subdev (such as the imx6-mipi-csi2 receiver), and so
v4l2_async_notifier_parse_fwnode_endpoints() will add imx6-mipi-csi2
multiple times. This is treated as an error by
v4l2_async_notifier_register() later.

To get around this problem, add an v4l2_async_notifier_add_subdev()
which first verifies the provided asd does not already exist in the
given notifier asd list or in other registered notifiers. If the asd
exists, the function returns -EEXIST and it's up to the caller to
decide if that is an error (in imx-media case it is never an error).

Patches 2-4 deal with adding that support.

3. Patch 5 adds v4l2_async_register_fwnode_subdev(), which is a
convenience function for parsing a subdev's fwnode port endpoints
for connected remote subdevs, registering a subdev notifier, and
then registering the sub-device itself.

The remaining patches update the subdev drivers to register a
subdev notifier with endpoint parsing, and the changes to imx-media
to support that.

Signed-off-by: Steve Longerbeam 
Acked-by: Philipp Zabel 


Steve Longerbeam (13):
   media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is
 error
   media: v4l2: async: Allow searching for asd of any type
   media: v4l2: async: Add v4l2_async_notifier_add_subdev
   media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
   media: v4l2-fwnode: Add a convenience function for registering subdevs
 with notifiers
   media: platform: video-mux: Register a subdev notifier
   media: imx: csi: Register a subdev notifier
   media: imx: mipi csi-2: Register a subdev notifier
   media: staging/imx: of: Remove recursive graph walk
   media: staging/imx: Loop through all registered subdevs for media
 links
   media: staging/imx: Rename root notifier
   media: staging/imx: Switch to v4l2_async_notifier_add_subdev
   media: staging/imx: TODO: Remove one assumption about OF graph parsing

  drivers/media/pci/intel/ipu3/ipu3-cio2.c  |  13 +-
  drivers/media/platform/omap3isp/isp.c |   3 +
  drivers/media/platform/rcar-vin/rcar-core.c   |   3 +
  drivers/media/platform/video-mux.c|  35 ++-
  drivers/media/v4l2-core/v4l2-async.c  | 275 --
  drivers/media/v4l2-core/v4l2-fwnode.c | 230 ++
  drivers/staging/media/imx/TODO|  29 +--
  drivers/staging/media/imx/imx-media-csi.c |  11 +-
  drivers/staging/media/imx/imx-media-dev.c | 134 +++
  drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
  drivers/staging/media/imx/imx-media-of.c  | 106 +
  drivers/staging/media/imx/imx-media.h |   6 +-
  drivers/staging/media/imx/imx6-mipi-csi2.c|  31 ++-
  include/media/v4l2-async.h|  24 +-
  include/media/v4l2-fwnode.h   |  64 -
  15 files changed, 546 insertions(+), 423 

Re: [PATCH v12 11/33] rcar-vin: set a default field to fallback on

2018-03-09 Thread Hans Verkuil
On 09/03/18 18:07, Niklas Söderlund wrote:
> Hi Hans,
> 
> Thanks for your feedback.
> 
> On 2018-03-09 17:28:39 +0100, Hans Verkuil wrote:
>> On 09/03/18 17:17, Niklas Söderlund wrote:
>>> Hi Hans,
>>>
>>> Thanks for your feedback, I don't think I can appreciate how happy I'm 
>>> that you reviewed this patch-set, Thank you!
>>
>> You're welcome!
>>
>>>
>>> On 2018-03-09 16:25:23 +0100, Hans Verkuil wrote:
 On 07/03/18 23:04, Niklas Söderlund wrote:
> If the field is not supported by the driver it should not try to keep
> the current field. Instead it should set it to a default fallback. Since
> trying a format should always result in the same state regardless of the
> current state of the device.
>
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 +++--
>  1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index c2265324c7c96308..ebcd78b1bb6e8cb6 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -23,6 +23,7 @@
>  #include "rcar-vin.h"
>  
>  #define RVIN_DEFAULT_FORMAT  V4L2_PIX_FMT_YUYV
> +#define RVIN_DEFAULT_FIELD   V4L2_FIELD_NONE
>  
>  /* 
> -
>   * Format Conversions
> @@ -143,7 +144,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
>   case V4L2_FIELD_INTERLACED:
>   break;
>   default:
> - vin->format.field = V4L2_FIELD_NONE;
> + vin->format.field = RVIN_DEFAULT_FIELD;
>   break;
>   }
>  
> @@ -213,10 +214,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   u32 walign;
>   int ret;
>  
> - /* Keep current field if no specific one is asked for */
> - if (pix->field == V4L2_FIELD_ANY)
> - pix->field = vin->format.field;
> -
>   /* If requested format is not supported fallback to the default */
>   if (!rvin_format_from_pixel(pix->pixelformat)) {
>   vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> @@ -246,7 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   case V4L2_FIELD_INTERLACED:
>   break;
>   default:
> - pix->field = V4L2_FIELD_NONE;
> + pix->field = RVIN_DEFAULT_FIELD;
>   break;
>   }
>  
>

 I wonder if this code is correct. What if the adv7180 is the source? Does 
 that even
 support FIELD_NONE? I suspect that the default field should actually 
 depend on the
 source. FIELD_NONE for dv_timings based or sensor based subdevs and 
 FIELD_INTERLACED
 for SDTV (g/s_std) subdevs.
>>>
>>> I see what you mean but I think this is correct. The field is only set 
>>> to V4L2_FIELD_NONE if the field returned from the source is not one of 
>>> TOP, BOTTOM, ALTERNATE, NONE, INERLACED, INTERLACED_TB, INTERLACED_BT.  
>>> So it works perfectly with the adv7180 as it will return 
>>> V4L2_FIELD_INTERLACED and then VIN will accept that and not change it.  
>>> So the field do depend on the source both before and after this change.
>>
>> Is it? If I pass FIELD_ANY to VIDIOC_TRY_FMT then that is passed to the
>> adv7180 via __rvin_try_format and __rvin_try_format_source. But
>> __rvin_try_format_source puts back the old field value after calling
>> set_fmt for the adv7180 (pix->field = field).
>>
>> So pix->field is still FIELD_ANY when it enters the switch and so falls
>> into the default case and it becomes FIELD_NONE.
>>
>> What's weird is the 'pix->field = field' in __rvin_try_format_source().
>> Could that be a bug? Without that line what you say here would be correct.
> 
> Ahh yes, you are correct. I did not see this as I handle this in a later 
> patch in the series '[PATCH v12 16/33] rcar-vin: simplify how formats 
> are set and reset':
> 
> +   if (field != V4L2_FIELD_ANY)
> +   pix->field = field;
>  
> -   pix->field = field;
> 
> If I move this change to this patch do you think that would address your 
> concern?

Yes, that would make a lot more sense.

After making that change you can add my:

Reviewed-by: Hans Verkuil 

to this patch.

Regards,

Hans

 The intent is that if V4L2_FIELD_ANY is requested by the user
> it should get what the source provides but I still like to allow for the 
> user to request a specific field format. For example in follow up 
> patches to this series I add SEQ_TB/BT and the user might want to 
> request to receive frames in that format.
> 
>>
>> Regards,
>>
>>  Hans
>>
>>>
>>> This check is just to block the driver reporting 

Re: [PATCH v12 11/33] rcar-vin: set a default field to fallback on

2018-03-09 Thread Niklas Söderlund
Hi Hans,

Thanks for your feedback.

On 2018-03-09 17:28:39 +0100, Hans Verkuil wrote:
> On 09/03/18 17:17, Niklas Söderlund wrote:
> > Hi Hans,
> > 
> > Thanks for your feedback, I don't think I can appreciate how happy I'm 
> > that you reviewed this patch-set, Thank you!
> 
> You're welcome!
> 
> > 
> > On 2018-03-09 16:25:23 +0100, Hans Verkuil wrote:
> >> On 07/03/18 23:04, Niklas Söderlund wrote:
> >>> If the field is not supported by the driver it should not try to keep
> >>> the current field. Instead it should set it to a default fallback. Since
> >>> trying a format should always result in the same state regardless of the
> >>> current state of the device.
> >>>
> >>> Signed-off-by: Niklas Söderlund 
> >>> Reviewed-by: Laurent Pinchart 
> >>> ---
> >>>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 +++--
> >>>  1 file changed, 3 insertions(+), 6 deletions(-)
> >>>
> >>> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> >>> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>> index c2265324c7c96308..ebcd78b1bb6e8cb6 100644
> >>> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>> @@ -23,6 +23,7 @@
> >>>  #include "rcar-vin.h"
> >>>  
> >>>  #define RVIN_DEFAULT_FORMAT  V4L2_PIX_FMT_YUYV
> >>> +#define RVIN_DEFAULT_FIELD   V4L2_FIELD_NONE
> >>>  
> >>>  /* 
> >>> -
> >>>   * Format Conversions
> >>> @@ -143,7 +144,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
> >>>   case V4L2_FIELD_INTERLACED:
> >>>   break;
> >>>   default:
> >>> - vin->format.field = V4L2_FIELD_NONE;
> >>> + vin->format.field = RVIN_DEFAULT_FIELD;
> >>>   break;
> >>>   }
> >>>  
> >>> @@ -213,10 +214,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
> >>>   u32 walign;
> >>>   int ret;
> >>>  
> >>> - /* Keep current field if no specific one is asked for */
> >>> - if (pix->field == V4L2_FIELD_ANY)
> >>> - pix->field = vin->format.field;
> >>> -
> >>>   /* If requested format is not supported fallback to the default */
> >>>   if (!rvin_format_from_pixel(pix->pixelformat)) {
> >>>   vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> >>> @@ -246,7 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
> >>>   case V4L2_FIELD_INTERLACED:
> >>>   break;
> >>>   default:
> >>> - pix->field = V4L2_FIELD_NONE;
> >>> + pix->field = RVIN_DEFAULT_FIELD;
> >>>   break;
> >>>   }
> >>>  
> >>>
> >>
> >> I wonder if this code is correct. What if the adv7180 is the source? Does 
> >> that even
> >> support FIELD_NONE? I suspect that the default field should actually 
> >> depend on the
> >> source. FIELD_NONE for dv_timings based or sensor based subdevs and 
> >> FIELD_INTERLACED
> >> for SDTV (g/s_std) subdevs.
> > 
> > I see what you mean but I think this is correct. The field is only set 
> > to V4L2_FIELD_NONE if the field returned from the source is not one of 
> > TOP, BOTTOM, ALTERNATE, NONE, INERLACED, INTERLACED_TB, INTERLACED_BT.  
> > So it works perfectly with the adv7180 as it will return 
> > V4L2_FIELD_INTERLACED and then VIN will accept that and not change it.  
> > So the field do depend on the source both before and after this change.
> 
> Is it? If I pass FIELD_ANY to VIDIOC_TRY_FMT then that is passed to the
> adv7180 via __rvin_try_format and __rvin_try_format_source. But
> __rvin_try_format_source puts back the old field value after calling
> set_fmt for the adv7180 (pix->field = field).
> 
> So pix->field is still FIELD_ANY when it enters the switch and so falls
> into the default case and it becomes FIELD_NONE.
> 
> What's weird is the 'pix->field = field' in __rvin_try_format_source().
> Could that be a bug? Without that line what you say here would be correct.

Ahh yes, you are correct. I did not see this as I handle this in a later 
patch in the series '[PATCH v12 16/33] rcar-vin: simplify how formats 
are set and reset':

+   if (field != V4L2_FIELD_ANY)
+   pix->field = field;
 
-   pix->field = field;

If I move this change to this patch do you think that would address your 
concern? The intent is that if V4L2_FIELD_ANY is requested by the user 
it should get what the source provides but I still like to allow for the 
user to request a specific field format. For example in follow up 
patches to this series I add SEQ_TB/BT and the user might want to 
request to receive frames in that format.

> 
> Regards,
> 
>   Hans
> 
> > 
> > This check is just to block the driver reporting SEQ_TB/BT if a source 
> > where to report that (I known of no source who reports that) to 
> > userspace as the driver do not yet support this.  I have patches to add 
> > support for this but I will keep them back until this series are picked 
> > up :-)
> > 
> >>
> >> I 

[PATCH] V4L: remove myself as soc-camera maintainer

2018-03-09 Thread Guennadi Liakhovetski
The soc-camera framework is deprecated, patches for it are very rare
and only contain trivial clean up. Further I haven't got any more
soc-camera systems running modern kernels.

Signed-off-by: Guennadi Liakhovetski 
---
 MAINTAINERS | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 64cd083..80655f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12942,10 +12942,9 @@ S: Maintained
 F: drivers/net/ethernet/smsc/smsc9420.*
 
 SOC-CAMERA V4L2 SUBSYSTEM
-M: Guennadi Liakhovetski 
 L: linux-media@vger.kernel.org
 T: git git://linuxtv.org/media_tree.git
-S: Maintained
+S: Orphan
 F: include/media/soc*
 F: drivers/media/i2c/soc_camera/
 F: drivers/media/platform/soc_camera/
-- 
1.9.3



Re: [PATCH v12 11/33] rcar-vin: set a default field to fallback on

2018-03-09 Thread Hans Verkuil
On 09/03/18 17:17, Niklas Söderlund wrote:
> Hi Hans,
> 
> Thanks for your feedback, I don't think I can appreciate how happy I'm 
> that you reviewed this patch-set, Thank you!

You're welcome!

> 
> On 2018-03-09 16:25:23 +0100, Hans Verkuil wrote:
>> On 07/03/18 23:04, Niklas Söderlund wrote:
>>> If the field is not supported by the driver it should not try to keep
>>> the current field. Instead it should set it to a default fallback. Since
>>> trying a format should always result in the same state regardless of the
>>> current state of the device.
>>>
>>> Signed-off-by: Niklas Söderlund 
>>> Reviewed-by: Laurent Pinchart 
>>> ---
>>>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 +++--
>>>  1 file changed, 3 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
>>> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
>>> index c2265324c7c96308..ebcd78b1bb6e8cb6 100644
>>> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
>>> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
>>> @@ -23,6 +23,7 @@
>>>  #include "rcar-vin.h"
>>>  
>>>  #define RVIN_DEFAULT_FORMATV4L2_PIX_FMT_YUYV
>>> +#define RVIN_DEFAULT_FIELD V4L2_FIELD_NONE
>>>  
>>>  /* 
>>> -
>>>   * Format Conversions
>>> @@ -143,7 +144,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
>>> case V4L2_FIELD_INTERLACED:
>>> break;
>>> default:
>>> -   vin->format.field = V4L2_FIELD_NONE;
>>> +   vin->format.field = RVIN_DEFAULT_FIELD;
>>> break;
>>> }
>>>  
>>> @@ -213,10 +214,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>>> u32 walign;
>>> int ret;
>>>  
>>> -   /* Keep current field if no specific one is asked for */
>>> -   if (pix->field == V4L2_FIELD_ANY)
>>> -   pix->field = vin->format.field;
>>> -
>>> /* If requested format is not supported fallback to the default */
>>> if (!rvin_format_from_pixel(pix->pixelformat)) {
>>> vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
>>> @@ -246,7 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>>> case V4L2_FIELD_INTERLACED:
>>> break;
>>> default:
>>> -   pix->field = V4L2_FIELD_NONE;
>>> +   pix->field = RVIN_DEFAULT_FIELD;
>>> break;
>>> }
>>>  
>>>
>>
>> I wonder if this code is correct. What if the adv7180 is the source? Does 
>> that even
>> support FIELD_NONE? I suspect that the default field should actually depend 
>> on the
>> source. FIELD_NONE for dv_timings based or sensor based subdevs and 
>> FIELD_INTERLACED
>> for SDTV (g/s_std) subdevs.
> 
> I see what you mean but I think this is correct. The field is only set 
> to V4L2_FIELD_NONE if the field returned from the source is not one of 
> TOP, BOTTOM, ALTERNATE, NONE, INERLACED, INTERLACED_TB, INTERLACED_BT.  
> So it works perfectly with the adv7180 as it will return 
> V4L2_FIELD_INTERLACED and then VIN will accept that and not change it.  
> So the field do depend on the source both before and after this change.

Is it? If I pass FIELD_ANY to VIDIOC_TRY_FMT then that is passed to the
adv7180 via __rvin_try_format and __rvin_try_format_source. But
__rvin_try_format_source puts back the old field value after calling
set_fmt for the adv7180 (pix->field = field).

So pix->field is still FIELD_ANY when it enters the switch and so falls
into the default case and it becomes FIELD_NONE.

What's weird is the 'pix->field = field' in __rvin_try_format_source().
Could that be a bug? Without that line what you say here would be correct.

Regards,

Hans

> 
> This check is just to block the driver reporting SEQ_TB/BT if a source 
> where to report that (I known of no source who reports that) to 
> userspace as the driver do not yet support this.  I have patches to add 
> support for this but I will keep them back until this series are picked 
> up :-)
> 
>>
>> I might very well be missing something here but it looks suspicious.
>>
>> Regards,
>>
>>  Hans
> 



Re: [PATCH v12 11/33] rcar-vin: set a default field to fallback on

2018-03-09 Thread Niklas Söderlund
Hi Hans,

Thanks for your feedback, I don't think I can appreciate how happy I'm 
that you reviewed this patch-set, Thank you!

On 2018-03-09 16:25:23 +0100, Hans Verkuil wrote:
> On 07/03/18 23:04, Niklas Söderlund wrote:
> > If the field is not supported by the driver it should not try to keep
> > the current field. Instead it should set it to a default fallback. Since
> > trying a format should always result in the same state regardless of the
> > current state of the device.
> > 
> > Signed-off-by: Niklas Söderlund 
> > Reviewed-by: Laurent Pinchart 
> > ---
> >  drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 +++--
> >  1 file changed, 3 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> > b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > index c2265324c7c96308..ebcd78b1bb6e8cb6 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > @@ -23,6 +23,7 @@
> >  #include "rcar-vin.h"
> >  
> >  #define RVIN_DEFAULT_FORMATV4L2_PIX_FMT_YUYV
> > +#define RVIN_DEFAULT_FIELD V4L2_FIELD_NONE
> >  
> >  /* 
> > -
> >   * Format Conversions
> > @@ -143,7 +144,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
> > case V4L2_FIELD_INTERLACED:
> > break;
> > default:
> > -   vin->format.field = V4L2_FIELD_NONE;
> > +   vin->format.field = RVIN_DEFAULT_FIELD;
> > break;
> > }
> >  
> > @@ -213,10 +214,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
> > u32 walign;
> > int ret;
> >  
> > -   /* Keep current field if no specific one is asked for */
> > -   if (pix->field == V4L2_FIELD_ANY)
> > -   pix->field = vin->format.field;
> > -
> > /* If requested format is not supported fallback to the default */
> > if (!rvin_format_from_pixel(pix->pixelformat)) {
> > vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> > @@ -246,7 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
> > case V4L2_FIELD_INTERLACED:
> > break;
> > default:
> > -   pix->field = V4L2_FIELD_NONE;
> > +   pix->field = RVIN_DEFAULT_FIELD;
> > break;
> > }
> >  
> > 
> 
> I wonder if this code is correct. What if the adv7180 is the source? Does 
> that even
> support FIELD_NONE? I suspect that the default field should actually depend 
> on the
> source. FIELD_NONE for dv_timings based or sensor based subdevs and 
> FIELD_INTERLACED
> for SDTV (g/s_std) subdevs.

I see what you mean but I think this is correct. The field is only set 
to V4L2_FIELD_NONE if the field returned from the source is not one of 
TOP, BOTTOM, ALTERNATE, NONE, INERLACED, INTERLACED_TB, INTERLACED_BT.  
So it works perfectly with the adv7180 as it will return 
V4L2_FIELD_INTERLACED and then VIN will accept that and not change it.  
So the field do depend on the source both before and after this change.

This check is just to block the driver reporting SEQ_TB/BT if a source 
where to report that (I known of no source who reports that) to 
userspace as the driver do not yet support this.  I have patches to add 
support for this but I will keep them back until this series are picked 
up :-)

> 
> I might very well be missing something here but it looks suspicious.
> 
> Regards,
> 
>   Hans

-- 
Regards,
Niklas Söderlund


[PATCH v2] media: lgdt330x: add block error counts via DVBv5

2018-03-09 Thread Mauro Carvalho Chehab
Show the UCB error counts via DVBv5.

Please notice that there's no scale indication at the driver.
As we don't have the datasheet, let's assume that it is receiving
data at a rate of 10.000 packets per second. Ideally, this should
be read or estimated.

In order to avoid flooding I2C bus with data, the maximum
polling rate for those stats was set to 1 second.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 100 +
 1 file changed, 76 insertions(+), 24 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index b430b0500f12..927fd68e05ec 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -65,6 +65,8 @@ struct lgdt330x_state {
/* Demodulator private data */
enum fe_modulation current_modulation;
u32 snr;/* Result of last SNR calculation */
+   u16 ucblocks;
+   unsigned long last_stats_time;
 
/* Tuner private data */
u32 current_frequency;
@@ -296,6 +298,11 @@ static int lgdt330x_init(struct dvb_frontend *fe)
 
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.len = 1;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_count.len = 1;
+   p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   state->last_stats_time = 0;
 
return lgdt330x_sw_reset(state);
 }
@@ -303,29 +310,9 @@ static int lgdt330x_init(struct dvb_frontend *fe)
 static int lgdt330x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
-   int err;
-   u8 buf[2];
 
-   *ucblocks = 0;
+   *ucblocks = state->ucblocks;
 
-   switch (state->config.demod_chip) {
-   case LGDT3302:
-   err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
-  buf, sizeof(buf));
-   break;
-   case LGDT3303:
-   err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
-  buf, sizeof(buf));
-   break;
-   default:
-   dev_warn(>client->dev,
-"Only LGDT3302 and LGDT3303 are supported chips.\n");
-   err = -ENODEV;
-   }
-   if (err < 0)
-   return err;
-
-   *ucblocks = (buf[0] << 8) | buf[1];
return 0;
 }
 
@@ -644,6 +631,7 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
struct lgdt330x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = >dtv_property_cache;
u8 buf[3];
+   int err;
 
*status = 0; /* Reset status result */
 
@@ -698,13 +686,45 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
 __func__);
}
 
-   if (*status & FE_HAS_LOCK && lgdt3302_read_snr(fe) >= 0) {
+   if (!(*status & FE_HAS_LOCK)) {
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   return 0;
+   }
+
+   if (state->last_stats_time &&
+   time_is_after_jiffies(state->last_stats_time))
+   return 0;
+
+   state->last_stats_time = jiffies + msecs_to_jiffies(1000);
+
+   err = lgdt3302_read_snr(fe);
+   if (!err) {
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
} else {
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
 
+   err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+  buf, sizeof(buf));
+   if (!err) {
+   state->ucblocks = (buf[0] << 8) | buf[1];
+
+   dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
+
+   p->block_error.stat[0].uvalue += state->ucblocks;
+   /* FIXME: what's the basis for block count */
+   p->block_count.stat[0].uvalue += 1;
+
+   p->block_error.stat[0].scale = FE_SCALE_COUNTER;
+   p->block_count.stat[0].scale = FE_SCALE_COUNTER;
+   } else {
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return 0;
 }
 
@@ -713,8 +733,8 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
 {
struct lgdt330x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = >dtv_property_cache;
-   int err;
u8 buf[3];
+   int err;
 
*status = 0; /* Reset status result */
 
@@ -772,13 +792,45 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,

[GIT PULL FOR v4.17] Various fixes

2018-03-09 Thread Hans Verkuil
The following changes since commit 3f127ce11353fd1071cae9b65bc13add6aec6b90:

  media: em28xx-cards: fix em28xx_duplicate_dev() (2018-03-08 06:06:51 -0500)

are available in the Git repository at:

  git://linuxtv.org/hverkuil/media_tree.git for-v4.17c

for you to fetch changes up to 579f4f639b7507ab1bff5ecde52ad4ef3cd565ec:

  cpia2_usb: drop bogus interface-release call (2018-03-09 16:56:47 +0100)


Douglas Fischer (3):
  media: radio: Tuning bugfix for si470x over i2c
  media: radio: Critical v4l2 registration bugfix for si470x over i2c
  media: radio: Critical interrupt bugfix for si470x over i2c

Hans Verkuil (1):
  media: add tuner standby op, use where needed

Hugues Fruchet (4):
  media: stm32-dcmi: fix lock scheme
  media: stm32-dcmi: rework overrun/error case
  media: stm32-dcmi: fix unnecessary parentheses
  media: stm32-dcmi: add JPEG support

Jean-Michel Hautbois (2):
  dt-bindings: media: adv7604: Extend bindings to allow specifying slave 
map addresses
  media: adv7604: Add support for i2c_new_secondary_device

Johan Hovold (1):
  cpia2_usb: drop bogus interface-release call

Kieran Bingham (3):
  media: i2c: adv748x: Simplify regmap configuration
  media: i2c: adv748x: Add missing CBUS page
  media: i2c: adv748x: Add support for i2c_new_secondary_device

Luca Ceresoli (3):
  media: vb2-core: vb2_buffer_done: consolidate docs
  media: vb2-core: document the REQUEUEING state
  media: vb2-core: vb2_ops: document non-interrupt-context calling

Philipp Zabel (1):
  media: imx: add 8-bit grayscale support

 Documentation/devicetree/bindings/media/i2c/adv7604.txt |  18 +++-
 drivers/media/i2c/adv748x/adv748x-core.c| 185 
+---
 drivers/media/i2c/adv748x/adv748x.h |  14 +--
 drivers/media/i2c/adv7604.c |  62 +-
 drivers/media/pci/cx23885/cx23885-core.c|   2 +-
 drivers/media/pci/cx23885/cx23885-dvb.c |   4 +-
 drivers/media/pci/cx88/cx88-cards.c |   2 +-
 drivers/media/pci/cx88/cx88-dvb.c   |   4 +-
 drivers/media/pci/saa7134/saa7134-video.c   |   2 +-
 drivers/media/platform/stm32/stm32-dcmi.c   | 267 
++
 drivers/media/radio/si470x/radio-si470x-common.c|  17 +++-
 drivers/media/radio/si470x/radio-si470x-i2c.c   |  32 ++-
 drivers/media/radio/si470x/radio-si470x.h   |   2 +
 drivers/media/tuners/e4000.c|  16 +---
 drivers/media/tuners/fc2580.c   |  16 +---
 drivers/media/tuners/msi001.c   |  19 +
 drivers/media/usb/au0828/au0828-video.c |   4 +-
 drivers/media/usb/cpia2/cpia2_usb.c |   3 -
 drivers/media/usb/cx231xx/cx231xx-video.c   |   2 +-
 drivers/media/usb/em28xx/em28xx-video.c |   4 +-
 drivers/media/v4l2-core/tuner-core.c|  15 +---
 drivers/staging/media/imx/imx-media-csi.c   |   1 +
 drivers/staging/media/imx/imx-media-utils.c |   8 +-
 include/media/v4l2-subdev.h |   4 +
 include/media/videobuf2-core.h  |  33 +---
 25 files changed, 390 insertions(+), 346 deletions(-)


Re: [PATCH] media: rc: meson-ir: add timeout on idle

2018-03-09 Thread Matthias Reichl
Hi Sean,

On Thu, Mar 08, 2018 at 04:43:27PM +, Sean Young wrote:
> On Tue, Mar 06, 2018 at 06:41:22PM +0100, Matthias Reichl wrote:
> > Meson doesn't seem to be able to generate timeout events
> > in hardware. So install a software timer to generate the
> > timeout events required by the decoders to prevent
> > "ghost keypresses".
> > 
> > Signed-off-by: Matthias Reichl 
> > ---
> >  drivers/media/rc/meson-ir.c | 22 ++
> >  1 file changed, 22 insertions(+)
> > 
> > diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
> > index f2204eb77e2a..f34c5836412b 100644
> > --- a/drivers/media/rc/meson-ir.c
> > +++ b/drivers/media/rc/meson-ir.c
> > @@ -69,6 +69,7 @@ struct meson_ir {
> > void __iomem*reg;
> > struct rc_dev   *rc;
> > spinlock_t  lock;
> > +   struct timer_list timeout_timer;
> >  };
> >  
> >  static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg,
> > @@ -98,6 +99,10 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
> > rawir.pulse = !!(status & STATUS_IR_DEC_IN);
> >  
> > ir_raw_event_store(ir->rc, );
> > +
> > +   mod_timer(>timeout_timer,
> > +   jiffies + nsecs_to_jiffies(ir->rc->timeout));
> > +
> > ir_raw_event_handle(ir->rc);
> >  
> > spin_unlock(>lock);
> > @@ -105,6 +110,17 @@ static irqreturn_t meson_ir_irq(int irqno, void 
> > *dev_id)
> > return IRQ_HANDLED;
> >  }
> >  
> > +static void meson_ir_timeout_timer(struct timer_list *t)
> > +{
> > +   struct meson_ir *ir = from_timer(ir, t, timeout_timer);
> > +   DEFINE_IR_RAW_EVENT(rawir);
> > +
> > +   rawir.timeout = true;
> > +   rawir.duration = ir->rc->timeout;
> > +   ir_raw_event_store(ir->rc, );
> > +   ir_raw_event_handle(ir->rc);
> > +}
> 
> Now there can be concurrent access to the raw IR kfifo from the interrupt
> handler and the timer. As there is a race condition between the timeout
> timer and new IR arriving from the interrupt handler, the timeout could
> end being generated after new IR and corrupting a message. There is very
> similar functionality in rc-ir-raw.c (with a spinlock).

Ah, thanks for the hint! Now I also noticed your commit a few
weeks ago - must have missed that before.

> > +
> >  static int meson_ir_probe(struct platform_device *pdev)
> >  {
> > struct device *dev = >dev;
> > @@ -145,7 +161,9 @@ static int meson_ir_probe(struct platform_device *pdev)
> > ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY;
> > ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
> > ir->rc->rx_resolution = US_TO_NS(MESON_TRATE);
> > +   ir->rc->min_timeout = 1;
> > ir->rc->timeout = MS_TO_NS(200);
> > +   ir->rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
> 
> Any idea why the default timeout is to 200ms? It seems very high.

Indeed it is very high, but I have no idea where that might be
coming from - so I didn't touch it.

I've been testing rc-5 and NEC remotes with 20-50ms timeouts
on meson-ir/upstream kernel and a couple of LibreELEC users are
using 30-50ms timeouts without issues on Amlogic devices as well
(on 3.14 vendor kernel with meson-ir timeout patch):

https://forum.libreelec.tv/thread/11643-le9-0-remote-configs-ir-keytable-amlogic-devices/?postID=83124#post83124

Out of curiosity: where does the 125ms IR_DEFAULT_TIMEOUT value
come from? For raw IR signals processed by the decoders this seems
rather high to me as well. On my RPi3 with gpio-ir-recv I'm
using 30ms timeout (with an rc-5 remote) without issues.

> > ir->rc->driver_name = DRIVER_NAME;
> >  
> > spin_lock_init(>lock);
> > @@ -157,6 +175,8 @@ static int meson_ir_probe(struct platform_device *pdev)
> > return ret;
> > }
> >  
> > +   timer_setup(>timeout_timer, meson_ir_timeout_timer, 0);
> > +
> > ret = devm_request_irq(dev, irq, meson_ir_irq, 0, NULL, ir);
> > if (ret) {
> > dev_err(dev, "failed to request irq\n");
> > @@ -198,6 +218,8 @@ static int meson_ir_remove(struct platform_device *pdev)
> > meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
> > spin_unlock_irqrestore(>lock, flags);
> >  
> > +   del_timer_sync(>timeout_timer);
> > +
> > return 0;
> >  }
> >  
> > -- 
> > 2.11.0
> 
> Would you mind trying this patch?

Tested-by: Matthias Reichl 

Thanks a lot, this patch works fine! And having a common function
in rc-core looks like a very good idea to me as well.

Only thing I'd like to have added is min/max timeout values set
in meson-ir so it's configurable via ir-ctl. A separate patch for
that would make sense, though, I guess.

so long & thanks,

Hias

> 
> Thanks
> 
> Sean
> ---
> >>From f98f4fc05d743ac48a95694996985b2c1f0c4a4b Mon Sep 17 00:00:00 2001
> From: Sean Young 
> Date: Thu, 8 Mar 2018 14:42:44 +
> Subject: [PATCH] media: rc: meson-ir: add timeout on idle
> 
> Meson doesn't seem to be able to generate timeout events in hardware. So
> install a software timer to generate the timeout 

[PATCH 09/11] media: lgdt330x: provide DVBv5 Carrier S/N measurements

2018-03-09 Thread Mauro Carvalho Chehab
Change the logic at the driver to provide CNR stats via
DVBv5 API.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 47 +-
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index bb61b4fb1df1..75b9ae6583e8 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -64,7 +64,7 @@ struct lgdt330x_state {
 
/* Demodulator private data */
enum fe_modulation current_modulation;
-   u32 snr; /* Result of last SNR calculation */
+   u32 snr;/* Result of last SNR calculation */
 
/* Tuner private data */
u32 current_frequency;
@@ -187,6 +187,7 @@ static int lgdt330x_sw_reset(struct lgdt330x_state *state)
 static int lgdt330x_init(struct dvb_frontend *fe)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
+   struct dtv_frontend_properties *p = >dtv_property_cache;
char  *chip_name;
interr;
/*
@@ -292,6 +293,10 @@ static int lgdt330x_init(struct dvb_frontend *fe)
dprintk(state, "Initialized the %s chip\n", chip_name);
if (err < 0)
return err;
+
+   p->cnr.len = 1;
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
return lgdt330x_sw_reset(state);
 }
 
@@ -513,7 +518,7 @@ static u32 calculate_snr(u32 mse, u32 c)
return 10 * (c - mse);
 }
 
-static int lgdt3302_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int lgdt3302_read_snr(struct dvb_frontend *fe)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
u8 buf[5];  /* read data buffer */
@@ -546,11 +551,13 @@ static int lgdt3302_read_snr(struct dvb_frontend *fe, u16 
*snr)
dev_err(>client->dev,
"%s: Modulation set to unsupported value\n",
__func__);
+
+   state->snr = 0;
+
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
 
state->snr = calculate_snr(noise, c);
-   *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
state->snr >> 24, (((state->snr >> 8) & 0x) * 100) >> 16);
@@ -558,7 +565,7 @@ static int lgdt3302_read_snr(struct dvb_frontend *fe, u16 
*snr)
return 0;
 }
 
-static int lgdt3303_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int lgdt3303_read_snr(struct dvb_frontend *fe)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
u8 buf[5];  /* read data buffer */
@@ -591,11 +598,11 @@ static int lgdt3303_read_snr(struct dvb_frontend *fe, u16 
*snr)
dev_err(>client->dev,
"%s: Modulation set to unsupported value\n",
__func__);
+   state->snr = 0;
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
 
state->snr = calculate_snr(noise, c);
-   *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
state->snr >> 24, (((state->snr >> 8) & 0x) * 100) >> 16);
@@ -603,6 +610,15 @@ static int lgdt3303_read_snr(struct dvb_frontend *fe, u16 
*snr)
return 0;
 }
 
+static int lgdt330x_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+   struct lgdt330x_state *state = fe->demodulator_priv;
+
+   *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+   return 0;
+}
+
 static int lgdt330x_read_signal_strength(struct dvb_frontend *fe, u16 
*strength)
 {
/* Calculate Strength from SNR up to 35dB */
@@ -632,6 +648,7 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
enum fe_status *status)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
+   struct dtv_frontend_properties *p = >dtv_property_cache;
u8 buf[3];
 
*status = 0; /* Reset status result */
@@ -687,6 +704,13 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
 __func__);
}
 
+   if (*status & FE_HAS_LOCK && lgdt3302_read_snr(fe) >= 0) {
+   p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
+   } else {
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return 0;
 }
 
@@ -694,6 +718,7 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
enum fe_status *status)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
+   struct dtv_frontend_properties *p = >dtv_property_cache;
int err;
u8 buf[3];
 
@@ -752,6 +777,14 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
 "%s: 

[PATCH 08/11] media: lgdt330x: move *read_status functions

2018-03-09 Thread Mauro Carvalho Chehab
In preparation to implement DVBv5 stats on this driver, move
the *read_status functions to happen after SNR and signal
strength routines.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 255 +
 1 file changed, 128 insertions(+), 127 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index c7355282bb3e..bb61b4fb1df1 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -472,133 +472,6 @@ static int lgdt330x_get_frontend(struct dvb_frontend *fe,
return 0;
 }
 
-static int lgdt3302_read_status(struct dvb_frontend *fe,
-   enum fe_status *status)
-{
-   struct lgdt330x_state *state = fe->demodulator_priv;
-   u8 buf[3];
-
-   *status = 0; /* Reset status result */
-
-   /* AGC status register */
-   i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
-   dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
-   if ((buf[0] & 0x0c) == 0x8) {
-   /*
-* Test signal does not exist flag
-* as well as the AGC lock flag.
-*/
-   *status |= FE_HAS_SIGNAL;
-   }
-
-   /*
-* You must set the Mask bits to 1 in the IRQ_MASK in order
-* to see that status bit in the IRQ_STATUS register.
-* This is done in SwReset();
-*/
-
-   /* signal status */
-   i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
-   dprintk(state,
-   "TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 
0x%02x\n",
-   buf[0], buf[1], buf[2]);
-
-   /* sync status */
-   if ((buf[2] & 0x03) == 0x01)
-   *status |= FE_HAS_SYNC;
-
-   /* FEC error status */
-   if ((buf[2] & 0x0c) == 0x08)
-   *status |= FE_HAS_LOCK | FE_HAS_VITERBI;
-
-   /* Carrier Recovery Lock Status Register */
-   i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-   dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
-   switch (state->current_modulation) {
-   case QAM_256:
-   case QAM_64:
-   /* Need to understand why there are 3 lock levels here */
-   if ((buf[0] & 0x07) == 0x07)
-   *status |= FE_HAS_CARRIER;
-   break;
-   case VSB_8:
-   if ((buf[0] & 0x80) == 0x80)
-   *status |= FE_HAS_CARRIER;
-   break;
-   default:
-   dev_warn(>client->dev,
-"%s: Modulation set to unsupported value\n",
-__func__);
-   }
-
-   return 0;
-}
-
-static int lgdt3303_read_status(struct dvb_frontend *fe,
-   enum fe_status *status)
-{
-   struct lgdt330x_state *state = fe->demodulator_priv;
-   int err;
-   u8 buf[3];
-
-   *status = 0; /* Reset status result */
-
-   /* lgdt3303 AGC status register */
-   err = i2c_read_demod_bytes(state, 0x58, buf, 1);
-   if (err < 0)
-   return err;
-
-   dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
-   if ((buf[0] & 0x21) == 0x01) {
-   /*
-* Test input signal does not exist flag
-* as well as the AGC lock flag.
-*/
-   *status |= FE_HAS_SIGNAL;
-   }
-
-   /* Carrier Recovery Lock Status Register */
-   i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-   dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
-   switch (state->current_modulation) {
-   case QAM_256:
-   case QAM_64:
-   /* Need to understand why there are 3 lock levels here */
-   if ((buf[0] & 0x07) == 0x07)
-   *status |= FE_HAS_CARRIER;
-   else
-   break;
-   i2c_read_demod_bytes(state, 0x8a, buf, 1);
-   dprintk(state, "QAM LOCK = 0x%02x\n", buf[0]);
-
-   if ((buf[0] & 0x04) == 0x04)
-   *status |= FE_HAS_SYNC;
-   if ((buf[0] & 0x01) == 0x01)
-   *status |= FE_HAS_LOCK;
-   if ((buf[0] & 0x08) == 0x08)
-   *status |= FE_HAS_VITERBI;
-   break;
-   case VSB_8:
-   if ((buf[0] & 0x80) == 0x80)
-   *status |= FE_HAS_CARRIER;
-   else
-   break;
-   i2c_read_demod_bytes(state, 0x38, buf, 1);
-   dprintk(state, "8-VSB LOCK = 0x%02x\n", buf[0]);
-
-   if ((buf[0] & 0x02) == 0x00)
-   *status |= FE_HAS_SYNC;
-   if ((buf[0] & 0xfd) == 0x01)
-   *status |= FE_HAS_VITERBI | FE_HAS_LOCK;
-   break;
-   default:
-   dev_warn(>client->dev,
-"%s: Modulation set to 

[PATCH 03/11] media: lgdt330x: use pr_foo() macros

2018-03-09 Thread Mauro Carvalho Chehab
Cleanup the usecases of dprintk() by using pr_fmt() and replace
printk by pr_foo().

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 64 ++
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index ad0842fcdba5..a3139eb69c93 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include 
 #include 
 #include 
@@ -48,9 +50,11 @@
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off lgdt330x frontend debugging 
(default:off).");
-#define dprintk(args...) do {  \
-   if (debug)  \
-   printk(KERN_DEBUG "lgdt330x: " args);   \
+
+#define dprintk(fmt, arg...) do {  \
+   if (debug)  \
+   printk(KERN_DEBUG pr_fmt("%s: " fmt),   \
+  __func__, ##arg);\
 } while (0)
 
 struct lgdt330x_state {
@@ -85,8 +89,8 @@ static int i2c_write_demod_bytes(struct lgdt330x_state *state,
for (i = 0; i < len - 1; i += 2) {
err = i2c_transfer(state->i2c, , 1);
if (err != 1) {
-   printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- 
%02x, err = %i)\n",
-  __func__, msg.buf[0], msg.buf[1], err);
+   pr_warn("%s: error (addr %02x <- %02x, err = %i)\n",
+   __func__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
@@ -122,8 +126,8 @@ static int i2c_read_demod_bytes(struct lgdt330x_state 
*state,
 
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
-   printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x 
error (ret == %i)\n",
-  __func__, state->config->demod_address, reg, ret);
+   pr_warn("%s: addr 0x%02x select 0x%02x error (ret == %i)\n",
+   __func__, state->config->demod_address, reg, ret);
if (ret >= 0)
ret = -EIO;
} else {
@@ -295,7 +299,7 @@ static int lgdt330x_init(struct dvb_frontend *fe)
printk(KERN_WARNING "Only LGDT3302 and LGDT3303 are supported 
chips.\n");
err = -ENODEV;
}
-   dprintk("%s entered as %s\n", __func__, chip_name);
+   dprintk("entered as %s\n", chip_name);
if (err < 0)
return err;
return lgdt330x_sw_reset(state);
@@ -378,7 +382,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe)
if (state->current_modulation != p->modulation) {
switch (p->modulation) {
case VSB_8:
-   dprintk("%s: VSB_8 MODE\n", __func__);
+   dprintk("VSB_8 MODE\n");
 
/* Select VSB mode */
top_ctrl_cfg[1] = 0x03;
@@ -395,7 +399,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe)
break;
 
case QAM_64:
-   dprintk("%s: QAM_64 MODE\n", __func__);
+   dprintk("QAM_64 MODE\n");
 
/* Select QAM_64 mode */
top_ctrl_cfg[1] = 0x00;
@@ -412,7 +416,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe)
break;
 
case QAM_256:
-   dprintk("%s: QAM_256 MODE\n", __func__);
+   dprintk("QAM_256 MODE\n");
 
/* Select QAM_256 mode */
top_ctrl_cfg[1] = 0x01;
@@ -428,13 +432,13 @@ static int lgdt330x_set_parameters(struct dvb_frontend 
*fe)
}
break;
default:
-   printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) 
UNSUPPORTED\n",
-  __func__, p->modulation);
+   pr_warn("%s: Modulation type(%d) UNSUPPORTED\n",
+   __func__, p->modulation);
return -1;
}
if (err < 0)
-   printk(KERN_WARNING "lgdt330x: %s: error blasting bytes 
to lgdt3303 for modulation type(%d)\n",
-  __func__, p->modulation);
+   pr_warn("%s: error blasting bytes to lgdt3303 for 
modulation type(%d)\n",
+   __func__, p->modulation);
 
/*
 * select serial or parallel MPEG hardware interface
@@ -488,7 +492,7 @@ 

[PATCH 04/11] media: lgdt330x: print info when device gets probed

2018-03-09 Thread Mauro Carvalho Chehab
It is useful to know if the driver load succeded. So,
add a printk info there.

While here, improve the .init debug printed message.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index a3139eb69c93..1e52831cb603 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -299,7 +299,7 @@ static int lgdt330x_init(struct dvb_frontend *fe)
printk(KERN_WARNING "Only LGDT3302 and LGDT3303 are supported 
chips.\n");
err = -ENODEV;
}
-   dprintk("entered as %s\n", chip_name);
+   dprintk("Initialized the %s chip\n", chip_name);
if (err < 0)
return err;
return lgdt330x_sw_reset(state);
@@ -817,6 +817,9 @@ struct dvb_frontend *lgdt330x_attach(const struct 
lgdt330x_config *config,
state->current_frequency = -1;
state->current_modulation = -1;
 
+   pr_info("Demod loaded for LGDT330%s chip\n",
+   config->demod_chip == LGDT3302 ? "2" : "3");
+
return >frontend;
 
 error:
-- 
2.14.3



[PATCH 05/11] media: lgdt330x: convert it to the new I2C binding way

2018-03-09 Thread Mauro Carvalho Chehab
Convert the driver to allow its usage with the new I2C
binding way.

Please notice that this patch doesn't convert the
callers to bind to it using the new way.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/common/b2c2/flexcop-fe-tuner.c |   4 +-
 drivers/media/dvb-frontends/lgdt330x.c   | 219 +--
 drivers/media/dvb-frontends/lgdt330x.h   |  18 ++-
 drivers/media/pci/bt8xx/dvb-bt8xx.c  |   4 +-
 drivers/media/pci/cx23885/cx23885-dvb.c  |   6 +-
 drivers/media/pci/cx88/cx88-dvb.c|   7 +-
 drivers/media/pci/ngene/ngene-cards.c|   4 +-
 drivers/media/usb/dvb-usb/cxusb.c|   9 +-
 drivers/media/usb/em28xx/em28xx-dvb.c|   3 +-
 drivers/media/usb/pvrusb2/pvrusb2-devattr.c  |   4 +-
 10 files changed, 177 insertions(+), 101 deletions(-)

diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c 
b/drivers/media/common/b2c2/flexcop-fe-tuner.c
index a1ce3e8eb1d3..aac1aadb0cb1 100644
--- a/drivers/media/common/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c
@@ -495,7 +495,6 @@ static int airstar_atsc2_attach(struct flexcop_device *fc,
 /* AirStar ATSC 3rd generation */
 #if FE_SUPPORTED(LGDT330X)
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
-   .demod_address   = 0x59,
.demod_chip  = LGDT3303,
.serial_mpeg = 0x04,
.clock_polarity_flip = 1,
@@ -504,7 +503,8 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
 static int airstar_atsc3_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
 {
-   fc->fe = dvb_attach(lgdt330x_attach, _atsc_hd5000_config, i2c);
+   fc->fe = dvb_attach(lgdt330x_attach, _atsc_hd5000_config,
+   0x59, i2c);
if (!fc->fe)
return 0;
 
diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index 1e52831cb603..a6fd5a239026 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -29,8 +29,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include 
 #include 
 #include 
@@ -51,17 +49,16 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off lgdt330x frontend debugging 
(default:off).");
 
-#define dprintk(fmt, arg...) do {  \
+#define dprintk(state, fmt, arg...) do {   \
if (debug)  \
-   printk(KERN_DEBUG pr_fmt("%s: " fmt),   \
-  __func__, ##arg);\
+   dev_printk(KERN_DEBUG, >client->dev, fmt, ##arg);\
 } while (0)
 
 struct lgdt330x_state {
-   struct i2c_adapter *i2c;
+   struct i2c_client *client;
 
/* Configuration settings */
-   const struct lgdt330x_config *config;
+   struct lgdt330x_config config;
 
struct dvb_frontend frontend;
 
@@ -74,29 +71,24 @@ struct lgdt330x_state {
 };
 
 static int i2c_write_demod_bytes(struct lgdt330x_state *state,
-u8 *buf, /* data bytes to send */
+const u8 *buf, /* data bytes to send */
 int len  /* number of bytes to send */)
 {
-   struct i2c_msg msg = {
-   .addr = state->config->demod_address,
-   .flags = 0,
-   .buf = buf,
-   .len = 2
-   };
int i;
int err;
 
for (i = 0; i < len - 1; i += 2) {
-   err = i2c_transfer(state->i2c, , 1);
-   if (err != 1) {
-   pr_warn("%s: error (addr %02x <- %02x, err = %i)\n",
-   __func__, msg.buf[0], msg.buf[1], err);
+   err = i2c_master_send(state->client, buf, 2);
+   if (err != 2) {
+   dev_warn(>client->dev,
+"%s: error (addr %02x <- %02x, err = %i)\n",
+   __func__, buf[0], buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
-   msg.buf += 2;
+   buf += 2;
}
return 0;
 }
@@ -111,12 +103,12 @@ static int i2c_read_demod_bytes(struct lgdt330x_state 
*state,
u8 wr[] = { reg };
struct i2c_msg msg[] = {
{
-   .addr = state->config->demod_address,
+   .addr = state->client->addr,
.flags = 0,
.buf = wr,
.len = 1
}, {
-   .addr = state->config->demod_address,
+   .addr = state->client->addr,
.flags = I2C_M_RD,
 

[PATCH 01/11] media: lgdt330x: use kernel-doc instead of inlined comments

2018-03-09 Thread Mauro Carvalho Chehab
Change the lgdt330x_config documentation to use kernel-doc
style.

No functional changes.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.h | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.h 
b/drivers/media/dvb-frontends/lgdt330x.h
index 61434cbecd2c..18bd54eabca4 100644
--- a/drivers/media/dvb-frontends/lgdt330x.h
+++ b/drivers/media/dvb-frontends/lgdt330x.h
@@ -26,25 +26,26 @@ typedef enum lg_chip_t {
LGDT3303
 }lg_chip_type;
 
+/**
+ * struct lgdt330x_config - contains lgdt330x configuration
+ *
+ * @demod_address: The demodulator's i2c address
+ * @demod_chip:LG demodulator chip LGDT3302 or LGDT3303
+ * @serial_mpeg:   MPEG hardware interface - 0:parallel 1:serial
+ * @pll_rf_set:Callback function to set PLL interface
+ * @set_ts_params: Callback function to set device param for start_dma
+ * @clock_polarity_flip:
+ * Flip the polarity of the mpeg data transfer clock using alternate
+ * init data.
+ * This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled
+ */
 struct lgdt330x_config
 {
-   /* The demodulator's i2c address */
u8 demod_address;
-
-   /* LG demodulator chip LGDT3302 or LGDT3303 */
lg_chip_type demod_chip;
-
-   /* MPEG hardware interface - 0:parallel 1:serial */
int serial_mpeg;
-
-   /* PLL interface */
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-
-   /* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-   /* Flip the polarity of the mpeg data transfer clock using alternate 
init data
-* This option applies ONLY to LGDT3303 - 0:disabled (default) 
1:enabled */
int clock_polarity_flip;
 };
 
-- 
2.14.3



[PATCH 11/11] media: lgdt330x: add block error counts via DVBv5

2018-03-09 Thread Mauro Carvalho Chehab
Show the UCB error counts via DVBv5.

Please notice that there's no scale indication at the driver.
As we don't have the datasheet, let's assume that it is receiving
data at a rate of 10.000 packets per second. Ideally, this should
be read or estimated.

In order to avoid flooding I2C bus with data, the maximum
polling rate for those stats was set to 1 second.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 98 --
 1 file changed, 70 insertions(+), 28 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index b430b0500f12..f14948df223b 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -65,6 +65,8 @@ struct lgdt330x_state {
/* Demodulator private data */
enum fe_modulation current_modulation;
u32 snr;/* Result of last SNR calculation */
+   u16 ucblocks;
+   unsigned long last_stats_time;
 
/* Tuner private data */
u32 current_frequency;
@@ -296,6 +298,11 @@ static int lgdt330x_init(struct dvb_frontend *fe)
 
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.len = 1;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_count.len = 1;
+   p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   state->last_stats_time = 0;
 
return lgdt330x_sw_reset(state);
 }
@@ -303,29 +310,9 @@ static int lgdt330x_init(struct dvb_frontend *fe)
 static int lgdt330x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
-   int err;
-   u8 buf[2];
 
-   *ucblocks = 0;
+   *ucblocks = state->ucblocks;
 
-   switch (state->config.demod_chip) {
-   case LGDT3302:
-   err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
-  buf, sizeof(buf));
-   break;
-   case LGDT3303:
-   err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
-  buf, sizeof(buf));
-   break;
-   default:
-   dev_warn(>client->dev,
-"Only LGDT3302 and LGDT3303 are supported chips.\n");
-   err = -ENODEV;
-   }
-   if (err < 0)
-   return err;
-
-   *ucblocks = (buf[0] << 8) | buf[1];
return 0;
 }
 
@@ -644,6 +631,7 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
struct lgdt330x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = >dtv_property_cache;
u8 buf[3];
+   int err;
 
*status = 0; /* Reset status result */
 
@@ -698,11 +686,38 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
 __func__);
}
 
-   if (*status & FE_HAS_LOCK && lgdt3302_read_snr(fe) >= 0) {
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+   if (!(*status & FE_HAS_LOCK))
+   return 0;
+
+   if (state->last_stats_time &&
+   time_is_after_jiffies(state->last_stats_time))
+   return 0;
+
+   state->last_stats_time = jiffies +msecs_to_jiffies(1000);
+
+   err = lgdt3302_read_snr(fe);
+   if (!err) {
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
-   } else {
-   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+  buf, sizeof(buf));
+   if (!err) {
+   state->ucblocks = (buf[0] << 8) | buf[1];
+
+   dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
+
+   p->block_error.stat[0].uvalue += state->ucblocks;
+   /* FIXME: what's the basis for block count */
+   p->block_count.stat[0].uvalue += 1;
+
+   p->block_error.stat[0].scale = FE_SCALE_COUNTER;
+   p->block_count.stat[0].scale = FE_SCALE_COUNTER;
}
 
return 0;
@@ -713,8 +728,8 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
 {
struct lgdt330x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = >dtv_property_cache;
-   int err;
u8 buf[3];
+   int err;
 
*status = 0; /* Reset status result */
 
@@ -772,11 +787,38 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
 __func__);
}
 
-   if (*status & FE_HAS_LOCK && lgdt3303_read_snr(fe) >= 0) {
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.stat[0].scale = 

[PATCH 02/11] media: lgdt330x: fix coding style issues

2018-03-09 Thread Mauro Carvalho Chehab
As we're about to convert this driver to use the new i2c
binding way, let's first solve most coding style issues,
in order to avoid mixing coding style changes with code
changes.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 358 +++--
 1 file changed, 204 insertions(+), 154 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index 8ad03bd81af5..ad0842fcdba5 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -47,18 +47,17 @@
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging 
(default:off).");
-#define dprintk(args...) \
-do { \
-if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
+MODULE_PARM_DESC(debug, "Turn on/off lgdt330x frontend debugging 
(default:off).");
+#define dprintk(args...) do {  \
+   if (debug)  \
+   printk(KERN_DEBUG "lgdt330x: " args);   \
 } while (0)
 
-struct lgdt330x_state
-{
-   struct i2c_adapter* i2c;
+struct lgdt330x_state {
+   struct i2c_adapter *i2c;
 
/* Configuration settings */
-   const struct lgdt330x_config* config;
+   const struct lgdt330x_config *config;
 
struct dvb_frontend frontend;
 
@@ -70,21 +69,24 @@ struct lgdt330x_state
u32 current_frequency;
 };
 
-static int i2c_write_demod_bytes (struct lgdt330x_state* state,
- u8 *buf, /* data bytes to send */
- int len  /* number of bytes to send */ )
+static int i2c_write_demod_bytes(struct lgdt330x_state *state,
+u8 *buf, /* data bytes to send */
+int len  /* number of bytes to send */)
 {
-   struct i2c_msg msg =
-   { .addr = state->config->demod_address,
- .flags = 0,
- .buf = buf,
- .len = 2 };
+   struct i2c_msg msg = {
+   .addr = state->config->demod_address,
+   .flags = 0,
+   .buf = buf,
+   .len = 2
+   };
int i;
int err;
 
-   for (i=0; ii2c, , 1)) != 1) {
-   printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- 
%02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
+   for (i = 0; i < len - 1; i += 2) {
+   err = i2c_transfer(state->i2c, , 1);
+   if (err != 1) {
+   printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- 
%02x, err = %i)\n",
+  __func__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
@@ -99,21 +101,29 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* 
state,
  * This routine writes the register (reg) to the demod bus
  * then reads the data returned for (len) bytes.
  */
-
 static int i2c_read_demod_bytes(struct lgdt330x_state *state,
enum I2C_REG reg, u8 *buf, int len)
 {
-   u8 wr [] = { reg };
-   struct i2c_msg msg [] = {
-   { .addr = state->config->demod_address,
- .flags = 0, .buf = wr,  .len = 1 },
-   { .addr = state->config->demod_address,
- .flags = I2C_M_RD, .buf = buf, .len = len },
+   u8 wr[] = { reg };
+   struct i2c_msg msg[] = {
+   {
+   .addr = state->config->demod_address,
+   .flags = 0,
+   .buf = wr,
+   .len = 1
+   }, {
+   .addr = state->config->demod_address,
+   .flags = I2C_M_RD,
+   .buf = buf,
+   .len = len
+   },
};
int ret;
+
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
-   printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x 
error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+   printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x 
error (ret == %i)\n",
+  __func__, state->config->demod_address, reg, ret);
if (ret >= 0)
ret = -EIO;
} else {
@@ -123,19 +133,21 @@ static int i2c_read_demod_bytes(struct lgdt330x_state 
*state,
 }
 
 /* Software reset */
-static int lgdt3302_SwReset(struct lgdt330x_state* state)
+static int lgdt3302_sw_reset(struct lgdt330x_state *state)
 {
u8 ret;
u8 reset[] = {
IRQ_MASK,
-   0x00 /* bit 6 is active low software reset
- * bits 5-0 are 1 to mask interrupts */
+   /*
+* 

[PATCH 07/11] media: lgdt330x: constify several register init arrays

2018-03-09 Thread Mauro Carvalho Chehab
There are several register init arrays there that can be
constified.

The change reduced a little bit the amount of initialized
data:

   textdata bss dec hex filename
   6372 360   467361a50 
old/drivers/media/dvb-frontends/lgdt330x.o
   6500 264   467681a70 
new/drivers/media/dvb-frontends/lgdt330x.o

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 43 ++
 1 file changed, 18 insertions(+), 25 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index e93ffe8891e5..c7355282bb3e 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -186,19 +186,14 @@ static int lgdt330x_sw_reset(struct lgdt330x_state *state)
 
 static int lgdt330x_init(struct dvb_frontend *fe)
 {
-   /*
-* Hardware reset is done using gpio[0] of cx23880x chip.
-* I'd like to do it here, but don't know how to find chip address.
-* cx88-cards.c arranges for the reset bit to be inactive (high).
-* Maybe there needs to be a callable function in cx88-core or
-* the caller of this function needs to do it.
-*/
-
+   struct lgdt330x_state *state = fe->demodulator_priv;
+   char  *chip_name;
+   interr;
/*
 * Array of byte pairs 
 * to initialize each different chip
 */
-   static u8 lgdt3302_init_data[] = {
+   static const u8 lgdt3302_init_data[] = {
/* Use 50MHz param values from spec sheet since xtal is 50 */
/*
 * Change the value of NCOCTFV[25:0] of carrier
@@ -243,24 +238,25 @@ static int lgdt330x_init(struct dvb_frontend *fe)
AGC_LOOP_BANDWIDTH0, 0x08,
AGC_LOOP_BANDWIDTH1, 0x9a
};
-
-   static u8 lgdt3303_init_data[] = {
+   static const u8 lgdt3303_init_data[] = {
0x4c, 0x14
};
-
-   static u8 flip_1_lgdt3303_init_data[] = {
+   static const u8 flip_1_lgdt3303_init_data[] = {
0x4c, 0x14,
0x87, 0xf3
};
-
-   static u8 flip_2_lgdt3303_init_data[] = {
+   static const u8 flip_2_lgdt3303_init_data[] = {
0x4c, 0x14,
0x87, 0xda
};
 
-   struct lgdt330x_state *state = fe->demodulator_priv;
-   char  *chip_name;
-   interr;
+   /*
+* Hardware reset is done using gpio[0] of cx23880x chip.
+* I'd like to do it here, but don't know how to find chip address.
+* cx88-cards.c arranges for the reset bit to be inactive (high).
+* Maybe there needs to be a callable function in cx88-core or
+* the caller of this function needs to do it.
+*/
 
switch (state->config.demod_chip) {
case LGDT3302:
@@ -337,11 +333,12 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend 
*fe, u32 *ucblocks)
 static int lgdt330x_set_parameters(struct dvb_frontend *fe)
 {
struct dtv_frontend_properties *p = >dtv_property_cache;
+   struct lgdt330x_state *state = fe->demodulator_priv;
/*
 * Array of byte pairs 
 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
 */
-   static u8 lgdt3303_8vsb_44_data[] = {
+   static const u8 lgdt3303_8vsb_44_data[] = {
0x04, 0x00,
0x0d, 0x40,
0x0e, 0x87,
@@ -349,12 +346,11 @@ static int lgdt330x_set_parameters(struct dvb_frontend 
*fe)
0x10, 0x01,
0x47, 0x8b
};
-
/*
 * Array of byte pairs 
 * to initialize QAM for lgdt3303 chip
 */
-   static u8 lgdt3303_qam_data[] = {
+   static const u8 lgdt3303_qam_data[] = {
0x04, 0x00,
0x0d, 0x00,
0x0e, 0x00,
@@ -367,10 +363,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe)
0x49, 0x08,
0x4a, 0x9b
};
-
-   struct lgdt330x_state *state = fe->demodulator_priv;
-
-   static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
+   u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
 
int err = 0;
/* Change only if we are actually changing the modulation */
-- 
2.14.3



[PATCH 06/11] media: lgdt330x: do some cleanups at status logic

2018-03-09 Thread Mauro Carvalho Chehab
Simplify a few ifs there.

While here, add debug messages for the 8-vsb and qam log status
flags.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index a6fd5a239026..e93ffe8891e5 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -515,10 +515,8 @@ static int lgdt3302_read_status(struct dvb_frontend *fe,
*status |= FE_HAS_SYNC;
 
/* FEC error status */
-   if ((buf[2] & 0x0c) == 0x08) {
-   *status |= FE_HAS_LOCK;
-   *status |= FE_HAS_VITERBI;
-   }
+   if ((buf[2] & 0x0c) == 0x08)
+   *status |= FE_HAS_LOCK | FE_HAS_VITERBI;
 
/* Carrier Recovery Lock Status Register */
i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
@@ -578,6 +576,8 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
else
break;
i2c_read_demod_bytes(state, 0x8a, buf, 1);
+   dprintk(state, "QAM LOCK = 0x%02x\n", buf[0]);
+
if ((buf[0] & 0x04) == 0x04)
*status |= FE_HAS_SYNC;
if ((buf[0] & 0x01) == 0x01)
@@ -591,12 +591,12 @@ static int lgdt3303_read_status(struct dvb_frontend *fe,
else
break;
i2c_read_demod_bytes(state, 0x38, buf, 1);
+   dprintk(state, "8-VSB LOCK = 0x%02x\n", buf[0]);
+
if ((buf[0] & 0x02) == 0x00)
*status |= FE_HAS_SYNC;
-   if ((buf[0] & 0x01) == 0x01) {
-   *status |= FE_HAS_LOCK;
-   *status |= FE_HAS_VITERBI;
-   }
+   if ((buf[0] & 0xfd) == 0x01)
+   *status |= FE_HAS_VITERBI | FE_HAS_LOCK;
break;
default:
dev_warn(>client->dev,
-- 
2.14.3



[PATCH 10/11] media: lgdt330x: get rid of read_ber stub

2018-03-09 Thread Mauro Carvalho Chehab
This routine does nothing. Remove it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/dvb-frontends/lgdt330x.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/media/dvb-frontends/lgdt330x.c 
b/drivers/media/dvb-frontends/lgdt330x.c
index 75b9ae6583e8..b430b0500f12 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -300,12 +300,6 @@ static int lgdt330x_init(struct dvb_frontend *fe)
return lgdt330x_sw_reset(state);
 }
 
-static int lgdt330x_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-   *ber = 0; /* Not supplied by the demod chips */
-   return 0;
-}
-
 static int lgdt330x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
struct lgdt330x_state *state = fe->demodulator_priv;
@@ -909,7 +903,6 @@ static const struct dvb_frontend_ops lgdt3302_ops = {
.get_frontend = lgdt330x_get_frontend,
.get_tune_settings= lgdt330x_get_tune_settings,
.read_status  = lgdt3302_read_status,
-   .read_ber = lgdt330x_read_ber,
.read_signal_strength = lgdt330x_read_signal_strength,
.read_snr = lgdt330x_read_snr,
.read_ucblocks= lgdt330x_read_ucblocks,
@@ -932,7 +925,6 @@ static const struct dvb_frontend_ops lgdt3303_ops = {
.get_frontend = lgdt330x_get_frontend,
.get_tune_settings= lgdt330x_get_tune_settings,
.read_status  = lgdt3303_read_status,
-   .read_ber = lgdt330x_read_ber,
.read_signal_strength = lgdt330x_read_signal_strength,
.read_snr = lgdt330x_read_snr,
.read_ucblocks= lgdt330x_read_ucblocks,
-- 
2.14.3



Re: [PATCH v12 33/33] rcar-vin: enable support for r8a77970

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a77970.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 23 +++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index 0040f92bfdff947a..a7e65c720f2c191b 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -971,6 +971,25 @@ static const struct rvin_info rcar_info_r8a7796 = {
>   .routes = rcar_info_r8a7796_routes,
>  };
>  
> +static const struct rvin_group_route _rcar_info_r8a77970_routes[] = {
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
> + { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
> + { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
> + { /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a77970 = {
> + .model = RCAR_GEN3,
> + .use_mc = true,
> + .max_width = 4096,
> + .max_height = 4096,
> + .routes = _rcar_info_r8a77970_routes,
> +};
> +
>  static const struct of_device_id rvin_of_id_table[] = {
>   {
>   .compatible = "renesas,vin-r8a7778",
> @@ -1008,6 +1027,10 @@ static const struct of_device_id rvin_of_id_table[] = {
>   .compatible = "renesas,vin-r8a7796",
>   .data = _info_r8a7796,
>   },
> + {
> + .compatible = "renesas,vin-r8a77970",
> + .data = _info_r8a77970,
> + },
>   { /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, rvin_of_id_table);
> 



Re: [PATCH v12 32/33] rcar-vin: enable support for r8a7796

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a7796.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 44 
> +
>  1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index bc116cc0181171e0..0040f92bfdff947a 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -931,6 +931,46 @@ static const struct rvin_info rcar_info_r8a7795es1 = {
>   .routes = rcar_info_r8a7795es1_routes,
>  };
>  
> +static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
> + { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
> + { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
> + { /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a7796 = {
> + .model = RCAR_GEN3,
> + .use_mc = true,
> + .max_width = 4096,
> + .max_height = 4096,
> + .routes = rcar_info_r8a7796_routes,
> +};
> +
>  static const struct of_device_id rvin_of_id_table[] = {
>   {
>   .compatible = "renesas,vin-r8a7778",
> @@ -964,6 +1004,10 @@ static const struct of_device_id rvin_of_id_table[] = {
>   .compatible = "renesas,vin-r8a7795",
>   .data = _info_r8a7795,
>   },
> + {
> + .compatible = "renesas,vin-r8a7796",
> + .data = _info_r8a7796,
> + },
>   { /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, rvin_of_id_table);
> 



Re: [PATCH v12 31/33] rcar-vin: enable support for r8a7795

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a7795 ES1.x and ES2.0.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/Kconfig |   2 +-
>  drivers/media/platform/rcar-vin/rcar-core.c | 120 
> 
>  2 files changed, 121 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/Kconfig 
> b/drivers/media/platform/rcar-vin/Kconfig
> index af4c98b44d2e22cb..8fa7ee468c63afb9 100644
> --- a/drivers/media/platform/rcar-vin/Kconfig
> +++ b/drivers/media/platform/rcar-vin/Kconfig
> @@ -6,7 +6,7 @@ config VIDEO_RCAR_VIN
>   select V4L2_FWNODE
>   ---help---
> Support for Renesas R-Car Video Input (VIN) driver.
> -   Supports R-Car Gen2 SoCs.
> +   Supports R-Car Gen2 and Gen3 SoCs.
>  
> To compile this driver as a module, choose M here: the
> module will be called rcar-vin.
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index a1c441c1a314feb7..bc116cc0181171e0 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -21,6 +21,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -832,6 +833,104 @@ static const struct rvin_info rcar_info_gen2 = {
>   .max_height = 2048,
>  };
>  
> +static const struct rvin_group_route rcar_info_r8a7795_routes[] = {
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
> + { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
> + { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
> + { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
> + { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
> + { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
> + { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
> + { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
> + { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
> + { /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a7795 = {
> + .model = RCAR_GEN3,
> + .use_mc = true,
> + .max_width = 4096,
> + .max_height = 4096,
> + .routes = rcar_info_r8a7795_routes,
> +};
> +
> +static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
> + { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) },
> + { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
> + { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) },
> + { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
> + { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
> + { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
> + { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = 

Re: [PATCH v12 30/33] rcar-vin: extend {start,stop}_streaming to work with media controller

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> The procedure to start or stop streaming using the non-MC single
> subdevice and the MC graph and multiple subdevices are quite different.
> Create a new function to abstract which method is used based on which
> mode the driver is running in and add logic to start the MC graph.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c | 133 
> +++--
>  1 file changed, 126 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
> b/drivers/media/platform/rcar-vin/rcar-dma.c
> index da113531f0ce7dc0..580b286acbf2dab6 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -1082,15 +1082,136 @@ static void rvin_buffer_queue(struct vb2_buffer *vb)
>   spin_unlock_irqrestore(>qlock, flags);
>  }
>  
> +static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev 
> *sd,
> +struct media_pad *pad)
> +{
> + struct v4l2_subdev_format fmt = {
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + };
> +
> + fmt.pad = pad->index;
> + if (v4l2_subdev_call(sd, pad, get_fmt, NULL, ))
> + return -EPIPE;
> +
> + switch (fmt.format.code) {
> + case MEDIA_BUS_FMT_YUYV8_1X16:
> + case MEDIA_BUS_FMT_UYVY8_2X8:
> + case MEDIA_BUS_FMT_UYVY10_2X10:
> + case MEDIA_BUS_FMT_RGB888_1X24:
> + vin->mbus_code = fmt.format.code;
> + break;
> + default:
> + return -EPIPE;
> + }
> +
> + switch (fmt.format.field) {
> + case V4L2_FIELD_TOP:
> + case V4L2_FIELD_BOTTOM:
> + case V4L2_FIELD_NONE:
> + case V4L2_FIELD_INTERLACED_TB:
> + case V4L2_FIELD_INTERLACED_BT:
> + case V4L2_FIELD_INTERLACED:
> + case V4L2_FIELD_SEQ_TB:
> + case V4L2_FIELD_SEQ_BT:
> + /* Supported natively */
> + break;
> + case V4L2_FIELD_ALTERNATE:
> + switch (vin->format.field) {
> + case V4L2_FIELD_TOP:
> + case V4L2_FIELD_BOTTOM:
> + case V4L2_FIELD_NONE:
> + break;
> + case V4L2_FIELD_INTERLACED_TB:
> + case V4L2_FIELD_INTERLACED_BT:
> + case V4L2_FIELD_INTERLACED:
> + case V4L2_FIELD_SEQ_TB:
> + case V4L2_FIELD_SEQ_BT:
> + /* Use VIN hardware to combine the two fields */
> + fmt.format.height *= 2;
> + break;
> + default:
> + return -EPIPE;
> + }
> + break;
> + default:
> + return -EPIPE;
> + }
> +
> + if (fmt.format.width != vin->format.width ||
> + fmt.format.height != vin->format.height ||
> + fmt.format.code != vin->mbus_code)
> + return -EPIPE;
> +
> + return 0;
> +}
> +
> +static int rvin_set_stream(struct rvin_dev *vin, int on)
> +{
> + struct media_pipeline *pipe;
> + struct media_device *mdev;
> + struct v4l2_subdev *sd;
> + struct media_pad *pad;
> + int ret;
> +
> + /* No media controller used, simply pass operation to subdevice. */
> + if (!vin->info->use_mc) {
> + ret = v4l2_subdev_call(vin->digital->subdev, video, s_stream,
> +on);
> +
> + return ret == -ENOIOCTLCMD ? 0 : ret;
> + }
> +
> + pad = media_entity_remote_pad(>pad);
> + if (!pad)
> + return -EPIPE;
> +
> + sd = media_entity_to_v4l2_subdev(pad->entity);
> +
> + if (!on) {
> + media_pipeline_stop(>vdev.entity);
> + return v4l2_subdev_call(sd, video, s_stream, 0);
> + }
> +
> + ret = rvin_mc_validate_format(vin, sd, pad);
> + if (ret)
> + return ret;
> +
> + /*
> +  * The graph lock needs to be taken to protect concurrent
> +  * starts of multiple VIN instances as they might share
> +  * a common subdevice down the line and then should use
> +  * the same pipe.
> +  */
> + mdev = vin->vdev.entity.graph_obj.mdev;
> + mutex_lock(>graph_mutex);
> + pipe = sd->entity.pipe ? sd->entity.pipe : >vdev.pipe;
> + ret = __media_pipeline_start(>vdev.entity, pipe);
> + mutex_unlock(>graph_mutex);
> + if (ret)
> + return ret;
> +
> + ret = v4l2_subdev_call(sd, video, s_stream, 1);
> + if (ret == -ENOIOCTLCMD)
> + ret = 0;
> + if (ret)
> + media_pipeline_stop(>vdev.entity);
> +
> + return ret;
> +}
> +
>  static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>   struct rvin_dev *vin = vb2_get_drv_priv(vq);
> - struct v4l2_subdev *sd;
>   

Re: [PATCH v12 29/33] rcar-vin: add link notify for Gen3

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> Add the ability to process media device link change requests. Link
> enabling is a bit complicated on Gen3, whether or not it's possible to
> enable a link depends on what other links already are enabled. On Gen3
> the 8 VINs are split into two subgroup's (VIN0-3 and VIN4-7) and from a
> routing perspective these two groups are independent of each other.
> Each subgroup's routing is controlled by the subgroup VIN master
> instance (VIN0 and VIN4).
> 
> There are a limited number of possible route setups available for each
> subgroup and the configuration of each setup is dictated by the
> hardware. On H3 for example there are 6 possible route setups for each
> subgroup to choose from.
> 
> This leads to the media device link notification code being rather large
> since it will find the best routing configuration to try and accommodate
> as many links as possible. When it's not possible to enable a new link
> due to hardware constrains the link_notifier callback will return
> -EMLINK.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> 
> ---
> 
> * Changes since v11
> - Fixed spelling
> - Updated comment to clarify the intent that no link can be enabled if
> any video node is open.
> - Use container_of() instead of a loop to find struct vin_dev from the
> video device.
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 147 
> 
>  1 file changed, 147 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index 52fad495533bc427..a1c441c1a314feb7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -24,6 +24,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include "rcar-vin.h"
>  
> @@ -44,6 +45,151 @@
>   */
>  #define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
>  
> +/* 
> -
> + * Media Controller link notification
> + */
> +
> +/* group lock should be held when calling this function. */
> +static int rvin_group_entity_to_csi_id(struct rvin_group *group,
> +struct media_entity *entity)
> +{
> + struct v4l2_subdev *sd;
> + unsigned int i;
> +
> + sd = media_entity_to_v4l2_subdev(entity);
> +
> + for (i = 0; i < RVIN_CSI_MAX; i++)
> + if (group->csi[i].subdev == sd)
> + return i;
> +
> + return -ENODEV;
> +}
> +
> +static unsigned int rvin_group_get_mask(struct rvin_dev *vin,
> + enum rvin_csi_id csi_id,
> + unsigned char channel)
> +{
> + const struct rvin_group_route *route;
> + unsigned int mask = 0;
> +
> + for (route = vin->info->routes; route->mask; route++) {
> + if (route->vin == vin->id &&
> + route->csi == csi_id &&
> + route->channel == channel) {
> + vin_dbg(vin,
> + "Adding route: vin: %d csi: %d channel: %d\n",
> + route->vin, route->csi, route->channel);
> + mask |= route->mask;
> + }
> + }
> +
> + return mask;
> +}
> +
> +/*
> + * Link setup for the links between a VIN and a CSI-2 receiver is a bit
> + * complex. The reason for this is that the register controlling routing
> + * is not present in each VIN instance. There are special VINs which
> + * control routing for themselves and other VINs. There are not many
> + * different possible links combinations that can be enabled at the same
> + * time, therefor all already enabled links which are controlled by a
> + * master VIN need to be taken into account when making the decision
> + * if a new link can be enabled or not.
> + *
> + * 1. Find out which VIN the link the user tries to enable is connected to.
> + * 2. Lookup which master VIN controls the links for this VIN.
> + * 3. Start with a bitmask with all bits set.
> + * 4. For each previously enabled link from the master VIN bitwise AND its
> + *route mask (see documentation for mask in struct rvin_group_route)
> + *with the bitmask.
> + * 5. Bitwise AND the mask for the link the user tries to enable to the 
> bitmask.
> + * 6. If the bitmask is not empty at this point the new link can be enabled
> + *while keeping all previous links enabled. Update the CHSEL value of the
> + *master VIN and inform the user that the link could be enabled.
> + *
> + * Please note that no link can be enabled if any VIN in the group is
> + * currently open.
> + */
> +static int rvin_group_link_notify(struct media_link *link, u32 flags,
> +   unsigned int notification)
> +{
> + struct rvin_group *group = container_of(link->graph_obj.mdev,

Re: [PATCH v12 28/33] rcar-vin: parse Gen3 OF and setup media graph

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> The parsing and registering CSI-2 subdevices with the v4l2 async
> framework is a collaborative effort shared between the VIN instances
> which are part of the group. When the last VIN in the group is probed it
> asks all other VINs to parse its share of OF and record the async
> subdevices it finds in the notifier belonging to the last probed VIN.
> 
> Once all CSI-2 subdevices in this notifier are bound proceed to register
> all VIN video devices of the group and crate media device links between
> all CSI-2 and VIN entities according to the SoC specific routing
> configuration.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 246 
> +++-
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  12 +-
>  2 files changed, 254 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index fd4478095ac4e5b1..52fad495533bc427 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -27,6 +27,23 @@
>  
>  #include "rcar-vin.h"
>  
> +/*
> + * The companion CSI-2 receiver driver (rcar-csi2) is known
> + * and we know it has one source pad (pad 0) and four sink
> + * pads (pad 1-4). So to translate a pad on the remote
> + * CSI-2 receiver to/from the VIN internal channel number simply
> + * subtract/add one from the pad/channel number.
> + */
> +#define rvin_group_csi_pad_to_channel(pad) ((pad) - 1)
> +#define rvin_group_csi_channel_to_pad(channel) ((channel) + 1)
> +
> +/*
> + * Not all VINs are created equal, master VINs control the
> + * routing for other VIN's. We can figure out which VIN is
> + * master by looking at a VINs id.
> + */
> +#define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
> +
>  /* 
> -
>   * Gen3 CSI2 Group Allocator
>   */
> @@ -409,6 +426,216 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
>   return 0;
>  }
>  
> +/* 
> -
> + * Group async notifier
> + */
> +
> +static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
> +{
> + struct rvin_dev *vin = notifier_to_vin(notifier);
> + const struct rvin_group_route *route;
> + unsigned int i;
> + int ret;
> +
> + ret = v4l2_device_register_subdev_nodes(>v4l2_dev);
> + if (ret) {
> + vin_err(vin, "Failed to register subdev nodes\n");
> + return ret;
> + }
> +
> + /* Register all video nodes for the group. */
> + for (i = 0; i < RCAR_VIN_NUM; i++) {
> + if (vin->group->vin[i]) {
> + ret = rvin_v4l2_register(vin->group->vin[i]);
> + if (ret)
> + return ret;
> + }
> + }
> +
> + /* Create all media device links between VINs and CSI-2's. */
> + mutex_lock(>group->lock);
> + for (route = vin->info->routes; route->mask; route++) {
> + struct media_pad *source_pad, *sink_pad;
> + struct media_entity *source, *sink;
> + unsigned int source_idx;
> +
> + /* Check that VIN is part of the group. */
> + if (!vin->group->vin[route->vin])
> + continue;
> +
> + /* Check that VIN' master is part of the group. */
> + if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
> + continue;
> +
> + /* Check that CSI-2 is part of the group. */
> + if (!vin->group->csi[route->csi].subdev)
> + continue;
> +
> + source = >group->csi[route->csi].subdev->entity;
> + source_idx = rvin_group_csi_channel_to_pad(route->channel);
> + source_pad = >pads[source_idx];
> +
> + sink = >group->vin[route->vin]->vdev.entity;
> + sink_pad = >pads[0];
> +
> + /* Skip if link already exists. */
> + if (media_entity_find_link(source_pad, sink_pad))
> + continue;
> +
> + ret = media_create_pad_link(source, source_idx, sink, 0, 0);
> + if (ret) {
> + vin_err(vin, "Error adding link from %s to %s\n",
> + source->name, sink->name);
> + break;
> + }
> + }
> + mutex_unlock(>group->lock);
> +
> + return ret;
> +}
> +
> +static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
> +  struct v4l2_subdev *subdev,
> +  struct v4l2_async_subdev *asd)
> +{
> +   

Re: [PATCH v12 20/33] rcar-vin: add function to manipulate Gen3 chsel value

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> feature of this register is that it's only present in the VIN0 and VIN4
> instances. The register in VIN0 controls the routing for VIN0-3 and the
> register in VIN4 controls routing for VIN4-7.
> 
> To be able to control routing from a media device this function is need
> to control runtime PM for the subgroup master (VIN0 and VIN4). The
> subgroup master must be switched on before the register is manipulated,
> once the operation is complete it's safe to switch the master off and
> the new routing will still be in effect.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c | 38 
> ++
>  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
>  2 files changed, 40 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
> b/drivers/media/platform/rcar-vin/rcar-dma.c
> index 483d31f07b934929..75382ee0f3fc1dde 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -16,6 +16,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  
> @@ -1224,3 +1225,40 @@ int rvin_dma_register(struct rvin_dev *vin, int irq)
>  
>   return ret;
>  }
> +
> +/* 
> -
> + * Gen3 CHSEL manipulation
> + */
> +
> +/*
> + * There is no need to have locking around changing the routing
> + * as it's only possible to do so when no VIN in the group is
> + * streaming so nothing can race with the VNMC register.
> + */
> +int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> +{
> + u32 ifmd, vnmc;
> + int ret;
> +
> + ret = pm_runtime_get_sync(vin->dev);
> + if (ret < 0)
> + return ret;
> +
> + /* Make register writes take effect immediately. */
> + vnmc = rvin_read(vin, VNMC_REG);
> + rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> +
> + ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> + VNCSI_IFMD_CSI_CHSEL(chsel);
> +
> + rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> +
> + vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> +
> + /* Restore VNMC. */
> + rvin_write(vin, vnmc, VNMC_REG);
> +
> + pm_runtime_put(vin->dev);
> +
> + return ret;
> +}
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h 
> b/drivers/media/platform/rcar-vin/rcar-vin.h
> index 5e3ea8d401d934d1..8e20455927fe5224 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -169,4 +169,6 @@ const struct rvin_video_format 
> *rvin_format_from_pixel(u32 pixelformat);
>  /* Cropping, composing and scaling */
>  void rvin_crop_scale_comp(struct rvin_dev *vin);
>  
> +int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> +
>  #endif
> 



Re: [PATCH v12 27/33] rcar-vin: add chsel information to rvin_info

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> Each Gen3 SoC has a limited set of predefined routing possibilities for
> which CSI-2 device and channel can be routed to which VIN instance.
> Prepare to store this information in the struct rvin_info.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> 
> ---
> 
> * Changes since v11
> - Fixed spelling.
> - Reorderd filed order in struct rvin_group_route.
> - Renamed chan to channel in struct rvin_group_route.
> ---
>  drivers/media/platform/rcar-vin/rcar-vin.h | 42 
> ++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h 
> b/drivers/media/platform/rcar-vin/rcar-vin.h
> index d64cbb5716ab6f6a..9a68a5909fe07ec7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -43,6 +43,14 @@ enum model_id {
>   RCAR_GEN3,
>  };
>  
> +enum rvin_csi_id {
> + RVIN_CSI20,
> + RVIN_CSI21,
> + RVIN_CSI40,
> + RVIN_CSI41,
> + RVIN_CSI_MAX,
> +};
> +
>  /**
>   * STOPPED  - No operation in progress
>   * RUNNING  - Operation in progress have buffers
> @@ -81,12 +89,45 @@ struct rvin_graph_entity {
>   unsigned int sink_pad;
>  };
>  
> +/**
> + * struct rvin_group_route - describes a route from a channel of a
> + *   CSI-2 receiver to a VIN
> + *
> + * @csi: CSI-2 receiver ID.
> + * @channel: Output channel of the CSI-2 receiver.
> + * @vin: VIN ID.
> + * @mask:Bitmask of the different CHSEL register values that
> + *   allow for a route from @csi + @chan to @vin.
> + *
> + * .. note::
> + *   Each R-Car CSI-2 receiver has four output channels facing the VIN
> + *   devices, each channel can carry one CSI-2 Virtual Channel (VC).
> + *   There is no correlation between channel number and CSI-2 VC. It's
> + *   up to the CSI-2 receiver driver to configure which VC is output
> + *   on which channel, the VIN devices only care about output channels.
> + *
> + *   There are in some cases multiple CHSEL register settings which would
> + *   allow for the same route from @csi + @channel to @vin. For example
> + *   on R-Car H3 both the CHSEL values 0 and 3 allow for a route from
> + *   CSI40/VC0 to VIN0. All possible CHSEL values for a route need to be
> + *   recorded as a bitmask in @mask, in this example bit 0 and 3 should
> + *   be set.
> + */
> +struct rvin_group_route {
> + enum rvin_csi_id csi;
> + unsigned int channel;
> + unsigned int vin;
> + unsigned int mask;
> +};
> +
>  /**
>   * struct rvin_info - Information about the particular VIN implementation
>   * @model:   VIN model
>   * @use_mc:  use media controller instead of controlling subdevice
>   * @max_width:   max input width the VIN supports
>   * @max_height:  max input height the VIN supports
> + * @routes:  list of possible routes from the CSI-2 recivers to
> + *   all VINs. The list mush be NULL terminated.
>   */
>  struct rvin_info {
>   enum model_id model;
> @@ -94,6 +135,7 @@ struct rvin_info {
>  
>   unsigned int max_width;
>   unsigned int max_height;
> + const struct rvin_group_route *routes;
>  };
>  
>  /**
> 



Re: [PATCH v12 26/33] rcar-vin: change name of video device

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> The rcar-vin driver needs to be part of a media controller to support
> Gen3. Give each VIN instance a unique name so it can be referenced from
> userspace.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index ea0759a645e49490..7c10557d965ea6ed 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -993,7 +993,7 @@ int rvin_v4l2_register(struct rvin_dev *vin)
>   /* video node */
>   vdev->v4l2_dev = >v4l2_dev;
>   vdev->queue = >queue;
> - strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
> + snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
>   vdev->release = video_device_release_empty;
>   vdev->lock = >lock;
>   vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
> 



Re: [PATCH v12 25/33] rcar-vin: add group allocator functions

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> In media controller mode all VIN instances needs to be part of the same
> media graph. There is also a need for each VIN instance to know about
> and in some cases be able to communicate with other VIN instances.
> 
> Add an allocator framework where the first VIN instance to be probed
> creates a shared data structure and registers a media device.
> Consecutive VINs insert themself into the global group.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 174 
> +++-
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  31 +
>  2 files changed, 203 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index 592dbd8642361f1e..fd4478095ac4e5b1 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -20,12 +20,174 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
>  
>  #include "rcar-vin.h"
>  
> +/* 
> -
> + * Gen3 CSI2 Group Allocator
> + */
> +
> +/* FIXME:  This should if we find a system that supports more
> + * than one group for the whole system be replaced with a linked
> + * list of groups. And eventually all of this should be replaced
> + * with a global device allocator API.
> + *
> + * But for now this works as on all supported systems there will
> + * be only one group for all instances.
> + */
> +
> +static DEFINE_MUTEX(rvin_group_lock);
> +static struct rvin_group *rvin_group_data;
> +
> +static void rvin_group_cleanup(struct rvin_group *group)
> +{
> + media_device_unregister(>mdev);
> + media_device_cleanup(>mdev);
> + mutex_destroy(>lock);
> +}
> +
> +static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
> +{
> + struct media_device *mdev = >mdev;
> + const struct of_device_id *match;
> + struct device_node *np;
> + int ret;
> +
> + mutex_init(>lock);
> +
> + /* Count number of VINs in the system */
> + group->count = 0;
> + for_each_matching_node(np, vin->dev->driver->of_match_table)
> + if (of_device_is_available(np))
> + group->count++;
> +
> + vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
> +
> + mdev->dev = vin->dev;
> +
> + match = of_match_node(vin->dev->driver->of_match_table,
> +   vin->dev->of_node);
> +
> + strlcpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
> + strlcpy(mdev->model, match->compatible, sizeof(mdev->model));
> + snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
> +  dev_name(mdev->dev));
> +
> + media_device_init(mdev);
> +
> + ret = media_device_register(>mdev);
> + if (ret)
> + rvin_group_cleanup(group);
> +
> + return ret;
> +}
> +
> +static void rvin_group_release(struct kref *kref)
> +{
> + struct rvin_group *group =
> + container_of(kref, struct rvin_group, refcount);
> +
> + mutex_lock(_group_lock);
> +
> + rvin_group_data = NULL;
> +
> + rvin_group_cleanup(group);
> +
> + kfree(group);
> +
> + mutex_unlock(_group_lock);
> +}
> +
> +static int rvin_group_get(struct rvin_dev *vin)
> +{
> + struct rvin_group *group;
> + u32 id;
> + int ret;
> +
> + /* Make sure VIN id is present and sane */
> + ret = of_property_read_u32(vin->dev->of_node, "renesas,id", );
> + if (ret) {
> + vin_err(vin, "%pOF: No renesas,id property found\n",
> + vin->dev->of_node);
> + return -EINVAL;
> + }
> +
> + if (id >= RCAR_VIN_NUM) {
> + vin_err(vin, "%pOF: Invalid renesas,id '%u'\n",
> + vin->dev->of_node, id);
> + return -EINVAL;
> + }
> +
> + /* Join or create a VIN group */
> + mutex_lock(_group_lock);
> + if (rvin_group_data) {
> + group = rvin_group_data;
> + kref_get(>refcount);
> + } else {
> + group = kzalloc(sizeof(*group), GFP_KERNEL);
> + if (!group) {
> + ret = -ENOMEM;
> + goto err_group;
> + }
> +
> + ret = rvin_group_init(group, vin);
> + if (ret) {
> + kfree(group);
> + vin_err(vin, "Failed to initialize group\n");
> + goto err_group;
> + }
> +
> + kref_init(>refcount);
> +
> + rvin_group_data = group;
> + }
> + mutex_unlock(_group_lock);
> +
> + /* Add VIN to group */
> + mutex_lock(>lock);

Re: [PATCH v12 23/33] rcar-vin: force default colorspace for media centric mode

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:05, Niklas Söderlund wrote:
> The V4L2 specification clearly documents the colorspace fields as being
> set by drivers for capture devices. Using the values supplied by
> userspace thus wouldn't comply with the API. Until the API is updated to
> allow for userspace to set these Hans wants the fields to be set by the
> driver to fixed values.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 21 +++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index 2280535ca981993f..ea0759a645e49490 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -664,12 +664,29 @@ static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
>   * V4L2 Media Controller
>   */
>  
> +static int rvin_mc_try_format(struct rvin_dev *vin, struct v4l2_pix_format 
> *pix)
> +{
> + /*
> +  * The V4L2 specification clearly documents the colorspace fields
> +  * as being set by drivers for capture devices. Using the values
> +  * supplied by userspace thus wouldn't comply with the API. Until
> +  * the API is updated force fixed vaules.
> +  */
> + pix->colorspace = RVIN_DEFAULT_COLORSPACE;
> + pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
> + pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
> + pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, pix->colorspace,
> +   pix->ycbcr_enc);
> +
> + return rvin_format_align(vin, pix);
> +}
> +
>  static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv,
>  struct v4l2_format *f)
>  {
>   struct rvin_dev *vin = video_drvdata(file);
>  
> - return rvin_format_align(vin, >fmt.pix);
> + return rvin_mc_try_format(vin, >fmt.pix);
>  }
>  
>  static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
> @@ -681,7 +698,7 @@ static int rvin_mc_s_fmt_vid_cap(struct file *file, void 
> *priv,
>   if (vb2_is_busy(>queue))
>   return -EBUSY;
>  
> - ret = rvin_format_align(vin, >fmt.pix);
> + ret = rvin_mc_try_format(vin, >fmt.pix);
>   if (ret)
>   return ret;
>  
> 



Re: [PATCH v12 17/33] rcar-vin: cache video standard

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> At stream on time the driver should not query the subdevice for which
> standard are used. Instead it should be cached when userspace sets the
> standard and used at stream on time.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c |  6 ++
>  drivers/media/platform/rcar-vin/rcar-dma.c  |  7 ++-
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 10 --
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  2 ++
>  4 files changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index cc863e4ec9a4d4b3..ae0339d4ec104e8c 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -96,6 +96,12 @@ static int rvin_digital_subdevice_attach(struct rvin_dev 
> *vin,
>   if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
>   return ret;
>  
> + /* Read standard */
> + vin->std = V4L2_STD_UNKNOWN;
> + ret = v4l2_subdev_call(subdev, video, g_std, >std);
> + if (ret < 0 && ret != -ENOIOCTLCMD)
> + return ret;
> +
>   /* Add the controls */
>   ret = v4l2_ctrl_handler_init(>ctrl_handler, 16);
>   if (ret < 0)
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
> b/drivers/media/platform/rcar-vin/rcar-dma.c
> index c8831e189d362c8b..7c64f1f8ec63bcf4 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -592,7 +592,6 @@ void rvin_crop_scale_comp(struct rvin_dev *vin)
>  static int rvin_setup(struct rvin_dev *vin)
>  {
>   u32 vnmc, dmr, dmr2, interrupts;
> - v4l2_std_id std;
>   bool progressive = false, output_is_yuv = false, input_is_yuv = false;
>  
>   switch (vin->format.field) {
> @@ -606,10 +605,8 @@ static int rvin_setup(struct rvin_dev *vin)
>   /* Default to TB */
>   vnmc = VNMC_IM_FULL;
>   /* Use BT if video standard can be read and is 60 Hz format */
> - if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, )) {
> - if (std & V4L2_STD_525_60)
> - vnmc = VNMC_IM_FULL | VNMC_FOC;
> - }
> + if (vin->std & V4L2_STD_525_60)
> + vnmc = VNMC_IM_FULL | VNMC_FOC;
>   break;
>   case V4L2_FIELD_INTERLACED_TB:
>   vnmc = VNMC_IM_FULL;
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index c4be0bcb8b16f941..43370c57d4b6239a 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -477,6 +477,8 @@ static int rvin_s_std(struct file *file, void *priv, 
> v4l2_std_id a)
>   if (ret < 0)
>   return ret;
>  
> + vin->std = a;
> +
>   /* Changing the standard will change the width/height */
>   return rvin_reset_format(vin);
>  }
> @@ -484,9 +486,13 @@ static int rvin_s_std(struct file *file, void *priv, 
> v4l2_std_id a)
>  static int rvin_g_std(struct file *file, void *priv, v4l2_std_id *a)
>  {
>   struct rvin_dev *vin = video_drvdata(file);
> - struct v4l2_subdev *sd = vin_to_source(vin);
>  
> - return v4l2_subdev_call(sd, video, g_std, a);
> + if (v4l2_subdev_has_op(vin_to_source(vin), pad, dv_timings_cap))
> + return -ENOIOCTLCMD;
> +
> + *a = vin->std;
> +
> + return 0;
>  }
>  
>  static int rvin_subscribe_event(struct v4l2_fh *fh,
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h 
> b/drivers/media/platform/rcar-vin/rcar-vin.h
> index 7fcf984f21466855..458373af9e60ea07 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -119,6 +119,7 @@ struct rvin_info {
>   * @crop:active cropping
>   * @compose: active composing
>   * @source:  active size of the video source
> + * @std: active video standard of the video source
>   */
>  struct rvin_dev {
>   struct device *dev;
> @@ -146,6 +147,7 @@ struct rvin_dev {
>   struct v4l2_rect crop;
>   struct v4l2_rect compose;
>   struct v4l2_rect source;
> + v4l2_std_id std;
>  };
>  
>  #define vin_to_source(vin)   ((vin)->digital->subdev)
> 



Re: [PATCH v8 0/2] media: v4l: Add support for the Cadence MIPI-CSI2 RX

2018-03-09 Thread Maxime Ripard
On Thu, Feb 15, 2018 at 02:33:33PM +0100, Maxime Ripard wrote:
> Hi,
> 
> Here is another attempt at supporting the MIPI-CSI2 RX block from
> Cadence.
> 
> This IP block is able to receive CSI data over up to 4 lanes, and
> split it to over 4 streams. Those streams are basically the interfaces
> to the video grabbers that will perform the capture.
> 
> It is able to map streams to both CSI datatypes and virtual channels,
> dynamically. This is unclear at this point what the right way to
> support it would be, so the driver only uses a static mapping between
> the virtual channels and streams, and ignores the data types.

Ping?

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com


signature.asc
Description: PGP signature


Re: [PATCH v12 16/33] rcar-vin: simplify how formats are set and reset

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> With the recent cleanup of the format code to prepare for Gen3 it's
> possible to simplify the Gen2 format code path as well. Clean up the
> process by defining two functions to handle the set format and reset of
> format when the standard is changed.
> 
> While at it replace the driver local struct rvin_source_fmt with a
> struct v4l2_rect as all it's used for is keep track of the source
> dimensions.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> 
> ---
> 
> * Changes since v11
> - This patch where 'rcar-vin: read subdevice format for crop only when
> needed'
> - Keep caching the source dimensions and drop all changes to
> rvin_g_selection() and rvin_s_selection().
> - Inline rvin_get_vin_format_from_source() into rvin_reset_format()
> which now is the only user left.
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 120 
> 
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  14 +---
>  2 files changed, 55 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index 680b25f610d1d8bb..c4be0bcb8b16f941 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -138,67 +138,60 @@ static int rvin_format_align(struct rvin_dev *vin, 
> struct v4l2_pix_format *pix)
>   * V4L2
>   */
>  
> -static void rvin_reset_crop_compose(struct rvin_dev *vin)
> -{
> - vin->crop.top = vin->crop.left = 0;
> - vin->crop.width = vin->source.width;
> - vin->crop.height = vin->source.height;
> -
> - vin->compose.top = vin->compose.left = 0;
> - vin->compose.width = vin->format.width;
> - vin->compose.height = vin->format.height;
> -}
> -
>  static int rvin_reset_format(struct rvin_dev *vin)
>  {
>   struct v4l2_subdev_format fmt = {
>   .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + .pad = vin->digital->source_pad,
>   };
> - struct v4l2_mbus_framefmt *mf = 
>   int ret;
>  
> - fmt.pad = vin->digital->source_pad;
> -
>   ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, );
>   if (ret)
>   return ret;
>  
> - vin->format.width   = mf->width;
> - vin->format.height  = mf->height;
> - vin->format.colorspace  = mf->colorspace;
> - vin->format.field   = mf->field;
> + v4l2_fill_pix_format(>format, );
>  
> - rvin_reset_crop_compose(vin);
> + ret = rvin_format_align(vin, >format);
> + if (ret)
> + return ret;
>  
> - vin->format.bytesperline = rvin_format_bytesperline(>format);
> - vin->format.sizeimage = rvin_format_sizeimage(>format);
> + vin->source.top = vin->crop.top = 0;
> + vin->source.left = vin->crop.left = 0;
> + vin->source.width = vin->crop.width = vin->format.width;
> + vin->source.height = vin->crop.height = vin->format.height;
> +
> + vin->compose.top = vin->compose.left = 0;
> + vin->compose.width = vin->format.width;
> + vin->compose.height = vin->format.height;
>  
>   return 0;
>  }
>  
> -static int __rvin_try_format_source(struct rvin_dev *vin,
> - u32 which,
> - struct v4l2_pix_format *pix,
> - struct rvin_source_fmt *source)
> +static int rvin_try_format(struct rvin_dev *vin, u32 which,
> +struct v4l2_pix_format *pix,
> +struct v4l2_rect *crop, struct v4l2_rect *compose)
>  {
> - struct v4l2_subdev *sd;
> + struct v4l2_subdev *sd = vin_to_source(vin);
>   struct v4l2_subdev_pad_config *pad_cfg;
>   struct v4l2_subdev_format format = {
>   .which = which,
> + .pad = vin->digital->source_pad,
>   };
>   enum v4l2_field field;
>   u32 width, height;
>   int ret;
>  
> - sd = vin_to_source(vin);
> -
> - v4l2_fill_mbus_format(, pix, vin->digital->code);
> -
>   pad_cfg = v4l2_subdev_alloc_pad_config(sd);
>   if (pad_cfg == NULL)
>   return -ENOMEM;
>  
> - format.pad = vin->digital->source_pad;
> + if (!rvin_format_from_pixel(pix->pixelformat) ||
> + (vin->info->model == RCAR_M1 &&
> +  pix->pixelformat == V4L2_PIX_FMT_XBGR32))
> + pix->pixelformat = RVIN_DEFAULT_FORMAT;
> +
> + v4l2_fill_mbus_format(, pix, vin->digital->code);
>  
>   /* Allow the video device to override field and to scale */
>   field = pix->field;
> @@ -211,39 +204,34 @@ static int __rvin_try_format_source(struct rvin_dev 
> *vin,
>  
>   v4l2_fill_pix_format(pix, );
>  
> - source->width = pix->width;
> - source->height = pix->height;
> + crop->top = crop->left = 0;
> + crop->width = pix->width;
> + crop->height = pix->height;
> +
> + 

Re: [PATCH v12 15/33] rcar-vin: break out format alignment and checking

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> Part of the format alignment and checking can be shared with the Gen3
> format handling. Break that part out to a separate function.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Hans Verkuil 

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 85 
> -
>  1 file changed, 48 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index 01f2a14169a74ff3..680b25f610d1d8bb 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -87,6 +87,53 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format 
> *pix)
>   return pix->bytesperline * pix->height;
>  }
>  
> +static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format 
> *pix)
> +{
> + u32 walign;
> +
> + if (!rvin_format_from_pixel(pix->pixelformat) ||
> + (vin->info->model == RCAR_M1 &&
> +  pix->pixelformat == V4L2_PIX_FMT_XBGR32))
> + pix->pixelformat = RVIN_DEFAULT_FORMAT;
> +
> + switch (pix->field) {
> + case V4L2_FIELD_TOP:
> + case V4L2_FIELD_BOTTOM:
> + case V4L2_FIELD_NONE:
> + case V4L2_FIELD_INTERLACED_TB:
> + case V4L2_FIELD_INTERLACED_BT:
> + case V4L2_FIELD_INTERLACED:
> + break;
> + case V4L2_FIELD_ALTERNATE:
> + /*
> +  * Driver dose not (yet) support outputting ALTERNATE to a
> +  * userspace. It does support outputting INTERLACED so use
> +  * the VIN hardware to combine the two fields.
> +  */
> + pix->field = V4L2_FIELD_INTERLACED;
> + pix->height *= 2;
> + break;
> + default:
> + pix->field = RVIN_DEFAULT_FIELD;
> + break;
> + }
> +
> + /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
> + walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
> +
> + /* Limit to VIN capabilities */
> + v4l_bound_align_image(>width, 2, vin->info->max_width, walign,
> +   >height, 4, vin->info->max_height, 2, 0);
> +
> + pix->bytesperline = rvin_format_bytesperline(pix);
> + pix->sizeimage = rvin_format_sizeimage(pix);
> +
> + vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
> + pix->width, pix->height, pix->bytesperline, pix->sizeimage);
> +
> + return 0;
> +}
> +
>  /* 
> -
>   * V4L2
>   */
> @@ -184,7 +231,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>struct v4l2_pix_format *pix,
>struct rvin_source_fmt *source)
>  {
> - u32 walign;
>   int ret;
>  
>   if (!rvin_format_from_pixel(pix->pixelformat) ||
> @@ -197,42 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   if (ret)
>   return ret;
>  
> - switch (pix->field) {
> - case V4L2_FIELD_TOP:
> - case V4L2_FIELD_BOTTOM:
> - case V4L2_FIELD_NONE:
> - case V4L2_FIELD_INTERLACED_TB:
> - case V4L2_FIELD_INTERLACED_BT:
> - case V4L2_FIELD_INTERLACED:
> - break;
> - case V4L2_FIELD_ALTERNATE:
> - /*
> -  * Driver dose not (yet) support outputting ALTERNATE to a
> -  * userspace. It does support outputting INTERLACED so use
> -  * the VIN hardware to combine the two fields.
> -  */
> - pix->field = V4L2_FIELD_INTERLACED;
> - pix->height *= 2;
> - break;
> - default:
> - pix->field = RVIN_DEFAULT_FIELD;
> - break;
> - }
> -
> - /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
> - walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
> -
> - /* Limit to VIN capabilities */
> - v4l_bound_align_image(>width, 2, vin->info->max_width, walign,
> -   >height, 4, vin->info->max_height, 2, 0);
> -
> - pix->bytesperline = rvin_format_bytesperline(pix);
> - pix->sizeimage = rvin_format_sizeimage(pix);
> -
> - vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
> - pix->width, pix->height, pix->bytesperline, pix->sizeimage);
> -
> - return 0;
> + return rvin_format_align(vin, pix);
>  }
>  
>  static int rvin_querycap(struct file *file, void *priv,
> 



Re: [PATCH v12 14/33] rcar-vin: align pixelformat check

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> If the pixelformat is not supported it should not fail but be set to
> something that works. While we are at it move the two different
> checks of the pixelformat to the same statement.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 14 +++---
>  1 file changed, 3 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index 55fa69aa7c454928..01f2a14169a74ff3 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -187,12 +187,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   u32 walign;
>   int ret;
>  
> - /* If requested format is not supported fallback to the default */
> - if (!rvin_format_from_pixel(pix->pixelformat)) {
> - vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> - pix->pixelformat, RVIN_DEFAULT_FORMAT);
> + if (!rvin_format_from_pixel(pix->pixelformat) ||
> + (vin->info->model == RCAR_M1 &&
> +  pix->pixelformat == V4L2_PIX_FMT_XBGR32))
>   pix->pixelformat = RVIN_DEFAULT_FORMAT;
> - }
>  
>   /* Limit to source capabilities */
>   ret = __rvin_try_format_source(vin, which, pix, source);
> @@ -231,12 +229,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   pix->bytesperline = rvin_format_bytesperline(pix);
>   pix->sizeimage = rvin_format_sizeimage(pix);
>  
> - if (vin->info->model == RCAR_M1 &&
> - pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> - vin_err(vin, "pixel format XBGR32 not supported on M1\n");
> - return -EINVAL;
> - }
> -
>   vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
>   pix->width, pix->height, pix->bytesperline, pix->sizeimage);
>  
> 



Re: [PATCH v12 13/33] rcar-vin: update bytesperline and sizeimage calculation

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> Remove over complicated logic to calculate the value for bytesperline
> and sizeimage that was carried over from the soc_camera port. There is
> no need to find the max value of bytesperline and sizeimage from
> user-space as they are set to 0 before the max_t() operation.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 

Reviewed-by: Hans Verkuil 

Thanks!

Hans

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 10 ++
>  1 file changed, 2 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index b76d59be64e0132d..55fa69aa7c454928 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -194,10 +194,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   pix->pixelformat = RVIN_DEFAULT_FORMAT;
>   }
>  
> - /* Always recalculate */
> - pix->bytesperline = 0;
> - pix->sizeimage = 0;
> -
>   /* Limit to source capabilities */
>   ret = __rvin_try_format_source(vin, which, pix, source);
>   if (ret)
> @@ -232,10 +228,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   v4l_bound_align_image(>width, 2, vin->info->max_width, walign,
> >height, 4, vin->info->max_height, 2, 0);
>  
> - pix->bytesperline = max_t(u32, pix->bytesperline,
> -   rvin_format_bytesperline(pix));
> - pix->sizeimage = max_t(u32, pix->sizeimage,
> -rvin_format_sizeimage(pix));
> + pix->bytesperline = rvin_format_bytesperline(pix);
> + pix->sizeimage = rvin_format_sizeimage(pix);
>  
>   if (vin->info->model == RCAR_M1 &&
>   pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> 



Re: [PATCH v12 12/33] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> There was never proper support in the VIN driver to deliver ALTERNATING
> field format to user-space, remove this field option. The problem is
> that ALTERNATING field order requires the sequence numbers of buffers
> returned to userspace to reflect if fields where dropped or not,

where -> were

With that tiny typo fixed you can add my:

Reviewed-by: Hans Verkuil 

Regards,

Hans

> something which is not possible with the VIN drivers capture logic.
> 
> The VIN driver can still capture from a video source which delivers
> frames in ALTERNATING field order, but needs to combine them using the
> VIN hardware into INTERLACED field order. Before this change if a source
> was delivering fields using ALTERNATE the driver would default to
> combining them using this hardware feature. Only if the user explicitly
> requested ALTERNATE field order would incorrect frames be delivered.
> 
> The height should not be cut in half for the format for TOP or BOTTOM
> fields settings. This was a mistake and it was made visible by the
> scaling refactoring. Correct behavior is that the user should request a
> frame size that fits the half height frame reflected in the field
> setting. If not the VIN will do its best to scale the top or bottom to
> the requested format and cropping and scaling do not work as expected.
> 
> Signed-off-by: Niklas Söderlund 
> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +--
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 40 
> +++--
>  2 files changed, 10 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
> b/drivers/media/platform/rcar-vin/rcar-dma.c
> index fd14be20a6604d7a..c8831e189d362c8b 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -617,7 +617,6 @@ static int rvin_setup(struct rvin_dev *vin)
>   case V4L2_FIELD_INTERLACED_BT:
>   vnmc = VNMC_IM_FULL | VNMC_FOC;
>   break;
> - case V4L2_FIELD_ALTERNATE:
>   case V4L2_FIELD_NONE:
>   if (vin->continuous) {
>   vnmc = VNMC_IM_ODD_EVEN;
> @@ -757,18 +756,6 @@ static int rvin_get_active_slot(struct rvin_dev *vin, 
> u32 vnms)
>   return 0;
>  }
>  
> -static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
> -{
> - if (vin->format.field == V4L2_FIELD_ALTERNATE) {
> - /* If FS is set it's a Even field */
> - if (vnms & VNMS_FS)
> - return V4L2_FIELD_BOTTOM;
> - return V4L2_FIELD_TOP;
> - }
> -
> - return vin->format.field;
> -}
> -
>  static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t 
> addr)
>  {
>   const struct rvin_video_format *fmt;
> @@ -941,7 +928,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
>   goto done;
>  
>   /* Capture frame */
> - vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
> + vin->queue_buf[slot]->field = vin->format.field;
>   vin->queue_buf[slot]->sequence = sequence;
>   vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
>   vb2_buffer_done(>queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index ebcd78b1bb6e8cb6..b76d59be64e0132d 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -121,33 +121,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
>   vin->format.colorspace  = mf->colorspace;
>   vin->format.field   = mf->field;
>  
> - /*
> -  * If the subdevice uses ALTERNATE field mode and G_STD is
> -  * implemented use the VIN HW to combine the two fields to
> -  * one INTERLACED frame. The ALTERNATE field mode can still
> -  * be requested in S_FMT and be respected, this is just the
> -  * default which is applied at probing or when S_STD is called.
> -  */
> - if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> - v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> - vin->format.field = V4L2_FIELD_INTERLACED;
> -
> - switch (vin->format.field) {
> - case V4L2_FIELD_TOP:
> - case V4L2_FIELD_BOTTOM:
> - case V4L2_FIELD_ALTERNATE:
> - vin->format.height /= 2;
> - break;
> - case V4L2_FIELD_NONE:
> - case V4L2_FIELD_INTERLACED_TB:
> - case V4L2_FIELD_INTERLACED_BT:
> - case V4L2_FIELD_INTERLACED:
> - break;
> - default:
> - vin->format.field = RVIN_DEFAULT_FIELD;
> - break;
> - }
> -
>   rvin_reset_crop_compose(vin);
>  
>   vin->format.bytesperline = rvin_format_bytesperline(>format);
> @@ -233,15 +206,20 @@ static int __rvin_try_format(struct rvin_dev *vin,

Re: [PATCH v12 11/33] rcar-vin: set a default field to fallback on

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> If the field is not supported by the driver it should not try to keep
> the current field. Instead it should set it to a default fallback. Since
> trying a format should always result in the same state regardless of the
> current state of the device.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 +++--
>  1 file changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c 
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> index c2265324c7c96308..ebcd78b1bb6e8cb6 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -23,6 +23,7 @@
>  #include "rcar-vin.h"
>  
>  #define RVIN_DEFAULT_FORMAT  V4L2_PIX_FMT_YUYV
> +#define RVIN_DEFAULT_FIELD   V4L2_FIELD_NONE
>  
>  /* 
> -
>   * Format Conversions
> @@ -143,7 +144,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
>   case V4L2_FIELD_INTERLACED:
>   break;
>   default:
> - vin->format.field = V4L2_FIELD_NONE;
> + vin->format.field = RVIN_DEFAULT_FIELD;
>   break;
>   }
>  
> @@ -213,10 +214,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   u32 walign;
>   int ret;
>  
> - /* Keep current field if no specific one is asked for */
> - if (pix->field == V4L2_FIELD_ANY)
> - pix->field = vin->format.field;
> -
>   /* If requested format is not supported fallback to the default */
>   if (!rvin_format_from_pixel(pix->pixelformat)) {
>   vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> @@ -246,7 +243,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>   case V4L2_FIELD_INTERLACED:
>   break;
>   default:
> - pix->field = V4L2_FIELD_NONE;
> + pix->field = RVIN_DEFAULT_FIELD;
>   break;
>   }
>  
> 

I wonder if this code is correct. What if the adv7180 is the source? Does that 
even
support FIELD_NONE? I suspect that the default field should actually depend on 
the
source. FIELD_NONE for dv_timings based or sensor based subdevs and 
FIELD_INTERLACED
for SDTV (g/s_std) subdevs.

I might very well be missing something here but it looks suspicious.

Regards,

Hans


Re: [PATCH v12 06/33] rcar-vin: move subdevice handling to async callbacks

2018-03-09 Thread Hans Verkuil
On 07/03/18 23:04, Niklas Söderlund wrote:
> In preparation for Gen3 support move the subdevice initialization and
> clean up from rvin_v4l2_{register,unregister}() directly to the async
> callbacks. This simplifies the addition of Gen3 support as the
> rvin_v4l2_register() can be shared for both Gen2 and Gen3 while direct
> subdevice control are only used on Gen2.
> 
> While moving this code drop a large comment which is copied from the
> framework documentation and fold rvin_mbus_supported() into its only
> caller. Also move the initialization and cleanup code to separate
> functions to increase readability.
> 
> Signed-off-by: Niklas Söderlund 
> Reviewed-by: Laurent Pinchart 
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 108 
> +++-
>  drivers/media/platform/rcar-vin/rcar-v4l2.c |  35 -
>  2 files changed, 74 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index 47f06acde2e698f2..663309ca9c04f208 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -46,46 +46,88 @@ static int rvin_find_pad(struct v4l2_subdev *sd, int 
> direction)
>   return -EINVAL;
>  }
>  
> -static bool rvin_mbus_supported(struct rvin_graph_entity *entity)
> +/* The vin lock shuld be held when calling the subdevice attach and detach */

shuld -> should

Actually, I'd say 'shall' instead of 'should'.

After that trivial change you can add my:

Reviewed-by: Hans Verkuil 

Regards,

Hans


Re: [RFCv4,19/21] media: vim2m: add request support

2018-03-09 Thread Paul Kocialkowski
Hi,

On Thu, 2018-03-08 at 22:48 +0900, Alexandre Courbot wrote:
> Hi Paul!
> 
> Thanks a lot for taking the time to try this! I am also working on
> getting it to work with an actual driver, but you apparently found
> rough edges that I missed.
> 
> On Thu, Mar 8, 2018 at 1:37 AM, Paul Kocialkowski
>  wrote:
> > Hi,
> > 
> > First off, I'd like to take the occasion to say thank-you for your
> > work.
> > This is a major piece of plumbing that is required for me to add
> > support
> > for the Allwinner CedarX VPU hardware in upstream Linux. Other
> > drivers,
> > such as tegra-vde (that was recently merged in staging) are also
> > badly
> > in need of this API.
> > 
> > I have a few comments based on my experience integrating this
> > request
> > API with the Cedrus VPU driver (and the associated libva backend),
> > that
> > also concern the vim2m driver.
> > 
> > On Tue, 2018-02-20 at 13:44 +0900, Alexandre Courbot wrote:
> > > Set the necessary ops for supporting requests in vim2m.
> > > 
> > > Signed-off-by: Alexandre Courbot 
> > > ---
> > >  drivers/media/platform/Kconfig |  1 +
> > >  drivers/media/platform/vim2m.c | 75
> > > ++
> > >  2 files changed, 76 insertions(+)
> > > 
> > > diff --git a/drivers/media/platform/Kconfig
> > > b/drivers/media/platform/Kconfig
> > > index 614fbef08ddc..09be0b5f9afe 100644
> > > --- a/drivers/media/platform/Kconfig
> > > +++ b/drivers/media/platform/Kconfig
> > 
> > [...]
> > 
> > > +static int vim2m_request_submit(struct media_request *req,
> > > + struct media_request_entity_data
> > > *_data)
> > > +{
> > > + struct v4l2_request_entity_data *data;
> > > +
> > > + data = to_v4l2_entity_data(_data);
> > 
> > We need to call v4l2_m2m_try_schedule here so that m2m scheduling
> > can
> > happen when only 2 buffers were queued and no other action was taken
> > from usespace. In that scenario, m2m scheduling currently doesn't
> > happen.
> 
> I don't think I understand the sequence of events that results in
> v4l2_m2m_try_schedule() not being called. Do you mean something like:
> 
> *
> * QBUF on output queue with request set
> * QBUF on capture queue
> * SUBMIT_REQUEST
> 
> ?
> 
> The call to vb2_request_submit() right after should trigger
> v4l2_m2m_try_schedule(), since the buffers associated to the request
> will enter the vb2 queue and be passed to the m2m framework, which
> will then call v4l2_m2m_try_schedule(). Or maybe you are thinking
> about a different sequence of events?

This is indeed the sequence of events that I'm seeing, but the
scheduling call simply did not happen on vb2_request_submit. I suppose I will 
need to investigate some more to find out exactly why.

IIRC, the m2m qbuf function is called (and fails to schedule) when the
ioctl happens, not when the task is submitted.

This issue is seen with vim2m as well as the rencently-submitted sunxi-
cedrus driver (with the in-driver calls to v4l2_m2m_try_schedule
removed, obviously). If needs be, I could provide a standalone test
program to reproduce it.

> > However, this requires access to the m2m context, which is not easy
> > to
> > get from req or _data. I'm not sure that some container_of magic
> > would
> > even do the trick here.
> 
> data_->entity will give you a pointer to the media_request_entity,
> which is part of vim2m_ctx. You can thus get the m2m context by doing
> container_of(data_->entity, struct vim2m_ctx, req_entity). See
> vim2m_entity_data_alloc() for an example.

Excellent, that's exactly what I was looking for! Thanks a lot and see
the related patch I submitted earlier today.

> > > + return vb2_request_submit(data);
> > 
> > vb2_request_submit does not lock the associated request mutex
> > although
> > it accesses the associated queued buffers list, which I believe this
> > mutex is supposed to protect.
> 
> After a request is submitted, the data protected by the mutex can only
> be accessed by the driver when it processes the request. It cannot be
> modified concurrently, so I think we are safe here.

Fait enough, that should be enough then. I've dropped this change.

Cheers,

Paul

> I am also wondering whether the ioctl locking doesn't make the request
> locking redundant. Request information can only be modified and
> accessed through ioctls until it is submitted, and after that there
> are no concurrent accesses. I need to think a bit more about it
> though.
> 
> Cheers,
> Alex.
> 
> > 
> > We could either wrap this call with media_request_lock(req) and
> > media_request_unlock(req) or have the lock in the function itself,
> > which
> > would require passing it the req pointer.
> > 
> > The latter would probably be safer for future use of the function.
> > 
> > > +}
> > > +
> > > +static const struct media_request_entity_ops
> > > vim2m_request_entity_ops
> > > = {
> > > + .data_alloc = vim2m_entity_data_alloc,
> > > + .data_free  

Re: [PATCH 5/9] media: platform: Add Sunxi Cedrus decoder driver

2018-03-09 Thread Paul Kocialkowski
Hi,

On Fri, 2018-03-09 at 14:57 +0100, Maxime Ripard wrote:
> Hi,
> 
> On Fri, Mar 09, 2018 at 11:14:41AM +0100, Paul Kocialkowski wrote:
> > +/*
> > + * mem2mem callbacks
> > + */
> > +
> > +void job_abort(void *priv)
> > +{}
> 
> Is that still needed?

It looks like we need a dummy callback here, the v4l2_m2m_init function
puts a hard requirement on it.

The feature is definitely not used for now, but maybe this could be
hooked to aborting the matching request? It was probably designed for
the case where the driver handles a queue of jobs on its own (that's how
it's used in vim2m) and such an internal queue is perhaps irrelevant
when using the request API (and fences later).

> > +/*
> > + * device_run() - prepares and starts processing
> > + */
> > +void device_run(void *priv)
> > +{
> 
> This function (and the one above) should probably made static. Or at
> least if you can't, they should have a much more specific name in
> order not to conflict with anything from the core.

Good point, let's go for static. Since these are passed as function
pointers, it shouldn't be a problem.

> > +   /*
> > +* The VPU is only able to handle bus addresses so we have
> > to subtract
> > +* the RAM offset to the physcal addresses
> > +*/
> > +   in_buf -= PHYS_OFFSET;
> > +   out_luma   -= PHYS_OFFSET;
> > +   out_chroma -= PHYS_OFFSET;
> 
> You should take care of that by putting it in the dma_pfn_offset field
> of the struct device (at least before we come up with something
> better).
> 
> You'll then be able to use the dma_addr_t directly without modifying
> it.

Definitely!

> > +   vpu->syscon = syscon_regmap_lookup_by_phandle(vpu->dev-
> > >of_node,
> > + "syscon");
> > +   if (IS_ERR(vpu->syscon)) {
> > +   vpu->syscon = NULL;
> > +   } else {
> > +   regmap_write_bits(vpu->syscon,
> > SYSCON_SRAM_CTRL_REG0,
> > + SYSCON_SRAM_C1_MAP_VE,
> > + SYSCON_SRAM_C1_MAP_VE);
> > +   }
> 
> This should be using our SRAM controller driver (and API), see
> Documentation/devicetree/bindings/sram/sunxi-sram.txt
> include/linux/soc/sunxi/sunxi_sram.h

I'll look into that.

> > +   ret = clk_prepare_enable(vpu->ahb_clk);
> > +   if (ret) {
> > +   dev_err(vpu->dev, "could not enable ahb clock\n");
> > +   return -EFAULT;
> > +   }
> > +   ret = clk_prepare_enable(vpu->mod_clk);
> > +   if (ret) {
> > +   clk_disable_unprepare(vpu->ahb_clk);
> > +   dev_err(vpu->dev, "could not enable mod clock\n");
> > +   return -EFAULT;
> > +   }
> > +   ret = clk_prepare_enable(vpu->ram_clk);
> > +   if (ret) {
> > +   clk_disable_unprepare(vpu->mod_clk);
> > +   clk_disable_unprepare(vpu->ahb_clk);
> > +   dev_err(vpu->dev, "could not enable ram clock\n");
> > +   return -EFAULT;
> > +   }
> 
> Ideally, this should be using runtime_pm to manage the device power
> state, and disable it when not used.

I'll add that to my tasks list. I suppose we shouldn't make this a
priority for now, but this is definitely good to have.

> > +   reset_control_assert(vpu->rstc);
> > +   reset_control_deassert(vpu->rstc);
> 
> You can use reset_control_reset here

Noted!

> > +   return 0;
> > +}
> > +
> > +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *vpu)
> > +{
> > +   clk_disable_unprepare(vpu->ram_clk);
> > +   clk_disable_unprepare(vpu->mod_clk);
> > +   clk_disable_unprepare(vpu->ahb_clk);
> 
> The device is not put back into reset here

Good catch, thanks!

Cheers,

-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

signature.asc
Description: This is a digitally signed message part


Re: [PATCH v6 00/17] Rockchip ISP1 Driver

2018-03-09 Thread Hans Verkuil
Hi Jacob,

This is getting very close. Besides this round of review comments the main
blocker is mbus_config. But Thomasz is looking at that, so I will wait until
that is resolved.

Also for your v7 include the patches from Sakari that add Meta Output support.

This patch series relies on those, so it is easiest to review if they are part
of the patch series.

Regards,

Hans

On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> changes in V6:
>   - add mipi txrx phy support
>   - remove bool and enum from uapi header
>   - add buf_prepare op
>   - correct some spelling problems
>   - return all queued buffers when starting stream failed
> 
> changes in V5: Sync with local changes,
>   - fix the SP height limit
>   - speed up the second stream capture
>   - the second stream can't force sync for rsz when start/stop streaming
>   - add frame id to param vb2 buf
>   - enable luminance maximum threshold
> 
> changes in V4:
>   - fix some bugs during development
>   - move quantization settings to rkisp1 subdev
>   - correct some spelling problems
>   - describe ports in dt-binding documents
> 
> changes in V3:
>   - add some comments
>   - fix wrong use of v4l2_async_subdev_notifier_register
>   - optimize two paths capture at a time
>   - remove compose
>   - re-struct headers
>   - add a tmp wiki page: http://opensource.rock-chips.com/wiki_Rockchip-isp1
> 
> changes in V2:
>   mipi-phy:
> - use async probing
> - make it be a child device of the GRF
>   isp:
> - add dummy buffer
> - change the way to get bus configuration, which make it possible to
> add parallel sensor support in the future(without mipi-phy 
> driver).
> 
> This patch series add a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 
> SoC.
> 
> Wiki Pages:
> http://opensource.rock-chips.com/wiki_Rockchip-isp1
> 
> The deprecated g_mbus_config op is not dropped in  V6 because i am waiting 
> tomasz's patches.
> 
> v4l2-compliance for V6(isp params/stats nodes are passed):
> 
> v4l2-compliance SHA   : 93dc5f20727fede5097d67f8b9adabe4b8046d5b
> 
> Compliance test for device /dev/video0:
> 
> Driver Info:
> Driver name  : rkisp1
> Card type: rkisp1
> Bus info : platform:ff91.isp
> Driver version   : 4.16.0
> Capabilities : 0x84201000
> Video Capture Multiplanar
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps  : 0x04201000
> Video Capture Multiplanar
> Streaming
> Extended Pix Format
> Media Driver Info:
> Driver name  : rkisp1
> Model: rkisp1
> Serial   : 
> Bus info : 
> Media version: 4.16.0
> Hardware revision: 0x (0)
> Driver version   : 4.16.0
> Interface Info:
> ID   : 0x0307
> Type : V4L Video
> Entity Info:
> ID   : 0x0006 (6)
> Name : rkisp1_selfpath
> Function : V4L2 I/O
> Pad 0x0109   : Sink
>   Link 0x0221: from remote pad 0x104 of entity 
> 'rkisp1-isp-subdev': Data, Enabled
> 
> Required ioctls:
> test MC information (see 'Media Driver Info' above): OK
> test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
> test second /dev/video0 open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
> 
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 1 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test 

Re: [PATCH v6 08/17] media: rkisp1: add capture device driver

2018-03-09 Thread Hans Verkuil
On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> This is the capture device interface driver that provides the v4l2
> user interface. Frames can be received from ISP1.
> 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Shunqian Zheng 
> Signed-off-by: Yichong Zhong 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Eddie Cai 
> Signed-off-by: Jeffy Chen 
> Signed-off-by: Allon Huang 
> Signed-off-by: Tomasz Figa 

Acked-by: Hans Verkuil 

Regards,

Hans


Re: [PATCH v6 07/17] media: rkisp1: add ISP1 params driver

2018-03-09 Thread Hans Verkuil
On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> Add the output video driver that accept params from userspace.
> 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Shunqian Zheng 
> Signed-off-by: Yichong Zhong 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Eddie Cai 
> Signed-off-by: Jeffy Chen 
> Signed-off-by: Allon Huang 
> Signed-off-by: Tomasz Figa 
> ---
>  drivers/media/platform/rockchip/isp1/isp_params.c | 1539 
> +
>  drivers/media/platform/rockchip/isp1/isp_params.h |   49 +
>  2 files changed, 1588 insertions(+)
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
> 
> diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c 
> b/drivers/media/platform/rockchip/isp1/isp_params.c
> new file mode 100644
> index ..747108e02836
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/isp_params.c



> +static int rkisp1_params_querycap(struct file *file,
> +   void *priv, struct v4l2_capability *cap)
> +{
> + struct video_device *vdev = video_devdata(file);
> +
> + strcpy(cap->driver, DRIVER_NAME);

Use strlcpy!

> + strlcpy(cap->card, vdev->name, sizeof(cap->card));
> + strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
> +
> + return 0;
> +}
> +
> +/* ISP params video device IOCTLs */
> +static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
> + .vidioc_reqbufs = vb2_ioctl_reqbufs,
> + .vidioc_querybuf = vb2_ioctl_querybuf,
> + .vidioc_create_bufs = vb2_ioctl_create_bufs,
> + .vidioc_qbuf = vb2_ioctl_qbuf,
> + .vidioc_dqbuf = vb2_ioctl_dqbuf,
> + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
> + .vidioc_expbuf = vb2_ioctl_expbuf,
> + .vidioc_streamon = vb2_ioctl_streamon,
> + .vidioc_streamoff = vb2_ioctl_streamoff,
> + .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
> + .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> + .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> + .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> + .vidioc_querycap = rkisp1_params_querycap,
> + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> +};
> +
> +static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
> +  unsigned int *num_buffers,
> +  unsigned int *num_planes,
> +  unsigned int sizes[],
> +  struct device *alloc_devs[])
> +{
> + struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> +
> + *num_buffers = clamp_t(u32, *num_buffers,
> +RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
> +RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
> +
> + *num_planes = 1;
> +
> + sizes[0] = sizeof(struct rkisp1_isp_params_cfg);
> +
> + INIT_LIST_HEAD(_vdev->params);
> + params_vdev->first_params = true;
> +
> + return 0;
> +}
> +
> +static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> +{
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_buffer *params_buf = to_rkisp1_buffer(vbuf);
> + struct vb2_queue *vq = vb->vb2_queue;
> + struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> + struct rkisp1_isp_params_cfg *new_params;
> + unsigned long flags;
> +
> + unsigned int cur_frame_id = -1;
> + cur_frame_id = atomic_read(_vdev->dev->isp_sdev.frm_sync_seq) - 
> 1;
> +
> + if (params_vdev->first_params) {
> + new_params = (struct rkisp1_isp_params_cfg *)
> + (vb2_plane_vaddr(vb, 0));
> + vbuf->sequence = cur_frame_id;
> + vb2_buffer_done(_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
> + params_vdev->first_params = false;
> + params_vdev->cur_params = *new_params;
> + return;
> + }
> +
> + params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
> + spin_lock_irqsave(_vdev->config_lock, flags);
> + list_add_tail(_buf->queue, _vdev->params);
> + spin_unlock_irqrestore(_vdev->config_lock, flags);
> +}
> +
> +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +{
> +if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_isp_params_cfg))
> +return -EINVAL;
> +
> +vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_isp_params_cfg));
> +
> + return 0;
> +}
> +
> +static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> +{
> + struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> + struct rkisp1_buffer 

Re: [PATCH v6 06/17] media: rkisp1: add ISP1 statistics driver

2018-03-09 Thread Hans Verkuil
On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> Add the capture video driver for rockchip isp1 statistics block.
> 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Shunqian Zheng 
> Signed-off-by: Yichong Zhong 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Eddie Cai 
> Signed-off-by: Jeffy Chen 
> Signed-off-by: Allon Huang 
> Signed-off-by: Tomasz Figa 

Acked-by: Hans Verkuil 

Regards,

Hans


Re: [PATCH v6 05/17] media: rkisp1: add Rockchip ISP1 subdev driver

2018-03-09 Thread Hans Verkuil
On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> Add the subdev driver for rockchip isp1.
> 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Shunqian Zheng 
> Signed-off-by: Yichong Zhong 
> Signed-off-by: Jacob Chen 
> Signed-off-by: Eddie Cai 
> Signed-off-by: Jeffy Chen 
> Signed-off-by: Allon Huang 
> Signed-off-by: Tomasz Figa 
> ---
>  drivers/media/platform/rockchip/isp1/rkisp1.c | 1177 
> +
>  drivers/media/platform/rockchip/isp1/rkisp1.h |  105 +++
>  2 files changed, 1282 insertions(+)
>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h
> 
> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c 
> b/drivers/media/platform/rockchip/isp1/rkisp1.c
> new file mode 100644
> index ..bb16c8118c16
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
> @@ -0,0 +1,1177 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "common.h"
> +#include "regs.h"
> +
> +#define CIF_ISP_INPUT_W_MAX  4032
> +#define CIF_ISP_INPUT_H_MAX  3024
> +#define CIF_ISP_INPUT_W_MIN  32
> +#define CIF_ISP_INPUT_H_MIN  32
> +#define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX
> +#define CIF_ISP_OUTPUT_H_MAX CIF_ISP_INPUT_H_MAX
> +#define CIF_ISP_OUTPUT_W_MIN CIF_ISP_INPUT_W_MIN
> +#define CIF_ISP_OUTPUT_H_MIN CIF_ISP_INPUT_H_MIN
> +
> +/*
> + * NOTE: MIPI controller and input MUX are also configured in this file,
> + * because ISP Subdev is not only describe ISP submodule(input size,format, 
> output size, format),
> + * but also a virtual route device.
> + */
> +
> +/*
> + * There are many variables named with format/frame in below code,
> + * please see here for their meaning.
> + *
> + * Cropping regions of ISP
> + *
> + * +-+
> + * | Sensor image|
> + * | +---+   |
> + * | | ISP_ACQ (for black level) |   |
> + * | | in_frm|   |
> + * | | ++|   |
> + * | | |ISP_OUT ||   |
> + * | | |in_crop ||   |
> + * | | |+-+ ||   |
> + * | | ||   ISP_IS| ||   |
> + * | | ||   rkisp1_isp_subdev: out_crop   | ||   |
> + * | | |+-+ ||   |
> + * | | ++|   |
> + * | +---+   |
> + * +-+
> + */
> +
> +static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
> +{
> + return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
> +}
> +
> +/* Get sensor by enabled media link */
> +static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
> +{
> + struct media_pad *local;
> + struct media_entity *sensor_me;
> +
> + local = >entity.pads[RKISP1_ISP_PAD_SINK];
> + sensor_me = media_entity_remote_pad(local)->entity;
> +
> + return media_entity_to_v4l2_subdev(sensor_me);
> +}
> +
> +static struct rkisp1_sensor_info *sd_to_sensor(struct rkisp1_device *dev,
> +struct v4l2_subdev *sd)
> +{
> + int i;
> +
> + for (i = 0; i < dev->num_sensors; ++i)
> + if (dev->sensors[i].sd == sd)
> + return >sensors[i];
> +
> + return NULL;
> +}
> +
> +/  register operations /
> +
> +/*
> + * Image Stabilization.
> + * This should only be called when configuring CIF
> + * or at the frame end interrupt
> + */
> +static void rkisp1_config_ism(struct rkisp1_device *dev)
> +{
> + void __iomem *base = dev->base_addr;
> + struct v4l2_rect *out_crop = >isp_sdev.out_crop;
> + u32 val;
> +
> + writel(0, base + CIF_ISP_IS_RECENTER);
> + writel(0, base + CIF_ISP_IS_MAX_DX);
> + writel(0, base + CIF_ISP_IS_MAX_DY);
> + writel(0, base + CIF_ISP_IS_DISPLACE);
> + writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
> + writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
> + writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
> + writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
> +
> + /* IS(Image Stabilization) is always on, working as 

Re: [PATCH 5/9] media: platform: Add Sunxi Cedrus decoder driver

2018-03-09 Thread Maxime Ripard
Hi,

On Fri, Mar 09, 2018 at 11:14:41AM +0100, Paul Kocialkowski wrote:
> +/*
> + * mem2mem callbacks
> + */
> +
> +void job_abort(void *priv)
> +{}

Is that still needed?

> +/*
> + * device_run() - prepares and starts processing
> + */
> +void device_run(void *priv)
> +{

This function (and the one above) should probably made static. Or at
least if you can't, they should have a much more specific name in
order not to conflict with anything from the core.


> + /*
> +  * The VPU is only able to handle bus addresses so we have to subtract
> +  * the RAM offset to the physcal addresses
> +  */
> + in_buf -= PHYS_OFFSET;
> + out_luma   -= PHYS_OFFSET;
> + out_chroma -= PHYS_OFFSET;

You should take care of that by putting it in the dma_pfn_offset field
of the struct device (at least before we come up with something
better).

You'll then be able to use the dma_addr_t directly without modifying it.

> + vpu->syscon = syscon_regmap_lookup_by_phandle(vpu->dev->of_node,
> +   "syscon");
> + if (IS_ERR(vpu->syscon)) {
> + vpu->syscon = NULL;
> + } else {
> + regmap_write_bits(vpu->syscon, SYSCON_SRAM_CTRL_REG0,
> +   SYSCON_SRAM_C1_MAP_VE,
> +   SYSCON_SRAM_C1_MAP_VE);
> + }

This should be using our SRAM controller driver (and API), see
Documentation/devicetree/bindings/sram/sunxi-sram.txt
include/linux/soc/sunxi/sunxi_sram.h

> + ret = clk_prepare_enable(vpu->ahb_clk);
> + if (ret) {
> + dev_err(vpu->dev, "could not enable ahb clock\n");
> + return -EFAULT;
> + }
> + ret = clk_prepare_enable(vpu->mod_clk);
> + if (ret) {
> + clk_disable_unprepare(vpu->ahb_clk);
> + dev_err(vpu->dev, "could not enable mod clock\n");
> + return -EFAULT;
> + }
> + ret = clk_prepare_enable(vpu->ram_clk);
> + if (ret) {
> + clk_disable_unprepare(vpu->mod_clk);
> + clk_disable_unprepare(vpu->ahb_clk);
> + dev_err(vpu->dev, "could not enable ram clock\n");
> + return -EFAULT;
> + }

Ideally, this should be using runtime_pm to manage the device power
state, and disable it when not used.

> + reset_control_assert(vpu->rstc);
> + reset_control_deassert(vpu->rstc);

You can use reset_control_reset here

> + return 0;
> +}
> +
> +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *vpu)
> +{
> + clk_disable_unprepare(vpu->ram_clk);
> + clk_disable_unprepare(vpu->mod_clk);
> + clk_disable_unprepare(vpu->ahb_clk);

The device is not put back into reset here

Thanks!
Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com


signature.asc
Description: PGP signature


Re: [linux-sunxi] [PATCH 6/9] sunxi-cedrus: Add device tree binding document

2018-03-09 Thread Priit Laes
On Fri, Mar 09, 2018 at 11:14:42AM +0100, Paul Kocialkowski wrote:
> From: Florent Revest 
> 
> Device Tree bindings for the Allwinner's video engine
> 
> Signed-off-by: Florent Revest 
> ---
>  .../devicetree/bindings/media/sunxi-cedrus.txt | 44 
> ++
>  1 file changed, 44 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/sunxi-cedrus.txt
> 
> diff --git a/Documentation/devicetree/bindings/media/sunxi-cedrus.txt 
> b/Documentation/devicetree/bindings/media/sunxi-cedrus.txt
> new file mode 100644
> index ..138581113c49
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/sunxi-cedrus.txt
> @@ -0,0 +1,44 @@
> +Device-Tree bindings for SUNXI video engine found in sunXi SoC family
> +
> +Required properties:
> +- compatible : "allwinner,sun4i-a10-video-engine";
> +- memory-region : DMA pool for buffers allocation;
> +- clocks : list of clock specifiers, corresponding to
> +   entries in clock-names property;
> +- clock-names: should contain "ahb", "mod" and "ram" entries;
> +- resets : phandle for reset;
> +- interrupts : should contain VE interrupt number;
> +- reg: should contain register base and length of VE.
> +
> +Example:
> +
> +reserved-memory {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + ve_reserved: cma {
> + compatible = "shared-dma-pool";
> + reg = <0x43d0 0x900>;
> + no-map;
> + linux,cma-default;
> + };
> +};
> +
> +video-engine {
> + compatible = "allwinner,sun4i-a10-video-engine";
> + memory-region = <_reserved>;
> +
> + clocks = <_gates 32>, < CLK_VE>,
> +  <_gates 0>;

This should be updated to sunxi-ng clocks:

clocks = < CLK_BUS_VE>, < CLK_VE>, < CLK_DRAM_VE>;

> + clock-names = "ahb", "mod", "ram";
> +
> + assigned-clocks = < CLK_VE>;
> + assigned-clock-rates = <32000>;
> +
> + resets = < RST_VE>;
> +
> + interrupts = <53>;
> +
> + reg = <0x01c0e000 4096>;
> +};
> -- 
> 2.16.2
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to linux-sunxi+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.


Re: [linux-sunxi] [PATCH 6/9] sunxi-cedrus: Add device tree binding document

2018-03-09 Thread Paul Kocialkowski
Hi,

Thanks for the review!

On Fri, 2018-03-09 at 15:38 +0200, Priit Laes wrote:
> On Fri, Mar 09, 2018 at 11:14:42AM +0100, Paul Kocialkowski wrote:
> > From: Florent Revest 
> > 
> > Device Tree bindings for the Allwinner's video engine
> > 
> > Signed-off-by: Florent Revest 
> > ---
> >  .../devicetree/bindings/media/sunxi-cedrus.txt | 44
> > ++
> >  1 file changed, 44 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/media/sunxi-
> > cedrus.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/media/sunxi-
> > cedrus.txt b/Documentation/devicetree/bindings/media/sunxi-
> > cedrus.txt
> > new file mode 100644
> > index ..138581113c49
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/sunxi-cedrus.txt
> > @@ -0,0 +1,44 @@
> > +Device-Tree bindings for SUNXI video engine found in sunXi SoC
> > family
> > +
> > +Required properties:
> > +- compatible   : "allwinner,sun4i-a10-video-engine";
> > +- memory-region : DMA pool for buffers allocation;
> > +- clocks   : list of clock specifiers, corresponding to
> > + entries in clock-names property;
> > +- clock-names  : should contain "ahb", "mod" and "ram"
> > entries;
> > +- resets   : phandle for reset;
> > +- interrupts   : should contain VE interrupt number;
> > +- reg  : should contain register base and length
> > of VE.
> > +
> > +Example:
> > +
> > +reserved-memory {
> > +   #address-cells = <1>;
> > +   #size-cells = <1>;
> > +   ranges;
> > +
> > +   ve_reserved: cma {
> > +   compatible = "shared-dma-pool";
> > +   reg = <0x43d0 0x900>;
> > +   no-map;
> > +   linux,cma-default;
> > +   };
> > +};
> > +
> > +video-engine {
> > +   compatible = "allwinner,sun4i-a10-video-engine";
> > +   memory-region = <_reserved>;
> > +
> > +   clocks = <_gates 32>, < CLK_VE>,
> > +<_gates 0>;
> 
> This should be updated to sunxi-ng clocks:
> 
> clocks = < CLK_BUS_VE>, < CLK_VE>, < CLK_DRAM_VE>;

I will definitely keep that in mind and make the change for the next
revision, thanks!

> > +   clock-names = "ahb", "mod", "ram";
> > +
> > +   assigned-clocks = < CLK_VE>;
> > +   assigned-clock-rates = <32000>;
> > +
> > +   resets = < RST_VE>;
> > +
> > +   interrupts = <53>;
> > +
> > +   reg = <0x01c0e000 4096>;
> > +};
> > -- 
> > 2.16.2
> > 
> > -- 
> > You received this message because you are subscribed to the Google
> > Groups "linux-sunxi" group.
> > To unsubscribe from this group and stop receiving emails from it,
> > send an email to linux-sunxi+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

signature.asc
Description: This is a digitally signed message part


Re: [PATCH v6 02/17] media: doc: add document for rkisp1 meta buffer format

2018-03-09 Thread Hans Verkuil
On 08/03/18 10:47, Jacob Chen wrote:
> From: Jacob Chen 
> 
> This commit add docuemnt for rkisp1 meta buffer format
> 
> Signed-off-by: Jacob Chen 
> Acked-by: Hans Verkuil 
> ---
>  Documentation/media/uapi/v4l/meta-formats.rst|  2 ++
>  .../media/uapi/v4l/pixfmt-meta-rkisp1-params.rst | 20 
> 
>  .../media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst   | 18 ++
>  3 files changed, 40 insertions(+)
>  create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
>  create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
> 
> diff --git a/Documentation/media/uapi/v4l/meta-formats.rst 
> b/Documentation/media/uapi/v4l/meta-formats.rst
> index 0c4e1ecf5879..44e7edbf1dae 100644
> --- a/Documentation/media/uapi/v4l/meta-formats.rst
> +++ b/Documentation/media/uapi/v4l/meta-formats.rst
> @@ -15,3 +15,5 @@ These formats are used for the :ref:`metadata` interface 
> only.
>  pixfmt-meta-uvc
>  pixfmt-meta-vsp1-hgo
>  pixfmt-meta-vsp1-hgt
> +pixfmt-meta-rkisp1-params
> +pixfmt-meta-rkisp1-stat
> diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst 
> b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
> new file mode 100644
> index ..2ff4f4309795
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
> @@ -0,0 +1,20 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _v4l2-meta-fmt-rkisp1-params:
> +
> +***
> +V4L2_META_FMT_RK_ISP1_PARAMS
> +***
> +
> +Rockchip ISP1 Parameters Data
> +
> +Description
> +===
> +
> +This format describes input parameters for the Rockchip ISP1.
> +
> +It uses c-struct :c:type:`rkisp1_isp_params_cfg`, which is defined in
> +the ``linux/rkisp1-config.h`` header file, see it for details.
> +
> +The parameters consist of multiple modules.
> +The module won't be updated if the correspond bit was not set in 
> module_*_update.

correspond -> corresponding

> diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst 
> b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
> new file mode 100644
> index ..dca8befe58f1
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
> @@ -0,0 +1,18 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _v4l2-meta-fmt-rkisp1-stat:
> +
> +***
> +V4L2_META_FMT_RK_ISP1_STAT_3A
> +***
> +
> +Rockchip ISP1 Statistics Data
> +
> +Description
> +===
> +
> +This format describes image color statistics information generated by the 
> Rockchip
> +ISP1.
> +
> +It use c-struct :c:type:`rkisp1_stat_buffer`, which is defined in

use -> uses

> +the ``linux/cifisp_stat.h`` header file, see it for details.
> 

Regards,

Hans


Re: [PATCH v6 03/17] media: rkisp1: Add user space ABI definitions

2018-03-09 Thread Hans Verkuil
A quick review:

On 08/03/18 10:47, Jacob Chen wrote:
> From: Jeffy Chen 
> 
> Add the header for userspace
> 
> Signed-off-by: Jeffy Chen 
> Signed-off-by: Jacob Chen 
> ---
>  include/uapi/linux/rkisp1-config.h | 798 
> +
>  1 file changed, 798 insertions(+)
>  create mode 100644 include/uapi/linux/rkisp1-config.h
> 
> diff --git a/include/uapi/linux/rkisp1-config.h 
> b/include/uapi/linux/rkisp1-config.h
> new file mode 100644
> index ..1284eb9fd09d
> --- /dev/null
> +++ b/include/uapi/linux/rkisp1-config.h
> @@ -0,0 +1,798 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip isp1 driver
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +/*
> + * References:
> + * REF_01 - ISP_user_manual, Rev 2.57

So this is internal to Rockchip and not available at all?
That should be mentioned otherwise people will ask you for it :-)

> + */
> +
> +#ifndef _UAPI_RKISP1_CONFIG_H
> +#define _UAPI_RKISP1_CONFIG_H
> +
> +#include 
> +#include 
> +
> +#define CIFISP_MODULE_DPCC  (1 << 0)
> +#define CIFISP_MODULE_BLS   (1 << 1)
> +#define CIFISP_MODULE_SDG   (1 << 2)
> +#define CIFISP_MODULE_HST   (1 << 3)
> +#define CIFISP_MODULE_LSC   (1 << 4)
> +#define CIFISP_MODULE_AWB_GAIN  (1 << 5)
> +#define CIFISP_MODULE_FLT   (1 << 6)
> +#define CIFISP_MODULE_BDM   (1 << 7)
> +#define CIFISP_MODULE_CTK   (1 << 8)
> +#define CIFISP_MODULE_GOC   (1 << 9)
> +#define CIFISP_MODULE_CPROC (1 << 10)
> +#define CIFISP_MODULE_AFC   (1 << 11)
> +#define CIFISP_MODULE_AWB   (1 << 12)
> +#define CIFISP_MODULE_IE(1 << 13)
> +#define CIFISP_MODULE_AEC   (1 << 14)
> +#define CIFISP_MODULE_WDR   (1 << 15)
> +#define CIFISP_MODULE_DPF   (1 << 16)
> +#define CIFISP_MODULE_DPF_STRENGTH  (1 << 17)

Are these abbreviations (DPCC, BLS, etc) documented somewhere publicly?
If not, can you add a short comment before each define explaining what
the abbreviation means?

I see that these abbreviations are actually defined later on with
struct cifisp_isp_other_cfg. I still think they should also be documented
here at the start of the header.

> +
> +#define CIFISP_CTK_COEFF_MAX0x100
> +#define CIFISP_CTK_OFFSET_MAX   0x800
> +
> +#define CIFISP_AE_MEAN_MAX  25
> +#define CIFISP_HIST_BIN_N_MAX   16
> +#define CIFISP_AFM_MAX_WINDOWS  3
> +#define CIFISP_DEGAMMA_CURVE_SIZE   17
> +
> +#define CIFISP_BDM_MAX_TH   0xFF
> +
> +/*
> + * Black level compensation
> + */
> +/* maximum value for horizontal start address */
> +#define CIFISP_BLS_START_H_MAX 0x0FFF
> +/* maximum value for horizontal stop address */
> +#define CIFISP_BLS_STOP_H_MAX  0x0FFF
> +/* maximum value for vertical start address */
> +#define CIFISP_BLS_START_V_MAX 0x0FFF
> +/* maximum value for vertical stop address */
> +#define CIFISP_BLS_STOP_V_MAX  0x0FFF
> +/* maximum is 2^18 = 262144*/
> +#define CIFISP_BLS_SAMPLES_MAX 0x0012
> +/* maximum value for fixed black level */
> +#define CIFISP_BLS_FIX_SUB_MAX 0x0FFF
> +/* minimum value for fixed black level */
> +#define CIFISP_BLS_FIX_SUB_MIN 0xF000
> +/* 13 bit range (signed)*/
> +#define CIFISP_BLS_FIX_MASK0x1FFF
> +
> +/*
> + * Automatic white balance measurments

measurments -> measurements

> + */
> +#define CIFISP_AWB_MAX_GRID1
> +#define CIFISP_AWB_MAX_FRAMES  7
> +
> +/*
> + * Gamma out
> + */
> +/* Maximum number of color samples supported */
> +#define CIFISP_GAMMA_OUT_MAX_SAMPLES   17
> +
> +/*
> + * Lens shade correction
> + */
> +#define CIFISP_LSC_GRAD_TBL_SIZE   8
> +#define CIFISP_LSC_SIZE_TBL_SIZE   8
> +/*
> + * The following matches the tuning process,
> + * not the max capabilities of the chip.
> + * Last value unused.
> + */
> +#define  CIFISP_LSC_DATA_TBL_SIZE   290
> +
> +/*
> + * Histogram calculation
> + */
> +/* Last 3 values unused. */
> +#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28
> +
> +/*
> + * Defect Pixel Cluster Correction
> + */
> +#define CIFISP_DPCC_METHODS_MAX   3
> +
> +/*
> + * Denoising pre filter
> + */
> +#define CIFISP_DPF_MAX_NLF_COEFFS  17
> +#define CIFISP_DPF_MAX_SPATIAL_COEFFS  6
> +
> +/*
> + * Measurement types
> + */
> +#define CIFISP_STAT_AWB   (1 << 0)
> +#define CIFISP_STAT_AUTOEXP   (1 << 1)
> +#define CIFISP_STAT_AFM_FIN   (1 << 2)

AFM_FIN could use a short comment explaining what it means.

> +#define CIFISP_STAT_HIST  (1 << 3)
> +
> +enum cifisp_histogram_mode {
> + CIFISP_HISTOGRAM_MODE_DISABLE,
> + 

  1   2   >