summaryrefslogtreecommitdiff
path: root/drivers/media/platform/vsp1/vsp1_clu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-07 22:34:37 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-07 22:34:37 +0300
commit3036bc45364f98515a2c446d7fac2c34dcfbeff4 (patch)
treef565c03254413b779981ee5e9ed81b19d5b62c78 /drivers/media/platform/vsp1/vsp1_clu.c
parentc90fca951e90ba470a3dc6087667edffcf8db21b (diff)
parent48a8bbc7ca494709522621929f8407ab823d73fc (diff)
downloadlinux-3036bc45364f98515a2c446d7fac2c34dcfbeff4.tar.xz
Merge tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - remove of atomisp driver from staging, as nobody would have time to dedicate huge efforts to fix all the problems there. Also, we have a feeling that the driver may not even run the way it is. - move Zoran driver to staging, in order to be either fixed to use VB2 and the proper media kAPIs or to be removed - remove videobuf-dvb driver, with is unused for a while - some V4L2 documentation fixes/improvements - new sensor drivers: imx258 and ov7251 - a new driver was added to allow using I2C transparent drivers - several improvements at the ddbridge driver - several improvements at the ISDB pt1 driver, making it more coherent with the DVB framework - added a new platform driver for MIPI CSI-2 RX: cadence - now, all media drivers can be compiled on x86 with COMPILE_TEST - almost all media drivers now build on non-x86 architectures with COMPILE_TEST - lots of other random stuff: cleanups, support for new board models, bug fixes, etc * tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (464 commits) media: omap2: fix compile-testing with FB_OMAP2=m media: media/radio/Kconfig: add back RADIO_ISA media: v4l2-ioctl.c: fix missing unlock in __video_do_ioctl() media: pxa_camera: ignore -ENOIOCTLCMD from v4l2_subdev_call for s_power media: arch: sh: migor: Fix TW9910 PDN gpio media: staging: tegra-vde: Reset VDE regardless of memory client resetting failure media: marvel-ccic: mmp: select VIDEOBUF2_VMALLOC/DMA_CONTIG media: marvel-ccic: allow ccic and mmp drivers to coexist media: uvcvideo: Prevent setting unavailable flags media: ddbridge: conditionally enable fast TS for stv0910-equipped bridges media: dvb-frontends/stv0910: make TS speed configurable media: ddbridge/mci: add identifiers to function definition arguments media: ddbridge/mci: protect against out-of-bounds array access in stop() media: rc: ensure input/lirc device can be opened after register media: rc: nuvoton: Keep device enabled during reg init media: rc: nuvoton: Keep track of users on CIR enable/disable media: rc: nuvoton: Tweak the interrupt enabling dance media: uvcvideo: Support realtek's UVC 1.5 device media: uvcvideo: Fix driver reference counting media: gspca_zc3xx: Enable short exposure times for OV7648 ...
Diffstat (limited to 'drivers/media/platform/vsp1/vsp1_clu.c')
-rw-r--r--drivers/media/platform/vsp1/vsp1_clu.c184
1 files changed, 80 insertions, 104 deletions
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c
index f2fb26e5ab4e..942fc14c19d1 100644
--- a/drivers/media/platform/vsp1/vsp1_clu.c
+++ b/drivers/media/platform/vsp1/vsp1_clu.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* vsp1_clu.c -- R-Car VSP1 Cubic Look-Up Table
*
* Copyright (C) 2015-2016 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#include <linux/device.h>
@@ -23,14 +19,16 @@
#define CLU_MIN_SIZE 4U
#define CLU_MAX_SIZE 8190U
+#define CLU_SIZE (17 * 17 * 17)
+
/* -----------------------------------------------------------------------------
* Device Access
*/
-static inline void vsp1_clu_write(struct vsp1_clu *clu, struct vsp1_dl_list *dl,
- u32 reg, u32 data)
+static inline void vsp1_clu_write(struct vsp1_clu *clu,
+ struct vsp1_dl_body *dlb, u32 reg, u32 data)
{
- vsp1_dl_list_write(dl, reg, data);
+ vsp1_dl_body_write(dlb, reg, data);
}
/* -----------------------------------------------------------------------------
@@ -47,19 +45,19 @@ static int clu_set_table(struct vsp1_clu *clu, struct v4l2_ctrl *ctrl)
struct vsp1_dl_body *dlb;
unsigned int i;
- dlb = vsp1_dl_fragment_alloc(clu->entity.vsp1, 1 + 17 * 17 * 17);
+ dlb = vsp1_dl_body_get(clu->pool);
if (!dlb)
return -ENOMEM;
- vsp1_dl_fragment_write(dlb, VI6_CLU_ADDR, 0);
- for (i = 0; i < 17 * 17 * 17; ++i)
- vsp1_dl_fragment_write(dlb, VI6_CLU_DATA, ctrl->p_new.p_u32[i]);
+ vsp1_dl_body_write(dlb, VI6_CLU_ADDR, 0);
+ for (i = 0; i < CLU_SIZE; ++i)
+ vsp1_dl_body_write(dlb, VI6_CLU_DATA, ctrl->p_new.p_u32[i]);
spin_lock_irq(&clu->lock);
swap(clu->clu, dlb);
spin_unlock_irq(&clu->lock);
- vsp1_dl_fragment_free(dlb);
+ vsp1_dl_body_put(dlb);
return 0;
}
@@ -118,18 +116,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {
* V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
+ MEDIA_BUS_FMT_ARGB8888_1X32,
+ MEDIA_BUS_FMT_AHSV8888_1X32,
+ MEDIA_BUS_FMT_AYUV8_1X32,
+};
+
static int clu_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
- };
-
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
- ARRAY_SIZE(codes));
+ return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
+ ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev,
@@ -145,51 +143,10 @@ static int clu_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
{
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
-
- mutex_lock(&clu->entity.lock);
-
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
- ret = -EINVAL;
- goto done;
- }
-
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
-
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
-
- if (fmt->pad == CLU_PAD_SOURCE) {
- /* The CLU output format can't be modified. */
- fmt->format = *format;
- goto done;
- }
-
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
- CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
- CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
-
- fmt->format = *format;
-
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
- CLU_PAD_SOURCE);
- *format = fmt->format;
-
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
+ return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
+ ARRAY_SIZE(clu_codes),
+ CLU_MIN_SIZE, CLU_MIN_SIZE,
+ CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/* -----------------------------------------------------------------------------
@@ -212,57 +169,65 @@ static const struct v4l2_subdev_ops clu_ops = {
* VSP1 Entity Operations
*/
-static void clu_configure(struct vsp1_entity *entity,
- struct vsp1_pipeline *pipe,
- struct vsp1_dl_list *dl,
- enum vsp1_entity_params params)
+static void clu_configure_stream(struct vsp1_entity *entity,
+ struct vsp1_pipeline *pipe,
+ struct vsp1_dl_body *dlb)
{
struct vsp1_clu *clu = to_clu(&entity->subdev);
- struct vsp1_dl_body *dlb;
+ struct v4l2_mbus_framefmt *format;
+
+ /*
+ * The yuv_mode can't be changed during streaming. Cache it internally
+ * for future runtime configuration calls.
+ */
+ format = vsp1_entity_get_pad_format(&clu->entity,
+ clu->entity.config,
+ CLU_PAD_SINK);
+ clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32;
+}
+
+static void clu_configure_frame(struct vsp1_entity *entity,
+ struct vsp1_pipeline *pipe,
+ struct vsp1_dl_list *dl,
+ struct vsp1_dl_body *dlb)
+{
+ struct vsp1_clu *clu = to_clu(&entity->subdev);
+ struct vsp1_dl_body *clu_dlb;
unsigned long flags;
u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN;
- switch (params) {
- case VSP1_ENTITY_PARAMS_INIT: {
- /*
- * The format can't be changed during streaming, only verify it
- * at setup time and store the information internally for future
- * runtime configuration calls.
- */
- struct v4l2_mbus_framefmt *format;
-
- format = vsp1_entity_get_pad_format(&clu->entity,
- clu->entity.config,
- CLU_PAD_SINK);
- clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32;
- break;
- }
-
- case VSP1_ENTITY_PARAMS_PARTITION:
- break;
+ /* 2D mode can only be used with the YCbCr pixel encoding. */
+ if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode)
+ ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D
+ | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D
+ | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D;
- case VSP1_ENTITY_PARAMS_RUNTIME:
- /* 2D mode can only be used with the YCbCr pixel encoding. */
- if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode)
- ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D
- | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D
- | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D;
+ vsp1_clu_write(clu, dlb, VI6_CLU_CTRL, ctrl);
- vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl);
+ spin_lock_irqsave(&clu->lock, flags);
+ clu_dlb = clu->clu;
+ clu->clu = NULL;
+ spin_unlock_irqrestore(&clu->lock, flags);
- spin_lock_irqsave(&clu->lock, flags);
- dlb = clu->clu;
- clu->clu = NULL;
- spin_unlock_irqrestore(&clu->lock, flags);
+ if (clu_dlb) {
+ vsp1_dl_list_add_body(dl, clu_dlb);
- if (dlb)
- vsp1_dl_list_add_fragment(dl, dlb);
- break;
+ /* Release our local reference. */
+ vsp1_dl_body_put(clu_dlb);
}
}
+static void clu_destroy(struct vsp1_entity *entity)
+{
+ struct vsp1_clu *clu = to_clu(&entity->subdev);
+
+ vsp1_dl_body_pool_destroy(clu->pool);
+}
+
static const struct vsp1_entity_operations clu_entity_ops = {
- .configure = clu_configure,
+ .configure_stream = clu_configure_stream,
+ .configure_frame = clu_configure_frame,
+ .destroy = clu_destroy,
};
/* -----------------------------------------------------------------------------
@@ -288,6 +253,17 @@ struct vsp1_clu *vsp1_clu_create(struct vsp1_device *vsp1)
if (ret < 0)
return ERR_PTR(ret);
+ /*
+ * Pre-allocate a body pool, with 3 bodies allowing a userspace update
+ * before the hardware has committed a previous set of tables, handling
+ * both the queued and pending dl entries. One extra entry is added to
+ * the CLU_SIZE to allow for the VI6_CLU_ADDR header.
+ */
+ clu->pool = vsp1_dl_body_pool_create(clu->entity.vsp1, 3, CLU_SIZE + 1,
+ 0);
+ if (!clu->pool)
+ return ERR_PTR(-ENOMEM);
+
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&clu->ctrls, 2);
v4l2_ctrl_new_custom(&clu->ctrls, &clu_table_control, NULL);