aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/ipu3/ipu3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/ipu3/ipu3.c')
-rw-r--r--drivers/staging/media/ipu3/ipu3.c284
1 files changed, 135 insertions, 149 deletions
diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c
index 3d0a34b86ff4..b7886edeb01b 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -45,7 +45,6 @@ static const struct imgu_node_mapping imgu_node_map[IMGU_NODE_NUM] = {
[IMGU_NODE_PARAMS] = {IPU3_CSS_QUEUE_PARAMS, "parameters"},
[IMGU_NODE_OUT] = {IPU3_CSS_QUEUE_OUT, "output"},
[IMGU_NODE_VF] = {IPU3_CSS_QUEUE_VF, "viewfinder"},
- [IMGU_NODE_PV] = {IPU3_CSS_QUEUE_VF, "postview"},
[IMGU_NODE_STAT_3A] = {IPU3_CSS_QUEUE_STAT_3A, "3a stat"},
};
@@ -58,10 +57,6 @@ unsigned int imgu_map_node(struct imgu_device *imgu, unsigned int css_queue)
{
unsigned int i;
- if (css_queue == IPU3_CSS_QUEUE_VF)
- return imgu->nodes[IMGU_NODE_VF].enabled ?
- IMGU_NODE_VF : IMGU_NODE_PV;
-
for (i = 0; i < IMGU_NODE_NUM; i++)
if (imgu_node_map[i].css_queue == css_queue)
break;
@@ -71,18 +66,22 @@ unsigned int imgu_map_node(struct imgu_device *imgu, unsigned int css_queue)
/**************** Dummy buffers ****************/
-static void imgu_dummybufs_cleanup(struct imgu_device *imgu)
+static void imgu_dummybufs_cleanup(struct imgu_device *imgu, unsigned int pipe)
{
unsigned int i;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
for (i = 0; i < IPU3_CSS_QUEUES; i++)
- ipu3_dmamap_free(imgu, &imgu->queues[i].dmap);
+ ipu3_dmamap_free(imgu,
+ &imgu_pipe->queues[i].dmap);
}
-static int imgu_dummybufs_preallocate(struct imgu_device *imgu)
+static int imgu_dummybufs_preallocate(struct imgu_device *imgu,
+ unsigned int pipe)
{
unsigned int i;
size_t size;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
for (i = 0; i < IPU3_CSS_QUEUES; i++) {
size = css_queue_buf_size_map[i];
@@ -94,8 +93,9 @@ static int imgu_dummybufs_preallocate(struct imgu_device *imgu)
if (i == IMGU_QUEUE_MASTER || size == 0)
continue;
- if (!ipu3_dmamap_alloc(imgu, &imgu->queues[i].dmap, size)) {
- imgu_dummybufs_cleanup(imgu);
+ if (!ipu3_dmamap_alloc(imgu,
+ &imgu_pipe->queues[i].dmap, size)) {
+ imgu_dummybufs_cleanup(imgu, pipe);
return -ENOMEM;
}
}
@@ -103,45 +103,46 @@ static int imgu_dummybufs_preallocate(struct imgu_device *imgu)
return 0;
}
-static int imgu_dummybufs_init(struct imgu_device *imgu)
+static int imgu_dummybufs_init(struct imgu_device *imgu, unsigned int pipe)
{
const struct v4l2_pix_format_mplane *mpix;
const struct v4l2_meta_format *meta;
- unsigned int i, j, node;
+ unsigned int i, k, node;
size_t size;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
/* Allocate a dummy buffer for each queue where buffer is optional */
for (i = 0; i < IPU3_CSS_QUEUES; i++) {
node = imgu_map_node(imgu, i);
- if (!imgu->queue_enabled[node] || i == IMGU_QUEUE_MASTER)
+ if (!imgu_pipe->queue_enabled[node] || i == IMGU_QUEUE_MASTER)
continue;
- if (!imgu->nodes[IMGU_NODE_VF].enabled &&
- !imgu->nodes[IMGU_NODE_PV].enabled &&
+ if (!imgu_pipe->nodes[IMGU_NODE_VF].enabled &&
i == IPU3_CSS_QUEUE_VF)
/*
- * Do not enable dummy buffers for VF/PV if it is not
+ * Do not enable dummy buffers for VF if it is not
* requested by the user.
*/
continue;
- meta = &imgu->nodes[node].vdev_fmt.fmt.meta;
- mpix = &imgu->nodes[node].vdev_fmt.fmt.pix_mp;
+ meta = &imgu_pipe->nodes[node].vdev_fmt.fmt.meta;
+ mpix = &imgu_pipe->nodes[node].vdev_fmt.fmt.pix_mp;
if (node == IMGU_NODE_STAT_3A || node == IMGU_NODE_PARAMS)
size = meta->buffersize;
else
size = mpix->plane_fmt[0].sizeimage;
- if (ipu3_css_dma_buffer_resize(imgu, &imgu->queues[i].dmap,
+ if (ipu3_css_dma_buffer_resize(imgu,
+ &imgu_pipe->queues[i].dmap,
size)) {
- imgu_dummybufs_cleanup(imgu);
+ imgu_dummybufs_cleanup(imgu, pipe);
return -ENOMEM;
}
- for (j = 0; j < IMGU_MAX_QUEUE_DEPTH; j++)
- ipu3_css_buf_init(&imgu->queues[i].dummybufs[j], i,
- imgu->queues[i].dmap.daddr);
+ for (k = 0; k < IMGU_MAX_QUEUE_DEPTH; k++)
+ ipu3_css_buf_init(&imgu_pipe->queues[i].dummybufs[k], i,
+ imgu_pipe->queues[i].dmap.daddr);
}
return 0;
@@ -149,40 +150,43 @@ static int imgu_dummybufs_init(struct imgu_device *imgu)
/* May be called from atomic context */
static struct ipu3_css_buffer *imgu_dummybufs_get(struct imgu_device *imgu,
- int queue)
+ int queue, unsigned int pipe)
{
unsigned int i;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
/* dummybufs are not allocated for master q */
if (queue == IPU3_CSS_QUEUE_IN)
return NULL;
- if (WARN_ON(!imgu->queues[queue].dmap.vaddr))
+ if (WARN_ON(!imgu_pipe->queues[queue].dmap.vaddr))
/* Buffer should not be allocated here */
return NULL;
for (i = 0; i < IMGU_MAX_QUEUE_DEPTH; i++)
- if (ipu3_css_buf_state(&imgu->queues[queue].dummybufs[i]) !=
+ if (ipu3_css_buf_state(&imgu_pipe->queues[queue].dummybufs[i]) !=
IPU3_CSS_BUFFER_QUEUED)
break;
if (i == IMGU_MAX_QUEUE_DEPTH)
return NULL;
- ipu3_css_buf_init(&imgu->queues[queue].dummybufs[i], queue,
- imgu->queues[queue].dmap.daddr);
+ ipu3_css_buf_init(&imgu_pipe->queues[queue].dummybufs[i], queue,
+ imgu_pipe->queues[queue].dmap.daddr);
- return &imgu->queues[queue].dummybufs[i];
+ return &imgu_pipe->queues[queue].dummybufs[i];
}
/* Check if given buffer is a dummy buffer */
static bool imgu_dummybufs_check(struct imgu_device *imgu,
- struct ipu3_css_buffer *buf)
+ struct ipu3_css_buffer *buf,
+ unsigned int pipe)
{
unsigned int i;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
for (i = 0; i < IMGU_MAX_QUEUE_DEPTH; i++)
- if (buf == &imgu->queues[buf->queue].dummybufs[i])
+ if (buf == &imgu_pipe->queues[buf->queue].dummybufs[i])
break;
return i < IMGU_MAX_QUEUE_DEPTH;
@@ -197,63 +201,64 @@ static void imgu_buffer_done(struct imgu_device *imgu, struct vb2_buffer *vb,
}
static struct ipu3_css_buffer *imgu_queue_getbuf(struct imgu_device *imgu,
- unsigned int node)
+ unsigned int node,
+ unsigned int pipe)
{
struct imgu_buffer *buf;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
if (WARN_ON(node >= IMGU_NODE_NUM))
return NULL;
/* Find first free buffer from the node */
- list_for_each_entry(buf, &imgu->nodes[node].buffers, vid_buf.list) {
+ list_for_each_entry(buf, &imgu_pipe->nodes[node].buffers, vid_buf.list) {
if (ipu3_css_buf_state(&buf->css_buf) == IPU3_CSS_BUFFER_NEW)
return &buf->css_buf;
}
/* There were no free buffers, try to return a dummy buffer */
- return imgu_dummybufs_get(imgu, imgu_node_map[node].css_queue);
+ return imgu_dummybufs_get(imgu, imgu_node_map[node].css_queue, pipe);
}
/*
* Queue as many buffers to CSS as possible. If all buffers don't fit into
* CSS buffer queues, they remain unqueued and will be queued later.
*/
-int imgu_queue_buffers(struct imgu_device *imgu, bool initial)
+int imgu_queue_buffers(struct imgu_device *imgu, bool initial, unsigned int pipe)
{
unsigned int node;
int r = 0;
struct imgu_buffer *ibuf;
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
if (!ipu3_css_is_streaming(&imgu->css))
return 0;
+ dev_dbg(&imgu->pci_dev->dev, "Queue buffers to pipe %d", pipe);
mutex_lock(&imgu->lock);
/* Buffer set is queued to FW only when input buffer is ready */
for (node = IMGU_NODE_NUM - 1;
- imgu_queue_getbuf(imgu, IMGU_NODE_IN);
+ imgu_queue_getbuf(imgu, IMGU_NODE_IN, pipe);
node = node ? node - 1 : IMGU_NODE_NUM - 1) {
if (node == IMGU_NODE_VF &&
- (imgu->css.pipe_id == IPU3_CSS_PIPE_ID_CAPTURE ||
- !imgu->nodes[IMGU_NODE_VF].enabled)) {
- continue;
- } else if (node == IMGU_NODE_PV &&
- (imgu->css.pipe_id == IPU3_CSS_PIPE_ID_VIDEO ||
- !imgu->nodes[IMGU_NODE_PV].enabled)) {
+ !imgu_pipe->nodes[IMGU_NODE_VF].enabled) {
+ dev_warn(&imgu->pci_dev->dev,
+ "Vf not enabled, ignore queue");
continue;
- } else if (imgu->queue_enabled[node]) {
+ } else if (imgu_pipe->queue_enabled[node]) {
struct ipu3_css_buffer *buf =
- imgu_queue_getbuf(imgu, node);
+ imgu_queue_getbuf(imgu, node, pipe);
int dummy;
if (!buf)
break;
- r = ipu3_css_buf_queue(&imgu->css, buf);
+ r = ipu3_css_buf_queue(&imgu->css, pipe, buf);
if (r)
break;
- dummy = imgu_dummybufs_check(imgu, buf);
+ dummy = imgu_dummybufs_check(imgu, buf, pipe);
if (!dummy)
ibuf = container_of(buf, struct imgu_buffer,
css_buf);
@@ -288,14 +293,15 @@ failed:
for (node = 0; node < IMGU_NODE_NUM; node++) {
struct imgu_buffer *buf, *buf0;
- if (!imgu->queue_enabled[node])
+ if (!imgu_pipe->queue_enabled[node])
continue; /* Skip disabled queues */
mutex_lock(&imgu->lock);
- list_for_each_entry_safe(buf, buf0, &imgu->nodes[node].buffers,
+ list_for_each_entry_safe(buf, buf0,
+ &imgu_pipe->nodes[node].buffers,
vid_buf.list) {
if (ipu3_css_buf_state(&buf->css_buf) ==
- IPU3_CSS_BUFFER_QUEUED)
+ IPU3_CSS_BUFFER_QUEUED)
continue; /* Was already queued, skip */
imgu_v4l2_buffer_done(&buf->vid_buf.vbb.vb2_buf,
@@ -328,10 +334,7 @@ static void imgu_powerdown(struct imgu_device *imgu)
int imgu_s_stream(struct imgu_device *imgu, int enable)
{
struct device *dev = &imgu->pci_dev->dev;
- struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES] = { NULL };
- struct v4l2_rect *rects[IPU3_CSS_RECTS] = { NULL };
- unsigned int i, node;
- int r;
+ int r, pipe;
if (!enable) {
/* Stop streaming */
@@ -347,54 +350,6 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
return 0;
}
- /* Start streaming */
-
- dev_dbg(dev, "stream on\n");
- for (i = 0; i < IMGU_NODE_NUM; i++)
- imgu->queue_enabled[i] = imgu->nodes[i].enabled;
-
- /*
- * CSS library expects that the following queues are
- * always enabled; if buffers are not provided to some of the
- * queues, it stalls due to lack of buffers.
- * Force the queues to be enabled and if the user really hasn't
- * enabled them, use dummy buffers.
- */
- imgu->queue_enabled[IMGU_NODE_OUT] = true;
- imgu->queue_enabled[IMGU_NODE_VF] = true;
- imgu->queue_enabled[IMGU_NODE_PV] = true;
- imgu->queue_enabled[IMGU_NODE_STAT_3A] = true;
-
- /* This is handled specially */
- imgu->queue_enabled[IPU3_CSS_QUEUE_PARAMS] = false;
-
- /* Initialize CSS formats */
- for (i = 0; i < IPU3_CSS_QUEUES; i++) {
- node = imgu_map_node(imgu, i);
- /* No need to reconfig meta nodes */
- if (node == IMGU_NODE_STAT_3A || node == IMGU_NODE_PARAMS)
- continue;
- fmts[i] = imgu->queue_enabled[node] ?
- &imgu->nodes[node].vdev_fmt.fmt.pix_mp : NULL;
- }
-
- /* Enable VF output only when VF or PV queue requested by user */
- imgu->css.vf_output_en = IPU3_NODE_VF_DISABLED;
- if (imgu->nodes[IMGU_NODE_VF].enabled)
- imgu->css.vf_output_en = IPU3_NODE_VF_ENABLED;
- else if (imgu->nodes[IMGU_NODE_PV].enabled)
- imgu->css.vf_output_en = IPU3_NODE_PV_ENABLED;
-
- rects[IPU3_CSS_RECT_EFFECTIVE] = &imgu->rect.eff;
- rects[IPU3_CSS_RECT_BDS] = &imgu->rect.bds;
- rects[IPU3_CSS_RECT_GDC] = &imgu->rect.gdc;
-
- r = ipu3_css_fmt_set(&imgu->css, fmts, rects);
- if (r) {
- dev_err(dev, "failed to set initial formats (%d)", r);
- return r;
- }
-
/* Set Power */
r = pm_runtime_get_sync(dev);
if (r < 0) {
@@ -417,24 +372,26 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
goto fail_start_streaming;
}
- /* Initialize dummy buffers */
- r = imgu_dummybufs_init(imgu);
- if (r) {
- dev_err(dev, "failed to initialize dummy buffers (%d)", r);
- goto fail_dummybufs;
- }
+ for_each_set_bit(pipe, imgu->css.enabled_pipes, IMGU_MAX_PIPE_NUM) {
+ /* Initialize dummy buffers */
+ r = imgu_dummybufs_init(imgu, pipe);
+ if (r) {
+ dev_err(dev, "failed to initialize dummy buffers (%d)", r);
+ goto fail_dummybufs;
+ }
- /* Queue as many buffers from queue as possible */
- r = imgu_queue_buffers(imgu, true);
- if (r) {
- dev_err(dev, "failed to queue initial buffers (%d)", r);
- goto fail_queueing;
+ /* Queue as many buffers from queue as possible */
+ r = imgu_queue_buffers(imgu, true, pipe);
+ if (r) {
+ dev_err(dev, "failed to queue initial buffers (%d)", r);
+ goto fail_queueing;
+ }
}
return 0;
-
fail_queueing:
- imgu_dummybufs_cleanup(imgu);
+ for_each_set_bit(pipe, imgu->css.enabled_pipes, IMGU_MAX_PIPE_NUM)
+ imgu_dummybufs_cleanup(imgu, pipe);
fail_dummybufs:
ipu3_css_stop_streaming(&imgu->css);
fail_start_streaming:
@@ -447,51 +404,66 @@ static int imgu_video_nodes_init(struct imgu_device *imgu)
{
struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES] = { NULL };
struct v4l2_rect *rects[IPU3_CSS_RECTS] = { NULL };
- unsigned int i;
+ struct imgu_media_pipe *imgu_pipe;
+ unsigned int i, j;
int r;
imgu->buf_struct_size = sizeof(struct imgu_buffer);
- for (i = 0; i < IMGU_NODE_NUM; i++) {
- imgu->nodes[i].name = imgu_node_map[i].name;
- imgu->nodes[i].output = i < IMGU_QUEUE_FIRST_INPUT;
- imgu->nodes[i].immutable = false;
- imgu->nodes[i].enabled = false;
+ for (j = 0; j < IMGU_MAX_PIPE_NUM; j++) {
+ imgu_pipe = &imgu->imgu_pipe[j];
- if (i != IMGU_NODE_PARAMS && i != IMGU_NODE_STAT_3A)
- fmts[imgu_node_map[i].css_queue] =
- &imgu->nodes[i].vdev_fmt.fmt.pix_mp;
- atomic_set(&imgu->nodes[i].sequence, 0);
- }
+ for (i = 0; i < IMGU_NODE_NUM; i++) {
+ imgu_pipe->nodes[i].name = imgu_node_map[i].name;
+ imgu_pipe->nodes[i].output = i < IMGU_QUEUE_FIRST_INPUT;
+ imgu_pipe->nodes[i].enabled = false;
- /* Master queue is always enabled */
- imgu->nodes[IMGU_QUEUE_MASTER].immutable = true;
- imgu->nodes[IMGU_QUEUE_MASTER].enabled = true;
+ if (i != IMGU_NODE_PARAMS && i != IMGU_NODE_STAT_3A)
+ fmts[imgu_node_map[i].css_queue] =
+ &imgu_pipe->nodes[i].vdev_fmt.fmt.pix_mp;
+ atomic_set(&imgu_pipe->nodes[i].sequence, 0);
+ }
+ }
r = imgu_v4l2_register(imgu);
if (r)
return r;
/* Set initial formats and initialize formats of video nodes */
- rects[IPU3_CSS_RECT_EFFECTIVE] = &imgu->rect.eff;
- rects[IPU3_CSS_RECT_BDS] = &imgu->rect.bds;
- ipu3_css_fmt_set(&imgu->css, fmts, rects);
+ for (j = 0; j < IMGU_MAX_PIPE_NUM; j++) {
+ imgu_pipe = &imgu->imgu_pipe[j];
- /* Pre-allocate dummy buffers */
- r = imgu_dummybufs_preallocate(imgu);
- if (r) {
- dev_err(&imgu->pci_dev->dev,
- "failed to pre-allocate dummy buffers (%d)", r);
- imgu_dummybufs_cleanup(imgu);
- imgu_v4l2_unregister(imgu);
+ rects[IPU3_CSS_RECT_EFFECTIVE] = &imgu_pipe->imgu_sd.rect.eff;
+ rects[IPU3_CSS_RECT_BDS] = &imgu_pipe->imgu_sd.rect.bds;
+ ipu3_css_fmt_set(&imgu->css, fmts, rects, j);
+
+ /* Pre-allocate dummy buffers */
+ r = imgu_dummybufs_preallocate(imgu, j);
+ if (r) {
+ dev_err(&imgu->pci_dev->dev,
+ "failed to pre-allocate dummy buffers (%d)", r);
+ goto out_cleanup;
+ }
}
return 0;
+
+out_cleanup:
+ for (j = 0; j < IMGU_MAX_PIPE_NUM; j++)
+ imgu_dummybufs_cleanup(imgu, j);
+
+ imgu_v4l2_unregister(imgu);
+
+ return r;
}
static void imgu_video_nodes_exit(struct imgu_device *imgu)
{
- imgu_dummybufs_cleanup(imgu);
+ int i;
+
+ for (i = 0; i < IMGU_MAX_PIPE_NUM; i++)
+ imgu_dummybufs_cleanup(imgu, i);
+
imgu_v4l2_unregister(imgu);
}
@@ -500,13 +472,15 @@ static void imgu_video_nodes_exit(struct imgu_device *imgu)
static irqreturn_t imgu_isr_threaded(int irq, void *imgu_ptr)
{
struct imgu_device *imgu = imgu_ptr;
+ struct imgu_media_pipe *imgu_pipe;
+ int p;
/* Dequeue / queue buffers */
do {
u64 ns = ktime_get_ns();
struct ipu3_css_buffer *b;
struct imgu_buffer *buf;
- unsigned int node;
+ unsigned int node, pipe;
bool dummy;
do {
@@ -525,25 +499,31 @@ static irqreturn_t imgu_isr_threaded(int irq, void *imgu_ptr)
}
node = imgu_map_node(imgu, b->queue);
- dummy = imgu_dummybufs_check(imgu, b);
+ pipe = b->pipe;
+ dummy = imgu_dummybufs_check(imgu, b, pipe);
if (!dummy)
buf = container_of(b, struct imgu_buffer, css_buf);
dev_dbg(&imgu->pci_dev->dev,
- "dequeue %s %s buffer %d from css\n",
+ "dequeue %s %s buffer %d daddr 0x%x from css\n",
dummy ? "dummy" : "user",
imgu_node_map[node].name,
- dummy ? 0 : buf->vid_buf.vbb.vb2_buf.index);
+ dummy ? 0 : buf->vid_buf.vbb.vb2_buf.index,
+ (u32)b->daddr);
if (dummy)
/* It was a dummy buffer, skip it */
continue;
/* Fill vb2 buffer entries and tell it's ready */
- if (!imgu->nodes[node].output) {
+ imgu_pipe = &imgu->imgu_pipe[pipe];
+ if (!imgu_pipe->nodes[node].output) {
buf->vid_buf.vbb.vb2_buf.timestamp = ns;
buf->vid_buf.vbb.field = V4L2_FIELD_NONE;
buf->vid_buf.vbb.sequence =
- atomic_inc_return(&imgu->nodes[node].sequence);
+ atomic_inc_return(
+ &imgu_pipe->nodes[node].sequence);
+ dev_dbg(&imgu->pci_dev->dev, "vb2 buffer sequence %d",
+ buf->vid_buf.vbb.sequence);
}
imgu_buffer_done(imgu, &buf->vid_buf.vbb.vb2_buf,
ipu3_css_buf_state(&buf->css_buf) ==
@@ -562,7 +542,8 @@ static irqreturn_t imgu_isr_threaded(int irq, void *imgu_ptr)
* to be queued to CSS.
*/
if (!atomic_read(&imgu->qbuf_barrier))
- imgu_queue_buffers(imgu, false);
+ for_each_set_bit(p, imgu->css.enabled_pipes, IMGU_MAX_PIPE_NUM)
+ imgu_queue_buffers(imgu, false, p);
return IRQ_HANDLED;
}
@@ -772,6 +753,7 @@ static int __maybe_unused imgu_resume(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct imgu_device *imgu = pci_get_drvdata(pci_dev);
int r = 0;
+ unsigned int pipe;
dev_dbg(dev, "enter %s\n", __func__);
@@ -793,9 +775,13 @@ static int __maybe_unused imgu_resume(struct device *dev)
goto out;
}
- r = imgu_queue_buffers(imgu, true);
- if (r)
- dev_err(dev, "failed to queue buffers (%d)", r);
+ for_each_set_bit(pipe, imgu->css.enabled_pipes, IMGU_MAX_PIPE_NUM) {
+ r = imgu_queue_buffers(imgu, true, pipe);
+ if (r)
+ dev_err(dev, "failed to queue buffers to pipe %d (%d)",
+ pipe, r);
+ }
+
out:
dev_dbg(dev, "leave %s\n", __func__);

Privacy Policy