mirror of
https://github.com/Fishwaldo/build.git
synced 2025-04-09 15:41:27 +00:00
- Chanaged default x.org configuration to disable glamor - Reintroduce patch to use DRM cursor plane as overlay in rk322x-current and -dev - Updated wifi patches for kernel 5.8.10 - Bumped rk322x to u-boot v2020.07, removed reserved zones from device trees - Updated OPTEE to v3.10, using ddrbin v1.10 - Bumped rk322x-current to kernel 5.8.y - Imported new patches from knaerzche's LibreELEC fork for rk322x-dev (kernel 5.8.y) - Adjusted existing patches to match changes, updated rk322x-dev kernel config file - Add default modprobe conf file for esp8089 to force the crystal frequency to 40Mhz for rk322x targets - Removed ssv6051 firmware packages to move to armbian-firmware repository - Switching ssv6051-wifi.cfg to /lib/firmware for rk322x-legacy - Removed P2P interface for esp8089 driver for rk322x-legacy - Optimized ssv6051 performance: kernel module gains -Os flag, disabled p2p interface, enabled HW crypto for CCMP cipher - Enabled remote control interface, IR GPIO kernel module and HDMI CEC modules
7852 lines
277 KiB
Diff
7852 lines
277 KiB
Diff
From 337af64a63b5d8d5a60ad8302cca0bfa4d0cc4ad Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:16 +0200
|
|
Subject: [PATCH] media: i2c: Use the new get_mbus_config pad op
|
|
|
|
Move the existing users of the g_mbus_config video operation to use the
|
|
newly introduced get_mbus_config pad operations.
|
|
|
|
All the ported drivers report a static media bus configuration and do no
|
|
support s_mbus_config so the operation implementation has not changed.
|
|
|
|
Bridge drivers needs to call the new pad operation and will receive an
|
|
-ENOICTLCMD when calling the old g_mbus_config video operation
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/i2c/adv7180.c | 7 ++++---
|
|
drivers/media/i2c/ml86v7667.c | 7 ++++---
|
|
drivers/media/i2c/mt9m001.c | 7 ++++---
|
|
drivers/media/i2c/mt9m111.c | 7 ++++---
|
|
drivers/media/i2c/ov9640.c | 7 ++++---
|
|
drivers/media/i2c/tc358743.c | 7 ++++---
|
|
drivers/media/i2c/tvp5150.c | 7 ++++---
|
|
7 files changed, 28 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
|
|
index 00159daa6fcd..e8744efe3cf0 100644
|
|
--- a/drivers/media/i2c/adv7180.c
|
|
+++ b/drivers/media/i2c/adv7180.c
|
|
@@ -760,8 +760,9 @@ static int adv7180_init_cfg(struct v4l2_subdev *sd,
|
|
return adv7180_set_pad_format(sd, cfg, &fmt);
|
|
}
|
|
|
|
-static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int adv7180_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
struct adv7180_state *state = to_state(sd);
|
|
|
|
@@ -852,7 +853,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {
|
|
.querystd = adv7180_querystd,
|
|
.g_input_status = adv7180_g_input_status,
|
|
.s_routing = adv7180_s_routing,
|
|
- .g_mbus_config = adv7180_g_mbus_config,
|
|
.g_pixelaspect = adv7180_g_pixelaspect,
|
|
.g_tvnorms = adv7180_g_tvnorms,
|
|
.s_stream = adv7180_s_stream,
|
|
@@ -869,6 +869,7 @@ static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
|
|
.enum_mbus_code = adv7180_enum_mbus_code,
|
|
.set_fmt = adv7180_set_pad_format,
|
|
.get_fmt = adv7180_get_pad_format,
|
|
+ .get_mbus_config = adv7180_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = {
|
|
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
|
|
index c444bd6a0658..ff212335326a 100644
|
|
--- a/drivers/media/i2c/ml86v7667.c
|
|
+++ b/drivers/media/i2c/ml86v7667.c
|
|
@@ -219,8 +219,9 @@ static int ml86v7667_fill_fmt(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
|
|
-static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int ml86v7667_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
|
|
V4L2_MBUS_DATA_ACTIVE_HIGH;
|
|
@@ -291,13 +292,13 @@ static const struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = {
|
|
.s_std = ml86v7667_s_std,
|
|
.querystd = ml86v7667_querystd,
|
|
.g_input_status = ml86v7667_g_input_status,
|
|
- .g_mbus_config = ml86v7667_g_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = {
|
|
.enum_mbus_code = ml86v7667_enum_mbus_code,
|
|
.get_fmt = ml86v7667_fill_fmt,
|
|
.set_fmt = ml86v7667_fill_fmt,
|
|
+ .get_mbus_config = ml86v7667_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
|
|
diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c
|
|
index 210ea76adb53..3b0ba8ed5233 100644
|
|
--- a/drivers/media/i2c/mt9m001.c
|
|
+++ b/drivers/media/i2c/mt9m001.c
|
|
@@ -689,8 +689,9 @@ static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
|
|
-static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int mt9m001_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
/* MT9M001 has all capture_format parameters fixed */
|
|
cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
|
|
@@ -703,7 +704,6 @@ static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
|
|
|
|
static const struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
|
|
.s_stream = mt9m001_s_stream,
|
|
- .g_mbus_config = mt9m001_g_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
|
|
@@ -717,6 +717,7 @@ static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
|
|
.set_selection = mt9m001_set_selection,
|
|
.get_fmt = mt9m001_get_fmt,
|
|
.set_fmt = mt9m001_set_fmt,
|
|
+ .get_mbus_config = mt9m001_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops mt9m001_subdev_ops = {
|
|
diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c
|
|
index 17e8253f5748..69697386ffcd 100644
|
|
--- a/drivers/media/i2c/mt9m111.c
|
|
+++ b/drivers/media/i2c/mt9m111.c
|
|
@@ -1137,8 +1137,9 @@ static int mt9m111_init_cfg(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
|
|
-static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int mt9m111_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
|
|
|
|
@@ -1155,7 +1156,6 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
|
|
}
|
|
|
|
static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
|
|
- .g_mbus_config = mt9m111_g_mbus_config,
|
|
.s_stream = mt9m111_s_stream,
|
|
.g_frame_interval = mt9m111_g_frame_interval,
|
|
.s_frame_interval = mt9m111_s_frame_interval,
|
|
@@ -1168,6 +1168,7 @@ static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
|
|
.set_selection = mt9m111_set_selection,
|
|
.get_fmt = mt9m111_get_fmt,
|
|
.set_fmt = mt9m111_set_fmt,
|
|
+ .get_mbus_config = mt9m111_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops mt9m111_subdev_ops = {
|
|
diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c
|
|
index 482609665305..0ef5af026d09 100644
|
|
--- a/drivers/media/i2c/ov9640.c
|
|
+++ b/drivers/media/i2c/ov9640.c
|
|
@@ -648,8 +648,9 @@ static const struct v4l2_subdev_core_ops ov9640_core_ops = {
|
|
};
|
|
|
|
/* Request bus settings on camera side */
|
|
-static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int ov9640_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
|
|
V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
|
@@ -661,13 +662,13 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
|
|
|
|
static const struct v4l2_subdev_video_ops ov9640_video_ops = {
|
|
.s_stream = ov9640_s_stream,
|
|
- .g_mbus_config = ov9640_g_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {
|
|
.enum_mbus_code = ov9640_enum_mbus_code,
|
|
.get_selection = ov9640_get_selection,
|
|
.set_fmt = ov9640_set_fmt,
|
|
+ .get_mbus_config = ov9640_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops ov9640_subdev_ops = {
|
|
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
|
|
index dbbab75f135e..a03dcab5ce61 100644
|
|
--- a/drivers/media/i2c/tc358743.c
|
|
+++ b/drivers/media/i2c/tc358743.c
|
|
@@ -1602,8 +1602,9 @@ static int tc358743_dv_timings_cap(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
|
|
-static int tc358743_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int tc358743_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
struct tc358743_state *state = to_state(sd);
|
|
|
|
@@ -1836,7 +1837,6 @@ static const struct v4l2_subdev_video_ops tc358743_video_ops = {
|
|
.s_dv_timings = tc358743_s_dv_timings,
|
|
.g_dv_timings = tc358743_g_dv_timings,
|
|
.query_dv_timings = tc358743_query_dv_timings,
|
|
- .g_mbus_config = tc358743_g_mbus_config,
|
|
.s_stream = tc358743_s_stream,
|
|
};
|
|
|
|
@@ -1848,6 +1848,7 @@ static const struct v4l2_subdev_pad_ops tc358743_pad_ops = {
|
|
.set_edid = tc358743_s_edid,
|
|
.enum_dv_timings = tc358743_enum_dv_timings,
|
|
.dv_timings_cap = tc358743_dv_timings_cap,
|
|
+ .get_mbus_config = tc358743_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops tc358743_ops = {
|
|
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
|
|
index 9df575238952..1c2050944b92 100644
|
|
--- a/drivers/media/i2c/tvp5150.c
|
|
+++ b/drivers/media/i2c/tvp5150.c
|
|
@@ -1191,8 +1191,9 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
|
|
}
|
|
}
|
|
|
|
-static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int tvp5150_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
struct tvp5150 *decoder = to_tvp5150(sd);
|
|
|
|
@@ -1721,7 +1722,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
|
|
.querystd = tvp5150_querystd,
|
|
.s_stream = tvp5150_s_stream,
|
|
.s_routing = tvp5150_s_routing,
|
|
- .g_mbus_config = tvp5150_g_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
|
|
@@ -1739,6 +1739,7 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
|
|
.get_fmt = tvp5150_fill_fmt,
|
|
.get_selection = tvp5150_get_selection,
|
|
.set_selection = tvp5150_set_selection,
|
|
+ .get_mbus_config = tvp5150_get_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops tvp5150_ops = {
|
|
|
|
From 4cc9a9a8b16549358ea377485df8fe21ea9e1bff Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Tue, 21 Jul 2020 09:53:17 +0200
|
|
Subject: [PATCH] media: i2c: ov6650: Use new [get|set]_mbus_config ops
|
|
|
|
Use the new get_mbus_config and set_mbus_config pad operations in place
|
|
of the video operations currently in use.
|
|
|
|
Compared to other drivers where the same conversion has been performed,
|
|
ov6650 proved to be a bit more tricky, as the existing g_mbus_config
|
|
implementation did not report the currently applied configuration but
|
|
the set of all possible configuration options.
|
|
|
|
Adapt the driver to support the semantic of the two newly introduced
|
|
operations:
|
|
- get_mbus_config reports the current media bus configuration
|
|
- set_mbus_config applies only changes explicitly requested and updates
|
|
the provided cfg parameter to report what has actually been applied to
|
|
the hardware.
|
|
|
|
Compile-tested only.
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/i2c/ov6650.c | 53 ++++++++++++++++++++++++++------------
|
|
1 file changed, 37 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
|
|
index 91906b94f978..48493af81198 100644
|
|
--- a/drivers/media/i2c/ov6650.c
|
|
+++ b/drivers/media/i2c/ov6650.c
|
|
@@ -921,55 +921,74 @@ static const struct v4l2_subdev_core_ops ov6650_core_ops = {
|
|
};
|
|
|
|
/* Request bus settings on camera side */
|
|
-static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg)
|
|
+static int ov6650_get_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
|
|
+ u8 comj, comf;
|
|
+ int ret;
|
|
+
|
|
+ ret = ov6650_reg_read(client, REG_COMJ, &comj);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
- cfg->flags = V4L2_MBUS_MASTER |
|
|
- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
|
|
- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
|
|
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
|
|
- V4L2_MBUS_DATA_ACTIVE_HIGH;
|
|
+ ret = ov6650_reg_read(client, REG_COMF, &comf);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH
|
|
+ | ((comj & COMJ_VSYNC_HIGH) ? V4L2_MBUS_VSYNC_ACTIVE_HIGH
|
|
+ : V4L2_MBUS_VSYNC_ACTIVE_LOW)
|
|
+ | ((comf & COMF_HREF_LOW) ? V4L2_MBUS_HSYNC_ACTIVE_LOW
|
|
+ : V4L2_MBUS_HSYNC_ACTIVE_HIGH)
|
|
+ | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING
|
|
+ : V4L2_MBUS_PCLK_SAMPLE_FALLING);
|
|
cfg->type = V4L2_MBUS_PARALLEL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Alter bus settings on camera side */
|
|
-static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
|
|
- const struct v4l2_mbus_config *cfg)
|
|
+static int ov6650_set_mbus_config(struct v4l2_subdev *sd,
|
|
+ unsigned int pad,
|
|
+ struct v4l2_mbus_config *cfg)
|
|
{
|
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
|
|
ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
|
|
- else
|
|
+ else if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
|
|
ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
|
|
ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
|
|
- else
|
|
+ else if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
|
|
ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
|
|
ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
|
|
- else
|
|
+ else if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
|
|
ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
- return ret;
|
|
+ /*
|
|
+ * Update the configuration to report what is actually applied to
|
|
+ * the hardware.
|
|
+ */
|
|
+ return ov6650_get_mbus_config(sd, pad, cfg);
|
|
}
|
|
|
|
static const struct v4l2_subdev_video_ops ov6650_video_ops = {
|
|
.s_stream = ov6650_s_stream,
|
|
.g_frame_interval = ov6650_g_frame_interval,
|
|
.s_frame_interval = ov6650_s_frame_interval,
|
|
- .g_mbus_config = ov6650_g_mbus_config,
|
|
- .s_mbus_config = ov6650_s_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
|
|
@@ -978,6 +997,8 @@ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
|
|
.set_selection = ov6650_set_selection,
|
|
.get_fmt = ov6650_get_fmt,
|
|
.set_fmt = ov6650_set_fmt,
|
|
+ .get_mbus_config = ov6650_get_mbus_config,
|
|
+ .set_mbus_config = ov6650_set_mbus_config,
|
|
};
|
|
|
|
static const struct v4l2_subdev_ops ov6650_subdev_ops = {
|
|
|
|
From 9b55924aa37a4ba85f84b8c4e382efffdf2b73df Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:18 +0200
|
|
Subject: [PATCH] media: pxa_camera: Use the new set_mbus_config op
|
|
|
|
Move the PXA camera driver to use the new set_mbus_config pad operation.
|
|
For this platform the change is not only cosmetic, as the pxa driver is
|
|
currently the only driver in mainline to make use of the g_mbus_config
|
|
and s_mbus_config video operations.
|
|
|
|
The existing driver semantic is the following:
|
|
- Collect all supported mbus config flags from the remote end
|
|
- Match them with the supported PXA mbus configuration flags
|
|
- If the remote subdevice allows multiple options for for VSYNC, HSYNC
|
|
and PCLK polarity, use platform data requested settings
|
|
|
|
The semantic of the new get_mbus_config and set_mbus_config differs from
|
|
the corresponding video ops, particularly in the fact get_mbus_config
|
|
reports the current mbus configuration and not the set of supported
|
|
configuration options, with set_mbus_config always reporting the actual
|
|
mbus configuration applied to the remote subdevice.
|
|
|
|
Adapt the driver to perform the following
|
|
- Set the remote subdevice mbus configuration according to the PXA
|
|
platform data preferences.
|
|
- If the applied configuration differs from the requested one (i.e. the
|
|
remote subdevice does not allow changing one setting) make sure that
|
|
- The remote end does not claim for DATA_ACTIVE_LOW, which seems not
|
|
supported by the platform
|
|
- The bus mastering roles match
|
|
|
|
While at there remove a few checks performed on the media bus
|
|
configuration at get_format() time as they do not belong there.
|
|
|
|
Compile-tested only.
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/platform/pxa_camera.c | 189 ++++++++--------------------
|
|
1 file changed, 51 insertions(+), 138 deletions(-)
|
|
|
|
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
|
|
index 3c5fe737d36f..3a2cd28178da 100644
|
|
--- a/drivers/media/platform/pxa_camera.c
|
|
+++ b/drivers/media/platform/pxa_camera.c
|
|
@@ -605,42 +605,6 @@ static const struct pxa_mbus_pixelfmt *pxa_mbus_get_fmtdesc(
|
|
return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
|
|
}
|
|
|
|
-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
|
|
- unsigned int flags)
|
|
-{
|
|
- unsigned long common_flags;
|
|
- bool hsync = true, vsync = true, pclk, data, mode;
|
|
- bool mipi_lanes, mipi_clock;
|
|
-
|
|
- common_flags = cfg->flags & flags;
|
|
-
|
|
- switch (cfg->type) {
|
|
- case V4L2_MBUS_PARALLEL:
|
|
- hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
|
- V4L2_MBUS_HSYNC_ACTIVE_LOW);
|
|
- vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
|
|
- V4L2_MBUS_VSYNC_ACTIVE_LOW);
|
|
- /* fall through */
|
|
- case V4L2_MBUS_BT656:
|
|
- pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
|
|
- V4L2_MBUS_PCLK_SAMPLE_FALLING);
|
|
- data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
|
|
- V4L2_MBUS_DATA_ACTIVE_LOW);
|
|
- mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
|
|
- return (!hsync || !vsync || !pclk || !data || !mode) ?
|
|
- 0 : common_flags;
|
|
- case V4L2_MBUS_CSI2_DPHY:
|
|
- mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
|
|
- mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
|
|
- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
|
|
- return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
|
|
- default:
|
|
- WARN_ON(1);
|
|
- return -EINVAL;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
/**
|
|
* struct pxa_camera_format_xlate - match between host and sensor formats
|
|
* @code: code of a sensor provided format
|
|
@@ -1231,31 +1195,6 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
-static int test_platform_param(struct pxa_camera_dev *pcdev,
|
|
- unsigned char buswidth, unsigned long *flags)
|
|
-{
|
|
- /*
|
|
- * Platform specified synchronization and pixel clock polarities are
|
|
- * only a recommendation and are only used during probing. The PXA270
|
|
- * quick capture interface supports both.
|
|
- */
|
|
- *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
|
|
- V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
|
|
- V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
|
- V4L2_MBUS_HSYNC_ACTIVE_LOW |
|
|
- V4L2_MBUS_VSYNC_ACTIVE_HIGH |
|
|
- V4L2_MBUS_VSYNC_ACTIVE_LOW |
|
|
- V4L2_MBUS_DATA_ACTIVE_HIGH |
|
|
- V4L2_MBUS_PCLK_SAMPLE_RISING |
|
|
- V4L2_MBUS_PCLK_SAMPLE_FALLING;
|
|
-
|
|
- /* If requested data width is supported by the platform, use it */
|
|
- if ((1 << (buswidth - 1)) & pcdev->width_flags)
|
|
- return 0;
|
|
-
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev,
|
|
unsigned long flags, __u32 pixfmt)
|
|
{
|
|
@@ -1598,99 +1537,78 @@ static int pxa_camera_init_videobuf2(struct pxa_camera_dev *pcdev)
|
|
*/
|
|
static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev)
|
|
{
|
|
+ unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample;
|
|
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
|
|
u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc;
|
|
- unsigned long bus_flags, common_flags;
|
|
+ int mbus_config;
|
|
int ret;
|
|
|
|
- ret = test_platform_param(pcdev,
|
|
- pcdev->current_fmt->host_fmt->bits_per_sample,
|
|
- &bus_flags);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
|
|
- if (!ret) {
|
|
- common_flags = pxa_mbus_config_compatible(&cfg,
|
|
- bus_flags);
|
|
- if (!common_flags) {
|
|
- dev_warn(pcdev_to_dev(pcdev),
|
|
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
|
|
- cfg.flags, bus_flags);
|
|
- return -EINVAL;
|
|
- }
|
|
- } else if (ret != -ENOIOCTLCMD) {
|
|
- return ret;
|
|
- } else {
|
|
- common_flags = bus_flags;
|
|
+ if (!((1 << (bus_width - 1)) & pcdev->width_flags)) {
|
|
+ dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u",
|
|
+ bus_width);
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
pcdev->channels = 1;
|
|
|
|
/* Make choices, based on platform preferences */
|
|
- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
|
|
- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
|
|
- if (pcdev->platform_flags & PXA_CAMERA_HSP)
|
|
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
|
|
- else
|
|
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
|
|
- }
|
|
+ mbus_config = 0;
|
|
+ if (pcdev->platform_flags & PXA_CAMERA_MASTER)
|
|
+ mbus_config |= V4L2_MBUS_MASTER;
|
|
+ else
|
|
+ mbus_config |= V4L2_MBUS_SLAVE;
|
|
|
|
- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
|
|
- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
|
|
- if (pcdev->platform_flags & PXA_CAMERA_VSP)
|
|
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
|
|
- else
|
|
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
|
|
- }
|
|
+ if (pcdev->platform_flags & PXA_CAMERA_HSP)
|
|
+ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH;
|
|
+ else
|
|
+ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW;
|
|
|
|
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
|
|
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
|
|
- if (pcdev->platform_flags & PXA_CAMERA_PCP)
|
|
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
|
|
- else
|
|
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
|
|
- }
|
|
+ if (pcdev->platform_flags & PXA_CAMERA_VSP)
|
|
+ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH;
|
|
+ else
|
|
+ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW;
|
|
|
|
- cfg.flags = common_flags;
|
|
- ret = sensor_call(pcdev, video, s_mbus_config, &cfg);
|
|
+ if (pcdev->platform_flags & PXA_CAMERA_PCP)
|
|
+ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING;
|
|
+ else
|
|
+ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
|
|
+ mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH;
|
|
+
|
|
+ cfg.flags = mbus_config;
|
|
+ ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg);
|
|
if (ret < 0 && ret != -ENOIOCTLCMD) {
|
|
- dev_dbg(pcdev_to_dev(pcdev),
|
|
- "camera s_mbus_config(0x%lx) returned %d\n",
|
|
- common_flags, ret);
|
|
+ dev_err(pcdev_to_dev(pcdev),
|
|
+ "Failed to call set_mbus_config: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
- pxa_camera_setup_cicr(pcdev, common_flags, pixfmt);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev,
|
|
- unsigned char buswidth)
|
|
-{
|
|
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
|
|
- unsigned long bus_flags, common_flags;
|
|
- int ret = test_platform_param(pcdev, buswidth, &bus_flags);
|
|
-
|
|
- if (ret < 0)
|
|
- return ret;
|
|
+ /*
|
|
+ * If the requested media bus configuration has not been fully applied
|
|
+ * make sure it is supported by the platform.
|
|
+ *
|
|
+ * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering
|
|
+ * roles should match.
|
|
+ */
|
|
+ if (cfg.flags != mbus_config) {
|
|
+ unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER |
|
|
+ V4L2_MBUS_SLAVE);
|
|
+ if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER |
|
|
+ V4L2_MBUS_SLAVE))) {
|
|
+ dev_err(pcdev_to_dev(pcdev),
|
|
+ "Unsupported mbus configuration: bus mastering\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
- ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
|
|
- if (!ret) {
|
|
- common_flags = pxa_mbus_config_compatible(&cfg,
|
|
- bus_flags);
|
|
- if (!common_flags) {
|
|
- dev_warn(pcdev_to_dev(pcdev),
|
|
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
|
|
- cfg.flags, bus_flags);
|
|
+ if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) {
|
|
+ dev_err(pcdev_to_dev(pcdev),
|
|
+ "Unsupported mbus configuration: DATA_ACTIVE_LOW\n");
|
|
return -EINVAL;
|
|
}
|
|
- } else if (ret == -ENOIOCTLCMD) {
|
|
- ret = 0;
|
|
}
|
|
|
|
- return ret;
|
|
+ pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = {
|
|
@@ -1738,11 +1656,6 @@ static int pxa_camera_get_formats(struct v4l2_device *v4l2_dev,
|
|
return 0;
|
|
}
|
|
|
|
- /* This also checks support for the requested bits-per-sample */
|
|
- ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample);
|
|
- if (ret < 0)
|
|
- return 0;
|
|
-
|
|
switch (code.code) {
|
|
case MEDIA_BUS_FMT_UYVY8_2X8:
|
|
formats++;
|
|
|
|
From 562b1d8a78c8367d9809491277a6c60441565aa4 Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:19 +0200
|
|
Subject: [PATCH] media: v4l2-subdev: Remove [s|g]_mbus_config video ops
|
|
|
|
With all sensor and platform drivers now converted to use the new
|
|
get_mbus_config and set_mbus_config pad operations, remove the
|
|
deprecated video operations g_mbus_config and s_mbus_config.
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
include/media/v4l2-subdev.h | 10 ----------
|
|
1 file changed, 10 deletions(-)
|
|
|
|
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
|
|
index f7fe78a6f65a..90098fb1d770 100644
|
|
--- a/include/media/v4l2-subdev.h
|
|
+++ b/include/media/v4l2-subdev.h
|
|
@@ -402,12 +402,6 @@ struct v4l2_mbus_frame_desc {
|
|
*
|
|
* @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS() ioctl handler code.
|
|
*
|
|
- * @g_mbus_config: get supported mediabus configurations
|
|
- *
|
|
- * @s_mbus_config: set a certain mediabus configuration. This operation is added
|
|
- * for compatibility with soc-camera drivers and should not be used by new
|
|
- * software.
|
|
- *
|
|
* @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
|
|
* can adjust @size to a lower value and must not write more data to the
|
|
* buffer starting at @data than the original value of @size.
|
|
@@ -435,10 +429,6 @@ struct v4l2_subdev_video_ops {
|
|
struct v4l2_dv_timings *timings);
|
|
int (*query_dv_timings)(struct v4l2_subdev *sd,
|
|
struct v4l2_dv_timings *timings);
|
|
- int (*g_mbus_config)(struct v4l2_subdev *sd,
|
|
- struct v4l2_mbus_config *cfg);
|
|
- int (*s_mbus_config)(struct v4l2_subdev *sd,
|
|
- const struct v4l2_mbus_config *cfg);
|
|
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
|
|
unsigned int *size);
|
|
};
|
|
|
|
From 1ea27db9eaddf1eb44e533e4baa49b5b3a50900f Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:20 +0200
|
|
Subject: [PATCH] media: v4l2- mediabus: Add usage note for V4L2_MBUS_*
|
|
|
|
With the removal of the legacy g_mbus_config and s_mbus_config video
|
|
operations, the sole users of V4L2_MBUS_* flags are now the newly
|
|
introduced get_mbus_config and set_mbus_config pad operations.
|
|
|
|
As the semantic of the new operations differs from the semantic of
|
|
the legacy ones, add a usage note in the v4l2-mediabus.h header to
|
|
specify how to use the flags.
|
|
|
|
Also add a TODO note to record that we intend to replace the existing
|
|
flags with fields, to prevent users from mixing conflicting values
|
|
in a single operation call.
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
include/media/v4l2-mediabus.h | 33 +++++++++++++++++++++++++++++----
|
|
1 file changed, 29 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
|
|
index 45f88f0248c4..59b1de197114 100644
|
|
--- a/include/media/v4l2-mediabus.h
|
|
+++ b/include/media/v4l2-mediabus.h
|
|
@@ -11,9 +11,34 @@
|
|
#include <linux/v4l2-mediabus.h>
|
|
#include <linux/bitops.h>
|
|
|
|
+/*
|
|
+ * How to use the V4L2_MBUS_* flags:
|
|
+ * Flags are defined for each of the possible states and values of a media
|
|
+ * bus configuration parameter. One and only one bit of each group of flags
|
|
+ * shall be set by the users of the v4l2_subdev_pad_ops.get_mbus_config and
|
|
+ * v4l2_subdev_pad_ops.set_mbus_config operations to ensure that no
|
|
+ * conflicting settings are specified when reporting and setting the media bus
|
|
+ * configuration with the two operations respectively. For example, it is
|
|
+ * invalid to set or clear both the V4L2_MBUS_HSYNC_ACTIVE_HIGH and the
|
|
+ * V4L2_MBUS_HSYNC_ACTIVE_LOW flag at the same time. Instead either flag
|
|
+ * V4L2_MBUS_HSYNC_ACTIVE_HIGH or flag V4L2_MBUS_HSYNC_ACTIVE_LOW shall be
|
|
+ * set. The same is true for the V4L2_MBUS_CSI2_1/2/3/4_LANE flags group: only
|
|
+ * one of these four bits shall be set.
|
|
+ *
|
|
+ * TODO: replace the existing V4L2_MBUS_* flags with structures of fields
|
|
+ * to avoid conflicting settings.
|
|
+ *
|
|
+ * In example:
|
|
+ * #define V4L2_MBUS_HSYNC_ACTIVE_HIGH BIT(2)
|
|
+ * #define V4L2_MBUS_HSYNC_ACTIVE_LOW BIT(3)
|
|
+ * will be replaced by a field whose value reports the intended active state of
|
|
+ * the signal:
|
|
+ * unsigned int v4l2_mbus_hsync_active : 1;
|
|
+ */
|
|
+
|
|
/* Parallel flags */
|
|
/*
|
|
- * Can the client run in master or in slave mode. By "Master mode" an operation
|
|
+ * The client runs in master or in slave mode. By "Master mode" an operation
|
|
* mode is meant, when the client (e.g., a camera sensor) is producing
|
|
* horizontal and vertical synchronisation. In "Slave mode" the host is
|
|
* providing these signals to the slave.
|
|
@@ -45,17 +70,17 @@
|
|
#define V4L2_MBUS_DATA_ENABLE_LOW BIT(15)
|
|
|
|
/* Serial flags */
|
|
-/* How many lanes the client can use */
|
|
+/* CSI-2 D-PHY number of data lanes. */
|
|
#define V4L2_MBUS_CSI2_1_LANE BIT(0)
|
|
#define V4L2_MBUS_CSI2_2_LANE BIT(1)
|
|
#define V4L2_MBUS_CSI2_3_LANE BIT(2)
|
|
#define V4L2_MBUS_CSI2_4_LANE BIT(3)
|
|
-/* On which channels it can send video data */
|
|
+/* CSI-2 Virtual Channel identifiers. */
|
|
#define V4L2_MBUS_CSI2_CHANNEL_0 BIT(4)
|
|
#define V4L2_MBUS_CSI2_CHANNEL_1 BIT(5)
|
|
#define V4L2_MBUS_CSI2_CHANNEL_2 BIT(6)
|
|
#define V4L2_MBUS_CSI2_CHANNEL_3 BIT(7)
|
|
-/* Does it support only continuous or also non-continuous clock mode */
|
|
+/* Clock non-continuous mode support. */
|
|
#define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK BIT(8)
|
|
#define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK BIT(9)
|
|
|
|
|
|
From 9aae063d84435edfb0212c7613f887105dd58009 Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:21 +0200
|
|
Subject: [PATCH] media: staging: media: imx: Update TODO entry
|
|
|
|
Update the TODO entry that mentioned a potential use case for the now
|
|
removed g_mbus_config video operation.
|
|
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/staging/media/imx/TODO | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
|
|
index a371cdedcdb0..9cfc1c1e78dc 100644
|
|
--- a/drivers/staging/media/imx/TODO
|
|
+++ b/drivers/staging/media/imx/TODO
|
|
@@ -10,6 +10,10 @@
|
|
driver uses the parsed DT bus config method until this issue is
|
|
resolved.
|
|
|
|
+ 2020-06: g_mbus has been removed in favour of the get_mbus_config pad
|
|
+ operation which should be used to avoid parsing the remote endpoint
|
|
+ configuration.
|
|
+
|
|
- This media driver supports inheriting V4L2 controls to the
|
|
video capture devices, from the subdevices in the capture device's
|
|
pipeline. The controls for each capture device are updated in the
|
|
|
|
From 33a781840365c6b8a2b86b1c6cb4aaa86941a5d6 Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:22 +0200
|
|
Subject: [PATCH] media: i2c: adv748x: Adjust TXA data lanes number
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
When outputting SD-Core output through the TXA MIPI CSI-2 interface,
|
|
the number of enabled data lanes should be reduced in order to guarantee
|
|
that the two video formats produced by the SD-Core (480i and 576i)
|
|
generate a MIPI CSI-2 link clock frequency compatible with the MIPI D-PHY
|
|
specifications.
|
|
|
|
Limit the number of enabled data lanes to 2, which is guaranteed to
|
|
support 480i and 576i formats.
|
|
|
|
Cache the number of enabled data lanes to be able to report it through
|
|
the new get_mbus_config operation.
|
|
|
|
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
|
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
|
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/i2c/adv748x/adv748x-core.c | 31 ++++++++++++++++++------
|
|
drivers/media/i2c/adv748x/adv748x.h | 1 +
|
|
2 files changed, 25 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c
|
|
index 23e02ff27b17..1fe7f97c6d52 100644
|
|
--- a/drivers/media/i2c/adv748x/adv748x-core.c
|
|
+++ b/drivers/media/i2c/adv748x/adv748x-core.c
|
|
@@ -241,10 +241,10 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx)
|
|
int ret = 0;
|
|
|
|
/* Enable n-lane MIPI */
|
|
- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret);
|
|
+ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
|
|
|
|
/* Set Auto DPHY Timing */
|
|
- adv748x_write_check(state, page, 0x00, 0xa0 | tx->num_lanes, &ret);
|
|
+ adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret);
|
|
|
|
/* ADI Required Write */
|
|
if (tx->src == &state->hdmi.sd) {
|
|
@@ -270,7 +270,7 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx)
|
|
usleep_range(2000, 2500);
|
|
|
|
/* Power-up CSI-TX */
|
|
- adv748x_write_check(state, page, 0x00, 0x20 | tx->num_lanes, &ret);
|
|
+ adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret);
|
|
usleep_range(1000, 1500);
|
|
|
|
/* ADI Required Writes */
|
|
@@ -292,7 +292,7 @@ static int adv748x_power_down_tx(struct adv748x_csi2 *tx)
|
|
adv748x_write_check(state, page, 0x1e, 0x00, &ret);
|
|
|
|
/* Enable n-lane MIPI */
|
|
- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret);
|
|
+ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
|
|
|
|
/* i2c_mipi_pll_en - 1'b1 */
|
|
adv748x_write_check(state, page, 0xda, 0x01, &ret);
|
|
@@ -357,14 +357,29 @@ static int adv748x_link_setup(struct media_entity *entity,
|
|
if (state->afe.tx) {
|
|
/* AFE Requires TXA enabled, even when output to TXB */
|
|
io10 |= ADV748X_IO_10_CSI4_EN;
|
|
- if (is_txa(tx))
|
|
+ if (is_txa(tx)) {
|
|
+ /*
|
|
+ * Output from the SD-core (480i and 576i) from the TXA
|
|
+ * interface requires reducing the number of enabled
|
|
+ * data lanes in order to guarantee a valid link
|
|
+ * frequency.
|
|
+ */
|
|
+ tx->active_lanes = min(tx->num_lanes, 2U);
|
|
io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE;
|
|
- else
|
|
+ } else {
|
|
+ /* TXB has a single data lane, no need to adjust. */
|
|
io10 |= ADV748X_IO_10_CSI1_EN;
|
|
+ }
|
|
}
|
|
|
|
- if (state->hdmi.tx)
|
|
+ if (state->hdmi.tx) {
|
|
+ /*
|
|
+ * Restore the number of active lanes, in case we have gone
|
|
+ * through an AFE->TXA streaming sessions.
|
|
+ */
|
|
+ tx->active_lanes = tx->num_lanes;
|
|
io10 |= ADV748X_IO_10_CSI4_EN;
|
|
+ }
|
|
|
|
return io_clrset(state, ADV748X_IO_10, io10_mask, io10);
|
|
}
|
|
@@ -596,6 +611,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state,
|
|
}
|
|
|
|
state->txa.num_lanes = num_lanes;
|
|
+ state->txa.active_lanes = num_lanes;
|
|
adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes);
|
|
}
|
|
|
|
@@ -607,6 +623,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state,
|
|
}
|
|
|
|
state->txb.num_lanes = num_lanes;
|
|
+ state->txb.active_lanes = num_lanes;
|
|
adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes);
|
|
}
|
|
|
|
diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h
|
|
index fccb388ce179..1061f425ece5 100644
|
|
--- a/drivers/media/i2c/adv748x/adv748x.h
|
|
+++ b/drivers/media/i2c/adv748x/adv748x.h
|
|
@@ -79,6 +79,7 @@ struct adv748x_csi2 {
|
|
unsigned int page;
|
|
unsigned int port;
|
|
unsigned int num_lanes;
|
|
+ unsigned int active_lanes;
|
|
|
|
struct media_pad pads[ADV748X_CSI2_NR_PADS];
|
|
struct v4l2_ctrl_handler ctrl_hdl;
|
|
|
|
From 5ccfd4f056cc53beef915bd24985449b7d20affc Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:23 +0200
|
|
Subject: [PATCH] media: i2c: adv748x: Implement get_mbus_config
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Implement the newly introduced get_mbus_config operation to report the
|
|
number of currently used data lanes on the MIPI CSI-2 interface.
|
|
|
|
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
|
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/i2c/adv748x/adv748x-csi2.c | 31 ++++++++++++++++++++++++
|
|
1 file changed, 31 insertions(+)
|
|
|
|
diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
|
|
index 2091cda50935..99bb63d05eef 100644
|
|
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
|
|
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
|
|
@@ -214,9 +214,40 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
|
|
return ret;
|
|
}
|
|
|
|
+static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
|
|
+ struct v4l2_mbus_config *config)
|
|
+{
|
|
+ struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
|
|
+
|
|
+ if (pad != ADV748X_CSI2_SOURCE)
|
|
+ return -EINVAL;
|
|
+
|
|
+ config->type = V4L2_MBUS_CSI2_DPHY;
|
|
+ switch (tx->active_lanes) {
|
|
+ case 1:
|
|
+ config->flags = V4L2_MBUS_CSI2_1_LANE;
|
|
+ break;
|
|
+
|
|
+ case 2:
|
|
+ config->flags = V4L2_MBUS_CSI2_2_LANE;
|
|
+ break;
|
|
+
|
|
+ case 3:
|
|
+ config->flags = V4L2_MBUS_CSI2_3_LANE;
|
|
+ break;
|
|
+
|
|
+ case 4:
|
|
+ config->flags = V4L2_MBUS_CSI2_4_LANE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
|
|
.get_fmt = adv748x_csi2_get_format,
|
|
.set_fmt = adv748x_csi2_set_format,
|
|
+ .get_mbus_config = adv748x_csi2_get_mbus_config,
|
|
};
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
|
From a7053f425fb6140bdf72c009cab1730e9d3094af Mon Sep 17 00:00:00 2001
|
|
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Date: Fri, 17 Jul 2020 16:53:24 +0200
|
|
Subject: [PATCH] media: rcar-csi2: Negotiate data lanes number
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Use the newly introduced get_mbus_config() subdevice pad operation to
|
|
retrieve the remote subdevice MIPI CSI-2 bus configuration and configure
|
|
the number of active data lanes accordingly.
|
|
|
|
In order to be able to call the remote subdevice operation cache the
|
|
index of the remote pad connected to the single CSI-2 input port.
|
|
|
|
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
|
|
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/platform/rcar-vin/rcar-csi2.c | 75 +++++++++++++++++++--
|
|
1 file changed, 68 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
|
|
index 151e6a90c5fb..fe99ae00e690 100644
|
|
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
|
|
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
|
|
@@ -363,6 +363,7 @@ struct rcar_csi2 {
|
|
struct v4l2_async_notifier notifier;
|
|
struct v4l2_async_subdev asd;
|
|
struct v4l2_subdev *remote;
|
|
+ unsigned int remote_pad;
|
|
|
|
struct v4l2_mbus_framefmt mf;
|
|
|
|
@@ -408,13 +409,14 @@ static void rcsi2_exit_standby(struct rcar_csi2 *priv)
|
|
reset_control_deassert(priv->rstc);
|
|
}
|
|
|
|
-static int rcsi2_wait_phy_start(struct rcar_csi2 *priv)
|
|
+static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,
|
|
+ unsigned int lanes)
|
|
{
|
|
unsigned int timeout;
|
|
|
|
/* Wait for the clock and data lanes to enter LP-11 state. */
|
|
for (timeout = 0; timeout <= 20; timeout++) {
|
|
- const u32 lane_mask = (1 << priv->lanes) - 1;
|
|
+ const u32 lane_mask = (1 << lanes) - 1;
|
|
|
|
if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) &&
|
|
(rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask)
|
|
@@ -446,7 +448,8 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps)
|
|
return 0;
|
|
}
|
|
|
|
-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
|
|
+static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp,
|
|
+ unsigned int lanes)
|
|
{
|
|
struct v4l2_subdev *source;
|
|
struct v4l2_ctrl *ctrl;
|
|
@@ -471,15 +474,64 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
|
|
* bps = link_freq * 2
|
|
*/
|
|
mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;
|
|
- do_div(mbps, priv->lanes * 1000000);
|
|
+ do_div(mbps, lanes * 1000000);
|
|
|
|
return mbps;
|
|
}
|
|
|
|
+static int rcsi2_get_active_lanes(struct rcar_csi2 *priv,
|
|
+ unsigned int *lanes)
|
|
+{
|
|
+ struct v4l2_mbus_config mbus_config = { 0 };
|
|
+ unsigned int num_lanes = UINT_MAX;
|
|
+ int ret;
|
|
+
|
|
+ *lanes = priv->lanes;
|
|
+
|
|
+ ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config,
|
|
+ priv->remote_pad, &mbus_config);
|
|
+ if (ret == -ENOIOCTLCMD) {
|
|
+ dev_dbg(priv->dev, "No remote mbus configuration available\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (ret) {
|
|
+ dev_err(priv->dev, "Failed to get remote mbus configuration\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) {
|
|
+ dev_err(priv->dev, "Unsupported media bus type %u\n",
|
|
+ mbus_config.type);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE)
|
|
+ num_lanes = 1;
|
|
+ else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE)
|
|
+ num_lanes = 2;
|
|
+ else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE)
|
|
+ num_lanes = 3;
|
|
+ else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE)
|
|
+ num_lanes = 4;
|
|
+
|
|
+ if (num_lanes > priv->lanes) {
|
|
+ dev_err(priv->dev,
|
|
+ "Unsupported mbus config: too many data lanes %u\n",
|
|
+ num_lanes);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ *lanes = num_lanes;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
|
{
|
|
const struct rcar_csi2_format *format;
|
|
u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
|
|
+ unsigned int lanes;
|
|
unsigned int i;
|
|
int mbps, ret;
|
|
|
|
@@ -521,10 +573,18 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
|
fld |= FLD_FLD_NUM(1);
|
|
}
|
|
|
|
+ /*
|
|
+ * Get the number of active data lanes inspecting the remote mbus
|
|
+ * configuration.
|
|
+ */
|
|
+ ret = rcsi2_get_active_lanes(priv, &lanes);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
phycnt = PHYCNT_ENABLECLK;
|
|
- phycnt |= (1 << priv->lanes) - 1;
|
|
+ phycnt |= (1 << lanes) - 1;
|
|
|
|
- mbps = rcsi2_calc_mbps(priv, format->bpp);
|
|
+ mbps = rcsi2_calc_mbps(priv, format->bpp, lanes);
|
|
if (mbps < 0)
|
|
return mbps;
|
|
|
|
@@ -571,7 +631,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
|
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
|
|
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
|
|
|
|
- ret = rcsi2_wait_phy_start(priv);
|
|
+ ret = rcsi2_wait_phy_start(priv, lanes);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -748,6 +808,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier,
|
|
}
|
|
|
|
priv->remote = subdev;
|
|
+ priv->remote_pad = pad;
|
|
|
|
dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad);
|
|
|
|
|
|
From ed9092fbdad008ed58e0bd8079b6d6484839d811 Mon Sep 17 00:00:00 2001
|
|
From: Dinghao Liu <dinghao.liu@zju.edu.cn>
|
|
Date: Sun, 28 Jun 2020 07:55:23 +0200
|
|
Subject: [PATCH] media: venus: core: Fix runtime PM imbalance in venus_probe
|
|
|
|
pm_runtime_get_sync() increments the runtime PM usage counter even
|
|
when it returns an error code. Thus a pairing decrement is needed on
|
|
the error handling path to keep the counter balanced. For other error
|
|
paths after this call, things are the same.
|
|
|
|
Fix this by adding pm_runtime_put_noidle() after 'err_runtime_disable'
|
|
label. But in this case, the error path after pm_runtime_put_sync()
|
|
will decrease PM usage counter twice. Thus add an extra
|
|
pm_runtime_get_noresume() in this path to balance PM counter.
|
|
|
|
Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/platform/qcom/venus/core.c | 5 ++++-
|
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index 203c6538044f..b0b932bf8c02 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -287,8 +287,10 @@ static int venus_probe(struct platform_device *pdev)
|
|
goto err_core_deinit;
|
|
|
|
ret = pm_runtime_put_sync(dev);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ pm_runtime_get_noresume(dev);
|
|
goto err_dev_unregister;
|
|
+ }
|
|
|
|
return 0;
|
|
|
|
@@ -299,6 +301,7 @@ static int venus_probe(struct platform_device *pdev)
|
|
err_venus_shutdown:
|
|
venus_shutdown(core);
|
|
err_runtime_disable:
|
|
+ pm_runtime_put_noidle(dev);
|
|
pm_runtime_set_suspended(dev);
|
|
pm_runtime_disable(dev);
|
|
hfi_destroy(core);
|
|
|
|
From 757449d0037dd11f6b783bc31b27c76c5fa636c8 Mon Sep 17 00:00:00 2001
|
|
From: Rajendra Nayak <rnayak@codeaurora.org>
|
|
Date: Wed, 29 Jul 2020 09:16:42 +0200
|
|
Subject: [PATCH] media: venus: core: Fix error handling in probe
|
|
|
|
Post a successful pm_ops->core_get, an error in probe
|
|
should exit by doing a pm_ops->core_put which seems
|
|
to be missing. So fix it.
|
|
|
|
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
|
|
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
|
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/platform/qcom/venus/core.c | 15 ++++++++++-----
|
|
1 file changed, 10 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index b0b932bf8c02..321ad77cb6cf 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -224,13 +224,15 @@ static int venus_probe(struct platform_device *pdev)
|
|
|
|
ret = dma_set_mask_and_coherent(dev, core->res->dma_mask);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto err_core_put;
|
|
|
|
if (!dev->dma_parms) {
|
|
dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
|
|
GFP_KERNEL);
|
|
- if (!dev->dma_parms)
|
|
- return -ENOMEM;
|
|
+ if (!dev->dma_parms) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_core_put;
|
|
+ }
|
|
}
|
|
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
|
|
|
@@ -242,11 +244,11 @@ static int venus_probe(struct platform_device *pdev)
|
|
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
|
"venus", core);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto err_core_put;
|
|
|
|
ret = hfi_create(core, &venus_core_ops);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto err_core_put;
|
|
|
|
pm_runtime_enable(dev);
|
|
|
|
@@ -305,6 +307,9 @@ static int venus_probe(struct platform_device *pdev)
|
|
pm_runtime_set_suspended(dev);
|
|
pm_runtime_disable(dev);
|
|
hfi_destroy(core);
|
|
+err_core_put:
|
|
+ if (core->pm_ops->core_put)
|
|
+ core->pm_ops->core_put(dev);
|
|
return ret;
|
|
}
|
|
|
|
|
|
From 207ffb881dd2058c1a86022671817cef37a9d273 Mon Sep 17 00:00:00 2001
|
|
From: Rajendra Nayak <rnayak@codeaurora.org>
|
|
Date: Wed, 29 Jul 2020 09:16:43 +0200
|
|
Subject: [PATCH] media: venus: core: Add support for opp tables/perf voting
|
|
|
|
Add support to add OPP tables and perf voting on the OPP powerdomain.
|
|
This is needed so venus votes on the corresponding performance state
|
|
for the OPP powerdomain along with setting the core clock rate.
|
|
|
|
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
|
|
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
|
|
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
|
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
---
|
|
drivers/media/platform/qcom/venus/core.c | 2 +
|
|
drivers/media/platform/qcom/venus/core.h | 5 +
|
|
.../media/platform/qcom/venus/pm_helpers.c | 92 +++++++++++++++++--
|
|
3 files changed, 92 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index 321ad77cb6cf..5fd70f8cf857 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -528,6 +528,7 @@ static const struct venus_resources sdm845_res_v2 = {
|
|
.vcodec_clks_num = 2,
|
|
.vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
|
|
.vcodec_pmdomains_num = 3,
|
|
+ .opp_pmdomain = (const char *[]) { "cx", NULL },
|
|
.vcodec_num = 2,
|
|
.max_load = 3110400, /* 4096x2160@90 */
|
|
.hfi_version = HFI_VERSION_4XX,
|
|
@@ -573,6 +574,7 @@ static const struct venus_resources sc7180_res = {
|
|
.vcodec_clks_num = 2,
|
|
.vcodec_pmdomains = { "venus", "vcodec0" },
|
|
.vcodec_pmdomains_num = 2,
|
|
+ .opp_pmdomain = (const char *[]) { "cx", NULL },
|
|
.vcodec_num = 1,
|
|
.hfi_version = HFI_VERSION_4XX,
|
|
.vmem_id = VIDC_RESOURCE_NONE,
|
|
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
|
|
index 7118612673c9..b0cc544ad39f 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.h
|
|
+++ b/drivers/media/platform/qcom/venus/core.h
|
|
@@ -62,6 +62,7 @@ struct venus_resources {
|
|
unsigned int vcodec_clks_num;
|
|
const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
|
|
unsigned int vcodec_pmdomains_num;
|
|
+ const char **opp_pmdomain;
|
|
unsigned int vcodec_num;
|
|
enum hfi_version hfi_version;
|
|
u32 max_load;
|
|
@@ -145,8 +146,12 @@ struct venus_core {
|
|
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
|
|
struct icc_path *video_path;
|
|
struct icc_path *cpucfg_path;
|
|
+ struct opp_table *opp_table;
|
|
+ bool has_opp_table;
|
|
struct device_link *pd_dl_venus;
|
|
struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
|
|
+ struct device_link *opp_dl_venus;
|
|
+ struct device *opp_pmdomain;
|
|
struct video_device *vdev_dec;
|
|
struct video_device *vdev_enc;
|
|
struct v4l2_device v4l2_dev;
|
|
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
|
|
index 531e7a41658f..3127af8985cf 100644
|
|
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
|
|
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
|
|
@@ -9,6 +9,7 @@
|
|
#include <linux/iopoll.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/pm_domain.h>
|
|
+#include <linux/pm_opp.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/types.h>
|
|
#include <media/v4l2-mem2mem.h>
|
|
@@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core)
|
|
|
|
static int core_clks_set_rate(struct venus_core *core, unsigned long freq)
|
|
{
|
|
- struct clk *clk = core->clks[0];
|
|
int ret;
|
|
|
|
- ret = clk_set_rate(clk, freq);
|
|
+ ret = dev_pm_opp_set_rate(core->dev, freq);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -744,13 +744,16 @@ static int venc_power_v4(struct device *dev, int on)
|
|
|
|
static int vcodec_domains_get(struct device *dev)
|
|
{
|
|
+ int ret;
|
|
+ struct opp_table *opp_table;
|
|
+ struct device **opp_virt_dev;
|
|
struct venus_core *core = dev_get_drvdata(dev);
|
|
const struct venus_resources *res = core->res;
|
|
struct device *pd;
|
|
unsigned int i;
|
|
|
|
if (!res->vcodec_pmdomains_num)
|
|
- return -ENODEV;
|
|
+ goto skip_pmdomains;
|
|
|
|
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
|
|
pd = dev_pm_domain_attach_by_name(dev,
|
|
@@ -767,7 +770,41 @@ static int vcodec_domains_get(struct device *dev)
|
|
if (!core->pd_dl_venus)
|
|
return -ENODEV;
|
|
|
|
+skip_pmdomains:
|
|
+ if (!core->has_opp_table)
|
|
+ return 0;
|
|
+
|
|
+ /* Attach the power domain for setting performance state */
|
|
+ opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
|
|
+ if (IS_ERR(opp_table)) {
|
|
+ ret = PTR_ERR(opp_table);
|
|
+ goto opp_attach_err;
|
|
+ }
|
|
+
|
|
+ core->opp_pmdomain = *opp_virt_dev;
|
|
+ core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
|
|
+ DL_FLAG_RPM_ACTIVE |
|
|
+ DL_FLAG_PM_RUNTIME |
|
|
+ DL_FLAG_STATELESS);
|
|
+ if (!core->opp_dl_venus) {
|
|
+ ret = -ENODEV;
|
|
+ goto opp_dl_add_err;
|
|
+ }
|
|
+
|
|
return 0;
|
|
+
|
|
+opp_dl_add_err:
|
|
+ dev_pm_domain_detach(core->opp_pmdomain, true);
|
|
+opp_attach_err:
|
|
+ if (core->pd_dl_venus) {
|
|
+ device_link_del(core->pd_dl_venus);
|
|
+ for (i = 0; i < res->vcodec_pmdomains_num; i++) {
|
|
+ if (IS_ERR_OR_NULL(core->pmdomains[i]))
|
|
+ continue;
|
|
+ dev_pm_domain_detach(core->pmdomains[i], true);
|
|
+ }
|
|
+ }
|
|
+ return ret;
|
|
}
|
|
|
|
static void vcodec_domains_put(struct device *dev)
|
|
@@ -777,7 +814,7 @@ static void vcodec_domains_put(struct device *dev)
|
|
unsigned int i;
|
|
|
|
if (!res->vcodec_pmdomains_num)
|
|
- return;
|
|
+ goto skip_pmdomains;
|
|
|
|
if (core->pd_dl_venus)
|
|
device_link_del(core->pd_dl_venus);
|
|
@@ -787,6 +824,15 @@ static void vcodec_domains_put(struct device *dev)
|
|
continue;
|
|
dev_pm_domain_detach(core->pmdomains[i], true);
|
|
}
|
|
+
|
|
+skip_pmdomains:
|
|
+ if (!core->has_opp_table)
|
|
+ return;
|
|
+
|
|
+ if (core->opp_dl_venus)
|
|
+ device_link_del(core->opp_dl_venus);
|
|
+
|
|
+ dev_pm_domain_detach(core->opp_pmdomain, true);
|
|
}
|
|
|
|
static int core_get_v4(struct device *dev)
|
|
@@ -815,19 +861,46 @@ static int core_get_v4(struct device *dev)
|
|
if (legacy_binding)
|
|
return 0;
|
|
|
|
+ core->opp_table = dev_pm_opp_set_clkname(dev, "core");
|
|
+ if (IS_ERR(core->opp_table))
|
|
+ return PTR_ERR(core->opp_table);
|
|
+
|
|
+ if (core->res->opp_pmdomain) {
|
|
+ ret = dev_pm_opp_of_add_table(dev);
|
|
+ if (!ret) {
|
|
+ core->has_opp_table = true;
|
|
+ } else if (ret != -ENODEV) {
|
|
+ dev_err(dev, "invalid OPP table in device tree\n");
|
|
+ dev_pm_opp_put_clkname(core->opp_table);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = vcodec_domains_get(dev);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ if (core->has_opp_table)
|
|
+ dev_pm_opp_of_remove_table(dev);
|
|
+ dev_pm_opp_put_clkname(core->opp_table);
|
|
return ret;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void core_put_v4(struct device *dev)
|
|
{
|
|
+ struct venus_core *core = dev_get_drvdata(dev);
|
|
+
|
|
if (legacy_binding)
|
|
return;
|
|
|
|
vcodec_domains_put(dev);
|
|
+
|
|
+ if (core->has_opp_table)
|
|
+ dev_pm_opp_of_remove_table(dev);
|
|
+ if (core->opp_table)
|
|
+ dev_pm_opp_put_clkname(core->opp_table);
|
|
+
|
|
}
|
|
|
|
static int core_power_v4(struct device *dev, int on)
|
|
@@ -835,10 +908,15 @@ static int core_power_v4(struct device *dev, int on)
|
|
struct venus_core *core = dev_get_drvdata(dev);
|
|
int ret = 0;
|
|
|
|
- if (on == POWER_ON)
|
|
+ if (on == POWER_ON) {
|
|
ret = core_clks_enable(core);
|
|
- else
|
|
+ } else {
|
|
+ /* Drop the performance state vote */
|
|
+ if (core->opp_pmdomain)
|
|
+ dev_pm_opp_set_rate(dev, 0);
|
|
+
|
|
core_clks_disable(core);
|
|
+ }
|
|
|
|
return ret;
|
|
}
|
|
|
|
From 3bf1ba10b6ac9cfff7ecd329c38dc31213e88ce1 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Mon, 27 Jul 2020 14:05:37 -0300
|
|
Subject: [PATCH] hantro: h264: Get the correct fallback reference buffer
|
|
|
|
If the bitstream and the application are incorrectly configuring
|
|
the reference pictures, the hardware will need to fallback
|
|
to using some other reference picture.
|
|
|
|
When the post-processor is enabled, the fallback buffer
|
|
should be a shadow buffer (postproc.dec_q), and not a
|
|
CAPTURE queue buffer, since the latter is post-processed
|
|
and not really the output of the decoder core.
|
|
|
|
Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing")
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/hantro/hantro_h264.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
|
|
index 194d05848077..6dcd47bd9ed3 100644
|
|
--- a/drivers/staging/media/hantro/hantro_h264.c
|
|
+++ b/drivers/staging/media/hantro/hantro_h264.c
|
|
@@ -325,7 +325,7 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
|
|
*/
|
|
dst_buf = hantro_get_dst_buf(ctx);
|
|
buf = &dst_buf->vb2_buf;
|
|
- dma_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
|
|
+ dma_addr = hantro_get_dec_buf_addr(ctx, buf);
|
|
}
|
|
|
|
return dma_addr;
|
|
|
|
From 28bebe4b9396ef9d2e4ae2a179abdb840ceddb03 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Mon, 27 Jul 2020 14:05:38 -0300
|
|
Subject: [PATCH] hantro: postproc: Fix motion vector space allocation
|
|
|
|
When the post-processor is enabled, the driver allocates
|
|
"shadow buffers" which are used for the decoder core,
|
|
and exposes the post-processed buffers to userspace.
|
|
|
|
For this reason, extra motion vector space has to
|
|
be allocated on the shadow buffers, which the driver
|
|
wasn't doing. Fix it.
|
|
|
|
This fix should address artifacts on high profile bitstreams.
|
|
|
|
Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing")
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/hantro/hantro_postproc.c | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c
|
|
index 44062ffceaea..6d2a8f2a8f0b 100644
|
|
--- a/drivers/staging/media/hantro/hantro_postproc.c
|
|
+++ b/drivers/staging/media/hantro/hantro_postproc.c
|
|
@@ -118,7 +118,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
|
|
unsigned int num_buffers = cap_queue->num_buffers;
|
|
unsigned int i, buf_size;
|
|
|
|
- buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage;
|
|
+ buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage +
|
|
+ hantro_h264_mv_size(ctx->dst_fmt.width,
|
|
+ ctx->dst_fmt.height);
|
|
|
|
for (i = 0; i < num_buffers; ++i) {
|
|
struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
|
|
|
|
From be1ec3a445d13ab0bac45fd84edb30a11a2c0b8c Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Fri, 14 Aug 2020 10:36:16 -0300
|
|
Subject: [PATCH] media: uapi: h264: Update reference lists
|
|
|
|
When dealing with with interlaced frames, reference lists must tell if
|
|
each particular reference is meant for top or bottom field. This info
|
|
is currently not provided at all in the H264 related controls.
|
|
|
|
Make reference lists hold a structure which will also hold an
|
|
enumerator type along index into DPB array. The enumerator must
|
|
be used to specify if reference is for top or bottom field.
|
|
|
|
Currently the only user of these lists is Cedrus which is just compile
|
|
fixed here. Actual usage of will come in a following commit.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../media/v4l/ext-ctrls-codec.rst | 44 ++++++++++++++++++-
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 6 +--
|
|
include/media/h264-ctrls.h | 23 +++++++---
|
|
3 files changed, 62 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index d0d506a444b1..b9b2617c3bda 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1843,10 +1843,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __u32
|
|
- ``slice_group_change_cycle``
|
|
-
|
|
- * - __u8
|
|
+ * - struct :c:type:`v4l2_h264_reference`
|
|
- ``ref_pic_list0[32]``
|
|
- Reference picture list after applying the per-slice modifications
|
|
- * - __u8
|
|
+ * - struct :c:type:`v4l2_h264_reference`
|
|
- ``ref_pic_list1[32]``
|
|
- Reference picture list after applying the per-slice modifications
|
|
* - __u32
|
|
@@ -1926,6 +1926,46 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- ``chroma_offset[32][2]``
|
|
-
|
|
|
|
+``Picture Reference``
|
|
+
|
|
+.. c:type:: v4l2_h264_reference
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. flat-table:: struct v4l2_h264_reference
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - enum :c:type:`v4l2_h264_field_reference`
|
|
+ - ``reference``
|
|
+ - Specifies how the picture is referenced.
|
|
+ * - __u8
|
|
+ - ``index``
|
|
+ - Index into the :c:type:`v4l2_ctrl_h264_decode_params`.dpb array.
|
|
+
|
|
+.. c:type:: v4l2_h264_field_reference
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. flat-table::
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - ``V4L2_H264_TOP_FIELD_REF``
|
|
+ - 0x1
|
|
+ - The top field in field pair is used for
|
|
+ short-term reference.
|
|
+ * - ``V4L2_H264_BOTTOM_FIELD_REF``
|
|
+ - 0x2
|
|
+ - The bottom field in field pair is used for
|
|
+ short-term reference.
|
|
+ * - ``V4L2_H264_FRAME_REF``
|
|
+ - 0x3
|
|
+ - The frame (or the top/bottom fields, if it's a field pair)
|
|
+ is used for short-term reference.
|
|
+
|
|
``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (struct)``
|
|
Specifies the decode parameters (as extracted from the bitstream)
|
|
for the associated H264 slice data. This includes the necessary
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index 54ee2aa423e2..cce527bbdf86 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -166,8 +166,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
|
|
static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run,
|
|
- const u8 *ref_list, u8 num_ref,
|
|
- enum cedrus_h264_sram_off sram)
|
|
+ const struct v4l2_h264_reference *ref_list,
|
|
+ u8 num_ref, enum cedrus_h264_sram_off sram)
|
|
{
|
|
const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params;
|
|
struct vb2_queue *cap_q;
|
|
@@ -188,7 +188,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
|
int buf_idx;
|
|
u8 dpb_idx;
|
|
|
|
- dpb_idx = ref_list[i];
|
|
+ dpb_idx = ref_list[i].index;
|
|
dpb = &decode->dpb[dpb_idx];
|
|
|
|
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index 080fd1293c42..5f635e8d25e2 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -19,6 +19,8 @@
|
|
*/
|
|
#define V4L2_H264_NUM_DPB_ENTRIES 16
|
|
|
|
+#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES)
|
|
+
|
|
/* Our pixel format isn't stable at the moment */
|
|
#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
|
|
|
|
@@ -140,6 +142,19 @@ struct v4l2_h264_pred_weight_table {
|
|
#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
|
|
#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
|
|
|
|
+enum v4l2_h264_field_reference {
|
|
+ V4L2_H264_TOP_FIELD_REF = 0x1,
|
|
+ V4L2_H264_BOTTOM_FIELD_REF = 0x2,
|
|
+ V4L2_H264_FRAME_REF = 0x3,
|
|
+};
|
|
+
|
|
+struct v4l2_h264_reference {
|
|
+ enum v4l2_h264_field_reference fields;
|
|
+
|
|
+ /* Index into v4l2_ctrl_h264_decode_params.dpb[] */
|
|
+ __u8 index;
|
|
+};
|
|
+
|
|
struct v4l2_ctrl_h264_slice_params {
|
|
/* Size in bytes, including header */
|
|
__u32 size;
|
|
@@ -178,12 +193,8 @@ struct v4l2_ctrl_h264_slice_params {
|
|
__u8 num_ref_idx_l1_active_minus1;
|
|
__u32 slice_group_change_cycle;
|
|
|
|
- /*
|
|
- * Entries on each list are indices into
|
|
- * v4l2_ctrl_h264_decode_params.dpb[].
|
|
- */
|
|
- __u8 ref_pic_list0[32];
|
|
- __u8 ref_pic_list1[32];
|
|
+ struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN];
|
|
+ struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN];
|
|
|
|
__u32 flags;
|
|
};
|
|
|
|
From 9e30508e5834c1a37aa07836bf7fc78f96559f82 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:17 -0300
|
|
Subject: [PATCH] media: uapi: h264: Further clarify scaling lists order
|
|
|
|
Commit 0b0393d59eb4a ("media: uapi: h264: clarify
|
|
expected scaling_list_4x4/8x8 order") improved the
|
|
documentation on H264 scaling lists order.
|
|
|
|
This commit improves the documentation by clarifying
|
|
that the lists themselves are expected in raster scan order.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 6 ++++--
|
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index b9b2617c3bda..694037ce888a 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1725,12 +1725,14 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- ``scaling_list_4x4[6][16]``
|
|
- Scaling matrix after applying the inverse scanning process.
|
|
Expected list order is Intra Y, Intra Cb, Intra Cr, Inter Y,
|
|
- Inter Cb, Inter Cr.
|
|
+ Inter Cb, Inter Cr. The values on each scaling list are
|
|
+ expected in raster scan order.
|
|
* - __u8
|
|
- ``scaling_list_8x8[6][64]``
|
|
- Scaling matrix after applying the inverse scanning process.
|
|
Expected list order is Intra Y, Inter Y, Intra Cb, Inter Cb,
|
|
- Intra Cr, Inter Cr.
|
|
+ Intra Cr, Inter Cr. The values on each scaling list are
|
|
+ expected in raster scan order.
|
|
|
|
``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (struct)``
|
|
Specifies the slice parameters (as extracted from the bitstream)
|
|
|
|
From da0e200cf7bd3c42b97c8fa8e941a756ffdbfb26 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:18 -0300
|
|
Subject: [PATCH] media: uapi: h264: Split prediction weight parameters
|
|
|
|
The prediction weight parameters are only required under
|
|
certain conditions, which depend on slice header parameters.
|
|
|
|
As specified in section 7.3.3 Slice header syntax, the prediction
|
|
weight table is present if:
|
|
|
|
((weighted_pred_flag && (slice_type == P || slice_type == SP)) || \
|
|
(weighted_bipred_idc == 1 && slice_type == B))
|
|
|
|
Given its size, it makes sense to move this table to its control,
|
|
so applications can avoid passing it if the slice doesn't specify it.
|
|
|
|
Before this change struct v4l2_ctrl_h264_slice_params was 960 bytes.
|
|
With this change, it's 188 bytes and struct v4l2_ctrl_h264_pred_weight
|
|
is 772 bytes.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../media/v4l/ext-ctrls-codec.rst | 19 ++++++++++++-------
|
|
drivers/media/v4l2-core/v4l2-ctrls.c | 8 ++++++++
|
|
drivers/staging/media/sunxi/cedrus/cedrus.c | 7 +++++++
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
|
|
.../staging/media/sunxi/cedrus/cedrus_dec.c | 2 ++
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 12 +++---------
|
|
include/media/h264-ctrls.h | 12 ++++++++++--
|
|
include/media/v4l2-ctrls.h | 2 ++
|
|
8 files changed, 45 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 694037ce888a..ddf9c6af7d0a 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1879,18 +1879,23 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- 0x00000008
|
|
-
|
|
|
|
-``Prediction Weight Table``
|
|
+``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)``
|
|
+ Prediction weight table defined according to :ref:`h264`,
|
|
+ section 7.4.3.2 "Prediction Weight Table Semantics".
|
|
+ The prediction weight table must be passed by applications
|
|
+ under the conditions explained in section 7.3.3 "Slice header
|
|
+ syntax".
|
|
|
|
- The bitstream parameters are defined according to :ref:`h264`,
|
|
- section 7.4.3.2 "Prediction Weight Table Semantics". For further
|
|
- documentation, refer to the above specification, unless there is
|
|
- an explicit comment stating otherwise.
|
|
+ .. note::
|
|
+
|
|
+ This compound control is not yet part of the public kernel API and
|
|
+ it is expected to change.
|
|
|
|
-.. c:type:: v4l2_h264_pred_weight_table
|
|
+.. c:type:: v4l2_ctrl_h264_pred_weights
|
|
|
|
.. cssclass:: longtable
|
|
|
|
-.. flat-table:: struct v4l2_h264_pred_weight_table
|
|
+.. flat-table:: struct v4l2_ctrl_h264_pred_weights
|
|
:header-rows: 0
|
|
:stub-columns: 0
|
|
:widths: 1 1 2
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
index 3f3fbcd60cc6..76c8dc8fb31c 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
@@ -897,6 +897,7 @@ const char *v4l2_ctrl_get_name(u32 id)
|
|
case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: return "H264 Decode Parameters";
|
|
case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: return "H264 Decode Mode";
|
|
case V4L2_CID_MPEG_VIDEO_H264_START_CODE: return "H264 Start Code";
|
|
+ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: return "H264 Prediction Weight Table";
|
|
case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: return "MPEG2 Level";
|
|
case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: return "MPEG2 Profile";
|
|
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
|
|
@@ -1412,6 +1413,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
|
|
case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS:
|
|
*type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS;
|
|
break;
|
|
+ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS:
|
|
+ *type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS;
|
|
+ break;
|
|
case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:
|
|
*type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER;
|
|
break;
|
|
@@ -1790,6 +1794,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
case V4L2_CTRL_TYPE_H264_SPS:
|
|
case V4L2_CTRL_TYPE_H264_PPS:
|
|
case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
|
|
+ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
|
|
case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
|
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
|
break;
|
|
@@ -2553,6 +2558,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
|
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
|
elem_size = sizeof(struct v4l2_ctrl_h264_decode_params);
|
|
break;
|
|
+ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
|
|
+ elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights);
|
|
+ break;
|
|
case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
|
elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header);
|
|
break;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
index bc27f9430eeb..826324faad7e 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
@@ -78,6 +78,13 @@ static const struct cedrus_control cedrus_controls[] = {
|
|
.codec = CEDRUS_CODEC_H264,
|
|
.required = true,
|
|
},
|
|
+ {
|
|
+ .cfg = {
|
|
+ .id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS,
|
|
+ },
|
|
+ .codec = CEDRUS_CODEC_H264,
|
|
+ .required = false,
|
|
+ },
|
|
{
|
|
.cfg = {
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE,
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index 96765555ab8a..93c843ae14bb 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -62,6 +62,7 @@ struct cedrus_h264_run {
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
|
|
const struct v4l2_ctrl_h264_slice_params *slice_params;
|
|
const struct v4l2_ctrl_h264_sps *sps;
|
|
+ const struct v4l2_ctrl_h264_pred_weights *pred_weights;
|
|
};
|
|
|
|
struct cedrus_mpeg2_run {
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
index 58c48e4fdfe9..6385026d1b6b 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
@@ -57,6 +57,8 @@ void cedrus_device_run(void *priv)
|
|
V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS);
|
|
run.h264.sps = cedrus_find_control_data(ctx,
|
|
V4L2_CID_MPEG_VIDEO_H264_SPS);
|
|
+ run.h264.pred_weights = cedrus_find_control_data(ctx,
|
|
+ V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS);
|
|
break;
|
|
|
|
case V4L2_PIX_FMT_HEVC_SLICE:
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index cce527bbdf86..d5636dbbb622 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -256,10 +256,8 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx,
|
|
static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run)
|
|
{
|
|
- const struct v4l2_ctrl_h264_slice_params *slice =
|
|
- run->h264.slice_params;
|
|
- const struct v4l2_h264_pred_weight_table *pred_weight =
|
|
- &slice->pred_weight_table;
|
|
+ const struct v4l2_ctrl_h264_pred_weights *pred_weight =
|
|
+ run->h264.pred_weights;
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
int i, j, k;
|
|
|
|
@@ -367,11 +365,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
|
|
cedrus_skip_bits(dev, slice->header_bit_size);
|
|
|
|
- if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
|
|
- (slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
|
|
- slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
|
|
- (pps->weighted_bipred_idc == 1 &&
|
|
- slice->slice_type == V4L2_H264_SLICE_TYPE_B))
|
|
+ if (V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice))
|
|
cedrus_write_pred_weight_table(ctx, run);
|
|
|
|
if ((slice->slice_type == V4L2_H264_SLICE_TYPE_P) ||
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index 5f635e8d25e2..d995614be159 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -36,6 +36,7 @@
|
|
#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004)
|
|
#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005)
|
|
#define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006)
|
|
+#define V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (V4L2_CID_MPEG_BASE+1007)
|
|
|
|
/* enum v4l2_ctrl_type type values */
|
|
#define V4L2_CTRL_TYPE_H264_SPS 0x0110
|
|
@@ -43,6 +44,7 @@
|
|
#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112
|
|
#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113
|
|
#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114
|
|
+#define V4L2_CTRL_TYPE_H264_PRED_WEIGHTS 0x0115
|
|
|
|
enum v4l2_mpeg_video_h264_decode_mode {
|
|
V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED,
|
|
@@ -125,7 +127,14 @@ struct v4l2_h264_weight_factors {
|
|
__s16 chroma_offset[32][2];
|
|
};
|
|
|
|
-struct v4l2_h264_pred_weight_table {
|
|
+#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \
|
|
+ ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \
|
|
+ ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \
|
|
+ (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \
|
|
+ ((pps)->weighted_bipred_idc == 1 && \
|
|
+ (slice)->slice_type == V4L2_H264_SLICE_TYPE_B))
|
|
+
|
|
+struct v4l2_ctrl_h264_pred_weights {
|
|
__u16 luma_log2_weight_denom;
|
|
__u16 chroma_log2_weight_denom;
|
|
struct v4l2_h264_weight_factors weight_factors[2];
|
|
@@ -177,7 +186,6 @@ struct v4l2_ctrl_h264_slice_params {
|
|
__s32 delta_pic_order_cnt0;
|
|
__s32 delta_pic_order_cnt1;
|
|
|
|
- struct v4l2_h264_pred_weight_table pred_weight_table;
|
|
/* Size in bits of dec_ref_pic_marking() syntax element. */
|
|
__u32 dec_ref_pic_marking_bit_size;
|
|
/* Size in bits of pic order count syntax. */
|
|
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
|
|
index f40e2cbb21d3..cb25f345e9ad 100644
|
|
--- a/include/media/v4l2-ctrls.h
|
|
+++ b/include/media/v4l2-ctrls.h
|
|
@@ -51,6 +51,7 @@ struct video_device;
|
|
* @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix.
|
|
* @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params.
|
|
* @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params.
|
|
+ * @p_h264_pred_weights: Pointer to a struct v4l2_ctrl_h264_pred_weights.
|
|
* @p_vp8_frame_header: Pointer to a VP8 frame header structure.
|
|
* @p_hevc_sps: Pointer to an HEVC sequence parameter set structure.
|
|
* @p_hevc_pps: Pointer to an HEVC picture parameter set structure.
|
|
@@ -74,6 +75,7 @@ union v4l2_ctrl_ptr {
|
|
struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
|
|
struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
|
|
struct v4l2_ctrl_h264_decode_params *p_h264_decode_params;
|
|
+ struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights;
|
|
struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
|
|
struct v4l2_ctrl_hevc_sps *p_hevc_sps;
|
|
struct v4l2_ctrl_hevc_pps *p_hevc_pps;
|
|
|
|
From 82c12e79f57d0b51b81efb2bb87a91288988d958 Mon Sep 17 00:00:00 2001
|
|
From: Philipp Zabel <p.zabel@pengutronix.de>
|
|
Date: Fri, 14 Aug 2020 10:36:19 -0300
|
|
Subject: [PATCH] media: uapi: h264: Clarify pic_order_cnt_bit_size field
|
|
|
|
Since pic_order_cnt_bit_size is not a syntax element itself, explicitly
|
|
state that it is the total size in bits of the pic_order_cnt_lsb,
|
|
delta_pic_order_cnt_bottom, delta_pic_order_cnt[0], and
|
|
delta_pic_order_cnt[1] syntax elements contained in the slice.
|
|
|
|
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
|
|
[Ezequiel: rebase]
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
|
---
|
|
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index ddf9c6af7d0a..32f3cebf16e5 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1815,7 +1815,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- Size in bits of the dec_ref_pic_marking() syntax element.
|
|
* - __u32
|
|
- ``pic_order_cnt_bit_size``
|
|
- -
|
|
+ - Combined size in bits of the picture order count related syntax
|
|
+ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom,
|
|
+ delta_pic_order_cnt0, and delta_pic_order_cnt1.
|
|
* - __u8
|
|
- ``cabac_init_idc``
|
|
-
|
|
|
|
From fced897398d6228473f01df99fd09fd4410f623d Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:20 -0300
|
|
Subject: [PATCH] media: uapi: h264: Increase size of 'first_mb_in_slice' field
|
|
|
|
Slice header syntax element 'first_mb_in_slice' can point
|
|
to the last macroblock, currently the field can only reference
|
|
65536 macroblocks which is insufficient for 8K videos.
|
|
|
|
Although unlikely, a 8192x4320 video (where macroblocks are 16x16),
|
|
would contain 138240 macroblocks on a frame.
|
|
|
|
As per the H264 specification, 'first_mb_in_slice' can be up to
|
|
PicSizeInMbs - 1, so increase the size of the field to 32-bits.
|
|
|
|
Note that v4l2_ctrl_h264_slice_params struct will be modified
|
|
in a follow-up commit, and so we defer its 64-bit padding.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 2 +-
|
|
include/media/h264-ctrls.h | 3 ++-
|
|
2 files changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 32f3cebf16e5..714a8d9ae6a0 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1774,7 +1774,7 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __u32
|
|
- ``header_bit_size``
|
|
-
|
|
- * - __u16
|
|
+ * - __u32
|
|
- ``first_mb_in_slice``
|
|
-
|
|
* - __u8
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index d995614be159..9ff085fdc9ab 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -174,7 +174,8 @@ struct v4l2_ctrl_h264_slice_params {
|
|
/* Offset in bits to slice_data() from the beginning of this slice. */
|
|
__u32 header_bit_size;
|
|
|
|
- __u16 first_mb_in_slice;
|
|
+ __u32 first_mb_in_slice;
|
|
+
|
|
__u8 slice_type;
|
|
__u8 pic_parameter_set_id;
|
|
__u8 colour_plane_id;
|
|
|
|
From 52266e3675e9359f13aa4d44a4ab392fd1f079c0 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:21 -0300
|
|
Subject: [PATCH] media: uapi: h264: Clean DPB entry interface
|
|
|
|
As discussed recently, the current interface for the
|
|
Decoded Picture Buffer is not enough to properly
|
|
support field coding.
|
|
|
|
This commit introduces enough semantics to support
|
|
frame and field coding, and to signal how DPB entries
|
|
are "used for reference".
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../media/v4l/ext-ctrls-codec.rst | 24 ++++++-------------
|
|
drivers/media/v4l2-core/v4l2-h264.c | 4 ++--
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 17 ++++++-------
|
|
include/media/h264-ctrls.h | 2 +-
|
|
4 files changed, 19 insertions(+), 28 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 714a8d9ae6a0..d14da8325382 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -2063,6 +2063,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __s32
|
|
- ``bottom_field_order_cnt``
|
|
-
|
|
+ * - enum :c:type:`v4l2_h264_field_reference`
|
|
+ - ``reference``
|
|
+ - Specifies how the DPB entry is referenced.
|
|
* - __u32
|
|
- ``flags``
|
|
- See :ref:`DPB Entry Flags <h264_dpb_flags>`
|
|
@@ -2080,29 +2083,16 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
|
|
* - ``V4L2_H264_DPB_ENTRY_FLAG_VALID``
|
|
- 0x00000001
|
|
- - The DPB entry is valid and should be considered
|
|
+ - The DPB entry is valid (non-empty) and should be considered.
|
|
* - ``V4L2_H264_DPB_ENTRY_FLAG_ACTIVE``
|
|
- 0x00000002
|
|
- - The DPB entry is currently being used as a reference frame
|
|
+ - The DPB entry is used for reference.
|
|
* - ``V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM``
|
|
- 0x00000004
|
|
- - The DPB entry is a long term reference frame
|
|
+ - The DPB entry is used for long-term reference.
|
|
* - ``V4L2_H264_DPB_ENTRY_FLAG_FIELD``
|
|
- 0x00000008
|
|
- - The DPB entry is a field reference, which means only one of the field
|
|
- will be used when decoding the new frame/field. When not set the DPB
|
|
- entry is a frame reference (both fields will be used). Note that this
|
|
- flag does not say anything about the number of fields contained in the
|
|
- reference frame, it just describes the one used to decode the new
|
|
- field/frame
|
|
- * - ``V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD``
|
|
- - 0x00000010
|
|
- - The DPB entry is a bottom field reference (only the bottom field of the
|
|
- reference frame is needed to decode the new frame/field). Only valid if
|
|
- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set. When
|
|
- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set but
|
|
- V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD is not, that means the
|
|
- DPB entry is a top field reference
|
|
+ - The DPB entry is a single field or a complementary field pair.
|
|
|
|
``V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (enum)``
|
|
Specifies the decoding mode to use. Currently exposes slice-based and
|
|
diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c
|
|
index edf6225f0522..12b751c09016 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-h264.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-h264.c
|
|
@@ -66,10 +66,10 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
|
|
else
|
|
b->refs[i].frame_num = dpb[i].frame_num;
|
|
|
|
- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD))
|
|
+ if (dpb[i].reference == V4L2_H264_FRAME_REF)
|
|
pic_order_count = min(dpb[i].top_field_order_cnt,
|
|
dpb[i].bottom_field_order_cnt);
|
|
- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD)
|
|
+ else if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF)
|
|
pic_order_count = dpb[i].bottom_field_order_cnt;
|
|
else
|
|
pic_order_count = dpb[i].top_field_order_cnt;
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 7b66e2743a4f..07a80e9a9df2 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -949,16 +949,17 @@ static void config_registers(struct rkvdec_ctx *ctx,
|
|
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
|
|
struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i);
|
|
|
|
- refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0) |
|
|
- RKVDEC_COLMV_USED_FLAG_REF;
|
|
+ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0);
|
|
|
|
- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD))
|
|
- refer_addr |= RKVDEC_TOPFIELD_USED_REF |
|
|
- RKVDEC_BOTFIELD_USED_REF;
|
|
- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD)
|
|
- refer_addr |= RKVDEC_BOTFIELD_USED_REF;
|
|
- else
|
|
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
|
|
+ refer_addr |= RKVDEC_COLMV_USED_FLAG_REF;
|
|
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)
|
|
+ refer_addr |= RKVDEC_FIELD_REF;
|
|
+
|
|
+ if (dpb[i].reference & V4L2_H264_TOP_FIELD_REF)
|
|
refer_addr |= RKVDEC_TOPFIELD_USED_REF;
|
|
+ if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF)
|
|
+ refer_addr |= RKVDEC_BOTFIELD_USED_REF;
|
|
|
|
writel_relaxed(dpb[i].top_field_order_cnt,
|
|
rkvdec->regs + poc_reg_tbl_top_field[i]);
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index 9ff085fdc9ab..4447697e9465 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -212,7 +212,6 @@ struct v4l2_ctrl_h264_slice_params {
|
|
#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02
|
|
#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04
|
|
#define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08
|
|
-#define V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD 0x10
|
|
|
|
struct v4l2_h264_dpb_entry {
|
|
__u64 reference_ts;
|
|
@@ -221,6 +220,7 @@ struct v4l2_h264_dpb_entry {
|
|
/* Note that field is indicated by v4l2_buffer.field */
|
|
__s32 top_field_order_cnt;
|
|
__s32 bottom_field_order_cnt;
|
|
+ enum v4l2_h264_field_reference reference;
|
|
__u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
|
|
};
|
|
|
|
|
|
From cd2980d0ab75400656f854ac48a147ef07b9f9ba Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:22 -0300
|
|
Subject: [PATCH] media: uapi: h264: Increase size of DPB entry pic_num
|
|
|
|
DPB entry PicNum maximum value is 2*MaxFrameNum for interlaced
|
|
content (field_pic_flag=1).
|
|
|
|
As specified, MaxFrameNum is 2^(log2_max_frame_num_minus4 + 4)
|
|
and log2_max_frame_num_minus4 is in the range of 0 to 12,
|
|
which means pic_num should be a 32-bit field.
|
|
|
|
The v4l2_h264_dpb_entry struct needs to be padded to avoid a hole,
|
|
which might be also useful to allow future uAPI extensions.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++-
|
|
drivers/media/v4l2-core/v4l2-ctrls.c | 13 +++++++++++++
|
|
include/media/h264-ctrls.h | 3 ++-
|
|
include/media/v4l2-h264.h | 2 +-
|
|
4 files changed, 20 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index d14da8325382..c0ae7fda803e 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -2054,7 +2054,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __u16
|
|
- ``frame_num``
|
|
-
|
|
- * - __u16
|
|
+ * - __u8
|
|
+ - ``reserved[2]``
|
|
+ - Applications and drivers must set this to zero.
|
|
+ * - __u32
|
|
- ``pic_num``
|
|
-
|
|
* - __s32
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
index 76c8dc8fb31c..b9457789fa55 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
@@ -1725,6 +1725,8 @@ static void std_log(const struct v4l2_ctrl *ctrl)
|
|
|
|
#define zero_padding(s) \
|
|
memset(&(s).padding, 0, sizeof((s).padding))
|
|
+#define zero_reserved(s) \
|
|
+ memset(&(s).reserved, 0, sizeof((s).reserved))
|
|
|
|
/*
|
|
* Compound controls validation requires setting unused fields/flags to zero
|
|
@@ -1735,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
{
|
|
struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
|
|
struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
|
|
+ struct v4l2_ctrl_h264_decode_params *p_h264_dec_params;
|
|
struct v4l2_ctrl_hevc_sps *p_hevc_sps;
|
|
struct v4l2_ctrl_hevc_pps *p_hevc_pps;
|
|
struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
|
|
@@ -1796,7 +1799,17 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
|
|
case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
|
|
case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
|
+ break;
|
|
+
|
|
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
|
+ p_h264_dec_params = p;
|
|
+
|
|
+ for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
|
|
+ struct v4l2_h264_dpb_entry *dpb_entry =
|
|
+ &p_h264_dec_params->dpb[i];
|
|
+
|
|
+ zero_reserved(*dpb_entry);
|
|
+ }
|
|
break;
|
|
|
|
case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index 4447697e9465..d178d7ad53b6 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -216,7 +216,8 @@ struct v4l2_ctrl_h264_slice_params {
|
|
struct v4l2_h264_dpb_entry {
|
|
__u64 reference_ts;
|
|
__u16 frame_num;
|
|
- __u16 pic_num;
|
|
+ __u8 reserved[2];
|
|
+ __u32 pic_num;
|
|
/* Note that field is indicated by v4l2_buffer.field */
|
|
__s32 top_field_order_cnt;
|
|
__s32 bottom_field_order_cnt;
|
|
diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h
|
|
index bc9ebb560ccf..1a5f26fc2a9a 100644
|
|
--- a/include/media/v4l2-h264.h
|
|
+++ b/include/media/v4l2-h264.h
|
|
@@ -33,7 +33,7 @@ struct v4l2_h264_reflist_builder {
|
|
struct {
|
|
s32 pic_order_count;
|
|
int frame_num;
|
|
- u16 pic_num;
|
|
+ u32 pic_num;
|
|
u16 longterm : 1;
|
|
} refs[V4L2_H264_NUM_DPB_ENTRIES];
|
|
s32 cur_pic_order_count;
|
|
|
|
From c380a6c41ab18183ff5d6342d8dc6cf7f22e6ed5 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:23 -0300
|
|
Subject: [PATCH] media: uapi: h264: Drop SLICE_PARAMS 'size' field
|
|
|
|
The SLICE_PARAMS control is intended for slice-based
|
|
devices. In this mode, the OUTPUT buffer contains
|
|
a single slice, and so the buffer's plane payload size
|
|
can be used to query the slice size.
|
|
|
|
To reduce the API surface drop the size from the
|
|
SLICE_PARAMS control.
|
|
|
|
A follow-up change will remove other members in SLICE_PARAMS
|
|
so we don't need to add padding fields here.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 3 ---
|
|
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 7 +++----
|
|
include/media/h264-ctrls.h | 3 ---
|
|
3 files changed, 3 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index c0ae7fda803e..e88c207d945b 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1760,9 +1760,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
:stub-columns: 0
|
|
:widths: 1 1 2
|
|
|
|
- * - __u32
|
|
- - ``size``
|
|
- -
|
|
* - __u32
|
|
- ``start_byte_offset``
|
|
Offset (in bytes) from the beginning of the OUTPUT buffer to the start
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index d5636dbbb622..7d9bd5860a1b 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -324,17 +324,16 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
struct vb2_buffer *src_buf = &run->src->vb2_buf;
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
dma_addr_t src_buf_addr;
|
|
- u32 len = slice->size * 8;
|
|
+ size_t slice_bytes = vb2_get_plane_payload(src_buf, 0);
|
|
unsigned int pic_width_in_mbs;
|
|
bool mbaff_pic;
|
|
u32 reg;
|
|
|
|
- cedrus_write(dev, VE_H264_VLD_LEN, len);
|
|
+ cedrus_write(dev, VE_H264_VLD_LEN, slice_bytes * 8);
|
|
cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
|
|
|
|
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
|
|
- cedrus_write(dev, VE_H264_VLD_END,
|
|
- src_buf_addr + vb2_get_plane_payload(src_buf, 0));
|
|
+ cedrus_write(dev, VE_H264_VLD_END, src_buf_addr + slice_bytes);
|
|
cedrus_write(dev, VE_H264_VLD_ADDR,
|
|
VE_H264_VLD_ADDR_VAL(src_buf_addr) |
|
|
VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index d178d7ad53b6..afcae3052085 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -165,9 +165,6 @@ struct v4l2_h264_reference {
|
|
};
|
|
|
|
struct v4l2_ctrl_h264_slice_params {
|
|
- /* Size in bytes, including header */
|
|
- __u32 size;
|
|
-
|
|
/* Offset in bytes to the start of slice in the OUTPUT buffer. */
|
|
__u32 start_byte_offset;
|
|
|
|
|
|
From 37293295255bb5ad4063fe1ca6945a6890c65cd4 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:24 -0300
|
|
Subject: [PATCH] media: uapi: h264: Clarify SLICE_BASED mode
|
|
|
|
Currently, the SLICE_BASED and FRAME_BASED modes documentation
|
|
is misleading and not matching the intended use-cases.
|
|
|
|
Drop non-required fields SLICE_PARAMS 'start_byte_offset' and
|
|
DECODE_PARAMS 'num_slices' and clarify the decoding modes in the
|
|
documentation.
|
|
|
|
On SLICE_BASED mode, a single slice is expected per OUTPUT buffer,
|
|
and therefore 'start_byte_offset' is not needed (since the offset
|
|
to the slice is the start of the buffer).
|
|
|
|
This mode requires the use of CAPTURE buffer holding, and so
|
|
the number of slices shall not be required.
|
|
|
|
On FRAME_BASED mode, the devices are expected to take care of slice
|
|
parsing. Neither SLICE_PARAMS are required (and shouldn't be
|
|
exposed by frame-based drivers), nor the number of slices.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../media/v4l/ext-ctrls-codec.rst | 39 +++++--------------
|
|
include/media/h264-ctrls.h | 4 --
|
|
2 files changed, 10 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index e88c207d945b..90caf6a0d5a0 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1748,9 +1748,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
This compound control is not yet part of the public kernel API
|
|
and it is expected to change.
|
|
|
|
- This structure is expected to be passed as an array, with one
|
|
- entry for each slice included in the bitstream buffer.
|
|
-
|
|
.. c:type:: v4l2_ctrl_h264_slice_params
|
|
|
|
.. cssclass:: longtable
|
|
@@ -1760,17 +1757,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
:stub-columns: 0
|
|
:widths: 1 1 2
|
|
|
|
- * - __u32
|
|
- - ``start_byte_offset``
|
|
- Offset (in bytes) from the beginning of the OUTPUT buffer to the start
|
|
- of the slice. If the slice starts with a start code, then this is the
|
|
- offset to such start code. When operating in slice-based decoding mode
|
|
- (see :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field should
|
|
- be set to 0. When operating in frame-based decoding mode, this field
|
|
- should be 0 for the first slice.
|
|
* - __u32
|
|
- ``header_bit_size``
|
|
- -
|
|
+ - Offset in bits to slice_data() from the beginning of this slice.
|
|
* - __u32
|
|
- ``first_mb_in_slice``
|
|
-
|
|
@@ -1998,12 +1987,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - struct :c:type:`v4l2_h264_dpb_entry`
|
|
- ``dpb[16]``
|
|
-
|
|
- * - __u16
|
|
- - ``num_slices``
|
|
- - Number of slices needed to decode the current frame/field. When
|
|
- operating in slice-based decoding mode (see
|
|
- :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field
|
|
- should always be set to one.
|
|
* - __u16
|
|
- ``nal_ref_idc``
|
|
- NAL reference ID value coming from the NAL Unit header
|
|
@@ -2121,22 +2104,20 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED``
|
|
- 0
|
|
- Decoding is done at the slice granularity.
|
|
- In this mode, ``num_slices`` field in struct
|
|
- :c:type:`v4l2_ctrl_h264_decode_params` should be set to 1,
|
|
- and ``start_byte_offset`` in struct
|
|
- :c:type:`v4l2_ctrl_h264_slice_params` should be set to 0.
|
|
The OUTPUT buffer must contain a single slice.
|
|
+ When this mode is selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS``
|
|
+ control shall be set. When multiple slices compose a frame,
|
|
+ use of ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` flag
|
|
+ is required.
|
|
* - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED``
|
|
- 1
|
|
- - Decoding is done at the frame granularity.
|
|
- In this mode, ``num_slices`` field in struct
|
|
- :c:type:`v4l2_ctrl_h264_decode_params` should be set to the number
|
|
- of slices in the frame, and ``start_byte_offset`` in struct
|
|
- :c:type:`v4l2_ctrl_h264_slice_params` should be set accordingly
|
|
- for each slice. For the first slice, ``start_byte_offset`` should
|
|
- be zero.
|
|
+ - Decoding is done at the frame granularity,
|
|
The OUTPUT buffer must contain all slices needed to decode the
|
|
frame. The OUTPUT buffer must also contain both fields.
|
|
+ This mode will be supported by devices that
|
|
+ parse the slice(s) header(s) in hardware. When this mode is
|
|
+ selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS``
|
|
+ control shall not be set.
|
|
|
|
``V4L2_CID_MPEG_VIDEO_H264_START_CODE (enum)``
|
|
Specifies the H264 slice start code expected for each slice.
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index afcae3052085..e180501e6385 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -165,9 +165,6 @@ struct v4l2_h264_reference {
|
|
};
|
|
|
|
struct v4l2_ctrl_h264_slice_params {
|
|
- /* Offset in bytes to the start of slice in the OUTPUT buffer. */
|
|
- __u32 start_byte_offset;
|
|
-
|
|
/* Offset in bits to slice_data() from the beginning of this slice. */
|
|
__u32 header_bit_size;
|
|
|
|
@@ -226,7 +223,6 @@ struct v4l2_h264_dpb_entry {
|
|
|
|
struct v4l2_ctrl_h264_decode_params {
|
|
struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES];
|
|
- __u16 num_slices;
|
|
__u16 nal_ref_idc;
|
|
__s32 top_field_order_cnt;
|
|
__s32 bottom_field_order_cnt;
|
|
|
|
From ff81175260cd33feaa7d0407ef50186422215fae Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:25 -0300
|
|
Subject: [PATCH] media: uapi: h264: Clean slice invariants syntax elements
|
|
|
|
The H.264 specification requires in section 7.4.3 "Slice header semantics",
|
|
that the following values shall be the same in all slice headers:
|
|
|
|
pic_parameter_set_id
|
|
frame_num
|
|
field_pic_flag
|
|
bottom_field_flag
|
|
idr_pic_id
|
|
pic_order_cnt_lsb
|
|
delta_pic_order_cnt_bottom
|
|
delta_pic_order_cnt[ 0 ]
|
|
delta_pic_order_cnt[ 1 ]
|
|
sp_for_switch_flag
|
|
slice_group_change_cycle
|
|
|
|
These bitstream fields are part of the slice header, and therefore
|
|
passed redundantly on each slice. The purpose of the redundancy
|
|
is to make the codec fault-tolerant in network scenarios.
|
|
|
|
This is of course not needed to be reflected in the V4L2 controls,
|
|
given the bitstream has already been parsed by applications.
|
|
Therefore, move the redundant fields to the per-frame decode
|
|
parameters control (DECODE_PARAMS).
|
|
|
|
Field 'pic_parameter_set_id' is simply removed in this case,
|
|
because the PPS control must currently contain the active PPS.
|
|
|
|
Syntax elements dec_ref_pic_marking() and those related
|
|
to pic order count, remain invariant as well, and therefore,
|
|
the fields dec_ref_pic_marking_bit_size and pic_order_cnt_bit_size
|
|
are also common to all slices.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
|
---
|
|
.../media/v4l/ext-ctrls-codec.rst | 86 +++++++++----------
|
|
drivers/media/v4l2-core/v4l2-ctrls.c | 7 ++
|
|
drivers/media/v4l2-core/v4l2-h264.c | 8 +-
|
|
.../staging/media/hantro/hantro_g1_h264_dec.c | 21 +++--
|
|
drivers/staging/media/hantro/hantro_h264.c | 3 +-
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 6 +-
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 9 +-
|
|
include/media/h264-ctrls.h | 39 +++++----
|
|
include/media/v4l2-h264.h | 1 -
|
|
9 files changed, 90 insertions(+), 90 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 90caf6a0d5a0..69dd3961b99b 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1766,44 +1766,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __u8
|
|
- ``slice_type``
|
|
-
|
|
- * - __u8
|
|
- - ``pic_parameter_set_id``
|
|
- -
|
|
* - __u8
|
|
- ``colour_plane_id``
|
|
-
|
|
* - __u8
|
|
- ``redundant_pic_cnt``
|
|
-
|
|
- * - __u16
|
|
- - ``frame_num``
|
|
- -
|
|
- * - __u16
|
|
- - ``idr_pic_id``
|
|
- -
|
|
- * - __u16
|
|
- - ``pic_order_cnt_lsb``
|
|
- -
|
|
- * - __s32
|
|
- - ``delta_pic_order_cnt_bottom``
|
|
- -
|
|
- * - __s32
|
|
- - ``delta_pic_order_cnt0``
|
|
- -
|
|
- * - __s32
|
|
- - ``delta_pic_order_cnt1``
|
|
- -
|
|
- * - struct :c:type:`v4l2_h264_pred_weight_table`
|
|
- - ``pred_weight_table``
|
|
- -
|
|
- * - __u32
|
|
- - ``dec_ref_pic_marking_bit_size``
|
|
- - Size in bits of the dec_ref_pic_marking() syntax element.
|
|
- * - __u32
|
|
- - ``pic_order_cnt_bit_size``
|
|
- - Combined size in bits of the picture order count related syntax
|
|
- elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom,
|
|
- delta_pic_order_cnt0, and delta_pic_order_cnt1.
|
|
* - __u8
|
|
- ``cabac_init_idc``
|
|
-
|
|
@@ -1830,9 +1798,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- ``num_ref_idx_l1_active_minus1``
|
|
- If num_ref_idx_active_override_flag is not set, this field must be
|
|
set to the value of num_ref_idx_l1_default_active_minus1.
|
|
- * - __u32
|
|
- - ``slice_group_change_cycle``
|
|
- -
|
|
+ * - __u8
|
|
+ - ``reserved``
|
|
+ - Applications and drivers must set this to zero.
|
|
* - struct :c:type:`v4l2_h264_reference`
|
|
- ``ref_pic_list0[32]``
|
|
- Reference picture list after applying the per-slice modifications
|
|
@@ -1854,17 +1822,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
:stub-columns: 0
|
|
:widths: 1 1 2
|
|
|
|
- * - ``V4L2_H264_SLICE_FLAG_FIELD_PIC``
|
|
- - 0x00000001
|
|
- -
|
|
- * - ``V4L2_H264_SLICE_FLAG_BOTTOM_FIELD``
|
|
- - 0x00000002
|
|
- -
|
|
* - ``V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED``
|
|
- - 0x00000004
|
|
+ - 0x00000001
|
|
-
|
|
* - ``V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH``
|
|
- - 0x00000008
|
|
+ - 0x00000002
|
|
-
|
|
|
|
``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)``
|
|
@@ -1990,12 +1952,44 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - __u16
|
|
- ``nal_ref_idc``
|
|
- NAL reference ID value coming from the NAL Unit header
|
|
+ * - __u16
|
|
+ - ``frame_num``
|
|
+ -
|
|
* - __s32
|
|
- ``top_field_order_cnt``
|
|
- Picture Order Count for the coded top field
|
|
* - __s32
|
|
- ``bottom_field_order_cnt``
|
|
- Picture Order Count for the coded bottom field
|
|
+ * - __u16
|
|
+ - ``idr_pic_id``
|
|
+ -
|
|
+ * - __u16
|
|
+ - ``pic_order_cnt_lsb``
|
|
+ -
|
|
+ * - __s32
|
|
+ - ``delta_pic_order_cnt_bottom``
|
|
+ -
|
|
+ * - __s32
|
|
+ - ``delta_pic_order_cnt0``
|
|
+ -
|
|
+ * - __s32
|
|
+ - ``delta_pic_order_cnt1``
|
|
+ -
|
|
+ * - __u32
|
|
+ - ``dec_ref_pic_marking_bit_size``
|
|
+ - Size in bits of the dec_ref_pic_marking() syntax element.
|
|
+ * - __u32
|
|
+ - ``pic_order_cnt_bit_size``
|
|
+ - Combined size in bits of the picture order count related syntax
|
|
+ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom,
|
|
+ delta_pic_order_cnt0, and delta_pic_order_cnt1.
|
|
+ * - __u32
|
|
+ - ``slice_group_change_cycle``
|
|
+ -
|
|
+ * - __u32
|
|
+ - ``reserved``
|
|
+ - Applications and drivers must set this to zero.
|
|
* - __u32
|
|
- ``flags``
|
|
- See :ref:`Decode Parameters Flags <h264_decode_params_flags>`
|
|
@@ -2014,6 +2008,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - ``V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC``
|
|
- 0x00000001
|
|
- That picture is an IDR picture
|
|
+ * - ``V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC``
|
|
+ - 0x00000002
|
|
+ -
|
|
+ * - ``V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD``
|
|
+ - 0x00000004
|
|
+ -
|
|
|
|
.. c:type:: v4l2_h264_dpb_entry
|
|
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
index b9457789fa55..b846f5b089c9 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
@@ -1737,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
{
|
|
struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
|
|
struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
|
|
+ struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
|
|
struct v4l2_ctrl_h264_decode_params *p_h264_dec_params;
|
|
struct v4l2_ctrl_hevc_sps *p_hevc_sps;
|
|
struct v4l2_ctrl_hevc_pps *p_hevc_pps;
|
|
@@ -1798,7 +1799,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
case V4L2_CTRL_TYPE_H264_PPS:
|
|
case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
|
|
case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
|
|
+ break;
|
|
+
|
|
case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
|
+ p_h264_slice_params = p;
|
|
+
|
|
+ zero_reserved(*p_h264_slice_params);
|
|
break;
|
|
|
|
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
|
@@ -1810,6 +1816,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
|
|
zero_reserved(*dpb_entry);
|
|
}
|
|
+ zero_reserved(*p_h264_dec_params);
|
|
break;
|
|
|
|
case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
|
diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c
|
|
index 12b751c09016..101fdeabfb06 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-h264.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-h264.c
|
|
@@ -18,14 +18,12 @@
|
|
*
|
|
* @b: the builder context to initialize
|
|
* @dec_params: decode parameters control
|
|
- * @slice_params: first slice parameters control
|
|
* @sps: SPS control
|
|
* @dpb: DPB to use when creating the reference list
|
|
*/
|
|
void
|
|
v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
|
|
const struct v4l2_ctrl_h264_decode_params *dec_params,
|
|
- const struct v4l2_ctrl_h264_slice_params *slice_params,
|
|
const struct v4l2_ctrl_h264_sps *sps,
|
|
const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES])
|
|
{
|
|
@@ -33,13 +31,13 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
|
|
unsigned int i;
|
|
|
|
max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
|
|
- cur_frame_num = slice_params->frame_num;
|
|
+ cur_frame_num = dec_params->frame_num;
|
|
|
|
memset(b, 0, sizeof(*b));
|
|
- if (!(slice_params->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC))
|
|
+ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC))
|
|
b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt,
|
|
dec_params->top_field_order_cnt);
|
|
- else if (slice_params->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
|
|
+ else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
|
|
b->cur_pic_order_count = dec_params->bottom_field_order_cnt;
|
|
else
|
|
b->cur_pic_order_count = dec_params->top_field_order_cnt;
|
|
diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
index 424c648ce9fc..f9839e9c6da5 100644
|
|
--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
@@ -23,7 +23,6 @@ static void set_params(struct hantro_ctx *ctx)
|
|
{
|
|
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
|
|
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
|
|
- const struct v4l2_ctrl_h264_slice_params *slices = ctrls->slices;
|
|
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
|
|
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
|
|
struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx);
|
|
@@ -42,11 +41,11 @@ static void set_params(struct hantro_ctx *ctx)
|
|
|
|
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
|
|
(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD ||
|
|
- slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC))
|
|
+ dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC))
|
|
reg |= G1_REG_DEC_CTRL0_PIC_INTERLACE_E;
|
|
- if (slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
|
|
+ if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
|
|
reg |= G1_REG_DEC_CTRL0_PIC_FIELDMODE_E;
|
|
- if (!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD))
|
|
+ if (!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD))
|
|
reg |= G1_REG_DEC_CTRL0_PIC_TOPFIELD_E;
|
|
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0);
|
|
|
|
@@ -75,7 +74,7 @@ static void set_params(struct hantro_ctx *ctx)
|
|
|
|
/* Decoder control register 4. */
|
|
reg = G1_REG_DEC_CTRL4_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) |
|
|
- G1_REG_DEC_CTRL4_FRAMENUM(slices[0].frame_num) |
|
|
+ G1_REG_DEC_CTRL4_FRAMENUM(dec_param->frame_num) |
|
|
G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc);
|
|
if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
|
|
reg |= G1_REG_DEC_CTRL4_CABAC_E;
|
|
@@ -88,8 +87,8 @@ static void set_params(struct hantro_ctx *ctx)
|
|
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4);
|
|
|
|
/* Decoder control register 5. */
|
|
- reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) |
|
|
- G1_REG_DEC_CTRL5_IDR_PIC_ID(slices[0].idr_pic_id);
|
|
+ reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) |
|
|
+ G1_REG_DEC_CTRL5_IDR_PIC_ID(dec_param->idr_pic_id);
|
|
if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)
|
|
reg |= G1_REG_DEC_CTRL5_CONST_INTRA_E;
|
|
if (pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)
|
|
@@ -103,10 +102,10 @@ static void set_params(struct hantro_ctx *ctx)
|
|
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL5);
|
|
|
|
/* Decoder control register 6. */
|
|
- reg = G1_REG_DEC_CTRL6_PPS_ID(slices[0].pic_parameter_set_id) |
|
|
+ reg = G1_REG_DEC_CTRL6_PPS_ID(pps->pic_parameter_set_id) |
|
|
G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) |
|
|
G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) |
|
|
- G1_REG_DEC_CTRL6_POC_LENGTH(slices[0].pic_order_cnt_bit_size);
|
|
+ G1_REG_DEC_CTRL6_POC_LENGTH(dec_param->pic_order_cnt_bit_size);
|
|
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL6);
|
|
|
|
/* Error concealment register. */
|
|
@@ -246,7 +245,7 @@ static void set_buffers(struct hantro_ctx *ctx)
|
|
/* Destination (decoded frame) buffer. */
|
|
dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
|
|
/* Adjust dma addr to start at second line for bottom field */
|
|
- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
|
|
+ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
|
|
offset = ALIGN(ctx->src_fmt.width, MB_DIM);
|
|
vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DST);
|
|
|
|
@@ -265,7 +264,7 @@ static void set_buffers(struct hantro_ctx *ctx)
|
|
* DMV buffer is split in two for field encoded frames,
|
|
* adjust offset for bottom field
|
|
*/
|
|
- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
|
|
+ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
|
|
offset += 32 * MB_WIDTH(ctx->src_fmt.width) *
|
|
MB_HEIGHT(ctx->src_fmt.height);
|
|
vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DIR_MV);
|
|
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
|
|
index 6dcd47bd9ed3..7578a4fc1b16 100644
|
|
--- a/drivers/staging/media/hantro/hantro_h264.c
|
|
+++ b/drivers/staging/media/hantro/hantro_h264.c
|
|
@@ -372,8 +372,7 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
|
|
|
|
/* Build the P/B{0,1} ref lists. */
|
|
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
|
|
- &ctrls->slices[0], ctrls->sps,
|
|
- ctx->h264_dec.dpb);
|
|
+ ctrls->sps, ctx->h264_dec.dpb);
|
|
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
|
|
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
|
|
h264_ctx->reflists.b1);
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 07a80e9a9df2..70752e30b3a3 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -730,7 +730,6 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx,
|
|
struct rkvdec_h264_run *run)
|
|
{
|
|
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
|
|
- const struct v4l2_ctrl_h264_slice_params *sl_params = &run->slices_params[0];
|
|
const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb;
|
|
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
|
|
const struct v4l2_ctrl_h264_sps *sps = run->sps;
|
|
@@ -754,7 +753,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx,
|
|
continue;
|
|
|
|
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ||
|
|
- dpb[i].frame_num < sl_params->frame_num) {
|
|
+ dpb[i].frame_num < dec_params->frame_num) {
|
|
p[i] = dpb[i].frame_num;
|
|
continue;
|
|
}
|
|
@@ -1094,8 +1093,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
|
|
|
|
/* Build the P/B{0,1} ref lists. */
|
|
v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params,
|
|
- &run.slices_params[0], run.sps,
|
|
- run.decode_params->dpb);
|
|
+ run.sps, run.decode_params->dpb);
|
|
h264_ctx->reflists.num_valid = reflist_builder.num_valid;
|
|
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
|
|
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index 7d9bd5860a1b..c8f626fdd3dd 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -95,7 +95,6 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
{
|
|
struct cedrus_h264_sram_ref_pic pic_list[CEDRUS_H264_FRAME_NUM];
|
|
const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params;
|
|
- const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params;
|
|
const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
|
|
struct vb2_queue *cap_q;
|
|
struct cedrus_buffer *output_buf;
|
|
@@ -144,7 +143,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
|
|
output_buf->codec.h264.position = position;
|
|
|
|
- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
|
|
+ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
|
|
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
|
|
else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
|
|
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_MBAFF;
|
|
@@ -407,7 +406,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
|
|
cedrus_write(dev, VE_H264_SPS, reg);
|
|
|
|
- mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) &&
|
|
+ mbaff_pic = !(decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) &&
|
|
(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
|
|
pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1;
|
|
|
|
@@ -421,9 +420,9 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
reg |= slice->cabac_init_idc & 0x3;
|
|
if (ctx->fh.m2m_ctx->new_frame)
|
|
reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
|
|
- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
|
|
+ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
|
|
reg |= VE_H264_SHS_FIELD_PIC;
|
|
- if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
|
|
+ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
|
|
reg |= VE_H264_SHS_BOTTOM_FIELD;
|
|
if (slice->flags & V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED)
|
|
reg |= VE_H264_SHS_DIRECT_SPATIAL_MV_PRED;
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index e180501e6385..1217b706128e 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -146,10 +146,8 @@ struct v4l2_ctrl_h264_pred_weights {
|
|
#define V4L2_H264_SLICE_TYPE_SP 3
|
|
#define V4L2_H264_SLICE_TYPE_SI 4
|
|
|
|
-#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01
|
|
-#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02
|
|
-#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
|
|
-#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
|
|
+#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01
|
|
+#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02
|
|
|
|
enum v4l2_h264_field_reference {
|
|
V4L2_H264_TOP_FIELD_REF = 0x1,
|
|
@@ -171,21 +169,8 @@ struct v4l2_ctrl_h264_slice_params {
|
|
__u32 first_mb_in_slice;
|
|
|
|
__u8 slice_type;
|
|
- __u8 pic_parameter_set_id;
|
|
__u8 colour_plane_id;
|
|
__u8 redundant_pic_cnt;
|
|
- __u16 frame_num;
|
|
- __u16 idr_pic_id;
|
|
- __u16 pic_order_cnt_lsb;
|
|
- __s32 delta_pic_order_cnt_bottom;
|
|
- __s32 delta_pic_order_cnt0;
|
|
- __s32 delta_pic_order_cnt1;
|
|
-
|
|
- /* Size in bits of dec_ref_pic_marking() syntax element. */
|
|
- __u32 dec_ref_pic_marking_bit_size;
|
|
- /* Size in bits of pic order count syntax. */
|
|
- __u32 pic_order_cnt_bit_size;
|
|
-
|
|
__u8 cabac_init_idc;
|
|
__s8 slice_qp_delta;
|
|
__s8 slice_qs_delta;
|
|
@@ -194,7 +179,8 @@ struct v4l2_ctrl_h264_slice_params {
|
|
__s8 slice_beta_offset_div2;
|
|
__u8 num_ref_idx_l0_active_minus1;
|
|
__u8 num_ref_idx_l1_active_minus1;
|
|
- __u32 slice_group_change_cycle;
|
|
+
|
|
+ __u8 reserved;
|
|
|
|
struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN];
|
|
struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN];
|
|
@@ -219,13 +205,28 @@ struct v4l2_h264_dpb_entry {
|
|
__u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
|
|
};
|
|
|
|
-#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
|
|
+#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
|
|
+#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02
|
|
+#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04
|
|
|
|
struct v4l2_ctrl_h264_decode_params {
|
|
struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES];
|
|
__u16 nal_ref_idc;
|
|
+ __u16 frame_num;
|
|
__s32 top_field_order_cnt;
|
|
__s32 bottom_field_order_cnt;
|
|
+ __u16 idr_pic_id;
|
|
+ __u16 pic_order_cnt_lsb;
|
|
+ __s32 delta_pic_order_cnt_bottom;
|
|
+ __s32 delta_pic_order_cnt0;
|
|
+ __s32 delta_pic_order_cnt1;
|
|
+ /* Size in bits of dec_ref_pic_marking() syntax element. */
|
|
+ __u32 dec_ref_pic_marking_bit_size;
|
|
+ /* Size in bits of pic order count syntax. */
|
|
+ __u32 pic_order_cnt_bit_size;
|
|
+ __u32 slice_group_change_cycle;
|
|
+
|
|
+ __u32 reserved;
|
|
__u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */
|
|
};
|
|
|
|
diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h
|
|
index 1a5f26fc2a9a..f08ba181263d 100644
|
|
--- a/include/media/v4l2-h264.h
|
|
+++ b/include/media/v4l2-h264.h
|
|
@@ -44,7 +44,6 @@ struct v4l2_h264_reflist_builder {
|
|
void
|
|
v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
|
|
const struct v4l2_ctrl_h264_decode_params *dec_params,
|
|
- const struct v4l2_ctrl_h264_slice_params *slice_params,
|
|
const struct v4l2_ctrl_h264_sps *sps,
|
|
const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]);
|
|
|
|
|
|
From c94048bd00c4faa5bf1be0b3b01d3cc41cb475bb Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:26 -0300
|
|
Subject: [PATCH] media: uapi: h264: Rename and clarify
|
|
PPS_FLAG_SCALING_MATRIX_PRESENT
|
|
|
|
Applications are expected to fill V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX
|
|
if a non-flat scaling matrix applies to the picture. This is the case if
|
|
SPS scaling_matrix_present_flag or PPS pic_scaling_matrix_present_flag
|
|
are set, and should be handled by applications.
|
|
|
|
On one hand, the PPS bitstream syntax element signals the presence of a
|
|
Picture scaling matrix modifying the Sequence (SPS) scaling matrix.
|
|
On the other hand, our flag should indicate if the scaling matrix
|
|
V4L2 control is applicable to this request.
|
|
|
|
Rename the flag from PPS_FLAG_PIC_SCALING_MATRIX_PRESENT to
|
|
PPS_FLAG_SCALING_MATRIX_PRESENT, to avoid mixing this flag with
|
|
bitstream syntax element pic_scaling_matrix_present_flag,
|
|
and clarify the meaning of our flag.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 +++--
|
|
include/media/h264-ctrls.h | 2 +-
|
|
2 files changed, 4 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 69dd3961b99b..03ce87aa5488 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -1695,9 +1695,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
* - ``V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE``
|
|
- 0x00000040
|
|
-
|
|
- * - ``V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT``
|
|
+ * - ``V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT``
|
|
- 0x00000080
|
|
- -
|
|
+ - Indicates that ``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX``
|
|
+ must be used for this picture.
|
|
|
|
``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (struct)``
|
|
Specifies the scaling matrix (as extracted from the bitstream) for
|
|
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
|
|
index 1217b706128e..070b9499d7bc 100644
|
|
--- a/include/media/h264-ctrls.h
|
|
+++ b/include/media/h264-ctrls.h
|
|
@@ -99,7 +99,7 @@ struct v4l2_ctrl_h264_sps {
|
|
#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010
|
|
#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020
|
|
#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040
|
|
-#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080
|
|
+#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080
|
|
|
|
struct v4l2_ctrl_h264_pps {
|
|
__u8 pic_parameter_set_id;
|
|
|
|
From 2344f270ec7a9f9559e6d1e57a124c6a89ce0602 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:27 -0300
|
|
Subject: [PATCH] media: hantro: Don't require unneeded H264_SLICE_PARAMS
|
|
|
|
Now that slice invariant parameters have been moved,
|
|
the driver no longer needs this control, so drop it.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/hantro/hantro_drv.c | 5 -----
|
|
drivers/staging/media/hantro/hantro_h264.c | 5 -----
|
|
drivers/staging/media/hantro/hantro_hw.h | 2 --
|
|
3 files changed, 12 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
|
|
index 34797507f214..3cd00cc0a364 100644
|
|
--- a/drivers/staging/media/hantro/hantro_drv.c
|
|
+++ b/drivers/staging/media/hantro/hantro_drv.c
|
|
@@ -306,11 +306,6 @@ static const struct hantro_ctrl controls[] = {
|
|
.cfg = {
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
|
|
},
|
|
- }, {
|
|
- .codec = HANTRO_H264_DECODER,
|
|
- .cfg = {
|
|
- .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
|
|
- },
|
|
}, {
|
|
.codec = HANTRO_H264_DECODER,
|
|
.cfg = {
|
|
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
|
|
index 7578a4fc1b16..089bfa9c625b 100644
|
|
--- a/drivers/staging/media/hantro/hantro_h264.c
|
|
+++ b/drivers/staging/media/hantro/hantro_h264.c
|
|
@@ -349,11 +349,6 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
|
|
if (WARN_ON(!ctrls->decode))
|
|
return -EINVAL;
|
|
|
|
- ctrls->slices =
|
|
- hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS);
|
|
- if (WARN_ON(!ctrls->slices))
|
|
- return -EINVAL;
|
|
-
|
|
ctrls->sps =
|
|
hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SPS);
|
|
if (WARN_ON(!ctrls->sps))
|
|
diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h
|
|
index f066de6b592d..219283a06f52 100644
|
|
--- a/drivers/staging/media/hantro/hantro_hw.h
|
|
+++ b/drivers/staging/media/hantro/hantro_hw.h
|
|
@@ -56,14 +56,12 @@ struct hantro_jpeg_enc_hw_ctx {
|
|
* struct hantro_h264_dec_ctrls
|
|
* @decode: Decode params
|
|
* @scaling: Scaling info
|
|
- * @slice: Slice params
|
|
* @sps: SPS info
|
|
* @pps: PPS info
|
|
*/
|
|
struct hantro_h264_dec_ctrls {
|
|
const struct v4l2_ctrl_h264_decode_params *decode;
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling;
|
|
- const struct v4l2_ctrl_h264_slice_params *slices;
|
|
const struct v4l2_ctrl_h264_sps *sps;
|
|
const struct v4l2_ctrl_h264_pps *pps;
|
|
};
|
|
|
|
From 419ccc9852409f2553c92ee3be909afa53d24d1d Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:28 -0300
|
|
Subject: [PATCH] media: rkvdec: Don't require unneeded H264_SLICE_PARAMS
|
|
|
|
Now that slice invariant parameters have been moved,
|
|
the driver no longer needs this control, so drop it.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Reviewed-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ----
|
|
drivers/staging/media/rkvdec/rkvdec.c | 5 -----
|
|
2 files changed, 9 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 70752e30b3a3..584e0d5c493b 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -109,7 +109,6 @@ struct rkvdec_h264_reflists {
|
|
struct rkvdec_h264_run {
|
|
struct rkvdec_run base;
|
|
const struct v4l2_ctrl_h264_decode_params *decode_params;
|
|
- const struct v4l2_ctrl_h264_slice_params *slices_params;
|
|
const struct v4l2_ctrl_h264_sps *sps;
|
|
const struct v4l2_ctrl_h264_pps *pps;
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
|
|
@@ -1066,9 +1065,6 @@ static void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx,
|
|
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS);
|
|
run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
|
|
- ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
- V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS);
|
|
- run->slices_params = ctrl ? ctrl->p_cur.p : NULL;
|
|
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
V4L2_CID_MPEG_VIDEO_H264_SPS);
|
|
run->sps = ctrl ? ctrl->p_cur.p : NULL;
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index c8151328fb70..7c5129593921 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -59,11 +59,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
|
|
.mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
|
|
},
|
|
- {
|
|
- .per_request = true,
|
|
- .mandatory = true,
|
|
- .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
|
|
- },
|
|
{
|
|
.per_request = true,
|
|
.mandatory = true,
|
|
|
|
From 85567a00727331d7a3269bd76319a048ef1ed505 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Fri, 14 Aug 2020 10:36:29 -0300
|
|
Subject: [PATCH] media: cedrus: h264: Properly configure reference field
|
|
|
|
When interlaced H264 content is being decoded, references must indicate
|
|
which field is being referenced. Currently this was done by checking
|
|
capture buffer flags. However, that is not correct because capture
|
|
buffer may hold both fields.
|
|
|
|
Fix this by checking newly introduced flags in reference lists.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++----
|
|
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index c8f626fdd3dd..1e89a8438f36 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -182,7 +182,6 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
|
for (i = 0; i < num_ref; i++) {
|
|
const struct v4l2_h264_dpb_entry *dpb;
|
|
const struct cedrus_buffer *cedrus_buf;
|
|
- const struct vb2_v4l2_buffer *ref_buf;
|
|
unsigned int position;
|
|
int buf_idx;
|
|
u8 dpb_idx;
|
|
@@ -197,12 +196,11 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
|
if (buf_idx < 0)
|
|
continue;
|
|
|
|
- ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]);
|
|
- cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf);
|
|
+ cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]);
|
|
position = cedrus_buf->codec.h264.position;
|
|
|
|
sram_array[i] |= position << 1;
|
|
- if (ref_buf->field == V4L2_FIELD_BOTTOM)
|
|
+ if (ref_list[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
|
|
sram_array[i] |= BIT(0);
|
|
}
|
|
|
|
|
|
From 102efa220abfcf3c08ceaf0a7c3ac5f88db5bc0c Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Fri, 14 Aug 2020 10:36:30 -0300
|
|
Subject: [PATCH] media: cedrus: h264: Fix frame list construction
|
|
|
|
Current frame list construction algorithm assumes that decoded image
|
|
will be output into its own buffer. That is true for progressive content
|
|
but not for interlaced where each field is decoded separately into same
|
|
buffer.
|
|
|
|
Fix that by checking if capture buffer is listed in DPB. If it is, reuse
|
|
it.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 15 +++++++++------
|
|
1 file changed, 9 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index 1e89a8438f36..fe041b444385 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -101,7 +101,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
unsigned long used_dpbs = 0;
|
|
unsigned int position;
|
|
- unsigned int output = 0;
|
|
+ int output = -1;
|
|
unsigned int i;
|
|
|
|
cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
|
@@ -124,6 +124,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
position = cedrus_buf->codec.h264.position;
|
|
used_dpbs |= BIT(position);
|
|
|
|
+ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) {
|
|
+ output = position;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
|
continue;
|
|
|
|
@@ -131,13 +136,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
|
dpb->top_field_order_cnt,
|
|
dpb->bottom_field_order_cnt,
|
|
&pic_list[position]);
|
|
-
|
|
- output = max(position, output);
|
|
}
|
|
|
|
- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM,
|
|
- output);
|
|
- if (position >= CEDRUS_H264_FRAME_NUM)
|
|
+ if (output >= 0)
|
|
+ position = output;
|
|
+ else
|
|
position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM);
|
|
|
|
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
|
|
|
|
From 47f1224e5d7f2d3d566d1da9df0f72ee0564a0d1 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Wed, 19 Aug 2020 11:37:55 -0300
|
|
Subject: [PATCH] media: rkvdec: Drop unneeded per_request driver-specific
|
|
control flag
|
|
|
|
Currently, the drivers makes no distinction between per_request
|
|
and mandatory, as both are used in the same request validate check.
|
|
|
|
The driver only cares to know if a given control is
|
|
required to be part of a request, so only one flag is needed.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 8 +-------
|
|
drivers/staging/media/rkvdec/rkvdec.h | 1 -
|
|
2 files changed, 1 insertion(+), 8 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 7c5129593921..9f59dfb62d3f 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -55,35 +55,29 @@ static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = {
|
|
|
|
static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
|
|
{
|
|
- .per_request = true,
|
|
.mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
|
|
},
|
|
{
|
|
- .per_request = true,
|
|
.mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_SPS,
|
|
.cfg.ops = &rkvdec_ctrl_ops,
|
|
},
|
|
{
|
|
- .per_request = true,
|
|
.mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS,
|
|
},
|
|
{
|
|
- .per_request = true,
|
|
.mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
|
|
},
|
|
{
|
|
- .mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE,
|
|
.cfg.min = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED,
|
|
.cfg.max = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED,
|
|
.cfg.def = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED,
|
|
},
|
|
{
|
|
- .mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_START_CODE,
|
|
.cfg.min = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
|
|
.cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
|
|
@@ -615,7 +609,7 @@ static int rkvdec_request_validate(struct media_request *req)
|
|
u32 id = ctrls->ctrls[i].cfg.id;
|
|
struct v4l2_ctrl *ctrl;
|
|
|
|
- if (!ctrls->ctrls[i].per_request || !ctrls->ctrls[i].mandatory)
|
|
+ if (!ctrls->ctrls[i].mandatory)
|
|
continue;
|
|
|
|
ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl, id);
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
|
|
index 2fc9f46b6910..77a137cca88e 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.h
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.h
|
|
@@ -25,7 +25,6 @@
|
|
struct rkvdec_ctx;
|
|
|
|
struct rkvdec_ctrl_desc {
|
|
- u32 per_request : 1;
|
|
u32 mandatory : 1;
|
|
struct v4l2_ctrl_config cfg;
|
|
};
|
|
|
|
From 90ea71bc465216778ac6fda4ca151f324df4d516 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:32 -0300
|
|
Subject: [PATCH] media: rkvdec: Use H264_SCALING_MATRIX only when required
|
|
|
|
Baseline, Main and Extended profiles are specified to
|
|
not support a scaling matrix. Also, High profiles
|
|
can optionally specify a scaling matrix, using
|
|
SPS and PPS NAL units.
|
|
|
|
To meet this expectation, applications are required to
|
|
set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control
|
|
and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT
|
|
flag only when a scaling matrix is specified for a picture.
|
|
|
|
Implement this on rkvdec, which has hardware support for this
|
|
case.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++++---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 1 -
|
|
2 files changed, 7 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 584e0d5c493b..9233260e14c1 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -708,9 +708,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
|
WRITE_PPS(pps->second_chroma_qp_index_offset,
|
|
SECOND_CHROMA_QP_INDEX_OFFSET);
|
|
|
|
- /* always use the matrix sent from userspace */
|
|
- WRITE_PPS(1, SCALING_LIST_ENABLE_FLAG);
|
|
-
|
|
+ WRITE_PPS(!!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT),
|
|
+ SCALING_LIST_ENABLE_FLAG);
|
|
+ /* To be on the safe side, program the scaling matrix address */
|
|
scaling_distance = offsetof(struct rkvdec_h264_priv_tbl, scaling_list);
|
|
scaling_list_address = h264_ctx->priv_tbl.dma + scaling_distance;
|
|
WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS);
|
|
@@ -792,9 +792,13 @@ static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx,
|
|
struct rkvdec_h264_run *run)
|
|
{
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix;
|
|
+ const struct v4l2_ctrl_h264_pps *pps = run->pps;
|
|
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
|
|
struct rkvdec_h264_priv_tbl *tbl = h264_ctx->priv_tbl.cpu;
|
|
|
|
+ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
|
+ return;
|
|
+
|
|
BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_4x4) !=
|
|
sizeof(scaling->scaling_list_4x4));
|
|
BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_8x8) !=
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 9f59dfb62d3f..d25c4a37e2af 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -68,7 +68,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS,
|
|
},
|
|
{
|
|
- .mandatory = true,
|
|
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
|
|
},
|
|
{
|
|
|
|
From 70d39439f485d511c9c929934a26341ef3b736ef Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:33 -0300
|
|
Subject: [PATCH] media: hantro: Use H264_SCALING_MATRIX only when required
|
|
|
|
Baseline, Main and Extended profiles are specified to
|
|
not support a scaling matrix. Also, High profiles
|
|
can optionally specify a scaling matrix, using
|
|
SPS and PPS NAL units.
|
|
|
|
To meet this expectation, applications are required to
|
|
set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control
|
|
and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT
|
|
flag only when a scaling matrix is specified for a picture.
|
|
|
|
Implement this on hantro, which has hardware support for this
|
|
case.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/hantro/hantro_g1_h264_dec.c | 5 ++---
|
|
drivers/staging/media/hantro/hantro_h264.c | 4 ++++
|
|
2 files changed, 6 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
index f9839e9c6da5..845bef73d218 100644
|
|
--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
|
|
@@ -59,9 +59,8 @@ static void set_params(struct hantro_ctx *ctx)
|
|
reg = G1_REG_DEC_CTRL2_CH_QP_OFFSET(pps->chroma_qp_index_offset) |
|
|
G1_REG_DEC_CTRL2_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset);
|
|
|
|
- /* always use the matrix sent from userspace */
|
|
- reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E;
|
|
-
|
|
+ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
|
|
+ reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E;
|
|
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
|
|
reg |= G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E;
|
|
vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2);
|
|
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
|
|
index 089bfa9c625b..b1bdc00ac262 100644
|
|
--- a/drivers/staging/media/hantro/hantro_h264.c
|
|
+++ b/drivers/staging/media/hantro/hantro_h264.c
|
|
@@ -197,6 +197,7 @@ assemble_scaling_list(struct hantro_ctx *ctx)
|
|
{
|
|
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling;
|
|
+ const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
|
|
const size_t num_list_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4);
|
|
const size_t list_len_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4[0]);
|
|
const size_t list_len_8x8 = ARRAY_SIZE(scaling->scaling_list_8x8[0]);
|
|
@@ -205,6 +206,9 @@ assemble_scaling_list(struct hantro_ctx *ctx)
|
|
const u32 *src;
|
|
int i, j;
|
|
|
|
+ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
|
+ return;
|
|
+
|
|
for (i = 0; i < num_list_4x4; i++) {
|
|
src = (u32 *)&scaling->scaling_list_4x4[i];
|
|
for (j = 0; j < list_len_4x4 / 4; j++)
|
|
|
|
From 6390458815944ce231b6282771e2a6c3fc6f2fa6 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Fri, 14 Aug 2020 10:36:34 -0300
|
|
Subject: [PATCH] media: cedrus: Use H264_SCALING_MATRIX only when required
|
|
|
|
Baseline, Main and Extended profiles are specified to
|
|
not support a scaling matrix. Also, High profiles
|
|
can optionally specify a scaling matrix, using
|
|
SPS and PPS NAL units.
|
|
|
|
To meet this expectation, applications are required to
|
|
set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control
|
|
and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT
|
|
flag only when a scaling matrix is specified for a picture.
|
|
|
|
Implement this on cedrus, which has hardware support for this
|
|
case.
|
|
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.c | 2 +-
|
|
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++++++
|
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
index 826324faad7e..6ebb39e0c0ce 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
@@ -76,7 +76,7 @@ static const struct cedrus_control cedrus_controls[] = {
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
|
|
},
|
|
.codec = CEDRUS_CODEC_H264,
|
|
- .required = true,
|
|
+ .required = false,
|
|
},
|
|
{
|
|
.cfg = {
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index fe041b444385..28319351e909 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -238,8 +238,12 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx,
|
|
{
|
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling =
|
|
run->h264.scaling_matrix;
|
|
+ const struct v4l2_ctrl_h264_pps *pps = run->h264.pps;
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
|
|
+ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
|
+ return;
|
|
+
|
|
cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_0,
|
|
scaling->scaling_list_8x8[0],
|
|
sizeof(scaling->scaling_list_8x8[0]));
|
|
@@ -442,6 +446,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
|
|
reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
|
|
reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
|
|
+ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
|
|
+ reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT;
|
|
cedrus_write(dev, VE_H264_SHS_QP, reg);
|
|
|
|
// clear status flags
|
|
|
|
From 711f57301ef4368ba23f70f6596994b7242803cc Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:33 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Fix reference frame_num wrap for second
|
|
field
|
|
|
|
When decoding the second field in a complementary field pair the second
|
|
field is sharing the same frame_num with the first field.
|
|
|
|
Currently the frame_num for the first field is wrapped when it matches the
|
|
field being decoded, this cause issues to decode the second field in a
|
|
complementary field pair.
|
|
|
|
Fix this by using inclusive comparison, less than or equal.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
Reviewed-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 9233260e14c1..8fab0151b884 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -752,7 +752,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx,
|
|
continue;
|
|
|
|
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ||
|
|
- dpb[i].frame_num < dec_params->frame_num) {
|
|
+ dpb[i].frame_num <= dec_params->frame_num) {
|
|
p[i] = dpb[i].frame_num;
|
|
continue;
|
|
}
|
|
|
|
From a957b522403e98c67b8c184fa3b7709c6e874d40 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:34 +0000
|
|
Subject: [PATCH] media: rkvdec: Ensure decoded resolution fit coded resolution
|
|
|
|
Ensure decoded CAPTURE buffer resolution is larger or equal to the coded
|
|
OPTUPT buffer resolution.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index d25c4a37e2af..b3e067031c83 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -223,6 +223,8 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
|
|
pix_mp->pixelformat = coded_desc->decoded_fmts[0];
|
|
|
|
/* Always apply the frmsize constraint of the coded end. */
|
|
+ pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width);
|
|
+ pix_mp->height = max(pix_mp->height, ctx->coded_fmt.fmt.pix_mp.height);
|
|
v4l2_apply_frmsize_constraints(&pix_mp->width,
|
|
&pix_mp->height,
|
|
&coded_desc->frmsize);
|
|
|
|
From 7c3bb86b8d315c1939a35c4dfe31e120758e5395 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:34 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Validate and use pic width and height in
|
|
mbs
|
|
|
|
The width and height in mbs is currently configured based on OUTPUT buffer
|
|
resolution, this works for frame pictures but can cause issues for field
|
|
pictures.
|
|
|
|
When frame_mbs_only_flag is 0 the height in mbs should be height of
|
|
the field instead of height of frame.
|
|
|
|
Validate pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1
|
|
against OUTPUT buffer resolution and use these values to configure HW.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++--
|
|
drivers/staging/media/rkvdec/rkvdec.c | 10 ++++++++++
|
|
2 files changed, 12 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 8fab0151b884..20a783a1bcc7 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -671,8 +671,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
|
LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4);
|
|
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO),
|
|
DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG);
|
|
- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS);
|
|
- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS);
|
|
+ WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS);
|
|
+ WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS);
|
|
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY),
|
|
FRAME_MBS_ONLY_FLAG);
|
|
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD),
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index b3e067031c83..06fc58440cd3 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -29,8 +29,11 @@
|
|
|
|
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
{
|
|
+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
|
|
+
|
|
if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) {
|
|
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
|
|
+ unsigned int width, height;
|
|
/*
|
|
* TODO: The hardware supports 10-bit and 4:2:2 profiles,
|
|
* but it's currently broken in the driver.
|
|
@@ -45,6 +48,13 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
if (sps->bit_depth_luma_minus8 != 0)
|
|
/* Only 8-bit is supported */
|
|
return -EINVAL;
|
|
+
|
|
+ width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
|
|
+ height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
|
|
+
|
|
+ if (width > ctx->coded_fmt.fmt.pix_mp.width ||
|
|
+ height > ctx->coded_fmt.fmt.pix_mp.height)
|
|
+ return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
From f28529ac6fd75419e2b1806777158b5912ea0cb4 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:35 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Fix bit depth wrap in pps packet
|
|
|
|
The luma and chroma bit depth fields in the pps packet is 3 bits wide.
|
|
8 is wrongly added to the bit depth value written to these 3-bit fields.
|
|
Because only the 3 LSB is written the hardware is configured correctly.
|
|
|
|
Correct this by not adding 8 to the luma and chroma bit depth value.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
Reviewed-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 20a783a1bcc7..f4b61dd45e7f 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -661,8 +661,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
|
WRITE_PPS(0xff, PROFILE_IDC);
|
|
WRITE_PPS(1, CONSTRAINT_SET3_FLAG);
|
|
WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC);
|
|
- WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA);
|
|
- WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA);
|
|
+ WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA);
|
|
+ WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA);
|
|
WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG);
|
|
WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4);
|
|
WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES);
|
|
|
|
From a0de7efadd3058c3837714fd1c71e31dd00b9eac Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:35 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Do not override output buffer sizeimage
|
|
|
|
The output buffer sizeimage is currently forced to 2 bytes per pixel, this
|
|
can lead to high memory usage for 4K content when multiple output buffers
|
|
is created by userspace.
|
|
|
|
Do not override output buffer sizeimage and let userspace have control of
|
|
output buffer sizeimage by only setting sizeimage if none is provided.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index f4b61dd45e7f..2e7749bac417 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
|
|
struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
|
|
|
|
fmt->num_planes = 1;
|
|
- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
|
|
- RKVDEC_H264_MAX_DEPTH_IN_BYTES;
|
|
+ if (!fmt->plane_fmt[0].sizeimage)
|
|
+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
|
|
+ RKVDEC_H264_MAX_DEPTH_IN_BYTES;
|
|
return 0;
|
|
}
|
|
|
|
|
|
From 2fd027124722012155dda6bf4af57d978ce0655c Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:35 +0000
|
|
Subject: [PATCH] media: v4l2-common: Add helpers to calculate bytesperline and
|
|
sizeimage
|
|
|
|
Add helper functions to calculate plane bytesperline and sizeimage, these
|
|
new helpers consider block width and height when calculating plane
|
|
bytesperline and sizeimage.
|
|
|
|
This prepare support for new pixel formats added in next patch that make
|
|
use of block width and height.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/media/v4l2-core/v4l2-common.c | 77 +++++++++++++--------------
|
|
1 file changed, 38 insertions(+), 39 deletions(-)
|
|
|
|
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
|
|
index 3dc17ebe14fa..4102c373b48a 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-common.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-common.c
|
|
@@ -333,6 +333,33 @@ static inline unsigned int v4l2_format_block_height(const struct v4l2_format_inf
|
|
return info->block_h[plane];
|
|
}
|
|
|
|
+static inline unsigned int v4l2_format_plane_width(const struct v4l2_format_info *info, int plane,
|
|
+ unsigned int width)
|
|
+{
|
|
+ unsigned int hdiv = plane ? info->hdiv : 1;
|
|
+ unsigned int bytes = DIV_ROUND_UP(width * info->bpp[plane],
|
|
+ v4l2_format_block_width(info, plane) *
|
|
+ v4l2_format_block_height(info, plane));
|
|
+
|
|
+ return DIV_ROUND_UP(bytes, hdiv);
|
|
+}
|
|
+
|
|
+static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane,
|
|
+ unsigned int height)
|
|
+{
|
|
+ unsigned int vdiv = plane ? info->vdiv : 1;
|
|
+ unsigned int lines = ALIGN(height, v4l2_format_block_height(info, plane));
|
|
+
|
|
+ return DIV_ROUND_UP(lines, vdiv);
|
|
+}
|
|
+
|
|
+static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane,
|
|
+ unsigned int width, unsigned int height)
|
|
+{
|
|
+ return v4l2_format_plane_width(info, plane, width) *
|
|
+ v4l2_format_plane_height(info, plane, height);
|
|
+}
|
|
+
|
|
void v4l2_apply_frmsize_constraints(u32 *width, u32 *height,
|
|
const struct v4l2_frmsize_stepwise *frmsize)
|
|
{
|
|
@@ -368,37 +395,19 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
|
|
|
|
if (info->mem_planes == 1) {
|
|
plane = &pixfmt->plane_fmt[0];
|
|
- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
|
|
+ plane->bytesperline = v4l2_format_plane_width(info, 0, width);
|
|
plane->sizeimage = 0;
|
|
|
|
- for (i = 0; i < info->comp_planes; i++) {
|
|
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
|
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
|
- unsigned int aligned_width;
|
|
- unsigned int aligned_height;
|
|
-
|
|
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
|
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
|
-
|
|
- plane->sizeimage += info->bpp[i] *
|
|
- DIV_ROUND_UP(aligned_width, hdiv) *
|
|
- DIV_ROUND_UP(aligned_height, vdiv);
|
|
- }
|
|
+ for (i = 0; i < info->comp_planes; i++)
|
|
+ plane->sizeimage +=
|
|
+ v4l2_format_plane_size(info, i, width, height);
|
|
} else {
|
|
for (i = 0; i < info->comp_planes; i++) {
|
|
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
|
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
|
- unsigned int aligned_width;
|
|
- unsigned int aligned_height;
|
|
-
|
|
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
|
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
|
-
|
|
plane = &pixfmt->plane_fmt[i];
|
|
plane->bytesperline =
|
|
- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv);
|
|
- plane->sizeimage =
|
|
- plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
|
|
+ v4l2_format_plane_width(info, i, width);
|
|
+ plane->sizeimage = plane->bytesperline *
|
|
+ v4l2_format_plane_height(info, i, height);
|
|
}
|
|
}
|
|
return 0;
|
|
@@ -422,22 +431,12 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
|
|
pixfmt->width = width;
|
|
pixfmt->height = height;
|
|
pixfmt->pixelformat = pixelformat;
|
|
- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
|
|
+ pixfmt->bytesperline = v4l2_format_plane_width(info, 0, width);
|
|
pixfmt->sizeimage = 0;
|
|
|
|
- for (i = 0; i < info->comp_planes; i++) {
|
|
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
|
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
|
- unsigned int aligned_width;
|
|
- unsigned int aligned_height;
|
|
-
|
|
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
|
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
|
-
|
|
- pixfmt->sizeimage += info->bpp[i] *
|
|
- DIV_ROUND_UP(aligned_width, hdiv) *
|
|
- DIV_ROUND_UP(aligned_height, vdiv);
|
|
- }
|
|
+ for (i = 0; i < info->comp_planes; i++)
|
|
+ pixfmt->sizeimage +=
|
|
+ v4l2_format_plane_size(info, i, width, height);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
|
|
|
|
From 889f4693a0947c22188ca643ed9ba3579f0abc66 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:36 +0000
|
|
Subject: [PATCH] media: v4l2: Add NV15 and NV20 pixel formats
|
|
|
|
Add NV15 and NV20 pixel formats used by the Rockchip Video Decoder for
|
|
10-bit buffers.
|
|
|
|
NV15 and NV20 is a packed 10-bit 4:2:0/4:2:2 semi-planar Y/CbCr format
|
|
similar to P010 and P210 but has no padding between components. Instead,
|
|
luminance and chrominance samples are grouped into 4s so that each group is
|
|
packed into an integer number of bytes:
|
|
|
|
YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes
|
|
|
|
The '15' and '20' suffix refers to the optimum effective bits per pixel
|
|
which is achieved when the total number of luminance samples is a multiple
|
|
of 8 for NV15 and 4 for NV20.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
.../userspace-api/media/v4l/pixfmt-nv15.rst | 101 ++++++++++++++++++
|
|
.../userspace-api/media/v4l/pixfmt-nv20.rst | 99 +++++++++++++++++
|
|
.../userspace-api/media/v4l/yuv-formats.rst | 2 +
|
|
drivers/media/v4l2-core/v4l2-common.c | 3 +
|
|
drivers/media/v4l2-core/v4l2-ioctl.c | 2 +
|
|
include/uapi/linux/videodev2.h | 3 +
|
|
6 files changed, 210 insertions(+)
|
|
create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv15.rst
|
|
create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv20.rst
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst
|
|
new file mode 100644
|
|
index 000000000000..d059db58c6e0
|
|
--- /dev/null
|
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst
|
|
@@ -0,0 +1,101 @@
|
|
+.. Permission is granted to copy, distribute and/or modify this
|
|
+.. document under the terms of the GNU Free Documentation License,
|
|
+.. Version 1.1 or any later version published by the Free Software
|
|
+.. Foundation, with no Invariant Sections, no Front-Cover Texts
|
|
+.. and no Back-Cover Texts. A copy of the license is included at
|
|
+.. Documentation/userspace-api/media/fdl-appendix.rst.
|
|
+..
|
|
+.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
|
|
+
|
|
+.. _V4L2-PIX-FMT-NV15:
|
|
+
|
|
+**************************
|
|
+V4L2_PIX_FMT_NV15 ('NV15')
|
|
+**************************
|
|
+
|
|
+Format with ½ horizontal and vertical chroma resolution, also known as
|
|
+YUV 4:2:0. One luminance and one chrominance plane with alternating
|
|
+chroma samples similar to ``V4L2_PIX_FMT_NV12`` but with 10-bit samples
|
|
+that are grouped into four and packed into five bytes.
|
|
+
|
|
+The '15' suffix refers to the optimum effective bits per pixel which is
|
|
+achieved when the total number of luminance samples is a multiple of 8.
|
|
+
|
|
+
|
|
+Description
|
|
+===========
|
|
+
|
|
+This is a packed 10-bit two-plane version of the YUV 4:2:0 format. The
|
|
+three components are separated into two sub-images or planes. The Y plane
|
|
+is first. The Y plane has five bytes per each group of four pixels. A
|
|
+combined CbCr plane immediately follows the Y plane in memory. The CbCr
|
|
+plane is the same width, in bytes, as the Y plane (and of the image), but
|
|
+is half as tall in pixels. Each CbCr pair belongs to four pixels. For
|
|
+example, Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`,
|
|
+Y'\ :sub:`01`, Y'\ :sub:`10`, Y'\ :sub:`11`.
|
|
+
|
|
+If the Y plane has pad bytes after each row, then the CbCr plane has as
|
|
+many pad bytes after its rows.
|
|
+
|
|
+**Byte Order.**
|
|
+Little endian. Each cell is one byte. Pixels cross the byte boundary.
|
|
+
|
|
+
|
|
+.. flat-table::
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+
|
|
+ * - start + 0:
|
|
+ - Y'\ :sub:`00[7:0]`
|
|
+ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]`
|
|
+ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]`
|
|
+ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]`
|
|
+ - Y'\ :sub:`03[9:2]`
|
|
+ * - start + 5:
|
|
+ - Y'\ :sub:`10[7:0]`
|
|
+ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]`
|
|
+ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]`
|
|
+ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]`
|
|
+ - Y'\ :sub:`13[9:2]`
|
|
+ * - start + 10:
|
|
+ - Cb'\ :sub:`00[7:0]`
|
|
+ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]`
|
|
+ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]`
|
|
+ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]`
|
|
+ - Cr'\ :sub:`01[9:2]`
|
|
+
|
|
+
|
|
+**Color Sample Location:**
|
|
+
|
|
+.. flat-table::
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+
|
|
+ * -
|
|
+ - 0
|
|
+ -
|
|
+ - 1
|
|
+ - 2
|
|
+ -
|
|
+ - 3
|
|
+ * - 0
|
|
+ - Y
|
|
+ -
|
|
+ - Y
|
|
+ - Y
|
|
+ -
|
|
+ - Y
|
|
+ * -
|
|
+ -
|
|
+ - C
|
|
+ -
|
|
+ -
|
|
+ - C
|
|
+ -
|
|
+ * - 1
|
|
+ - Y
|
|
+ -
|
|
+ - Y
|
|
+ - Y
|
|
+ -
|
|
+ - Y
|
|
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst
|
|
new file mode 100644
|
|
index 000000000000..a8123be0baa3
|
|
--- /dev/null
|
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst
|
|
@@ -0,0 +1,99 @@
|
|
+.. Permission is granted to copy, distribute and/or modify this
|
|
+.. document under the terms of the GNU Free Documentation License,
|
|
+.. Version 1.1 or any later version published by the Free Software
|
|
+.. Foundation, with no Invariant Sections, no Front-Cover Texts
|
|
+.. and no Back-Cover Texts. A copy of the license is included at
|
|
+.. Documentation/userspace-api/media/fdl-appendix.rst.
|
|
+..
|
|
+.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
|
|
+
|
|
+.. _V4L2-PIX-FMT-NV20:
|
|
+
|
|
+**************************
|
|
+V4L2_PIX_FMT_NV20 ('NV20')
|
|
+**************************
|
|
+
|
|
+Format with ½ horizontal chroma resolution, also known as YUV 4:2:2.
|
|
+One luminance and one chrominance plane with alternating chroma samples
|
|
+similar to ``V4L2_PIX_FMT_NV16`` but with 10-bit samples
|
|
+that are grouped into four and packed into five bytes.
|
|
+
|
|
+The '20' suffix refers to the optimum effective bits per pixel which is
|
|
+achieved when the total number of luminance samples is a multiple of 4.
|
|
+
|
|
+
|
|
+Description
|
|
+===========
|
|
+
|
|
+This is a packed 10-bit two-plane version of the YUV 4:2:2 format. The
|
|
+three components are separated into two sub-images or planes. The Y plane
|
|
+is first. The Y plane has five bytes per each group of four pixels. A
|
|
+combined CbCr plane immediately follows the Y plane in memory. The CbCr
|
|
+plane is the same width and height, in bytes, as the Y plane (and of the
|
|
+image). Each CbCr pair belongs to two pixels. For example,
|
|
+Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, Y'\ :sub:`01`.
|
|
+
|
|
+If the Y plane has pad bytes after each row, then the CbCr plane has as
|
|
+many pad bytes after its rows.
|
|
+
|
|
+**Byte Order.**
|
|
+Little endian. Each cell is one byte. Pixels cross the byte boundary.
|
|
+
|
|
+
|
|
+.. flat-table::
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+
|
|
+ * - start + 0:
|
|
+ - Y'\ :sub:`00[7:0]`
|
|
+ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]`
|
|
+ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]`
|
|
+ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]`
|
|
+ - Y'\ :sub:`03[9:2]`
|
|
+ * - start + 5:
|
|
+ - Y'\ :sub:`10[7:0]`
|
|
+ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]`
|
|
+ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]`
|
|
+ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]`
|
|
+ - Y'\ :sub:`13[9:2]`
|
|
+ * - start + 10:
|
|
+ - Cb'\ :sub:`00[7:0]`
|
|
+ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]`
|
|
+ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]`
|
|
+ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]`
|
|
+ - Cr'\ :sub:`01[9:2]`
|
|
+ * - start + 15:
|
|
+ - Cb'\ :sub:`10[7:0]`
|
|
+ - Cr'\ :sub:`10[5:0]`\ Cb'\ :sub:`10[9:8]`
|
|
+ - Cb'\ :sub:`11[3:0]`\ Cr'\ :sub:`10[9:6]`
|
|
+ - Cr'\ :sub:`11[1:0]`\ Cb'\ :sub:`11[9:4]`
|
|
+ - Cr'\ :sub:`11[9:2]`
|
|
+
|
|
+
|
|
+**Color Sample Location:**
|
|
+
|
|
+.. flat-table::
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+
|
|
+ * -
|
|
+ - 0
|
|
+ -
|
|
+ - 1
|
|
+ - 2
|
|
+ -
|
|
+ - 3
|
|
+ * - 0
|
|
+ - Y
|
|
+ - C
|
|
+ - Y
|
|
+ - Y
|
|
+ - C
|
|
+ - Y
|
|
+ * - 1
|
|
+ - Y
|
|
+ - C
|
|
+ - Y
|
|
+ - Y
|
|
+ - C
|
|
+ - Y
|
|
diff --git a/Documentation/userspace-api/media/v4l/yuv-formats.rst b/Documentation/userspace-api/media/v4l/yuv-formats.rst
|
|
index 8ee92d0cd769..7cca883f178a 100644
|
|
--- a/Documentation/userspace-api/media/v4l/yuv-formats.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/yuv-formats.rst
|
|
@@ -61,4 +61,6 @@ to brightness information.
|
|
pixfmt-nv16
|
|
pixfmt-nv16m
|
|
pixfmt-nv24
|
|
+ pixfmt-nv15
|
|
+ pixfmt-nv20
|
|
pixfmt-m420
|
|
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
|
|
index 4102c373b48a..0caac755d303 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-common.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-common.c
|
|
@@ -267,6 +267,9 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
|
|
{ .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
|
{ .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
|
|
|
+ { .format = V4L2_PIX_FMT_NV15, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 2, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } },
|
|
+ { .format = V4L2_PIX_FMT_NV20, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 1, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } },
|
|
+
|
|
{ .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
|
|
{ .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
|
|
{ .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 },
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
index ccf947632a3b..53de49087938 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
@@ -1321,6 +1321,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
|
|
case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break;
|
|
case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break;
|
|
case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break;
|
|
+ case V4L2_PIX_FMT_NV15: descr = "10-bit Y/CbCr 4:2:0 (Packed)"; break;
|
|
+ case V4L2_PIX_FMT_NV20: descr = "10-bit Y/CbCr 4:2:2 (Packed)"; break;
|
|
case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break;
|
|
case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break;
|
|
case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break;
|
|
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
|
|
index 6fe8822d2cb4..c8d7148cd9ae 100644
|
|
--- a/include/uapi/linux/videodev2.h
|
|
+++ b/include/uapi/linux/videodev2.h
|
|
@@ -610,6 +610,9 @@ struct v4l2_pix_format {
|
|
#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */
|
|
#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */
|
|
|
|
+#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit packed */
|
|
+#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/CbCr 4:2:2 10-bit packed */
|
|
+
|
|
/* two non contiguous planes - one Y, one Cr + Cb interleaved */
|
|
#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
|
|
#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */
|
|
|
|
From d09e5dfbcc096eddf5c5d11744d53bae5f1f7d00 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:36 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Use bytesperline and buffer height to
|
|
calculate stride
|
|
|
|
Use bytesperline and buffer height to calculate the strides configured.
|
|
|
|
This does not really change anything other than ensuring the bytesperline
|
|
that is signaled to userspace matches what is configured in HW.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++-----
|
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index 2e7749bac417..d33fccc92205 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -893,9 +893,9 @@ static void config_registers(struct rkvdec_ctx *ctx,
|
|
dma_addr_t rlc_addr;
|
|
dma_addr_t refer_addr;
|
|
u32 rlc_len;
|
|
- u32 hor_virstride = 0;
|
|
- u32 ver_virstride = 0;
|
|
- u32 y_virstride = 0;
|
|
+ u32 hor_virstride;
|
|
+ u32 ver_virstride;
|
|
+ u32 y_virstride;
|
|
u32 yuv_virstride = 0;
|
|
u32 offset;
|
|
dma_addr_t dst_addr;
|
|
@@ -906,8 +906,8 @@ static void config_registers(struct rkvdec_ctx *ctx,
|
|
|
|
f = &ctx->decoded_fmt;
|
|
dst_fmt = &f->fmt.pix_mp;
|
|
- hor_virstride = (sps->bit_depth_luma_minus8 + 8) * dst_fmt->width / 8;
|
|
- ver_virstride = round_up(dst_fmt->height, 16);
|
|
+ hor_virstride = dst_fmt->plane_fmt[0].bytesperline;
|
|
+ ver_virstride = dst_fmt->height;
|
|
y_virstride = hor_virstride * ver_virstride;
|
|
|
|
if (sps->chroma_format_idc == 0)
|
|
|
|
From f0e873d66825fcd9ea314dcdab0d214226b2b8b4 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:37 +0000
|
|
Subject: [PATCH] media: rkvdec: Extract rkvdec_fill_decoded_pixfmt helper
|
|
method
|
|
|
|
This extract setting decoded pixfmt into a helper method, current code is
|
|
replaced with a call to the new helper method.
|
|
|
|
The helper method is also called from a new function in next patch.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 29 ++++++++++++++-------------
|
|
1 file changed, 15 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 06fc58440cd3..dc16bf8d57a9 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -27,6 +27,17 @@
|
|
#include "rkvdec.h"
|
|
#include "rkvdec-regs.h"
|
|
|
|
+static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
|
|
+ struct v4l2_pix_format_mplane *pix_mp)
|
|
+{
|
|
+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
|
|
+ pix_mp->width, pix_mp->height);
|
|
+ pix_mp->plane_fmt[0].sizeimage += 128 *
|
|
+ DIV_ROUND_UP(pix_mp->width, 16) *
|
|
+ DIV_ROUND_UP(pix_mp->height, 16);
|
|
+ pix_mp->field = V4L2_FIELD_NONE;
|
|
+}
|
|
+
|
|
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
{
|
|
struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
|
|
@@ -167,13 +178,9 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx)
|
|
|
|
rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]);
|
|
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
- v4l2_fill_pixfmt_mp(&f->fmt.pix_mp,
|
|
- ctx->coded_fmt_desc->decoded_fmts[0],
|
|
- ctx->coded_fmt.fmt.pix_mp.width,
|
|
- ctx->coded_fmt.fmt.pix_mp.height);
|
|
- f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 *
|
|
- DIV_ROUND_UP(f->fmt.pix_mp.width, 16) *
|
|
- DIV_ROUND_UP(f->fmt.pix_mp.height, 16);
|
|
+ f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width;
|
|
+ f->fmt.pix_mp.height = ctx->coded_fmt.fmt.pix_mp.height;
|
|
+ rkvdec_fill_decoded_pixfmt(ctx, &f->fmt.pix_mp);
|
|
}
|
|
|
|
static int rkvdec_enum_framesizes(struct file *file, void *priv,
|
|
@@ -239,13 +246,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
|
|
&pix_mp->height,
|
|
&coded_desc->frmsize);
|
|
|
|
- v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
|
|
- pix_mp->width, pix_mp->height);
|
|
- pix_mp->plane_fmt[0].sizeimage +=
|
|
- 128 *
|
|
- DIV_ROUND_UP(pix_mp->width, 16) *
|
|
- DIV_ROUND_UP(pix_mp->height, 16);
|
|
- pix_mp->field = V4L2_FIELD_NONE;
|
|
+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
From 7743a31004da67bfd0f6246deaa59e670230c84e Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:37 +0000
|
|
Subject: [PATCH] media: rkvdec: Lock capture pixel format in s_ctrl and s_fmt
|
|
|
|
Add an optional valid_fmt operation that should return the valid
|
|
pixelformat of CAPTURE buffers.
|
|
|
|
This is used in next patch to ensure correct pixelformat is used for 10-bit
|
|
and 4:2:2 content.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 59 ++++++++++++++++++++++++---
|
|
drivers/staging/media/rkvdec/rkvdec.h | 2 +
|
|
2 files changed, 55 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index dc16bf8d57a9..6b2a2f4164b2 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -38,6 +38,16 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
|
|
pix_mp->field = V4L2_FIELD_NONE;
|
|
}
|
|
|
|
+static u32 rkvdec_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
|
|
+{
|
|
+ const struct rkvdec_coded_fmt_desc *coded_desc = ctx->coded_fmt_desc;
|
|
+
|
|
+ if (coded_desc->ops->valid_fmt)
|
|
+ return coded_desc->ops->valid_fmt(ctx, ctrl);
|
|
+
|
|
+ return ctx->valid_fmt;
|
|
+}
|
|
+
|
|
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
{
|
|
struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
|
|
@@ -60,6 +70,10 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
/* Only 8-bit is supported */
|
|
return -EINVAL;
|
|
|
|
+ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl))
|
|
+ /* Only current valid format */
|
|
+ return -EINVAL;
|
|
+
|
|
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
|
|
height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
|
|
|
|
@@ -70,8 +84,27 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
return 0;
|
|
}
|
|
|
|
+static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl)
|
|
+{
|
|
+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
|
|
+
|
|
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) {
|
|
+ ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl);
|
|
+ if (ctx->valid_fmt) {
|
|
+ struct v4l2_pix_format_mplane *pix_mp;
|
|
+
|
|
+ pix_mp = &ctx->decoded_fmt.fmt.pix_mp;
|
|
+ pix_mp->pixelformat = ctx->valid_fmt;
|
|
+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = {
|
|
.try_ctrl = rkvdec_try_ctrl,
|
|
+ .s_ctrl = rkvdec_s_ctrl,
|
|
};
|
|
|
|
static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
|
|
@@ -176,6 +209,7 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx)
|
|
{
|
|
struct v4l2_format *f = &ctx->decoded_fmt;
|
|
|
|
+ ctx->valid_fmt = 0;
|
|
rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]);
|
|
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width;
|
|
@@ -231,13 +265,17 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
|
|
if (WARN_ON(!coded_desc))
|
|
return -EINVAL;
|
|
|
|
- for (i = 0; i < coded_desc->num_decoded_fmts; i++) {
|
|
- if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat)
|
|
- break;
|
|
- }
|
|
+ if (ctx->valid_fmt) {
|
|
+ pix_mp->pixelformat = ctx->valid_fmt;
|
|
+ } else {
|
|
+ for (i = 0; i < coded_desc->num_decoded_fmts; i++) {
|
|
+ if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat)
|
|
+ break;
|
|
+ }
|
|
|
|
- if (i == coded_desc->num_decoded_fmts)
|
|
- pix_mp->pixelformat = coded_desc->decoded_fmts[0];
|
|
+ if (i == coded_desc->num_decoded_fmts)
|
|
+ pix_mp->pixelformat = coded_desc->decoded_fmts[0];
|
|
+ }
|
|
|
|
/* Always apply the frmsize constraint of the coded end. */
|
|
pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width);
|
|
@@ -312,6 +350,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv,
|
|
return ret;
|
|
|
|
ctx->decoded_fmt = *f;
|
|
+ ctx->valid_fmt = f->fmt.pix_mp.pixelformat;
|
|
return 0;
|
|
}
|
|
|
|
@@ -401,6 +440,14 @@ static int rkvdec_enum_capture_fmt(struct file *file, void *priv,
|
|
if (WARN_ON(!ctx->coded_fmt_desc))
|
|
return -EINVAL;
|
|
|
|
+ if (ctx->valid_fmt) {
|
|
+ if (f->index)
|
|
+ return -EINVAL;
|
|
+
|
|
+ f->pixelformat = ctx->valid_fmt;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (f->index >= ctx->coded_fmt_desc->num_decoded_fmts)
|
|
return -EINVAL;
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
|
|
index 77a137cca88e..e95c52e3168a 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.h
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.h
|
|
@@ -63,6 +63,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf)
|
|
struct rkvdec_coded_fmt_ops {
|
|
int (*adjust_fmt)(struct rkvdec_ctx *ctx,
|
|
struct v4l2_format *f);
|
|
+ u32 (*valid_fmt)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
|
|
int (*start)(struct rkvdec_ctx *ctx);
|
|
void (*stop)(struct rkvdec_ctx *ctx);
|
|
int (*run)(struct rkvdec_ctx *ctx);
|
|
@@ -96,6 +97,7 @@ struct rkvdec_ctx {
|
|
struct v4l2_fh fh;
|
|
struct v4l2_format coded_fmt;
|
|
struct v4l2_format decoded_fmt;
|
|
+ u32 valid_fmt;
|
|
const struct rkvdec_coded_fmt_desc *coded_fmt_desc;
|
|
struct v4l2_ctrl_handler ctrl_hdl;
|
|
struct rkvdec_dev *dev;
|
|
|
|
From 15bb8d006a05aecc371e530769f06bf52c2c65bc Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:37 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Support High 10 and 4:2:2 profiles
|
|
|
|
Add support and enable decoding of H264 High 10 and 4:2:2 profiles.
|
|
|
|
Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW
|
|
requirement on 10-bit format buffers.
|
|
|
|
The new valid_fmt operation is implemented and return a valid pixelformat
|
|
for the provided SPS control.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec-h264.c | 20 ++++++++++++++++++++
|
|
drivers/staging/media/rkvdec/rkvdec.c | 19 +++++++++----------
|
|
2 files changed, 29 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
index d33fccc92205..afc695d32186 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
|
|
@@ -1021,6 +1021,25 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
|
|
return 0;
|
|
}
|
|
|
|
+static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
|
|
+{
|
|
+ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
|
|
+
|
|
+ if (sps->bit_depth_luma_minus8 == 0) {
|
|
+ if (sps->chroma_format_idc == 2)
|
|
+ return V4L2_PIX_FMT_NV16;
|
|
+ else
|
|
+ return V4L2_PIX_FMT_NV12;
|
|
+ } else if (sps->bit_depth_luma_minus8 == 2) {
|
|
+ if (sps->chroma_format_idc == 2)
|
|
+ return V4L2_PIX_FMT_NV20;
|
|
+ else
|
|
+ return V4L2_PIX_FMT_NV15;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
|
|
{
|
|
struct rkvdec_dev *rkvdec = ctx->dev;
|
|
@@ -1124,6 +1143,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
|
|
|
|
const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = {
|
|
.adjust_fmt = rkvdec_h264_adjust_fmt,
|
|
+ .valid_fmt = rkvdec_h264_valid_fmt,
|
|
.start = rkvdec_h264_start,
|
|
.stop = rkvdec_h264_stop,
|
|
.run = rkvdec_h264_run,
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 6b2a2f4164b2..bd8ec2915fe9 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -31,7 +31,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
|
|
struct v4l2_pix_format_mplane *pix_mp)
|
|
{
|
|
v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
|
|
- pix_mp->width, pix_mp->height);
|
|
+ ALIGN(pix_mp->width, 64), pix_mp->height);
|
|
pix_mp->plane_fmt[0].sizeimage += 128 *
|
|
DIV_ROUND_UP(pix_mp->width, 16) *
|
|
DIV_ROUND_UP(pix_mp->height, 16);
|
|
@@ -55,19 +55,15 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
|
|
if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) {
|
|
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
|
|
unsigned int width, height;
|
|
- /*
|
|
- * TODO: The hardware supports 10-bit and 4:2:2 profiles,
|
|
- * but it's currently broken in the driver.
|
|
- * Reject them for now, until it's fixed.
|
|
- */
|
|
- if (sps->chroma_format_idc > 1)
|
|
- /* Only 4:0:0 and 4:2:0 are supported */
|
|
+
|
|
+ if (sps->chroma_format_idc > 2)
|
|
+ /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
|
|
return -EINVAL;
|
|
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
|
|
/* Luma and chroma bit depth mismatch */
|
|
return -EINVAL;
|
|
- if (sps->bit_depth_luma_minus8 != 0)
|
|
- /* Only 8-bit is supported */
|
|
+ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
|
|
+ /* Only 8-bit and 10-bit is supported */
|
|
return -EINVAL;
|
|
|
|
if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl))
|
|
@@ -145,6 +141,9 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = {
|
|
|
|
static const u32 rkvdec_h264_decoded_fmts[] = {
|
|
V4L2_PIX_FMT_NV12,
|
|
+ V4L2_PIX_FMT_NV15,
|
|
+ V4L2_PIX_FMT_NV16,
|
|
+ V4L2_PIX_FMT_NV20,
|
|
};
|
|
|
|
static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
|
|
|
|
From 26aca7fda4117f4bff16e3fb5349878fb322410b Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Mon, 6 Jul 2020 21:54:38 +0000
|
|
Subject: [PATCH] media: rkvdec: h264: Support profile and level controls
|
|
|
|
The Rockchip Video Decoder used in RK3399 supports H.264 profiles from
|
|
Baseline to High 4:2:2 up to Level 5.1, except for the Extended profile.
|
|
|
|
Expose the V4L2_CID_MPEG_VIDEO_H264_PROFILE and the
|
|
V4L2_CID_MPEG_VIDEO_H264_LEVEL control, so that userspace can query the
|
|
driver for the list of supported profiles and level.
|
|
|
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
|
Reviewed-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 13 +++++++++++++
|
|
1 file changed, 13 insertions(+)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index bd8ec2915fe9..87987a782d75 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -132,6 +132,19 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
|
|
.cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
|
|
.cfg.max = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
|
|
},
|
|
+ {
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
|
+ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE,
|
|
+ .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422,
|
|
+ .cfg.menu_skip_mask =
|
|
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED),
|
|
+ .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
|
|
+ },
|
|
+ {
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
|
|
+ .cfg.min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
|
|
+ .cfg.max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
|
|
+ },
|
|
};
|
|
|
|
static const struct rkvdec_ctrls rkvdec_h264_ctrls = {
|
|
|
|
From 272e8a34d1803cc88e74de99b10330cd57d18f26 Mon Sep 17 00:00:00 2001
|
|
From: Ezequiel Garcia <ezequiel@collabora.com>
|
|
Date: Mon, 18 May 2020 14:40:09 -0300
|
|
Subject: [PATCH] media: rkvdec: Fix .buf_prepare
|
|
|
|
The driver should only set the payload on .buf_prepare
|
|
if the buffer is CAPTURE type, or if an OUTPUT buffer
|
|
has a zeroed payload.
|
|
|
|
Fix it.
|
|
|
|
Fixes: cd33c830448ba ("media: rkvdec: Add the rkvdec driver")
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/rkvdec.c | 10 +++++++++-
|
|
1 file changed, 9 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 87987a782d75..91f8a1bb6176 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -543,7 +543,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb)
|
|
if (vb2_plane_size(vb, i) < sizeimage)
|
|
return -EINVAL;
|
|
}
|
|
- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
|
+
|
|
+ /*
|
|
+ * Buffer's bytesused is written by the driver for CAPTURE buffers,
|
|
+ * or if the application passed zero bytesused on an OUTPUT buffer.
|
|
+ */
|
|
+ if (!V4L2_TYPE_IS_OUTPUT(vq->type) ||
|
|
+ (V4L2_TYPE_IS_OUTPUT(vq->type) && !vb2_get_plane_payload(vb, 0)))
|
|
+ vb2_set_plane_payload(vb, 0,
|
|
+ f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
|
return 0;
|
|
}
|
|
|
|
|
|
From 6e771db436797df6146b1fe0ec94d4138bdaa2bc Mon Sep 17 00:00:00 2001
|
|
From: Boris Brezillon <boris.brezillon@collabora.com>
|
|
Date: Mon, 18 May 2020 14:40:10 -0300
|
|
Subject: [PATCH] media: uapi: Add VP9 stateless decoder controls
|
|
|
|
Add the VP9 stateless decoder controls plus the documentation that goes
|
|
with it.
|
|
|
|
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
.../userspace-api/media/v4l/biblio.rst | 10 +
|
|
.../media/v4l/ext-ctrls-codec.rst | 550 ++++++++++++++++++
|
|
drivers/media/v4l2-core/v4l2-ctrls.c | 239 ++++++++
|
|
drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
|
|
include/media/v4l2-ctrls.h | 1 +
|
|
include/media/vp9-ctrls.h | 485 +++++++++++++++
|
|
6 files changed, 1286 insertions(+)
|
|
create mode 100644 include/media/vp9-ctrls.h
|
|
|
|
diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst
|
|
index 3c9634173e82..e09102e572fd 100644
|
|
--- a/Documentation/userspace-api/media/v4l/biblio.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/biblio.rst
|
|
@@ -414,3 +414,13 @@ VP8
|
|
:title: RFC 6386: "VP8 Data Format and Decoding Guide"
|
|
|
|
:author: J. Bankoski et al.
|
|
+
|
|
+.. _vp9:
|
|
+
|
|
+VP9
|
|
+===
|
|
+
|
|
+
|
|
+:title: VP9 Bitstream & Decoding Process Specification
|
|
+
|
|
+:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design)
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index 03ce87aa5488..ca13b141d8c2 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -2689,6 +2689,556 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
|
- ``padding[3]``
|
|
- Applications and drivers must set this to zero.
|
|
|
|
+.. _v4l2-mpeg-vp9:
|
|
+
|
|
+``V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0..3) (struct)``
|
|
+ Stores VP9 probabilities attached to a specific frame context. The VP9
|
|
+ specification allows using a maximum of 4 contexts. Each frame being
|
|
+ decoded refers to one of those context. See section '7.1.2 Refresh
|
|
+ probs semantics' section of :ref:`vp9` for more details about these
|
|
+ contexts.
|
|
+
|
|
+ This control is bi-directional:
|
|
+
|
|
+ * all 4 contexts must be initialized by userspace just after the
|
|
+ stream is started and before the first decoding request is submitted.
|
|
+ * the referenced context might be read by the kernel when a decoding
|
|
+ request is submitted, and will be updated after the decoder is done
|
|
+ decoding the frame if the `V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX` flag
|
|
+ is set.
|
|
+ * contexts will be read back by user space before each decoding request
|
|
+ to retrieve the updated probabilities.
|
|
+ * userspace will re-initialize the context to their default values when
|
|
+ a reset context is required.
|
|
+
|
|
+ .. note::
|
|
+
|
|
+ This compound control is not yet part of the public kernel API and
|
|
+ it is expected to change.
|
|
+
|
|
+.. c:type:: v4l2_ctrl_vp9_frame_ctx
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_ctrl_vp9_frame_ctx
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - struct :c:type:`v4l2_vp9_probabilities`
|
|
+ - ``probs``
|
|
+ - Structure with VP9 probabilities attached to the context.
|
|
+
|
|
+.. c:type:: v4l2_vp9_probabilities
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_vp9_probabilities
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __u8
|
|
+ - ``tx8[2][1]``
|
|
+ - TX 8x8 probabilities.
|
|
+ * - __u8
|
|
+ - ``tx16[2][2]``
|
|
+ - TX 16x16 probabilities.
|
|
+ * - __u8
|
|
+ - ``tx32[2][3]``
|
|
+ - TX 32x32 probabilities.
|
|
+ * - __u8
|
|
+ - ``coef[4][2][2][6][6][3]``
|
|
+ - Coefficient probabilities.
|
|
+ * - __u8
|
|
+ - ``skip[3]``
|
|
+ - Skip probabilities.
|
|
+ * - __u8
|
|
+ - ``inter_mode[7][3]``
|
|
+ - Inter prediction mode probabilities.
|
|
+ * - __u8
|
|
+ - ``interp_filter[4][2]``
|
|
+ - Interpolation filter probabilities.
|
|
+ * - __u8
|
|
+ - ``is_inter[4]``
|
|
+ - Is inter-block probabilities.
|
|
+ * - __u8
|
|
+ - ``comp_mode[5]``
|
|
+ - Compound prediction mode probabilities.
|
|
+ * - __u8
|
|
+ - ``single_ref[5][2]``
|
|
+ - Single reference probabilities.
|
|
+ * - __u8
|
|
+ - ``comp_mode[5]``
|
|
+ - Compound reference probabilities.
|
|
+ * - __u8
|
|
+ - ``y_mode[4][9]``
|
|
+ - Y prediction mode probabilities.
|
|
+ * - __u8
|
|
+ - ``uv_mode[10][9]``
|
|
+ - UV prediction mode probabilities.
|
|
+ * - __u8
|
|
+ - ``partition[16][3]``
|
|
+ - Partition probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.joint[3]``
|
|
+ - Motion vector joint probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.sign[2]``
|
|
+ - Motion vector sign probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.class[2][10]``
|
|
+ - Motion vector class probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.class0_bit[2]``
|
|
+ - Motion vector class0 bit probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.bits[2][10]``
|
|
+ - Motion vector bits probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.class0_fr[2][2][3]``
|
|
+ - Motion vector class0 fractional bit probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.fr[2][3]``
|
|
+ - Motion vector fractional bit probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.class0_hp[2]``
|
|
+ - Motion vector class0 high precision fractional bit probabilities.
|
|
+ * - __u8
|
|
+ - ``mv.hp[2]``
|
|
+ - Motion vector high precision fractional bit probabilities.
|
|
+
|
|
+``V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (struct)``
|
|
+ Specifies the frame parameters for the associated VP9 frame decode request.
|
|
+ This includes the necessary parameters for configuring a stateless hardware
|
|
+ decoding pipeline for VP9. The bitstream parameters are defined according
|
|
+ to :ref:`vp9`.
|
|
+
|
|
+ .. note::
|
|
+
|
|
+ This compound control is not yet part of the public kernel API and
|
|
+ it is expected to change.
|
|
+
|
|
+.. c:type:: v4l2_ctrl_vp9_frame_decode_params
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_ctrl_vp9_frame_decode_params
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __u32
|
|
+ - ``flags``
|
|
+ - Combination of V4L2_VP9_FRAME_FLAG_* flags. See
|
|
+ :c:type:`v4l2_vp9_frame_flags`.
|
|
+ * - __u16
|
|
+ - ``compressed_header_size``
|
|
+ - Compressed header size in bytes.
|
|
+ * - __u16
|
|
+ - ``uncompressed_header_size``
|
|
+ - Uncompressed header size in bytes.
|
|
+ * - __u8
|
|
+ - ``profile``
|
|
+ - VP9 profile. Can be 0, 1, 2 or 3.
|
|
+ * - __u8
|
|
+ - ``reset_frame_context``
|
|
+ - Frame context that should be used/updated when decoding the frame.
|
|
+ * - __u8
|
|
+ - ``bit_depth``
|
|
+ - Component depth in bits. Must be 8 for profile 0 and 1. Must 10 or 12
|
|
+ for profile 2 and 3.
|
|
+ * - __u8
|
|
+ - ``interpolation_filter``
|
|
+ - Specifies the filter selection used for performing inter prediction. See
|
|
+ :c:type:`v4l2_vp9_interpolation_filter`.
|
|
+ * - __u8
|
|
+ - ``tile_cols_log2``
|
|
+ - Specifies the base 2 logarithm of the width of each tile (where the
|
|
+ width is measured in units of 8x8 blocks). Shall be less than or equal
|
|
+ to 6.
|
|
+ * - __u8
|
|
+ - ``tile_rows_log2``
|
|
+ - Specifies the base 2 logarithm of the height of each tile (where the
|
|
+ height is measured in units of 8x8 blocks)
|
|
+ * - __u8
|
|
+ - ``tx_mode``
|
|
+ - Specifies the TX mode. See :c:type:`v4l2_vp9_tx_mode`.
|
|
+ * - __u8
|
|
+ - ``reference_mode``
|
|
+ - Specifies the type of inter prediction to be used. See
|
|
+ :c:type:`v4l2_vp9_reference_mode`.
|
|
+ * - __u8
|
|
+ - ``padding``
|
|
+ - Needed to make this struct 64 bit aligned. Shall be filled with zeroes.
|
|
+ * - __u16
|
|
+ - ``frame_width_minus_1``
|
|
+ - Add 1 to get the frame width expressed in pixels.
|
|
+ * - __u16
|
|
+ - ``frame_height_minus_1``
|
|
+ - Add 1 to to get the frame height expressed in pixels.
|
|
+ * - __u16
|
|
+ - ``frame_width_minus_1``
|
|
+ - Add 1 to to get the expected render width expressed in pixels. This is
|
|
+ not used during the decoding process but might be used by HW scalers to
|
|
+ prepare a frame that's ready for scanout.
|
|
+ * - __u16
|
|
+ - frame_height_minus_1
|
|
+ - Add 1 to get the expected render height expressed in pixels. This is
|
|
+ not used during the decoding process but might be used by HW scalers to
|
|
+ prepare a frame that's ready for scanout.
|
|
+ * - __u64
|
|
+ - ``refs[3]``
|
|
+ - Array of reference frame timestamps.
|
|
+ * - struct :c:type:`v4l2_vp9_loop_filter`
|
|
+ - ``lf``
|
|
+ - Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter`.
|
|
+ * - struct :c:type:`v4l2_vp9_quantization`
|
|
+ - ``quant``
|
|
+ - Quantization parameters. See :c:type:`v4l2_vp9_quantization`.
|
|
+ * - struct :c:type:`v4l2_vp9_segmentation`
|
|
+ - ``seg``
|
|
+ - Segmentation parameters. See :c:type:`v4l2_vp9_segmentation`.
|
|
+ * - struct :c:type:`v4l2_vp9_probabilities`
|
|
+ - ``probs``
|
|
+ - Probabilities. See :c:type:`v4l2_vp9_probabilities`.
|
|
+
|
|
+.. c:type:: v4l2_vp9_frame_flags
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_frame_flags
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME``
|
|
+ - The frame is a key frame.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME``
|
|
+ - The frame should be displayed.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT``
|
|
+ - The decoding should be error resilient.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY``
|
|
+ - The frame does not reference other frames.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV``
|
|
+ - the frame might can high precision motion vectors.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX``
|
|
+ - Frame context should be updated after decoding.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE``
|
|
+ - Parallel decoding is used.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING``
|
|
+ - Vertical subsampling is enabled.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING``
|
|
+ - Horizontal subsampling is enabled.
|
|
+ * - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING``
|
|
+ - The full UV range is used.
|
|
+
|
|
+.. c:type:: v4l2_vp9_ref_id
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_ref_id
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_REF_ID_LAST``
|
|
+ - Last reference frame.
|
|
+ * - ``V4L2_REF_ID_GOLDEN``
|
|
+ - Golden reference frame.
|
|
+ * - ``V4L2_REF_ID_ALTREF``
|
|
+ - Alternative reference frame.
|
|
+ * - ``V4L2_REF_ID_CNT``
|
|
+ - Number of reference frames.
|
|
+
|
|
+.. c:type:: v4l2_vp9_tx_mode
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_tx_mode
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_TX_MODE_ONLY_4X4``
|
|
+ - Transform size is 4x4.
|
|
+ * - ``V4L2_VP9_TX_MODE_ALLOW_8X8``
|
|
+ - Transform size can be up to 8x8.
|
|
+ * - ``V4L2_VP9_TX_MODE_ALLOW_16X16``
|
|
+ - Transform size can be up to 16x16.
|
|
+ * - ``V4L2_VP9_TX_MODE_ALLOW_32X32``
|
|
+ - transform size can be up to 32x32.
|
|
+ * - ``V4L2_VP9_TX_MODE_SELECT``
|
|
+ - Bitstream contains transform size for each block.
|
|
+
|
|
+.. c:type:: v4l2_vp9_reference_mode
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_reference_mode
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_REF_MODE_SINGLE``
|
|
+ - Indicates that all the inter blocks use only a single reference frame
|
|
+ to generate motion compensated prediction.
|
|
+ * - ``V4L2_VP9_REF_MODE_COMPOUND``
|
|
+ - Requires all the inter blocks to use compound mode. Single reference
|
|
+ frame prediction is not allowed.
|
|
+ * - ``V4L2_VP9_REF_MODE_SELECT``
|
|
+ - Allows each individual inter block to select between single and
|
|
+ compound prediction modes.
|
|
+
|
|
+.. c:type:: v4l2_vp9_interpolation_filter
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_interpolation_filter
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_INTERP_FILTER_8TAP``
|
|
+ - Height tap filter.
|
|
+ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH``
|
|
+ - Height tap smooth filter.
|
|
+ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SHARP``
|
|
+ - Height tap sharp filter.
|
|
+ * - ``V4L2_VP9_INTERP_FILTER_BILINEAR``
|
|
+ - Bilinear filter.
|
|
+ * - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE``
|
|
+ - Filter selection is signaled at the block level.
|
|
+
|
|
+.. c:type:: v4l2_vp9_reset_frame_context
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_reset_frame_context
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_RESET_FRAME_CTX_NONE``
|
|
+ - Do not reset any frame context.
|
|
+ * - ``V4L2_VP9_RESET_FRAME_CTX_SPEC``
|
|
+ - Reset the frame context pointed by
|
|
+ :c:type:`v4l2_ctrl_vp9_frame_decode_params`.frame_context_idx.
|
|
+ * - ``V4L2_VP9_RESET_FRAME_CTX_ALL``
|
|
+ - Reset all frame contexts.
|
|
+
|
|
+.. c:type:: v4l2_vp9_intra_prediction_mode
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_intra_prediction_mode
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_INTRA_PRED_DC``
|
|
+ - DC intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_V``
|
|
+ - Vertical intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_H``
|
|
+ - Horizontal intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D45``
|
|
+ - D45 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D135``
|
|
+ - D135 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D117``
|
|
+ - D117 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D153``
|
|
+ - D153 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D207``
|
|
+ - D207 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_D63``
|
|
+ - D63 intra prediction.
|
|
+ * - ``V4L2_VP9_INTRA_PRED_MODE_TM``
|
|
+ - True motion intra prediction.
|
|
+
|
|
+.. c:type:: v4l2_vp9_segmentation
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_vp9_segmentation
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __u8
|
|
+ - ``flags``
|
|
+ - Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See
|
|
+ :c:type:`v4l2_vp9_segmentation_flags`.
|
|
+ * - __u8
|
|
+ - ``tree_probs[7]``
|
|
+ - Specifies the probability values to be used when decoding a Segment-ID.
|
|
+ See '5.15. Segmentation map' section of :ref:`vp9` for more details.
|
|
+ * - __u8
|
|
+ - ``pred_prob[3]``
|
|
+ - Specifies the probability values to be used when decoding a
|
|
+ Predicted-Segment-ID. See '6.4.14. Get segment id syntax'
|
|
+ section of :ref:`vp9` for more details.
|
|
+ * - __u8
|
|
+ - ``padding[5]``
|
|
+ - Used to align this struct on 64 bit. Shall be filled with zeroes.
|
|
+ * - __u8
|
|
+ - ``feature_enabled[8]``
|
|
+ - Bitmask defining which features are enabled in each segment.
|
|
+ * - __u8
|
|
+ - ``feature_data[8][4]``
|
|
+ - Data attached to each feature. Data entry is only valid if the feature
|
|
+ is enabled.
|
|
+
|
|
+.. c:type:: v4l2_vp9_segment_feature
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_segment_feature
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_SEGMENT_FEATURE_QP_DELTA``
|
|
+ - QP delta segment feature.
|
|
+ * - ``V4L2_VP9_SEGMENT_FEATURE_LF``
|
|
+ - Loop filter segment feature.
|
|
+ * - ``V4L2_VP9_SEGMENT_FEATURE_REF_FRAME``
|
|
+ - Reference frame segment feature.
|
|
+ * - ``V4L2_VP9_SEGMENT_FEATURE_SKIP``
|
|
+ - Skip segment feature.
|
|
+ * - ``V4L2_VP9_SEGMENT_FEATURE_CNT``
|
|
+ - Number of segment features.
|
|
+
|
|
+.. c:type:: v4l2_vp9_segmentation_flags
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_segmentation_flags
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED``
|
|
+ - Indicates that this frame makes use of the segmentation tool.
|
|
+ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP``
|
|
+ - Indicates that the segmentation map should be updated during the
|
|
+ decoding of this frame.
|
|
+ * - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE``
|
|
+ - Indicates that the updates to the segmentation map are coded
|
|
+ relative to the existing segmentation map.
|
|
+ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA``
|
|
+ - Indicates that new parameters are about to be specified for each
|
|
+ segment.
|
|
+ * - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE``
|
|
+ - Indicates that the segmentation parameters represent the actual values
|
|
+ to be used.
|
|
+
|
|
+.. c:type:: v4l2_vp9_quantization
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_vp9_quantization
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __u8
|
|
+ - ``base_q_idx``
|
|
+ - Indicates the base frame qindex.
|
|
+ * - __s8
|
|
+ - ``delta_q_y_dc``
|
|
+ - Indicates the Y DC quantizer relative to base_q_idx.
|
|
+ * - __s8
|
|
+ - ``delta_q_uv_dc``
|
|
+ - Indicates the UV DC quantizer relative to base_q_idx.
|
|
+ * - __s8
|
|
+ - ``delta_q_uv_ac``
|
|
+ - Indicates the UV AC quantizer relative to base_q_idx.
|
|
+ * - __u8
|
|
+ - ``padding[4]``
|
|
+ - Padding bytes used to align this struct on 64 bit. Must be set to 0.
|
|
+
|
|
+.. c:type:: v4l2_vp9_loop_filter
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: struct v4l2_vp9_loop_filter
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __u8
|
|
+ - ``flags``
|
|
+ - Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags.
|
|
+ See :c:type:`v4l2_vp9_loop_filter_flags`.
|
|
+ * - __u8
|
|
+ - ``level``
|
|
+ - Indicates the loop filter strength.
|
|
+ * - __u8
|
|
+ - ``sharpness``
|
|
+ - Indicates the sharpness level.
|
|
+ * - __s8
|
|
+ - ``ref_deltas[4]``
|
|
+ - Contains the adjustment needed for the filter level based on the chosen
|
|
+ reference frame.
|
|
+ * - __s8
|
|
+ - ``mode_deltas[2]``
|
|
+ - Contains the adjustment needed for the filter level based on the chosen
|
|
+ mode
|
|
+ * - __u8
|
|
+ - ``level_lookup[8][4][2]``
|
|
+ - Level lookup table.
|
|
+
|
|
+
|
|
+.. c:type:: v4l2_vp9_loop_filter_flags
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
|
+
|
|
+.. flat-table:: enum v4l2_vp9_loop_filter_flags
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 2
|
|
+
|
|
+ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED``
|
|
+ - When set, the filter level depends on the mode and reference frame used
|
|
+ to predict a block.
|
|
+ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE``
|
|
+ - When set, the bitstream contains additional syntax elements that
|
|
+ specify which mode and reference frame deltas are to be updated.
|
|
+
|
|
.. raw:: latex
|
|
|
|
\normalsize
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
index b846f5b089c9..5913088cbc6f 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
@@ -940,6 +940,11 @@ const char *v4l2_ctrl_get_name(u32 id)
|
|
case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile";
|
|
case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
|
|
case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header";
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: return "VP9 Frame Decode Parameters";
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): return "VP9 Frame Context 0";
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): return "VP9 Frame Context 1";
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): return "VP9 Frame Context 2";
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): return "VP9 Frame Context 3";
|
|
|
|
/* HEVC controls */
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
|
|
@@ -1419,6 +1424,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
|
|
case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:
|
|
*type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER;
|
|
break;
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS:
|
|
+ *type = V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS;
|
|
+ break;
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0):
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1):
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2):
|
|
+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3):
|
|
+ *type = V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT;
|
|
+ break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_SPS:
|
|
*type = V4L2_CTRL_TYPE_HEVC_SPS;
|
|
break;
|
|
@@ -1721,6 +1735,219 @@ static void std_log(const struct v4l2_ctrl *ctrl)
|
|
0; \
|
|
})
|
|
|
|
+static int
|
|
+validate_vp9_lf_params(struct v4l2_vp9_loop_filter *lf)
|
|
+{
|
|
+ unsigned int i, j, k;
|
|
+
|
|
+ if (lf->flags &
|
|
+ ~(V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED |
|
|
+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED implies
|
|
+ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE.
|
|
+ */
|
|
+ if (lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE &&
|
|
+ !(lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* That all values are in the accepted range. */
|
|
+ if (lf->level > GENMASK(5, 0))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (lf->sharpness > GENMASK(2, 0))
|
|
+ return -EINVAL;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
|
|
+ if (lf->ref_deltas[i] < -63 || lf->ref_deltas[i] > 63)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
|
|
+ if (lf->mode_deltas[i] < -63 || lf->mode_deltas[i] > 63)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(lf->level_lookup); i++) {
|
|
+ for (j = 0; j < ARRAY_SIZE(lf->level_lookup[0]); j++) {
|
|
+ for (k = 0; k < ARRAY_SIZE(lf->level_lookup[0][0]); k++) {
|
|
+ if (lf->level_lookup[i][j][k] > 63)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+validate_vp9_quant_params(struct v4l2_vp9_quantization *quant)
|
|
+{
|
|
+ if (quant->delta_q_y_dc < -15 || quant->delta_q_y_dc > 15 ||
|
|
+ quant->delta_q_uv_dc < -15 || quant->delta_q_uv_dc > 15 ||
|
|
+ quant->delta_q_uv_ac < -15 || quant->delta_q_uv_ac > 15)
|
|
+ return -EINVAL;
|
|
+
|
|
+ memset(quant->padding, 0, sizeof(quant->padding));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+validate_vp9_seg_params(struct v4l2_vp9_segmentation *seg)
|
|
+{
|
|
+ unsigned int i, j;
|
|
+
|
|
+ if (seg->flags &
|
|
+ ~(V4L2_VP9_SEGMENTATION_FLAG_ENABLED |
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP |
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE |
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA |
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP and
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA imply
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_ENABLED.
|
|
+ */
|
|
+ if ((seg->flags &
|
|
+ (V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP |
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) &&
|
|
+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE implies
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP.
|
|
+ */
|
|
+ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE &&
|
|
+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE implies
|
|
+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA.
|
|
+ */
|
|
+ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE &&
|
|
+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA))
|
|
+ return -EINVAL;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(seg->feature_enabled); i++) {
|
|
+ if (seg->feature_enabled[i] &
|
|
+ ~(V4L2_VP9_SEGMENT_FEATURE_QP_DELTA |
|
|
+ V4L2_VP9_SEGMENT_FEATURE_LF |
|
|
+ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME |
|
|
+ V4L2_VP9_SEGMENT_FEATURE_SKIP))
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(seg->feature_data); i++) {
|
|
+ const int range[] = {255, 63, 3, 0};
|
|
+
|
|
+ for (j = 0; j < ARRAY_SIZE(seg->feature_data[j]); j++) {
|
|
+ if (seg->feature_data[i][j] < -range[j] ||
|
|
+ seg->feature_data[i][j] > range[j])
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ memset(seg->padding, 0, sizeof(seg->padding));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+validate_vp9_frame_decode_params(struct v4l2_ctrl_vp9_frame_decode_params *dec_params)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* Make sure we're not passed invalid flags. */
|
|
+ if (dec_params->flags &
|
|
+ ~(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
|
|
+ V4L2_VP9_FRAME_FLAG_SHOW_FRAME |
|
|
+ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT |
|
|
+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY |
|
|
+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV |
|
|
+ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX |
|
|
+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE |
|
|
+ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING |
|
|
+ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING |
|
|
+ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * The refresh context and error resilient flags are mutually exclusive.
|
|
+ * Same goes for parallel decoding and error resilient modes.
|
|
+ */
|
|
+ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT &&
|
|
+ dec_params->flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX |
|
|
+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->profile > V4L2_VP9_PROFILE_MAX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->reset_frame_context > V4L2_VP9_RESET_FRAME_CTX_ALL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->frame_context_idx >= V4L2_VP9_NUM_FRAME_CTX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * Profiles 0 and 1 only support 8-bit depth, profiles 2 and 3 only 10
|
|
+ * and 12 bit depths.
|
|
+ */
|
|
+ if ((dec_params->profile < 2 && dec_params->bit_depth != 8) ||
|
|
+ (dec_params->profile >= 2 &&
|
|
+ (dec_params->bit_depth != 10 && dec_params->bit_depth != 12)))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Profile 0 and 2 only accept YUV 4:2:0. */
|
|
+ if ((dec_params->profile == 0 || dec_params->profile == 2) &&
|
|
+ (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) ||
|
|
+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Profile 1 and 3 only accept YUV 4:2:2, 4:4:0 and 4:4:4. */
|
|
+ if ((dec_params->profile == 1 || dec_params->profile == 3) &&
|
|
+ ((dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) &&
|
|
+ (dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->interpolation_filter > V4L2_VP9_INTERP_FILTER_SWITCHABLE)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * According to the spec, tile_cols_log2 shall be less than or equal
|
|
+ * to 6.
|
|
+ */
|
|
+ if (dec_params->tile_cols_log2 > 6)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->tx_mode > V4L2_VP9_TX_MODE_SELECT)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dec_params->reference_mode > V4L2_VP9_REF_MODE_SELECT)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ret = validate_vp9_lf_params(&dec_params->lf);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = validate_vp9_quant_params(&dec_params->quant);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = validate_vp9_seg_params(&dec_params->seg);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ memset(dec_params->padding, 0, sizeof(dec_params->padding));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Validate a new control */
|
|
|
|
#define zero_padding(s) \
|
|
@@ -1838,6 +2065,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
zero_padding(p_vp8_frame_header->coder_state);
|
|
break;
|
|
|
|
+ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS:
|
|
+ return validate_vp9_frame_decode_params(p);
|
|
+
|
|
+ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT:
|
|
+ break;
|
|
+
|
|
case V4L2_CTRL_TYPE_HEVC_SPS:
|
|
p_hevc_sps = p;
|
|
|
|
@@ -2584,6 +2817,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
|
case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
|
elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header);
|
|
break;
|
|
+ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT:
|
|
+ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_ctx);
|
|
+ break;
|
|
+ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS:
|
|
+ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_decode_params);
|
|
+ break;
|
|
case V4L2_CTRL_TYPE_HEVC_SPS:
|
|
elem_size = sizeof(struct v4l2_ctrl_hevc_sps);
|
|
break;
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
index 53de49087938..22eab942c8d4 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
|
@@ -1431,6 +1431,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
|
|
case V4L2_PIX_FMT_VP8: descr = "VP8"; break;
|
|
case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break;
|
|
case V4L2_PIX_FMT_VP9: descr = "VP9"; break;
|
|
+ case V4L2_PIX_FMT_VP9_FRAME: descr = "VP9 Frame"; break;
|
|
case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */
|
|
case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break;
|
|
case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */
|
|
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
|
|
index cb25f345e9ad..c427acc964b9 100644
|
|
--- a/include/media/v4l2-ctrls.h
|
|
+++ b/include/media/v4l2-ctrls.h
|
|
@@ -21,6 +21,7 @@
|
|
#include <media/fwht-ctrls.h>
|
|
#include <media/h264-ctrls.h>
|
|
#include <media/vp8-ctrls.h>
|
|
+#include <media/vp9-ctrls.h>
|
|
#include <media/hevc-ctrls.h>
|
|
|
|
/* forward references */
|
|
diff --git a/include/media/vp9-ctrls.h b/include/media/vp9-ctrls.h
|
|
new file mode 100644
|
|
index 000000000000..0cdea8a18b72
|
|
--- /dev/null
|
|
+++ b/include/media/vp9-ctrls.h
|
|
@@ -0,0 +1,485 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+/*
|
|
+ * These are the VP9 state controls for use with stateless VP9
|
|
+ * codec drivers.
|
|
+ *
|
|
+ * It turns out that these structs are not stable yet and will undergo
|
|
+ * more changes. So keep them private until they are stable and ready to
|
|
+ * become part of the official public API.
|
|
+ */
|
|
+
|
|
+#ifndef _VP9_CTRLS_H_
|
|
+#define _VP9_CTRLS_H_
|
|
+
|
|
+#include <linux/types.h>
|
|
+
|
|
+#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F')
|
|
+
|
|
+#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i))
|
|
+#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004)
|
|
+#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400
|
|
+#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags
|
|
+ *
|
|
+ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on
|
|
+ * the mode and reference frame used
|
|
+ * to predict a block
|
|
+ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional
|
|
+ * syntax elements that specify which
|
|
+ * mode and reference frame deltas
|
|
+ * are to be updated
|
|
+ *
|
|
+ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See
|
|
+ * section '7.2.8 Loop filter semantics' of the VP9 specification for more
|
|
+ * details.
|
|
+ */
|
|
+enum v4l2_vp9_loop_filter_flags {
|
|
+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0,
|
|
+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters
|
|
+ *
|
|
+ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags
|
|
+ * @level: indicates the loop filter strength
|
|
+ * @sharpness: indicates the sharpness level
|
|
+ * @ref_deltas: contains the adjustment needed for the filter level based on
|
|
+ * the chosen reference frame
|
|
+ * @mode_deltas: contains the adjustment needed for the filter level based on
|
|
+ * the chosen mode
|
|
+ * @level_lookup: level lookup table
|
|
+ *
|
|
+ * This structure contains all loop filter related parameters. See sections
|
|
+ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process'
|
|
+ * of the VP9 specification for more details.
|
|
+ */
|
|
+struct v4l2_vp9_loop_filter {
|
|
+ __u8 flags;
|
|
+ __u8 level;
|
|
+ __u8 sharpness;
|
|
+ __s8 ref_deltas[4];
|
|
+ __s8 mode_deltas[2];
|
|
+ __u8 level_lookup[8][4][2];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct v4l2_vp9_quantization - VP9 quantization parameters
|
|
+ *
|
|
+ * @base_q_idx: indicates the base frame qindex
|
|
+ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx
|
|
+ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx
|
|
+ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx
|
|
+ * @padding: padding bytes to align things on 64 bits. Must be set to 0
|
|
+ *
|
|
+ * Encodes the quantization parameters. See section '7.2.9 Quantization params
|
|
+ * syntax' of the VP9 specification for more details.
|
|
+ */
|
|
+struct v4l2_vp9_quantization {
|
|
+ __u8 base_q_idx;
|
|
+ __s8 delta_q_y_dc;
|
|
+ __s8 delta_q_uv_dc;
|
|
+ __s8 delta_q_uv_ac;
|
|
+ __u8 padding[4];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags
|
|
+ *
|
|
+ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of
|
|
+ * the segmentation tool
|
|
+ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map
|
|
+ * should be updated during the
|
|
+ * decoding of this frame
|
|
+ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to
|
|
+ * the segmentation map are coded
|
|
+ * relative to the existing
|
|
+ * segmentation map
|
|
+ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are
|
|
+ * about to be specified for each
|
|
+ * segment
|
|
+ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the
|
|
+ * segmentation parameters
|
|
+ * represent the actual values
|
|
+ * to be used
|
|
+ *
|
|
+ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See
|
|
+ * section '7.2.10 Segmentation params syntax' of the VP9 specification for
|
|
+ * more details.
|
|
+ */
|
|
+enum v4l2_vp9_segmentation_flags {
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0,
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1,
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2,
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3,
|
|
+ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4,
|
|
+};
|
|
+
|
|
+#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id))
|
|
+#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs
|
|
+ *
|
|
+ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature
|
|
+ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature
|
|
+ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature
|
|
+ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature
|
|
+ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features
|
|
+ *
|
|
+ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the
|
|
+ * VP9 specification for more details.
|
|
+ */
|
|
+enum v4l2_vp9_segment_feature {
|
|
+ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA,
|
|
+ V4L2_VP9_SEGMENT_FEATURE_LF,
|
|
+ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME,
|
|
+ V4L2_VP9_SEGMENT_FEATURE_SKIP,
|
|
+ V4L2_VP9_SEGMENT_FEATURE_CNT,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct v4l2_vp9_segmentation - VP9 segmentation parameters
|
|
+ *
|
|
+ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags
|
|
+ * @tree_probs: specifies the probability values to be used when
|
|
+ * decoding a Segment-ID. See '5.15. Segmentation map'
|
|
+ * section of the VP9 specification for more details.
|
|
+ * @pred_prob: specifies the probability values to be used when decoding a
|
|
+ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax'
|
|
+ * section of :ref:`vp9` for more details..
|
|
+ * @padding: padding used to make things aligned on 64 bits. Shall be zero
|
|
+ * filled
|
|
+ * @feature_enabled: bitmask defining which features are enabled in each
|
|
+ * segment
|
|
+ * @feature_data: data attached to each feature. Data entry is only valid if
|
|
+ * the feature is enabled
|
|
+ *
|
|
+ * Encodes the quantization parameters. See section '7.2.10 Segmentation
|
|
+ * params syntax' of the VP9 specification for more details.
|
|
+ */
|
|
+struct v4l2_vp9_segmentation {
|
|
+ __u8 flags;
|
|
+ __u8 tree_probs[7];
|
|
+ __u8 pred_probs[3];
|
|
+ __u8 padding[5];
|
|
+ __u8 feature_enabled[8];
|
|
+ __s16 feature_data[8][4];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes
|
|
+ *
|
|
+ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction
|
|
+ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction
|
|
+ *
|
|
+ * See section '7.4.5 Intra frame mode info semantics' for more details.
|
|
+ */
|
|
+enum v4l2_vp9_intra_prediction_mode {
|
|
+ V4L2_VP9_INTRA_PRED_MODE_DC,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_V,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_H,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D45,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D135,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D117,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D153,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D207,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_D63,
|
|
+ V4L2_VP9_INTRA_PRED_MODE_TM,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities
|
|
+ * @joint: motion vector joint probabilities
|
|
+ * @sign: motion vector sign probabilities
|
|
+ * @class: motion vector class probabilities
|
|
+ * @class0_bit: motion vector class0 bit probabilities
|
|
+ * @bits: motion vector bits probabilities
|
|
+ * @class0_fr: motion vector class0 fractional bit probabilities
|
|
+ * @fr: motion vector fractional bit probabilities
|
|
+ * @class0_hp: motion vector class0 high precision fractional bit probabilities
|
|
+ * @hp: motion vector high precision fractional bit probabilities
|
|
+ */
|
|
+struct v4l2_vp9_mv_probabilities {
|
|
+ __u8 joint[3];
|
|
+ __u8 sign[2];
|
|
+ __u8 class[2][10];
|
|
+ __u8 class0_bit[2];
|
|
+ __u8 bits[2][10];
|
|
+ __u8 class0_fr[2][2][3];
|
|
+ __u8 fr[2][3];
|
|
+ __u8 class0_hp[2];
|
|
+ __u8 hp[2];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct v4l2_vp9_probabilities - VP9 Probabilities
|
|
+ *
|
|
+ * @tx8: TX 8x8 probabilities
|
|
+ * @tx16: TX 16x16 probabilities
|
|
+ * @tx32: TX 32x32 probabilities
|
|
+ * @coef: coefficient probabilities
|
|
+ * @skip: skip probabilities
|
|
+ * @inter_mode: inter mode probabilities
|
|
+ * @interp_filter: interpolation filter probabilities
|
|
+ * @is_inter: is inter-block probabilities
|
|
+ * @comp_mode: compound prediction mode probabilities
|
|
+ * @single_ref: single ref probabilities
|
|
+ * @comp_ref: compound ref probabilities
|
|
+ * @y_mode: Y prediction mode probabilities
|
|
+ * @uv_mode: UV prediction mode probabilities
|
|
+ * @partition: partition probabilities
|
|
+ * @mv: motion vector probabilities
|
|
+ *
|
|
+ * Structure containing most VP9 probabilities. See the VP9 specification
|
|
+ * for more details.
|
|
+ */
|
|
+struct v4l2_vp9_probabilities {
|
|
+ __u8 tx8[2][1];
|
|
+ __u8 tx16[2][2];
|
|
+ __u8 tx32[2][3];
|
|
+ __u8 coef[4][2][2][6][6][3];
|
|
+ __u8 skip[3];
|
|
+ __u8 inter_mode[7][3];
|
|
+ __u8 interp_filter[4][2];
|
|
+ __u8 is_inter[4];
|
|
+ __u8 comp_mode[5];
|
|
+ __u8 single_ref[5][2];
|
|
+ __u8 comp_ref[5];
|
|
+ __u8 y_mode[4][9];
|
|
+ __u8 uv_mode[10][9];
|
|
+ __u8 partition[16][3];
|
|
+
|
|
+ struct v4l2_vp9_mv_probabilities mv;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_reset_frame_context - Valid values for
|
|
+ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context
|
|
+ *
|
|
+ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context
|
|
+ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by
|
|
+ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx
|
|
+ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts
|
|
+ *
|
|
+ * See section '7.2 Uncompressed header semantics' of the VP9 specification
|
|
+ * for more details.
|
|
+ */
|
|
+enum v4l2_vp9_reset_frame_context {
|
|
+ V4L2_VP9_RESET_FRAME_CTX_NONE,
|
|
+ V4L2_VP9_RESET_FRAME_CTX_SPEC,
|
|
+ V4L2_VP9_RESET_FRAME_CTX_ALL,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types
|
|
+ *
|
|
+ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter
|
|
+ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter
|
|
+ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter
|
|
+ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter
|
|
+ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the
|
|
+ * block level
|
|
+ *
|
|
+ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification
|
|
+ * for more details.
|
|
+ */
|
|
+enum v4l2_vp9_interpolation_filter {
|
|
+ V4L2_VP9_INTERP_FILTER_8TAP,
|
|
+ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH,
|
|
+ V4L2_VP9_INTERP_FILTER_8TAP_SHARP,
|
|
+ V4L2_VP9_INTERP_FILTER_BILINEAR,
|
|
+ V4L2_VP9_INTERP_FILTER_SWITCHABLE,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_reference_mode - VP9 reference modes
|
|
+ *
|
|
+ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a
|
|
+ * single reference frame to generate motion
|
|
+ * compensated prediction
|
|
+ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound
|
|
+ * mode. Single reference frame prediction is not
|
|
+ * allowed
|
|
+ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select
|
|
+ * between single and compound prediction modes
|
|
+ *
|
|
+ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification
|
|
+ * for more details.
|
|
+ */
|
|
+enum v4l2_vp9_reference_mode {
|
|
+ V4L2_VP9_REF_MODE_SINGLE,
|
|
+ V4L2_VP9_REF_MODE_COMPOUND,
|
|
+ V4L2_VP9_REF_MODE_SELECT,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_tx_mode - VP9 TX modes
|
|
+ *
|
|
+ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4
|
|
+ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8
|
|
+ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16
|
|
+ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32
|
|
+ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block
|
|
+ *
|
|
+ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more
|
|
+ * details.
|
|
+ */
|
|
+enum v4l2_vp9_tx_mode {
|
|
+ V4L2_VP9_TX_MODE_ONLY_4X4,
|
|
+ V4L2_VP9_TX_MODE_ALLOW_8X8,
|
|
+ V4L2_VP9_TX_MODE_ALLOW_16X16,
|
|
+ V4L2_VP9_TX_MODE_ALLOW_32X32,
|
|
+ V4L2_VP9_TX_MODE_SELECT,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs
|
|
+ *
|
|
+ * @V4L2_REF_ID_LAST: last reference frame
|
|
+ * @V4L2_REF_ID_GOLDEN: golden reference frame
|
|
+ * @V4L2_REF_ID_ALTREF: alternative reference frame
|
|
+ * @V4L2_REF_ID_CNT: number of reference frames
|
|
+ *
|
|
+ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more
|
|
+ * details.
|
|
+ */
|
|
+enum v4l2_vp9_ref_id {
|
|
+ V4L2_REF_ID_LAST,
|
|
+ V4L2_REF_ID_GOLDEN,
|
|
+ V4L2_REF_ID_ALTREF,
|
|
+ V4L2_REF_ID_CNT,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum v4l2_vp9_frame_flags - VP9 frame flags
|
|
+ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame
|
|
+ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed
|
|
+ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient
|
|
+ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames
|
|
+ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision
|
|
+ * motion vectors
|
|
+ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated
|
|
+ * after decoding
|
|
+ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used
|
|
+ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled
|
|
+ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled
|
|
+ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used
|
|
+ *
|
|
+ * Check the VP9 specification for more details.
|
|
+ */
|
|
+enum v4l2_vp9_frame_flags {
|
|
+ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0,
|
|
+ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1,
|
|
+ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2,
|
|
+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3,
|
|
+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4,
|
|
+ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5,
|
|
+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6,
|
|
+ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7,
|
|
+ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8,
|
|
+ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9,
|
|
+};
|
|
+
|
|
+#define V4L2_VP9_PROFILE_MAX 3
|
|
+
|
|
+/**
|
|
+ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control
|
|
+ *
|
|
+ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags
|
|
+ * @compressed_header_size: compressed header size in bytes
|
|
+ * @uncompressed_header_size: uncompressed header size in bytes
|
|
+ * @profile: VP9 profile. Can be 0, 1, 2 or 3
|
|
+ * @reset_frame_context: specifies whether the frame context should be reset
|
|
+ * to default values. See &v4l2_vp9_reset_frame_context
|
|
+ * for more details
|
|
+ * @frame_context_idx: frame context that should be used/updated
|
|
+ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all
|
|
+ * profiles support 10 and/or 12 bits depths
|
|
+ * @interpolation_filter: specifies the filter selection used for performing
|
|
+ * inter prediction. See &v4l2_vp9_interpolation_filter
|
|
+ * for more details
|
|
+ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile
|
|
+ * (where the width is measured in units of 8x8 blocks).
|
|
+ * Shall be less than or equal to 6
|
|
+ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile
|
|
+ * (where the height is measured in units of 8x8 blocks)
|
|
+ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details
|
|
+ * @reference_mode: specifies the type of inter prediction to be used. See
|
|
+ * &v4l2_vp9_reference_mode for more details
|
|
+ * @padding: needed to make this struct 64 bit aligned. Shall be filled with
|
|
+ * zeros
|
|
+ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed
|
|
+ * in pixels
|
|
+ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed
|
|
+ * in pixels
|
|
+ * @frame_width_minus_1: add 1 to it and you'll get the expected render width
|
|
+ * expressed in pixels. This is not used during the
|
|
+ * decoding process but might be used by HW scalers to
|
|
+ * prepare a frame that's ready for scanout
|
|
+ * @frame_height_minus_1: add 1 to it and you'll get the expected render height
|
|
+ * expressed in pixels. This is not used during the
|
|
+ * decoding process but might be used by HW scalers to
|
|
+ * prepare a frame that's ready for scanout
|
|
+ * @refs: array of reference frames. See &v4l2_vp9_ref_id for more details
|
|
+ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details
|
|
+ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details
|
|
+ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details
|
|
+ * @probs: probabilities. See &v4l2_vp9_probabilities for more details
|
|
+ */
|
|
+struct v4l2_ctrl_vp9_frame_decode_params {
|
|
+ __u32 flags;
|
|
+ __u16 compressed_header_size;
|
|
+ __u16 uncompressed_header_size;
|
|
+ __u8 profile;
|
|
+ __u8 reset_frame_context;
|
|
+ __u8 frame_context_idx;
|
|
+ __u8 bit_depth;
|
|
+ __u8 interpolation_filter;
|
|
+ __u8 tile_cols_log2;
|
|
+ __u8 tile_rows_log2;
|
|
+ __u8 tx_mode;
|
|
+ __u8 reference_mode;
|
|
+ __u8 padding[6];
|
|
+ __u16 frame_width_minus_1;
|
|
+ __u16 frame_height_minus_1;
|
|
+ __u16 render_width_minus_1;
|
|
+ __u16 render_height_minus_1;
|
|
+ __u64 refs[V4L2_REF_ID_CNT];
|
|
+ struct v4l2_vp9_loop_filter lf;
|
|
+ struct v4l2_vp9_quantization quant;
|
|
+ struct v4l2_vp9_segmentation seg;
|
|
+ struct v4l2_vp9_probabilities probs;
|
|
+};
|
|
+
|
|
+#define V4L2_VP9_NUM_FRAME_CTX 4
|
|
+
|
|
+/**
|
|
+ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control
|
|
+ *
|
|
+ * @probs: VP9 probabilities
|
|
+ *
|
|
+ * This control is accessed in both direction. The user should initialize the
|
|
+ * 4 contexts with default values just after starting the stream. Then before
|
|
+ * decoding a frame it should query the current frame context (the one passed
|
|
+ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize
|
|
+ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based
|
|
+ * on the bitstream info and passed to the kernel. The codec should update
|
|
+ * the frame context after the frame has been decoded, so that next time
|
|
+ * userspace query this context it contains the updated probabilities.
|
|
+ */
|
|
+struct v4l2_ctrl_vp9_frame_ctx {
|
|
+ struct v4l2_vp9_probabilities probs;
|
|
+};
|
|
+
|
|
+#endif /* _VP9_CTRLS_H_ */
|
|
|
|
From 3e089d23e73a5eb2b070f875845ff423a492f3ba Mon Sep 17 00:00:00 2001
|
|
From: Boris Brezillon <boris.brezillon@collabora.com>
|
|
Date: Mon, 18 May 2020 14:40:11 -0300
|
|
Subject: [PATCH] media: rkvdec: Add the VP9 backend
|
|
|
|
The Rockchip VDEC supports VP9 profile 0 up to 4096x2304@30fps. Add
|
|
a backend for this new format.
|
|
|
|
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
|
|
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
|
---
|
|
drivers/staging/media/rkvdec/Makefile | 2 +-
|
|
drivers/staging/media/rkvdec/rkvdec-vp9.c | 1577 +++++++++++++++++++++
|
|
drivers/staging/media/rkvdec/rkvdec.c | 54 +
|
|
drivers/staging/media/rkvdec/rkvdec.h | 6 +
|
|
4 files changed, 1638 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/staging/media/rkvdec/rkvdec-vp9.c
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile
|
|
index c08fed0a39f9..cb86b429cfaa 100644
|
|
--- a/drivers/staging/media/rkvdec/Makefile
|
|
+++ b/drivers/staging/media/rkvdec/Makefile
|
|
@@ -1,3 +1,3 @@
|
|
obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o
|
|
|
|
-rockchip-vdec-y += rkvdec.o rkvdec-h264.o
|
|
+rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
|
|
new file mode 100644
|
|
index 000000000000..37d0ea4e3570
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
|
|
@@ -0,0 +1,1577 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * Rockchip Video Decoder VP9 backend
|
|
+ *
|
|
+ * Copyright (C) 2019 Collabora, Ltd.
|
|
+ * Boris Brezillon <boris.brezillon@collabora.com>
|
|
+ *
|
|
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
|
|
+ * Alpha Lin <Alpha.Lin@rock-chips.com>
|
|
+ */
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <media/v4l2-mem2mem.h>
|
|
+
|
|
+#include "rkvdec.h"
|
|
+#include "rkvdec-regs.h"
|
|
+
|
|
+#define RKVDEC_VP9_PROBE_SIZE 4864
|
|
+#define RKVDEC_VP9_COUNT_SIZE 13232
|
|
+#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728
|
|
+
|
|
+struct rkvdec_vp9_intra_mode_probs {
|
|
+ u8 y_mode[105];
|
|
+ u8 uv_mode[23];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_intra_only_frame_probs {
|
|
+ u8 coef_intra[4][2][128];
|
|
+ struct rkvdec_vp9_intra_mode_probs intra_mode[10];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_inter_frame_probs {
|
|
+ u8 y_mode[4][9];
|
|
+ u8 comp_mode[5];
|
|
+ u8 comp_ref[5];
|
|
+ u8 single_ref[5][2];
|
|
+ u8 inter_mode[7][3];
|
|
+ u8 interp_filter[4][2];
|
|
+ u8 padding0[11];
|
|
+ u8 coef[2][4][2][128];
|
|
+ u8 uv_mode_0_2[3][9];
|
|
+ u8 padding1[5];
|
|
+ u8 uv_mode_3_5[3][9];
|
|
+ u8 padding2[5];
|
|
+ u8 uv_mode_6_8[3][9];
|
|
+ u8 padding3[5];
|
|
+ u8 uv_mode_9[9];
|
|
+ u8 padding4[7];
|
|
+ u8 padding5[16];
|
|
+ struct {
|
|
+ u8 joint[3];
|
|
+ u8 sign[2];
|
|
+ u8 class[2][10];
|
|
+ u8 class0_bit[2];
|
|
+ u8 bits[2][10];
|
|
+ u8 class0_fr[2][2][3];
|
|
+ u8 fr[2][3];
|
|
+ u8 class0_hp[2];
|
|
+ u8 hp[2];
|
|
+ } mv;
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_probs {
|
|
+ u8 partition[16][3];
|
|
+ u8 pred[3];
|
|
+ u8 tree[7];
|
|
+ u8 skip[3];
|
|
+ u8 tx32[2][3];
|
|
+ u8 tx16[2][2];
|
|
+ u8 tx8[2][1];
|
|
+ u8 is_inter[4];
|
|
+ /* 128 bit alignment */
|
|
+ u8 padding0[3];
|
|
+ union {
|
|
+ struct rkvdec_vp9_inter_frame_probs inter;
|
|
+ struct rkvdec_vp9_intra_only_frame_probs intra_only;
|
|
+ };
|
|
+};
|
|
+
|
|
+/* Data structure describing auxiliary buffer format. */
|
|
+struct rkvdec_vp9_priv_tbl {
|
|
+ struct rkvdec_vp9_probs probs;
|
|
+ u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_refs_counts {
|
|
+ u32 eob[2];
|
|
+ u32 coeff[3];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_inter_frame_symbol_counts {
|
|
+ u32 partition[16][4];
|
|
+ u32 skip[3][2];
|
|
+ u32 inter[4][2];
|
|
+ u32 tx32p[2][4];
|
|
+ u32 tx16p[2][4];
|
|
+ u32 tx8p[2][2];
|
|
+ u32 y_mode[4][10];
|
|
+ u32 uv_mode[10][10];
|
|
+ u32 comp[5][2];
|
|
+ u32 comp_ref[5][2];
|
|
+ u32 single_ref[5][2][2];
|
|
+ u32 mv_mode[7][4];
|
|
+ u32 filter[4][3];
|
|
+ u32 mv_joint[4];
|
|
+ u32 sign[2][2];
|
|
+ /* add 1 element for align */
|
|
+ u32 classes[2][11 + 1];
|
|
+ u32 class0[2][2];
|
|
+ u32 bits[2][10][2];
|
|
+ u32 class0_fp[2][2][4];
|
|
+ u32 fp[2][4];
|
|
+ u32 class0_hp[2][2];
|
|
+ u32 hp[2][2];
|
|
+ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_intra_frame_symbol_counts {
|
|
+ u32 partition[4][4][4];
|
|
+ u32 skip[3][2];
|
|
+ u32 intra[4][2];
|
|
+ u32 tx32p[2][4];
|
|
+ u32 tx16p[2][4];
|
|
+ u32 tx8p[2][2];
|
|
+ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_run {
|
|
+ struct rkvdec_run base;
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *decode_params;
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_frame_info {
|
|
+ u32 valid : 1;
|
|
+ u32 segmapid : 1;
|
|
+ u32 frame_context_idx : 2;
|
|
+ u32 reference_mode : 2;
|
|
+ u32 tx_mode : 3;
|
|
+ u32 interpolation_filter : 3;
|
|
+ u32 flags;
|
|
+ u64 timestamp;
|
|
+ struct v4l2_vp9_segmentation seg;
|
|
+ struct v4l2_vp9_loop_filter lf;
|
|
+};
|
|
+
|
|
+struct rkvdec_vp9_ctx {
|
|
+ struct rkvdec_aux_buf priv_tbl;
|
|
+ struct rkvdec_aux_buf count_tbl;
|
|
+ struct v4l2_ctrl_vp9_frame_ctx frame_context;
|
|
+ struct rkvdec_vp9_frame_info cur;
|
|
+ struct rkvdec_vp9_frame_info last;
|
|
+};
|
|
+
|
|
+static u32 rkvdec_fastdiv(u32 dividend, u16 divisor)
|
|
+{
|
|
+#define DIV_INV(d) (u32)(((1ULL << 32) + ((d) - 1)) / (d))
|
|
+#define DIVS_INV(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) \
|
|
+ DIV_INV(d0), DIV_INV(d1), DIV_INV(d2), DIV_INV(d3), \
|
|
+ DIV_INV(d4), DIV_INV(d5), DIV_INV(d6), DIV_INV(d7), \
|
|
+ DIV_INV(d8), DIV_INV(d9)
|
|
+
|
|
+ static const u32 inv[] = {
|
|
+ DIV_INV(2), DIV_INV(3), DIV_INV(4), DIV_INV(5),
|
|
+ DIV_INV(6), DIV_INV(7), DIV_INV(8), DIV_INV(9),
|
|
+ DIVS_INV(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
|
|
+ DIVS_INV(20, 21, 22, 23, 24, 25, 26, 27, 28, 29),
|
|
+ DIVS_INV(30, 31, 32, 33, 34, 35, 36, 37, 38, 39),
|
|
+ DIVS_INV(40, 41, 42, 43, 44, 45, 46, 47, 48, 49),
|
|
+ DIVS_INV(50, 51, 52, 53, 54, 55, 56, 57, 58, 59),
|
|
+ DIVS_INV(60, 61, 62, 63, 64, 65, 66, 67, 68, 69),
|
|
+ DIVS_INV(70, 71, 72, 73, 74, 75, 76, 77, 78, 79),
|
|
+ DIVS_INV(80, 81, 82, 83, 84, 85, 86, 87, 88, 89),
|
|
+ DIVS_INV(90, 91, 92, 93, 94, 95, 96, 97, 98, 99),
|
|
+ DIVS_INV(100, 101, 102, 103, 104, 105, 106, 107, 108, 109),
|
|
+ DIVS_INV(110, 111, 112, 113, 114, 115, 116, 117, 118, 119),
|
|
+ DIVS_INV(120, 121, 122, 123, 124, 125, 126, 127, 128, 129),
|
|
+ DIVS_INV(130, 131, 132, 133, 134, 135, 136, 137, 138, 139),
|
|
+ DIVS_INV(140, 141, 142, 143, 144, 145, 146, 147, 148, 149),
|
|
+ DIVS_INV(150, 151, 152, 153, 154, 155, 156, 157, 158, 159),
|
|
+ DIVS_INV(160, 161, 162, 163, 164, 165, 166, 167, 168, 169),
|
|
+ DIVS_INV(170, 171, 172, 173, 174, 175, 176, 177, 178, 179),
|
|
+ DIVS_INV(180, 181, 182, 183, 184, 185, 186, 187, 188, 189),
|
|
+ DIVS_INV(190, 191, 192, 193, 194, 195, 196, 197, 198, 199),
|
|
+ DIVS_INV(200, 201, 202, 203, 204, 205, 206, 207, 208, 209),
|
|
+ DIVS_INV(210, 211, 212, 213, 214, 215, 216, 217, 218, 219),
|
|
+ DIVS_INV(220, 221, 222, 223, 224, 225, 226, 227, 228, 229),
|
|
+ DIVS_INV(230, 231, 232, 233, 234, 235, 236, 237, 238, 239),
|
|
+ DIVS_INV(240, 241, 242, 243, 244, 245, 246, 247, 248, 249),
|
|
+ DIV_INV(250), DIV_INV(251), DIV_INV(252), DIV_INV(253),
|
|
+ DIV_INV(254), DIV_INV(255), DIV_INV(256),
|
|
+ };
|
|
+
|
|
+ if (divisor == 0)
|
|
+ return 0;
|
|
+ else if (divisor == 1)
|
|
+ return dividend;
|
|
+
|
|
+ if (WARN_ON(divisor - 2 >= ARRAY_SIZE(inv)))
|
|
+ return dividend;
|
|
+
|
|
+ return ((u64)dividend * inv[divisor - 2]) >> 32;
|
|
+}
|
|
+
|
|
+static const u8 vp9_kf_y_mode_prob[10][10][9] = {
|
|
+ {
|
|
+ /* above = dc */
|
|
+ { 137, 30, 42, 148, 151, 207, 70, 52, 91 },/*left = dc */
|
|
+ { 92, 45, 102, 136, 116, 180, 74, 90, 100 },/*left = v */
|
|
+ { 73, 32, 19, 187, 222, 215, 46, 34, 100 },/*left = h */
|
|
+ { 91, 30, 32, 116, 121, 186, 93, 86, 94 },/*left = d45 */
|
|
+ { 72, 35, 36, 149, 68, 206, 68, 63, 105 },/*left = d135*/
|
|
+ { 73, 31, 28, 138, 57, 124, 55, 122, 151 },/*left = d117*/
|
|
+ { 67, 23, 21, 140, 126, 197, 40, 37, 171 },/*left = d153*/
|
|
+ { 86, 27, 28, 128, 154, 212, 45, 43, 53 },/*left = d207*/
|
|
+ { 74, 32, 27, 107, 86, 160, 63, 134, 102 },/*left = d63 */
|
|
+ { 59, 67, 44, 140, 161, 202, 78, 67, 119 } /*left = tm */
|
|
+ }, { /* above = v */
|
|
+ { 63, 36, 126, 146, 123, 158, 60, 90, 96 },/*left = dc */
|
|
+ { 43, 46, 168, 134, 107, 128, 69, 142, 92 },/*left = v */
|
|
+ { 44, 29, 68, 159, 201, 177, 50, 57, 77 },/*left = h */
|
|
+ { 58, 38, 76, 114, 97, 172, 78, 133, 92 },/*left = d45 */
|
|
+ { 46, 41, 76, 140, 63, 184, 69, 112, 57 },/*left = d135*/
|
|
+ { 38, 32, 85, 140, 46, 112, 54, 151, 133 },/*left = d117*/
|
|
+ { 39, 27, 61, 131, 110, 175, 44, 75, 136 },/*left = d153*/
|
|
+ { 52, 30, 74, 113, 130, 175, 51, 64, 58 },/*left = d207*/
|
|
+ { 47, 35, 80, 100, 74, 143, 64, 163, 74 },/*left = d63 */
|
|
+ { 36, 61, 116, 114, 128, 162, 80, 125, 82 } /*left = tm */
|
|
+ }, { /* above = h */
|
|
+ { 82, 26, 26, 171, 208, 204, 44, 32, 105 },/*left = dc */
|
|
+ { 55, 44, 68, 166, 179, 192, 57, 57, 108 },/*left = v */
|
|
+ { 42, 26, 11, 199, 241, 228, 23, 15, 85 },/*left = h */
|
|
+ { 68, 42, 19, 131, 160, 199, 55, 52, 83 },/*left = d45 */
|
|
+ { 58, 50, 25, 139, 115, 232, 39, 52, 118 },/*left = d135*/
|
|
+ { 50, 35, 33, 153, 104, 162, 64, 59, 131 },/*left = d117*/
|
|
+ { 44, 24, 16, 150, 177, 202, 33, 19, 156 },/*left = d153*/
|
|
+ { 55, 27, 12, 153, 203, 218, 26, 27, 49 },/*left = d207*/
|
|
+ { 53, 49, 21, 110, 116, 168, 59, 80, 76 },/*left = d63 */
|
|
+ { 38, 72, 19, 168, 203, 212, 50, 50, 107 } /*left = tm */
|
|
+ }, { /* above = d45 */
|
|
+ { 103, 26, 36, 129, 132, 201, 83, 80, 93 },/*left = dc */
|
|
+ { 59, 38, 83, 112, 103, 162, 98, 136, 90 },/*left = v */
|
|
+ { 62, 30, 23, 158, 200, 207, 59, 57, 50 },/*left = h */
|
|
+ { 67, 30, 29, 84, 86, 191, 102, 91, 59 },/*left = d45 */
|
|
+ { 60, 32, 33, 112, 71, 220, 64, 89, 104 },/*left = d135*/
|
|
+ { 53, 26, 34, 130, 56, 149, 84, 120, 103 },/*left = d117*/
|
|
+ { 53, 21, 23, 133, 109, 210, 56, 77, 172 },/*left = d153*/
|
|
+ { 77, 19, 29, 112, 142, 228, 55, 66, 36 },/*left = d207*/
|
|
+ { 61, 29, 29, 93, 97, 165, 83, 175, 162 },/*left = d63 */
|
|
+ { 47, 47, 43, 114, 137, 181, 100, 99, 95 } /*left = tm */
|
|
+ }, { /* above = d135 */
|
|
+ { 69, 23, 29, 128, 83, 199, 46, 44, 101 },/*left = dc */
|
|
+ { 53, 40, 55, 139, 69, 183, 61, 80, 110 },/*left = v */
|
|
+ { 40, 29, 19, 161, 180, 207, 43, 24, 91 },/*left = h */
|
|
+ { 60, 34, 19, 105, 61, 198, 53, 64, 89 },/*left = d45 */
|
|
+ { 52, 31, 22, 158, 40, 209, 58, 62, 89 },/*left = d135*/
|
|
+ { 44, 31, 29, 147, 46, 158, 56, 102, 198 },/*left = d117*/
|
|
+ { 35, 19, 12, 135, 87, 209, 41, 45, 167 },/*left = d153*/
|
|
+ { 55, 25, 21, 118, 95, 215, 38, 39, 66 },/*left = d207*/
|
|
+ { 51, 38, 25, 113, 58, 164, 70, 93, 97 },/*left = d63 */
|
|
+ { 47, 54, 34, 146, 108, 203, 72, 103, 151 } /*left = tm */
|
|
+ }, { /* above = d117 */
|
|
+ { 64, 19, 37, 156, 66, 138, 49, 95, 133 },/*left = dc */
|
|
+ { 46, 27, 80, 150, 55, 124, 55, 121, 135 },/*left = v */
|
|
+ { 36, 23, 27, 165, 149, 166, 54, 64, 118 },/*left = h */
|
|
+ { 53, 21, 36, 131, 63, 163, 60, 109, 81 },/*left = d45 */
|
|
+ { 40, 26, 35, 154, 40, 185, 51, 97, 123 },/*left = d135*/
|
|
+ { 35, 19, 34, 179, 19, 97, 48, 129, 124 },/*left = d117*/
|
|
+ { 36, 20, 26, 136, 62, 164, 33, 77, 154 },/*left = d153*/
|
|
+ { 45, 18, 32, 130, 90, 157, 40, 79, 91 },/*left = d207*/
|
|
+ { 45, 26, 28, 129, 45, 129, 49, 147, 123 },/*left = d63 */
|
|
+ { 38, 44, 51, 136, 74, 162, 57, 97, 121 } /*left = tm */
|
|
+ }, { /* above = d153 */
|
|
+ { 75, 17, 22, 136, 138, 185, 32, 34, 166 },/*left = dc */
|
|
+ { 56, 39, 58, 133, 117, 173, 48, 53, 187 },/*left = v */
|
|
+ { 35, 21, 12, 161, 212, 207, 20, 23, 145 },/*left = h */
|
|
+ { 56, 29, 19, 117, 109, 181, 55, 68, 112 },/*left = d45 */
|
|
+ { 47, 29, 17, 153, 64, 220, 59, 51, 114 },/*left = d135*/
|
|
+ { 46, 16, 24, 136, 76, 147, 41, 64, 172 },/*left = d117*/
|
|
+ { 34, 17, 11, 108, 152, 187, 13, 15, 209 },/*left = d153*/
|
|
+ { 51, 24, 14, 115, 133, 209, 32, 26, 104 },/*left = d207*/
|
|
+ { 55, 30, 18, 122, 79, 179, 44, 88, 116 },/*left = d63 */
|
|
+ { 37, 49, 25, 129, 168, 164, 41, 54, 148 } /*left = tm */
|
|
+ }, { /* above = d207 */
|
|
+ { 82, 22, 32, 127, 143, 213, 39, 41, 70 },/*left = dc */
|
|
+ { 62, 44, 61, 123, 105, 189, 48, 57, 64 },/*left = v */
|
|
+ { 47, 25, 17, 175, 222, 220, 24, 30, 86 },/*left = h */
|
|
+ { 68, 36, 17, 106, 102, 206, 59, 74, 74 },/*left = d45 */
|
|
+ { 57, 39, 23, 151, 68, 216, 55, 63, 58 },/*left = d135*/
|
|
+ { 49, 30, 35, 141, 70, 168, 82, 40, 115 },/*left = d117*/
|
|
+ { 51, 25, 15, 136, 129, 202, 38, 35, 139 },/*left = d153*/
|
|
+ { 68, 26, 16, 111, 141, 215, 29, 28, 28 },/*left = d207*/
|
|
+ { 59, 39, 19, 114, 75, 180, 77, 104, 42 },/*left = d63 */
|
|
+ { 40, 61, 26, 126, 152, 206, 61, 59, 93 } /*left = tm */
|
|
+ }, { /* above = d63 */
|
|
+ { 78, 23, 39, 111, 117, 170, 74, 124, 94 },/*left = dc */
|
|
+ { 48, 34, 86, 101, 92, 146, 78, 179, 134 },/*left = v */
|
|
+ { 47, 22, 24, 138, 187, 178, 68, 69, 59 },/*left = h */
|
|
+ { 56, 25, 33, 105, 112, 187, 95, 177, 129 },/*left = d45 */
|
|
+ { 48, 31, 27, 114, 63, 183, 82, 116, 56 },/*left = d135*/
|
|
+ { 43, 28, 37, 121, 63, 123, 61, 192, 169 },/*left = d117*/
|
|
+ { 42, 17, 24, 109, 97, 177, 56, 76, 122 },/*left = d153*/
|
|
+ { 58, 18, 28, 105, 139, 182, 70, 92, 63 },/*left = d207*/
|
|
+ { 46, 23, 32, 74, 86, 150, 67, 183, 88 },/*left = d63 */
|
|
+ { 36, 38, 48, 92, 122, 165, 88, 137, 91 } /*left = tm */
|
|
+ }, { /* above = tm */
|
|
+ { 65, 70, 60, 155, 159, 199, 61, 60, 81 },/*left = dc */
|
|
+ { 44, 78, 115, 132, 119, 173, 71, 112, 93 },/*left = v */
|
|
+ { 39, 38, 21, 184, 227, 206, 42, 32, 64 },/*left = h */
|
|
+ { 58, 47, 36, 124, 137, 193, 80, 82, 78 },/*left = d45 */
|
|
+ { 49, 50, 35, 144, 95, 205, 63, 78, 59 },/*left = d135*/
|
|
+ { 41, 53, 52, 148, 71, 142, 65, 128, 51 },/*left = d117*/
|
|
+ { 40, 36, 28, 143, 143, 202, 40, 55, 137 },/*left = d153*/
|
|
+ { 52, 34, 29, 129, 183, 227, 42, 35, 43 },/*left = d207*/
|
|
+ { 42, 44, 44, 104, 105, 164, 64, 130, 80 },/*left = d63 */
|
|
+ { 43, 81, 53, 140, 169, 204, 68, 84, 72 } /*left = tm */
|
|
+ }
|
|
+};
|
|
+
|
|
+static const u8 kf_partition_probs[16][3] = {
|
|
+ /* 8x8 -> 4x4 */
|
|
+ { 158, 97, 94 }, /* a/l both not split */
|
|
+ { 93, 24, 99 }, /* a split, l not split */
|
|
+ { 85, 119, 44 }, /* l split, a not split */
|
|
+ { 62, 59, 67 }, /* a/l both split */
|
|
+ /* 16x16 -> 8x8 */
|
|
+ { 149, 53, 53 }, /* a/l both not split */
|
|
+ { 94, 20, 48 }, /* a split, l not split */
|
|
+ { 83, 53, 24 }, /* l split, a not split */
|
|
+ { 52, 18, 18 }, /* a/l both split */
|
|
+ /* 32x32 -> 16x16 */
|
|
+ { 150, 40, 39 }, /* a/l both not split */
|
|
+ { 78, 12, 26 }, /* a split, l not split */
|
|
+ { 67, 33, 11 }, /* l split, a not split */
|
|
+ { 24, 7, 5 }, /* a/l both split */
|
|
+ /* 64x64 -> 32x32 */
|
|
+ { 174, 35, 49 }, /* a/l both not split */
|
|
+ { 68, 11, 27 }, /* a split, l not split */
|
|
+ { 57, 15, 9 }, /* l split, a not split */
|
|
+ { 12, 3, 3 }, /* a/l both split */
|
|
+};
|
|
+
|
|
+static const u8 kf_uv_mode_prob[10][9] = {
|
|
+ { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, /* y = dc */
|
|
+ { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, /* y = v */
|
|
+ { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, /* y = h */
|
|
+ { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, /* y = d45 */
|
|
+ { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, /* y = d135 */
|
|
+ { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, /* y = d117 */
|
|
+ { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, /* y = d153 */
|
|
+ { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, /* y = d207 */
|
|
+ { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, /* y = d63 */
|
|
+ { 102, 19, 66, 162, 182, 122, 35, 59, 128 } /* y = tm */
|
|
+};
|
|
+
|
|
+static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
|
|
+{
|
|
+ unsigned int idx = 0;
|
|
+ u8 byte_count = 0, p;
|
|
+ s32 k, m, n;
|
|
+
|
|
+ for (k = 0; k < 6; k++) {
|
|
+ for (m = 0; m < 6; m++) {
|
|
+ for (n = 0; n < 3; n++) {
|
|
+ p = coef[k][m][n];
|
|
+ coeff_plane[idx++] = p;
|
|
+ byte_count++;
|
|
+ if (byte_count == 27) {
|
|
+ idx += 5;
|
|
+ byte_count = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void init_intra_only_probs(struct rkvdec_ctx *ctx,
|
|
+ const struct rkvdec_vp9_run *run)
|
|
+{
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
|
|
+ struct rkvdec_vp9_intra_only_frame_probs *rkprobs;
|
|
+ const struct v4l2_vp9_probabilities *probs;
|
|
+ unsigned int i, j, k, m;
|
|
+
|
|
+ rkprobs = &tbl->probs.intra_only;
|
|
+ dec_params = run->decode_params;
|
|
+ probs = &dec_params->probs;
|
|
+
|
|
+ /*
|
|
+ * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related
|
|
+ * prob 64 x 128 bits
|
|
+ */
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) {
|
|
+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++)
|
|
+ write_coeff_plane(probs->coef[i][j][0],
|
|
+ rkprobs->coef_intra[i][j]);
|
|
+ }
|
|
+
|
|
+ /* intra mode prob 80 x 128 bits */
|
|
+ for (i = 0; i < ARRAY_SIZE(vp9_kf_y_mode_prob); i++) {
|
|
+ u32 byte_count = 0;
|
|
+ int idx = 0;
|
|
+
|
|
+ /* vp9_kf_y_mode_prob */
|
|
+ for (j = 0; j < ARRAY_SIZE(vp9_kf_y_mode_prob[0]); j++) {
|
|
+ for (k = 0; k < ARRAY_SIZE(vp9_kf_y_mode_prob[0][0]);
|
|
+ k++) {
|
|
+ u8 val = vp9_kf_y_mode_prob[i][j][k];
|
|
+
|
|
+ rkprobs->intra_mode[i].y_mode[idx++] = val;
|
|
+ byte_count++;
|
|
+ if (byte_count == 27) {
|
|
+ byte_count = 0;
|
|
+ idx += 5;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ idx = 0;
|
|
+ if (i < 4) {
|
|
+ for (m = 0; m < (i < 3 ? 23 : 21); m++) {
|
|
+ const u8 *ptr = (const u8 *)kf_uv_mode_prob;
|
|
+
|
|
+ rkprobs->intra_mode[i].uv_mode[idx++] = ptr[i * 23 + m];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void init_inter_probs(struct rkvdec_ctx *ctx,
|
|
+ const struct rkvdec_vp9_run *run)
|
|
+{
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
|
|
+ struct rkvdec_vp9_inter_frame_probs *rkprobs;
|
|
+ const struct v4l2_vp9_probabilities *probs;
|
|
+ unsigned int i, j, k;
|
|
+
|
|
+ rkprobs = &tbl->probs.inter;
|
|
+ dec_params = run->decode_params;
|
|
+ probs = &dec_params->probs;
|
|
+
|
|
+ /*
|
|
+ * inter probs
|
|
+ * 151 x 128 bits, aligned to 152 x 128 bits
|
|
+ * inter only
|
|
+ * intra_y_mode & inter_block info 6 x 128 bits
|
|
+ */
|
|
+
|
|
+ memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode));
|
|
+ memcpy(rkprobs->comp_mode, probs->comp_mode,
|
|
+ sizeof(rkprobs->comp_mode));
|
|
+ memcpy(rkprobs->comp_ref, probs->comp_ref,
|
|
+ sizeof(rkprobs->comp_ref));
|
|
+ memcpy(rkprobs->single_ref, probs->single_ref,
|
|
+ sizeof(rkprobs->single_ref));
|
|
+ memcpy(rkprobs->inter_mode, probs->inter_mode,
|
|
+ sizeof(rkprobs->inter_mode));
|
|
+ memcpy(rkprobs->interp_filter, probs->interp_filter,
|
|
+ sizeof(rkprobs->interp_filter));
|
|
+
|
|
+ /* 128 x 128 bits coeff related */
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) {
|
|
+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) {
|
|
+ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++)
|
|
+ write_coeff_plane(probs->coef[i][j][k],
|
|
+ rkprobs->coef[k][i][j]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* intra uv mode 6 x 128 */
|
|
+ memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0],
|
|
+ sizeof(rkprobs->uv_mode_0_2));
|
|
+ memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3],
|
|
+ sizeof(rkprobs->uv_mode_3_5));
|
|
+ memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6],
|
|
+ sizeof(rkprobs->uv_mode_6_8));
|
|
+ memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9],
|
|
+ sizeof(rkprobs->uv_mode_9));
|
|
+
|
|
+ /* mv related 6 x 128 */
|
|
+ memcpy(rkprobs->mv.joint, probs->mv.joint,
|
|
+ sizeof(rkprobs->mv.joint));
|
|
+ memcpy(rkprobs->mv.sign, probs->mv.sign,
|
|
+ sizeof(rkprobs->mv.sign));
|
|
+ memcpy(rkprobs->mv.class, probs->mv.class,
|
|
+ sizeof(rkprobs->mv.class));
|
|
+ memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit,
|
|
+ sizeof(rkprobs->mv.class0_bit));
|
|
+ memcpy(rkprobs->mv.bits, probs->mv.bits,
|
|
+ sizeof(rkprobs->mv.bits));
|
|
+ memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr,
|
|
+ sizeof(rkprobs->mv.class0_fr));
|
|
+ memcpy(rkprobs->mv.fr, probs->mv.fr,
|
|
+ sizeof(rkprobs->mv.fr));
|
|
+ memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp,
|
|
+ sizeof(rkprobs->mv.class0_hp));
|
|
+ memcpy(rkprobs->mv.hp, probs->mv.hp,
|
|
+ sizeof(rkprobs->mv.hp));
|
|
+}
|
|
+
|
|
+static void init_probs(struct rkvdec_ctx *ctx,
|
|
+ const struct rkvdec_vp9_run *run)
|
|
+{
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
|
|
+ struct rkvdec_vp9_probs *rkprobs = &tbl->probs;
|
|
+ const struct v4l2_vp9_segmentation *seg;
|
|
+ const struct v4l2_vp9_probabilities *probs;
|
|
+ bool intra_only;
|
|
+
|
|
+ dec_params = run->decode_params;
|
|
+ probs = &dec_params->probs;
|
|
+ seg = &dec_params->seg;
|
|
+
|
|
+ memset(rkprobs, 0, sizeof(*rkprobs));
|
|
+
|
|
+ intra_only = !!(dec_params->flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME |
|
|
+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
|
|
+
|
|
+ /* sb info 5 x 128 bit */
|
|
+ memcpy(rkprobs->partition,
|
|
+ intra_only ? kf_partition_probs : probs->partition,
|
|
+ sizeof(rkprobs->partition));
|
|
+
|
|
+ memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred));
|
|
+ memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree));
|
|
+ memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip));
|
|
+ memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32));
|
|
+ memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16));
|
|
+ memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8));
|
|
+ memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter));
|
|
+
|
|
+ if (intra_only)
|
|
+ init_intra_only_probs(ctx, run);
|
|
+ else
|
|
+ init_inter_probs(ctx, run);
|
|
+}
|
|
+
|
|
+struct vp9d_ref_config {
|
|
+ u32 reg_frm_size;
|
|
+ u32 reg_hor_stride;
|
|
+ u32 reg_y_stride;
|
|
+ u32 reg_yuv_stride;
|
|
+ u32 reg_ref_base;
|
|
+};
|
|
+
|
|
+static struct vp9d_ref_config ref_config[3] = {
|
|
+ {
|
|
+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0),
|
|
+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0),
|
|
+ .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE,
|
|
+ .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE,
|
|
+ .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE,
|
|
+ },
|
|
+ {
|
|
+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1),
|
|
+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1),
|
|
+ .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE,
|
|
+ .reg_yuv_stride = 0,
|
|
+ .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE,
|
|
+ },
|
|
+ {
|
|
+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2),
|
|
+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2),
|
|
+ .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE,
|
|
+ .reg_yuv_stride = 0,
|
|
+ .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE,
|
|
+ }
|
|
+};
|
|
+
|
|
+static struct rkvdec_decoded_buffer *
|
|
+get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
|
|
+{
|
|
+ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
|
+ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
|
+ int buf_idx;
|
|
+
|
|
+ /*
|
|
+ * If a ref is unused or invalid, address of current destination
|
|
+ * buffer is returned.
|
|
+ */
|
|
+ buf_idx = vb2_find_timestamp(cap_q, timestamp, 0);
|
|
+ if (buf_idx < 0)
|
|
+ return vb2_to_rkvdec_decoded_buf(&dst->vb2_buf);
|
|
+
|
|
+ return vb2_to_rkvdec_decoded_buf(vb2_get_buffer(cap_q, buf_idx));
|
|
+}
|
|
+
|
|
+static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
|
|
+{
|
|
+ u32 aligned_pitch, aligned_height, yuv_len;
|
|
+
|
|
+ aligned_height = round_up(buf->vp9.height, 64);
|
|
+ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8;
|
|
+ yuv_len = (aligned_height * aligned_pitch * 3) / 2;
|
|
+
|
|
+ return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) +
|
|
+ yuv_len;
|
|
+}
|
|
+
|
|
+static void
|
|
+config_ref_registers(struct rkvdec_ctx *ctx,
|
|
+ const struct rkvdec_vp9_run *run,
|
|
+ struct rkvdec_decoded_buffer **ref_bufs,
|
|
+ enum v4l2_vp9_ref_id id)
|
|
+{
|
|
+ u32 aligned_pitch, aligned_height, y_len, yuv_len;
|
|
+ struct rkvdec_decoded_buffer *buf = ref_bufs[id];
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+
|
|
+ aligned_height = round_up(buf->vp9.height, 64);
|
|
+ writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(buf->vp9.width) |
|
|
+ RKVDEC_VP9_FRAMEHEIGHT(buf->vp9.height),
|
|
+ rkvdec->regs + ref_config[id].reg_frm_size);
|
|
+
|
|
+ writel_relaxed(vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0),
|
|
+ rkvdec->regs + ref_config[id].reg_ref_base);
|
|
+
|
|
+ if (&buf->base.vb == run->base.bufs.dst)
|
|
+ return;
|
|
+
|
|
+ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8;
|
|
+ y_len = aligned_height * aligned_pitch;
|
|
+ yuv_len = (y_len * 3) / 2;
|
|
+
|
|
+ writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) |
|
|
+ RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16),
|
|
+ rkvdec->regs + ref_config[id].reg_hor_stride);
|
|
+ writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16),
|
|
+ rkvdec->regs + ref_config[id].reg_y_stride);
|
|
+
|
|
+ if (!ref_config[id].reg_yuv_stride)
|
|
+ return;
|
|
+
|
|
+ writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16),
|
|
+ rkvdec->regs + ref_config[id].reg_yuv_stride);
|
|
+}
|
|
+
|
|
+static bool seg_featured_enabled(const struct v4l2_vp9_segmentation *seg,
|
|
+ enum v4l2_vp9_segment_feature feature,
|
|
+ unsigned int segid)
|
|
+{
|
|
+ u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature);
|
|
+
|
|
+ return !!(seg->feature_enabled[segid] & mask);
|
|
+}
|
|
+
|
|
+static void
|
|
+config_seg_registers(struct rkvdec_ctx *ctx,
|
|
+ unsigned int segid)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ const struct v4l2_vp9_segmentation *seg;
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+ s16 feature_val;
|
|
+ u8 feature_id;
|
|
+ u32 val = 0;
|
|
+
|
|
+ seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg;
|
|
+ feature_id = V4L2_VP9_SEGMENT_FEATURE_QP_DELTA;
|
|
+ if (seg_featured_enabled(seg, feature_id, segid)) {
|
|
+ feature_val = seg->feature_data[segid][feature_id];
|
|
+ val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
|
|
+ RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
|
|
+ }
|
|
+
|
|
+ feature_id = V4L2_VP9_SEGMENT_FEATURE_LF;
|
|
+ if (seg_featured_enabled(seg, feature_id, segid)) {
|
|
+ feature_val = seg->feature_data[segid][feature_id];
|
|
+ val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
|
|
+ RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
|
|
+ }
|
|
+
|
|
+ feature_id = V4L2_VP9_SEGMENT_FEATURE_REF_FRAME;
|
|
+ if (seg_featured_enabled(seg, feature_id, segid)) {
|
|
+ feature_val = seg->feature_data[segid][feature_id];
|
|
+ val |= RKVDEC_SEGID_REFERINFO_EN(1) |
|
|
+ RKVDEC_SEGID_REFERINFO(feature_val);
|
|
+ }
|
|
+
|
|
+ feature_id = V4L2_VP9_SEGMENT_FEATURE_SKIP;
|
|
+ if (seg_featured_enabled(seg, feature_id, segid))
|
|
+ val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
|
|
+
|
|
+ if (!segid &&
|
|
+ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE))
|
|
+ val |= RKVDEC_SEGID_ABS_DELTA(1);
|
|
+
|
|
+ writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid));
|
|
+}
|
|
+
|
|
+static void
|
|
+update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params)
|
|
+{
|
|
+ buf->vp9.width = dec_params->frame_width_minus_1 + 1;
|
|
+ buf->vp9.height = dec_params->frame_height_minus_1 + 1;
|
|
+ buf->vp9.bit_depth = dec_params->bit_depth;
|
|
+}
|
|
+
|
|
+static void
|
|
+update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx,
|
|
+ struct rkvdec_decoded_buffer *buf,
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params)
|
|
+{
|
|
+ vp9_ctx->cur.valid = true;
|
|
+ vp9_ctx->cur.frame_context_idx = dec_params->frame_context_idx;
|
|
+ vp9_ctx->cur.reference_mode = dec_params->reference_mode;
|
|
+ vp9_ctx->cur.tx_mode = dec_params->tx_mode;
|
|
+ vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter;
|
|
+ vp9_ctx->cur.flags = dec_params->flags;
|
|
+ vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp;
|
|
+ vp9_ctx->cur.seg = dec_params->seg;
|
|
+ vp9_ctx->cur.lf = dec_params->lf;
|
|
+}
|
|
+
|
|
+static void
|
|
+update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx)
|
|
+{
|
|
+ vp9_ctx->last = vp9_ctx->cur;
|
|
+}
|
|
+
|
|
+static void config_registers(struct rkvdec_ctx *ctx,
|
|
+ const struct rkvdec_vp9_run *run)
|
|
+{
|
|
+ u32 y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch;
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params;
|
|
+ struct rkvdec_decoded_buffer *ref_bufs[V4L2_REF_ID_CNT];
|
|
+ struct rkvdec_decoded_buffer *dst, *last, *mv_ref;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ u32 val, stream_len, last_frame_info = 0;
|
|
+ const struct v4l2_vp9_segmentation *seg;
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+ dma_addr_t addr;
|
|
+ bool intra_only;
|
|
+ unsigned int i;
|
|
+
|
|
+ dec_params = run->decode_params;
|
|
+ dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf);
|
|
+ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++)
|
|
+ ref_bufs[i] = get_ref_buf(ctx, &dst->base.vb,
|
|
+ dec_params->refs[i]);
|
|
+
|
|
+ if (vp9_ctx->last.valid)
|
|
+ last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
|
|
+ else
|
|
+ last = dst;
|
|
+
|
|
+ update_dec_buf_info(dst, dec_params);
|
|
+ update_ctx_cur_info(vp9_ctx, dst, dec_params);
|
|
+ seg = &dec_params->seg;
|
|
+
|
|
+ intra_only = !!(dec_params->flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME |
|
|
+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
|
|
+
|
|
+ writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9),
|
|
+ rkvdec->regs + RKVDEC_REG_SYSCTRL);
|
|
+
|
|
+ bit_depth = dec_params->bit_depth;
|
|
+ aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64);
|
|
+
|
|
+ aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width *
|
|
+ bit_depth,
|
|
+ 512) / 8;
|
|
+ y_len = aligned_height * aligned_pitch;
|
|
+ uv_len = y_len / 2;
|
|
+ yuv_len = y_len + uv_len;
|
|
+
|
|
+ writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) |
|
|
+ RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16),
|
|
+ rkvdec->regs + RKVDEC_REG_PICPAR);
|
|
+ writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16),
|
|
+ rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
|
|
+ writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16),
|
|
+ rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
|
|
+
|
|
+ stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0);
|
|
+ writel_relaxed(RKVDEC_STRM_LEN(stream_len),
|
|
+ rkvdec->regs + RKVDEC_REG_STRM_LEN);
|
|
+
|
|
+ /*
|
|
+ * Reset count buffer, because decoder only output intra related syntax
|
|
+ * counts when decoding intra frame, but update entropy need to update
|
|
+ * all the probabilities.
|
|
+ */
|
|
+ if (intra_only)
|
|
+ memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size);
|
|
+
|
|
+ vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid;
|
|
+ if (!intra_only &&
|
|
+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
|
|
+ (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) ||
|
|
+ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)))
|
|
+ vp9_ctx->cur.segmapid++;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++)
|
|
+ config_ref_registers(ctx, run, ref_bufs, i);
|
|
+
|
|
+ for (i = 0; i < 8; i++)
|
|
+ config_seg_registers(ctx, i);
|
|
+
|
|
+ writel_relaxed(RKVDEC_VP9_TX_MODE(dec_params->tx_mode) |
|
|
+ RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode),
|
|
+ rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG);
|
|
+
|
|
+ if (!intra_only) {
|
|
+ const struct v4l2_vp9_loop_filter *lf;
|
|
+ s8 delta;
|
|
+
|
|
+ if (vp9_ctx->last.valid)
|
|
+ lf = &vp9_ctx->last.lf;
|
|
+ else
|
|
+ lf = &vp9_ctx->cur.lf;
|
|
+
|
|
+ val = 0;
|
|
+ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
|
|
+ delta = lf->ref_deltas[i];
|
|
+ val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta);
|
|
+ }
|
|
+
|
|
+ writel_relaxed(val,
|
|
+ rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
|
|
+ delta = lf->mode_deltas[i];
|
|
+ last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i,
|
|
+ delta);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (vp9_ctx->last.valid && !intra_only &&
|
|
+ vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)
|
|
+ last_frame_info |= RKVDEC_SEG_EN_LASTFRAME;
|
|
+
|
|
+ if (vp9_ctx->last.valid &&
|
|
+ vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME)
|
|
+ last_frame_info |= RKVDEC_LAST_SHOW_FRAME;
|
|
+
|
|
+ if (vp9_ctx->last.valid &&
|
|
+ vp9_ctx->last.flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY))
|
|
+ last_frame_info |= RKVDEC_LAST_INTRA_ONLY;
|
|
+
|
|
+ if (vp9_ctx->last.valid &&
|
|
+ last->vp9.width == dst->vp9.width &&
|
|
+ last->vp9.height == dst->vp9.height)
|
|
+ last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR;
|
|
+
|
|
+ writel_relaxed(last_frame_info,
|
|
+ rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME);
|
|
+
|
|
+ writel_relaxed(stream_len - dec_params->compressed_header_size -
|
|
+ dec_params->uncompressed_header_size,
|
|
+ rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE);
|
|
+
|
|
+ for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) {
|
|
+ u32 refw = ref_bufs[i]->vp9.width;
|
|
+ u32 refh = ref_bufs[i]->vp9.height;
|
|
+ u32 hscale, vscale;
|
|
+
|
|
+ hscale = (refw << 14) / dst->vp9.width;
|
|
+ vscale = (refh << 14) / dst->vp9.height;
|
|
+ writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) |
|
|
+ RKVDEC_VP9_REF_VER_SCALE(vscale),
|
|
+ rkvdec->regs + RKVDEC_VP9_REF_SCALE(i));
|
|
+ }
|
|
+
|
|
+ addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0);
|
|
+ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
|
|
+ addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0);
|
|
+ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
|
|
+ writel_relaxed(vp9_ctx->priv_tbl.dma +
|
|
+ offsetof(struct rkvdec_vp9_priv_tbl, probs),
|
|
+ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
|
|
+ writel_relaxed(vp9_ctx->count_tbl.dma,
|
|
+ rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE);
|
|
+
|
|
+ writel_relaxed(vp9_ctx->priv_tbl.dma +
|
|
+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
|
|
+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid),
|
|
+ rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE);
|
|
+ writel_relaxed(vp9_ctx->priv_tbl.dma +
|
|
+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
|
|
+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)),
|
|
+ rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE);
|
|
+
|
|
+ if (!intra_only &&
|
|
+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
|
|
+ vp9_ctx->last.valid)
|
|
+ mv_ref = last;
|
|
+ else
|
|
+ mv_ref = dst;
|
|
+
|
|
+ writel_relaxed(get_mv_base_addr(mv_ref),
|
|
+ rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE);
|
|
+
|
|
+ writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width |
|
|
+ (ctx->decoded_fmt.fmt.pix_mp.height << 16),
|
|
+ rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE);
|
|
+}
|
|
+
|
|
+static int
|
|
+validate_dec_params(struct rkvdec_ctx *ctx,
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params)
|
|
+{
|
|
+ unsigned int aligned_width, aligned_height;
|
|
+
|
|
+ /* We only support profile 0. */
|
|
+ if (dec_params->profile != 0) {
|
|
+ dev_err(ctx->dev->dev, "unsupported profile %d\n",
|
|
+ dec_params->profile);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64);
|
|
+ aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64);
|
|
+
|
|
+ /*
|
|
+ * Userspace should update the capture/decoded format when the
|
|
+ * resolution changes.
|
|
+ */
|
|
+ if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width ||
|
|
+ aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) {
|
|
+ dev_err(ctx->dev->dev,
|
|
+ "unexpected bitstream resolution %dx%d\n",
|
|
+ dec_params->frame_width_minus_1 + 1,
|
|
+ dec_params->frame_height_minus_1 +1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
|
|
+ struct rkvdec_vp9_run *run)
|
|
+{
|
|
+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params;
|
|
+ const struct v4l2_ctrl_vp9_frame_ctx *fctx = NULL;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct v4l2_ctrl *ctrl;
|
|
+ u8 frm_ctx;
|
|
+ int ret;
|
|
+
|
|
+ rkvdec_run_preamble(ctx, &run->base);
|
|
+
|
|
+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS);
|
|
+ WARN_ON(!ctrl);
|
|
+
|
|
+ dec_params = ctrl ? ctrl->p_cur.p : NULL;
|
|
+ if (WARN_ON(!dec_params))
|
|
+ return -EINVAL;
|
|
+
|
|
+ ret = validate_dec_params(ctx, dec_params);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ run->decode_params = dec_params;
|
|
+
|
|
+ /* No need to load the frame context if we don't need to update it. */
|
|
+ if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX))
|
|
+ return 0;
|
|
+
|
|
+ /*
|
|
+ * When a refresh context is requested in parallel mode, we should just
|
|
+ * update the context with the probs passed in the decode parameters.
|
|
+ */
|
|
+ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE) {
|
|
+ vp9_ctx->frame_context.probs = dec_params->probs;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ frm_ctx = run->decode_params->frame_context_idx;
|
|
+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(frm_ctx));
|
|
+ if (WARN_ON(!ctrl))
|
|
+ return 0;
|
|
+
|
|
+ fctx = ctrl->p_cur.p;
|
|
+ vp9_ctx->frame_context = *fctx;
|
|
+
|
|
+ /*
|
|
+ * For intra-only frames, we must update the context TX and skip probs
|
|
+ * with the value passed in the decode params.
|
|
+ */
|
|
+ if (dec_params->flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) {
|
|
+ struct v4l2_vp9_probabilities *probs;
|
|
+
|
|
+ probs = &vp9_ctx->frame_context.probs;
|
|
+ memcpy(probs->skip, dec_params->probs.skip,
|
|
+ sizeof(probs->skip));
|
|
+ memcpy(probs->tx8, dec_params->probs.tx8,
|
|
+ sizeof(probs->tx8));
|
|
+ memcpy(probs->tx16, dec_params->probs.tx16,
|
|
+ sizeof(probs->tx16));
|
|
+ memcpy(probs->tx32, dec_params->probs.tx32,
|
|
+ sizeof(probs->tx32));
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+ struct rkvdec_vp9_run run = { };
|
|
+ int ret;
|
|
+
|
|
+ ret = rkvdec_vp9_run_preamble(ctx, &run);
|
|
+ if (ret) {
|
|
+ rkvdec_run_postamble(ctx, &run.base);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* Prepare probs. */
|
|
+ init_probs(ctx, &run);
|
|
+
|
|
+ /* Configure hardware registers. */
|
|
+ config_registers(ctx, &run);
|
|
+
|
|
+ rkvdec_run_postamble(ctx, &run.base);
|
|
+
|
|
+ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000));
|
|
+
|
|
+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
|
|
+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
|
|
+
|
|
+ writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
|
|
+ /* Start decoding! */
|
|
+ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E |
|
|
+ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E,
|
|
+ rkvdec->regs + RKVDEC_REG_INTERRUPT);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static u8 adapt_prob(u8 p1, u32 ct0, u32 ct1, u16 max_count, u32 update_factor)
|
|
+{
|
|
+ u32 ct = ct0 + ct1, p2;
|
|
+ u32 lo = 1;
|
|
+ u32 hi = 255;
|
|
+
|
|
+ if (!ct)
|
|
+ return p1;
|
|
+
|
|
+ p2 = ((ct0 << 8) + (ct >> 1)) / ct;
|
|
+ p2 = clamp(p2, lo, hi);
|
|
+ ct = min_t(u32, ct, max_count);
|
|
+
|
|
+ if (WARN_ON(max_count >= 257))
|
|
+ return p1;
|
|
+
|
|
+ update_factor = rkvdec_fastdiv(update_factor * ct, max_count);
|
|
+
|
|
+ return p1 + (((p2 - p1) * update_factor + 128) >> 8);
|
|
+}
|
|
+
|
|
+#define BAND_6(band) ((band) == 0 ? 3 : 6)
|
|
+
|
|
+static void adapt_coeff(u8 coef[6][6][3],
|
|
+ const struct rkvdec_vp9_refs_counts ref_cnt[6][6],
|
|
+ u32 uf)
|
|
+{
|
|
+ s32 l, m, n;
|
|
+
|
|
+ for (l = 0; l < 6; l++) {
|
|
+ for (m = 0; m < BAND_6(l); m++) {
|
|
+ u8 *p = coef[l][m];
|
|
+ const u32 n0 = ref_cnt[l][m].coeff[0];
|
|
+ const u32 n1 = ref_cnt[l][m].coeff[1];
|
|
+ const u32 n2 = ref_cnt[l][m].coeff[2];
|
|
+ const u32 neob = ref_cnt[l][m].eob[1];
|
|
+ const u32 eob_count = ref_cnt[l][m].eob[0];
|
|
+ const u32 branch_ct[3][2] = {
|
|
+ { neob, eob_count - neob },
|
|
+ { n0, n1 + n2 },
|
|
+ { n1, n2 }
|
|
+ };
|
|
+
|
|
+ for (n = 0; n < 3; n++)
|
|
+ p[n] = adapt_prob(p[n], branch_ct[n][0],
|
|
+ branch_ct[n][1], 24, uf);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_coef_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6],
|
|
+ unsigned int uf)
|
|
+{
|
|
+ unsigned int i, j, k;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) {
|
|
+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) {
|
|
+ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]);
|
|
+ k++) {
|
|
+ adapt_coeff(probs->coef[i][j][k],
|
|
+ ref_cnt[k][i][j],
|
|
+ uf);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void adapt_intra_frame_probs(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs;
|
|
+ const struct rkvdec_vp9_intra_frame_symbol_counts *sym_cnts;
|
|
+
|
|
+ sym_cnts = vp9_ctx->count_tbl.cpu;
|
|
+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_skip_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->skip); i++)
|
|
+ probs->skip[i] = adapt_prob(probs->skip[i],
|
|
+ sym_cnts->skip[i][0],
|
|
+ sym_cnts->skip[i][1],
|
|
+ 20, 128);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_is_inter_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++)
|
|
+ probs->is_inter[i] = adapt_prob(probs->is_inter[i],
|
|
+ sym_cnts->inter[i][0],
|
|
+ sym_cnts->inter[i][1],
|
|
+ 20, 128);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_comp_mode_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++)
|
|
+ probs->comp_mode[i] = adapt_prob(probs->comp_mode[i],
|
|
+ sym_cnts->comp[i][0],
|
|
+ sym_cnts->comp[i][1],
|
|
+ 20, 128);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_comp_ref_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++)
|
|
+ probs->comp_ref[i] = adapt_prob(probs->comp_ref[i],
|
|
+ sym_cnts->comp_ref[i][0],
|
|
+ sym_cnts->comp_ref[i][1],
|
|
+ 20, 128);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_single_ref_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) {
|
|
+ u8 *p = probs->single_ref[i];
|
|
+
|
|
+ p[0] = adapt_prob(p[0], sym_cnts->single_ref[i][0][0],
|
|
+ sym_cnts->single_ref[i][0][1], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], sym_cnts->single_ref[i][1][0],
|
|
+ sym_cnts->single_ref[i][1][1], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_partition_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->partition); i++) {
|
|
+ const u32 *c = sym_cnts->partition[i];
|
|
+ u8 *p = probs->partition[i];
|
|
+
|
|
+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128);
|
|
+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_tx_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) {
|
|
+ u8 *p16x16 = probs->tx16[i];
|
|
+ u8 *p32x32 = probs->tx32[i];
|
|
+ const u32 *c16 = sym_cnts->tx16p[i];
|
|
+ const u32 *c32 = sym_cnts->tx32p[i];
|
|
+ const u32 *c8 = sym_cnts->tx8p[i];
|
|
+ u8 *p8x8 = probs->tx8[i];
|
|
+
|
|
+ p8x8[0] = adapt_prob(p8x8[0], c8[0], c8[1], 20, 128);
|
|
+ p16x16[0] = adapt_prob(p16x16[0], c16[0], c16[1] + c16[2],
|
|
+ 20, 128);
|
|
+ p16x16[1] = adapt_prob(p16x16[1], c16[1], c16[2], 20, 128);
|
|
+ p32x32[0] = adapt_prob(p32x32[0], c32[0],
|
|
+ c32[1] + c32[2] + c32[3], 20, 128);
|
|
+ p32x32[1] = adapt_prob(p32x32[1], c32[1], c32[2] + c32[3],
|
|
+ 20, 128);
|
|
+ p32x32[2] = adapt_prob(p32x32[2], c32[2], c32[3], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_interp_filter_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) {
|
|
+ u8 *p = probs->interp_filter[i];
|
|
+ const u32 *c = sym_cnts->filter[i];
|
|
+
|
|
+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[1], c[2], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_inter_mode_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) {
|
|
+ const u32 *c = sym_cnts->mv_mode[i];
|
|
+ u8 *p = probs->inter_mode[i];
|
|
+
|
|
+ p[0] = adapt_prob(p[0], c[2], c[1] + c[0] + c[3], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[0], c[1] + c[3], 20, 128);
|
|
+ p[2] = adapt_prob(p[2], c[1], c[3], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_mv_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts,
|
|
+ bool high_prec_mv)
|
|
+{
|
|
+ const u32 *c = sym_cnts->mv_joint;
|
|
+ u8 *p = probs->mv.joint;
|
|
+ unsigned int i, j;
|
|
+ u32 sum;
|
|
+
|
|
+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128);
|
|
+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) {
|
|
+ p = probs->mv.sign;
|
|
+
|
|
+ p[i] = adapt_prob(p[i], sym_cnts->sign[i][0],
|
|
+ sym_cnts->sign[i][1], 20, 128);
|
|
+
|
|
+ p = probs->mv.class[i];
|
|
+ c = sym_cnts->classes[i];
|
|
+ sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] +
|
|
+ c[9] + c[10];
|
|
+ p[0] = adapt_prob(p[0], c[0], sum, 20, 128);
|
|
+ sum -= c[1];
|
|
+ p[1] = adapt_prob(p[1], c[1], sum, 20, 128);
|
|
+ sum -= c[2] + c[3];
|
|
+ p[2] = adapt_prob(p[2], c[2] + c[3], sum, 20, 128);
|
|
+ p[3] = adapt_prob(p[3], c[2], c[3], 20, 128);
|
|
+ sum -= c[4] + c[5];
|
|
+ p[4] = adapt_prob(p[4], c[4] + c[5], sum, 20, 128);
|
|
+ p[5] = adapt_prob(p[5], c[4], c[5], 20, 128);
|
|
+ sum -= c[6];
|
|
+ p[6] = adapt_prob(p[6], c[6], sum, 20, 128);
|
|
+ p[7] = adapt_prob(p[7], c[7] + c[8], c[9] + c[10], 20, 128);
|
|
+ p[8] = adapt_prob(p[8], c[7], c[8], 20, 128);
|
|
+ p[9] = adapt_prob(p[9], c[9], c[10], 20, 128);
|
|
+
|
|
+ p = probs->mv.class0_bit;
|
|
+ p[i] = adapt_prob(p[i],
|
|
+ sym_cnts->class0[i][0],
|
|
+ sym_cnts->class0[i][1], 20, 128);
|
|
+
|
|
+ p = probs->mv.bits[i];
|
|
+ for (j = 0; j < 10; j++)
|
|
+ p[j] = adapt_prob(p[j], sym_cnts->bits[i][j][0],
|
|
+ sym_cnts->bits[i][j][1], 20, 128);
|
|
+
|
|
+ for (j = 0; j < 2; j++) {
|
|
+ p = probs->mv.class0_fr[i][j];
|
|
+ c = sym_cnts->class0_fp[i][j];
|
|
+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3],
|
|
+ 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128);
|
|
+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128);
|
|
+ }
|
|
+
|
|
+ p = probs->mv.fr[i];
|
|
+ c = sym_cnts->fp[i];
|
|
+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128);
|
|
+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128);
|
|
+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128);
|
|
+
|
|
+ if (!high_prec_mv)
|
|
+ continue;
|
|
+
|
|
+ p = probs->mv.class0_hp;
|
|
+ p[i] = adapt_prob(p[i], sym_cnts->class0_hp[i][0],
|
|
+ sym_cnts->class0_hp[i][1], 20, 128);
|
|
+
|
|
+ p = probs->mv.hp;
|
|
+ p[i] = adapt_prob(p[i], sym_cnts->hp[i][0],
|
|
+ sym_cnts->hp[i][1], 20, 128);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_intra_mode_probs(u8 *p, const u32 *c)
|
|
+{
|
|
+ u32 sum = 0, s2;
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = V4L2_VP9_INTRA_PRED_MODE_V; i <= V4L2_VP9_INTRA_PRED_MODE_TM;
|
|
+ i++)
|
|
+ sum += c[i];
|
|
+
|
|
+ p[0] = adapt_prob(p[0], c[V4L2_VP9_INTRA_PRED_MODE_DC], sum, 20, 128);
|
|
+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_TM];
|
|
+ p[1] = adapt_prob(p[1], c[V4L2_VP9_INTRA_PRED_MODE_TM], sum, 20, 128);
|
|
+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_V];
|
|
+ p[2] = adapt_prob(p[2], c[V4L2_VP9_INTRA_PRED_MODE_V], sum, 20, 128);
|
|
+ s2 = c[V4L2_VP9_INTRA_PRED_MODE_H] + c[V4L2_VP9_INTRA_PRED_MODE_D135] +
|
|
+ c[V4L2_VP9_INTRA_PRED_MODE_D117];
|
|
+ sum -= s2;
|
|
+ p[3] = adapt_prob(p[3], s2, sum, 20, 128);
|
|
+ s2 -= c[V4L2_VP9_INTRA_PRED_MODE_H];
|
|
+ p[4] = adapt_prob(p[4], c[V4L2_VP9_INTRA_PRED_MODE_H], s2, 20, 128);
|
|
+ p[5] = adapt_prob(p[5], c[V4L2_VP9_INTRA_PRED_MODE_D135],
|
|
+ c[V4L2_VP9_INTRA_PRED_MODE_D117], 20, 128);
|
|
+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D45];
|
|
+ p[6] = adapt_prob(p[6], c[V4L2_VP9_INTRA_PRED_MODE_D45],
|
|
+ sum, 20, 128);
|
|
+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D63];
|
|
+ p[7] = adapt_prob(p[7], c[V4L2_VP9_INTRA_PRED_MODE_D63], sum,
|
|
+ 20, 128);
|
|
+ p[8] = adapt_prob(p[8], c[V4L2_VP9_INTRA_PRED_MODE_D153],
|
|
+ c[V4L2_VP9_INTRA_PRED_MODE_D207], 20, 128);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_y_intra_mode_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++)
|
|
+ adapt_intra_mode_probs(probs->y_mode[i], sym_cnts->y_mode[i]);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_uv_intra_mode_probs(struct v4l2_vp9_probabilities *probs,
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(probs->uv_mode); i++)
|
|
+ adapt_intra_mode_probs(probs->uv_mode[i],
|
|
+ sym_cnts->uv_mode[i]);
|
|
+}
|
|
+
|
|
+static void
|
|
+adapt_inter_frame_probs(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs;
|
|
+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts;
|
|
+
|
|
+ sym_cnts = vp9_ctx->count_tbl.cpu;
|
|
+ /* coefficients */
|
|
+ if (vp9_ctx->last.valid &&
|
|
+ !(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME))
|
|
+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112);
|
|
+ else
|
|
+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 128);
|
|
+
|
|
+ /* skip flag */
|
|
+ adapt_skip_probs(probs, sym_cnts);
|
|
+
|
|
+ /* intra/inter flag */
|
|
+ adapt_is_inter_probs(probs, sym_cnts);
|
|
+
|
|
+ /* comppred flag */
|
|
+ adapt_comp_mode_probs(probs, sym_cnts);
|
|
+
|
|
+ /* reference frames */
|
|
+ adapt_comp_ref_probs(probs, sym_cnts);
|
|
+
|
|
+ if (vp9_ctx->cur.reference_mode != V4L2_VP9_REF_MODE_COMPOUND)
|
|
+ adapt_single_ref_probs(probs, sym_cnts);
|
|
+
|
|
+ /* block partitioning */
|
|
+ adapt_partition_probs(probs, sym_cnts);
|
|
+
|
|
+ /* tx size */
|
|
+ if (vp9_ctx->cur.tx_mode == V4L2_VP9_TX_MODE_SELECT)
|
|
+ adapt_tx_probs(probs, sym_cnts);
|
|
+
|
|
+ /* interpolation filter */
|
|
+ if (vp9_ctx->cur.interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE)
|
|
+ adapt_interp_filter_probs(probs, sym_cnts);
|
|
+
|
|
+ /* inter modes */
|
|
+ adapt_inter_mode_probs(probs, sym_cnts);
|
|
+
|
|
+ /* mv probs */
|
|
+ adapt_mv_probs(probs, sym_cnts,
|
|
+ !!(vp9_ctx->cur.flags &
|
|
+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV));
|
|
+
|
|
+ /* y intra modes */
|
|
+ adapt_y_intra_mode_probs(probs, sym_cnts);
|
|
+
|
|
+ /* uv intra modes */
|
|
+ adapt_uv_intra_mode_probs(probs, sym_cnts);
|
|
+}
|
|
+
|
|
+static void adapt_probs(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ bool intra_only;
|
|
+
|
|
+ intra_only = !!(vp9_ctx->cur.flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME |
|
|
+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
|
|
+
|
|
+ if (intra_only)
|
|
+ adapt_intra_frame_probs(ctx);
|
|
+ else
|
|
+ adapt_inter_frame_probs(ctx);
|
|
+}
|
|
+
|
|
+static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
|
|
+ struct vb2_v4l2_buffer *src_buf,
|
|
+ struct vb2_v4l2_buffer *dst_buf,
|
|
+ enum vb2_buffer_state result)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct v4l2_ctrl *ctrl;
|
|
+ unsigned int fctx_idx;
|
|
+
|
|
+ if (result == VB2_BUF_STATE_ERROR)
|
|
+ goto out_update_last;
|
|
+
|
|
+ if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX))
|
|
+ goto out_update_last;
|
|
+
|
|
+ fctx_idx = vp9_ctx->cur.frame_context_idx;
|
|
+
|
|
+ if (!(vp9_ctx->cur.flags &
|
|
+ (V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT |
|
|
+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)))
|
|
+ adapt_probs(ctx);
|
|
+
|
|
+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
|
+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(fctx_idx));
|
|
+ if (WARN_ON(!ctrl))
|
|
+ goto out_update_last;
|
|
+
|
|
+ v4l2_ctrl_s_ctrl_compound(ctrl, V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT,
|
|
+ &vp9_ctx->frame_context);
|
|
+
|
|
+out_update_last:
|
|
+ update_ctx_last_info(vp9_ctx);
|
|
+}
|
|
+
|
|
+static int rkvdec_vp9_start(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+ struct rkvdec_vp9_priv_tbl *priv_tbl;
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx;
|
|
+ u8 *count_tbl;
|
|
+ int ret;
|
|
+
|
|
+ vp9_ctx = kzalloc(sizeof(*vp9_ctx), GFP_KERNEL);
|
|
+ if (!vp9_ctx)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ ctx->priv = vp9_ctx;
|
|
+
|
|
+ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl),
|
|
+ &vp9_ctx->priv_tbl.dma, GFP_KERNEL);
|
|
+ if (!priv_tbl) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free_ctx;
|
|
+ }
|
|
+
|
|
+ vp9_ctx->priv_tbl.size = sizeof(*priv_tbl);
|
|
+ vp9_ctx->priv_tbl.cpu = priv_tbl;
|
|
+ memset(priv_tbl, 0, sizeof(*priv_tbl));
|
|
+
|
|
+ count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE,
|
|
+ &vp9_ctx->count_tbl.dma, GFP_KERNEL);
|
|
+ if (!count_tbl) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free_priv_tbl;
|
|
+ }
|
|
+
|
|
+ vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE;
|
|
+ vp9_ctx->count_tbl.cpu = count_tbl;
|
|
+ memset(count_tbl, 0, sizeof(*count_tbl));
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_free_priv_tbl:
|
|
+ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size,
|
|
+ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma);
|
|
+
|
|
+err_free_ctx:
|
|
+ kfree(vp9_ctx);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx)
|
|
+{
|
|
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
|
|
+ struct rkvdec_dev *rkvdec = ctx->dev;
|
|
+
|
|
+ dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size,
|
|
+ vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma);
|
|
+ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size,
|
|
+ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma);
|
|
+ kfree(vp9_ctx);
|
|
+}
|
|
+
|
|
+static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx,
|
|
+ struct v4l2_format *f)
|
|
+{
|
|
+ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
|
|
+
|
|
+ fmt->num_planes = 1;
|
|
+ if (!fmt->plane_fmt[0].sizeimage)
|
|
+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops = {
|
|
+ .adjust_fmt = rkvdec_vp9_adjust_fmt,
|
|
+ .start = rkvdec_vp9_start,
|
|
+ .stop = rkvdec_vp9_stop,
|
|
+ .run = rkvdec_vp9_run,
|
|
+ .done = rkvdec_vp9_done,
|
|
+};
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 91f8a1bb6176..f0f28f6a68cf 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -159,6 +159,45 @@ static const u32 rkvdec_h264_decoded_fmts[] = {
|
|
V4L2_PIX_FMT_NV20,
|
|
};
|
|
|
|
+static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = {
|
|
+ {
|
|
+ .per_request = true,
|
|
+ .mandatory = true,
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS,
|
|
+ },
|
|
+ {
|
|
+ .mandatory = true,
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0),
|
|
+ },
|
|
+ {
|
|
+ .mandatory = true,
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1),
|
|
+ },
|
|
+ {
|
|
+ .mandatory = true,
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2),
|
|
+ },
|
|
+ {
|
|
+ .mandatory = true,
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3),
|
|
+ },
|
|
+ {
|
|
+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
|
|
+ .cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
|
|
+ .cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
|
|
+ .cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct rkvdec_ctrls rkvdec_vp9_ctrls = {
|
|
+ .ctrls = rkvdec_vp9_ctrl_descs,
|
|
+ .num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs),
|
|
+};
|
|
+
|
|
+static const u32 rkvdec_vp9_decoded_fmts[] = {
|
|
+ V4L2_PIX_FMT_NV12,
|
|
+};
|
|
+
|
|
static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
|
|
{
|
|
.fourcc = V4L2_PIX_FMT_H264_SLICE,
|
|
@@ -174,6 +213,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
|
|
.ops = &rkvdec_h264_fmt_ops,
|
|
.num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts),
|
|
.decoded_fmts = rkvdec_h264_decoded_fmts,
|
|
+ },
|
|
+ {
|
|
+ .fourcc = V4L2_PIX_FMT_VP9_FRAME,
|
|
+ .frmsize = {
|
|
+ .min_width = 64,
|
|
+ .max_width = 4096,
|
|
+ .step_width = 64,
|
|
+ .min_height = 64,
|
|
+ .max_height = 2304,
|
|
+ .step_height = 64,
|
|
+ },
|
|
+ .ctrls = &rkvdec_vp9_ctrls,
|
|
+ .ops = &rkvdec_vp9_fmt_ops,
|
|
+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts),
|
|
+ .decoded_fmts = rkvdec_vp9_decoded_fmts,
|
|
}
|
|
};
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
|
|
index e95c52e3168a..5f66f07acac5 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.h
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.h
|
|
@@ -51,6 +51,10 @@ struct rkvdec_vp9_decoded_buffer_info {
|
|
struct rkvdec_decoded_buffer {
|
|
/* Must be the first field in this struct. */
|
|
struct v4l2_m2m_buffer base;
|
|
+
|
|
+ union {
|
|
+ struct rkvdec_vp9_decoded_buffer_info vp9;
|
|
+ };
|
|
};
|
|
|
|
static inline struct rkvdec_decoded_buffer *
|
|
@@ -119,4 +123,6 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
|
|
void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
|
|
|
|
extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops;
|
|
+extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops;
|
|
+
|
|
#endif /* RKVDEC_H_ */
|