From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFBAC27A460; Wed, 22 Oct 2025 16:25:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150337; cv=none; b=WKGYt6Usu2ACajEfhWsUV/rTMLQ1elIayI7Fw8i7KuG0qOd51eCAYD3Jwl4xzm4K14XwjaNOwmQAJPRwL5sDDSLSZ7SIV/4OfUKWTEOLQwE19BEmEanoyDYPJGDif95pscl0wFrImuEBF33+uoH0mXu9cJnKFZMZinp/GglpxCA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150337; c=relaxed/simple; bh=uZrk9JWJFC8HDnxfKG1U0mihNvLZ+BbEwtxVUkBNzwY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ASsil50/hhLhIwD/dFgI0DtYu7vxElXmvecMh7qmShA3D0xwSE9c5JsAnrproHKZ2sJ/TlTGcFuzggXu0xkXPgEIzSgiNEFra2PK+NAgaAnuaTVzhRqJ2p+LeXPcl8bxYPSJFLfrkeLoxFKO60gwC0WBNm9fPuZHftWAry1QdKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=TpPMu1m8; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="TpPMu1m8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150333; bh=uZrk9JWJFC8HDnxfKG1U0mihNvLZ+BbEwtxVUkBNzwY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TpPMu1m8mkVyi8eEHPRjk+cyRR5sPjX5YXJ+RjPlrhCQvfNbS4B6COCObbhzZqpwp /qCo1XSf2paCm7bOukWIilqQvOd0M3AM2E1POEOGUyJxCFPDCzaVzviRQOaHx6YM1x +4ksKCmlM8FZf4gwQPXzeaUQcUee1IW3Ewf32XLj70ZZm5FIDKIy5wnp6f9x5zeKlc LrKj9ZajFrA0QLYDAqKPv//d5UtK+P2JL1/q8tuTG6F31U0H2UoZLaFHs4oExh5b3m tOsW7+xLRtHNjQY4hWi3GVxbeLXpkgFIkvU1ylZgl8BONwfekVueTisJbqGhjYWAHr MiYLw9x+WEjiw== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id BF93017E1404; Wed, 22 Oct 2025 18:25:30 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne Subject: [PATCH v3 01/15] media: uapi: HEVC: Add v4l2_ctrl_hevc_ext_sps_[ls]t_rps controls Date: Wed, 22 Oct 2025 12:22:00 -0400 Message-ID: <20251022162459.271603-2-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some hardware (e.g.: Rockchip's rk3588 hevc decoder) need the long and short term reference information for HEVC decoding. Add controls to provide it as the raw data form the stream. Signed-off-by: Detlev Casanova --- .../media/v4l/ext-ctrls-codec-stateless.rst | 114 ++++++++++++++++++ .../media/v4l/videodev2.h.rst.exceptions | 2 + .../media/v4l/vidioc-queryctrl.rst | 12 ++ 3 files changed, 128 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateles= s.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst index 0da635691fdc..bb6772cf3cee 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -2958,6 +2958,120 @@ This structure contains all loop filter related par= ameters. See sections - 0x00000004 - =20 +``V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS (struct)`` + Specifies the list of Long-Term reference sets parameters from the SPS. + These parameters are defined according to :ref:`hevc`. + They are described in section 7.4.3.2.1 "General sequence parameter set + RBSP semantics" of the specification. + This control is a dynamically sized 1-dimensional array, + V4L2_CTRL_FLAG_DYNAMIC_ARRAY flag must be set when using it. + +.. c:type:: v4l2_ctrl_hevc_ext_sps_lt_rps + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_ctrl_hevc_ext_sps_lt_rps + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u16 + - ``lt_ref_pic_poc_lsb_sps`` + - Long term reference picture order count as described in section 7.= 4.3.2.1 + "General sequence parameter set RBSP semantics" of the specificati= on. + * - __u8 + - ``flags`` + - See :ref:`Extended Long-Term RPS Flags ` + +.. _hevc_ext_sps_lt_rps_flags: + +``Extended SPS Long-Term RPS Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT`` + - 0x00000001 + - Specifies if the long-term reference picture is used 7.4.3.2.1 "Ge= neral sequence parameter + set RBSP semantics" of the specification. + +``V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS (struct)`` + Specifies the list of Short-Term reference sets parameters from the SP= S. + These parameters are defined according to :ref:`hevc`. + They are described in section 7.4.8 "Short-term reference picture set + semantics" of the specification. + This control is a dynamically sized 1-dimensional array, + V4L2_CTRL_FLAG_DYNAMIC_ARRAY flag must be set when using it. + +.. c:type:: v4l2_ctrl_hevc_ext_sps_st_rps + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_ctrl_hevc_ext_sps_st_rps + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``delta_idx_minus1`` + - Specifies the delta compare to the index. See details in section 7= .4.8 "Short-term + reference picture set semantics" of the specification. + * - __u8 + - ``delta_rps_sign`` + - Sign of the delta as specified in section 7.4.8 "Short-term refere= nce picture set + semantics" of the specification. + * - __u16 + - ``abs_delta_rps_minus1`` + - Absolute delta RPS as specified in section 7.4.8 "Short-term refer= ence picture set + semantics" of the specification. + * - __u8 + - ``num_negative_pics`` + - Number of short-term RPS entries that have picture order count val= ues less than the + picture order count value of the current picture. + * - __u8 + - ``num_positive_pics`` + - Number of short-term RPS entries that have picture order count val= ues greater than the + picture order count value of the current picture. + * - __u32 + - ``used_by_curr_pic`` + - Bit i specifies if short-term RPS i is used by the current picture. + * - __u32 + - ``use_delta_flag`` + - Bit i specifies if short-term RPS i is included in the short-term = RPS entries. + * - __u16 + - ``delta_poc_s0_minus1[16]`` + - Specifies the negative picture order count delta for the i-th entr= y in the short-term RPS. + See details in section 7.4.8 "Short-term reference picture set sem= antics" of the + specification. + * - __u16 + - ``delta_poc_s1_minus1[16]`` + - Specifies the positive picture order count delta for the i-th entr= y in the short-term RPS. + See details in section 7.4.8 "Short-term reference picture set sem= antics" of the + specification. + * - __u8 + - ``flags`` + - See :ref:`Extended Short-Term RPS Flags ` + +.. _hevc_ext_sps_st_rps_flags: + +``Extended SPS Short-Term RPS Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED`` + - 0x00000001 + - Specifies if the short-term RPS is predicted from another short te= rm RPS. See details in + section 7.4.8 "Short-term reference picture set semantics" of the = specification. + .. _v4l2-codec-stateless-av1: =20 ``V4L2_CID_STATELESS_AV1_SEQUENCE (struct)`` diff --git a/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptio= ns b/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions index 35d3456cc812..1663fdf8444c 100644 --- a/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions @@ -149,6 +149,8 @@ replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:typ= e:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_RECT :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_FWHT_PARAMS :c:type:`v4l2_ctrl_type` diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/D= ocumentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 3549417c7feb..128c044d2e3c 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -523,6 +523,18 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_ctrl_hevc_decode_params`, containing HEVC decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_hevc_ext_sps_lt_rps`, containing HEVC + extended Long-Term RPS for stateless video decoders. + * - ``V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_hevc_ext_sps_st_rps`, containing HEVC + extended Short-Term RPS for stateless video decoders. * - ``V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR`` - n/a - n/a --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 788052C3250; Wed, 22 Oct 2025 16:25:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150339; cv=none; b=nTE59JlP7VnPZHtJ6XVrg3dvne+dkuju8k1f0Q46CSwtuk5Zi/Ax73tDJd9zJCXL9jtxJQLRp3q+P8aIpLW3Qlm3OOyv94cZez2hebK3PUsXdvKjB2c8nkcL0OVcZ4gijuFb5KPNpyE70hoGNK4XuK1nnuimbJ+xm3DsEb5JJPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150339; c=relaxed/simple; bh=8TPyLAtUMFtqS9KVgtAyW3Gq/jSbs7fpIu+ZB1512g0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FMw3aohxy61WIBSabwTXanEKdo/LRE5nNnQdfE/64DhNtHtTehcJwBwAdbU9y7McuNeiH8W7GHWFxtG47SQJubIB0ioVljQE2TrjIpmO1UHoTC8UmW8OsVrK9/Rw4tr5dNYOqVGKiZpmLOOpOvYHiQYPvZ0DPy9N/r6S76wxhPg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=dXxX2aot; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="dXxX2aot" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150335; bh=8TPyLAtUMFtqS9KVgtAyW3Gq/jSbs7fpIu+ZB1512g0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dXxX2aotyr8cnyivFCPpapUgvW6F6E5Ap8BJvQkz1A/QWbhC1tfaEiuT7vQ4x/hog GGlnWmgRatOdY/S2uf746DPqFRfh/yvyJrmjoIKbwZeQMbv+J5dqavbU4ItugdPzEX kD/epH55+NJRCOAbL561JPFF52T2oi/KHpeeqrFPX3Tw+SeAD8R0Glh7nGCsWnUeqD FGgPWSNaFMwcIIUhPdyeWjFdEZ7bj2NAyT3C2NSlsmmcOth5fkk6PMBdy7o9U7zPPU pVWJPnoeD8Ygvi49jBFcoP+9qCCGPfTz97kAvWN7Gwlghl8vne39QE6giTm4OF3EUw Ahl1yQSTCluOQ== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 65B8F17E1407; Wed, 22 Oct 2025 18:25:33 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne Subject: [PATCH v3 02/15] media: v4l2-ctrls: Add hevc_ext_sps_[ls]t_rps controls Date: Wed, 22 Oct 2025 12:22:01 -0400 Message-ID: <20251022162459.271603-3-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The vdpu381 decoder found on newer Rockchip SoC need the information from the long term and short term ref pic sets from the SPS. So far, it wasn't included in the v4l2 API, so add it with new dynamic sized controls. Each element of the hevc_ext_sps_lt_rps array contains the long term ref pic set at that index. Each element of the hevc_ext_sps_st_rps contains the short term ref pic set at that index, as the raw data. It is the role of the drivers to calculate the reference sets values. Signed-off-by: Detlev Casanova --- drivers/media/v4l2-core/v4l2-ctrls-core.c | 18 +++++++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 10 ++++ include/uapi/linux/v4l2-controls.h | 61 +++++++++++++++++++++++ include/uapi/linux/videodev2.h | 2 + 4 files changed, 91 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2= -core/v4l2-ctrls-core.c index 85d07ef44f62..779936727505 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -418,6 +418,12 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctr= l) case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: pr_cont("HEVC_SLICE_PARAMS"); break; + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS: + pr_cont("HEVC_EXT_SPS_ST_RPS"); + break; + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS: + pr_cont("HEVC_EXT_SPS_LT_RPS"); + break; case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: pr_cont("HEVC_SCALING_MATRIX"); break; @@ -1173,6 +1179,12 @@ static int std_validate_compound(const struct v4l2_c= trl *ctrl, u32 idx, case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: break; =20 + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS: + break; + + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS: + break; + case V4L2_CTRL_TYPE_HDR10_CLL_INFO: break; =20 @@ -1925,6 +1937,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_c= trl_handler *hdl, case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: elem_size =3D sizeof(struct v4l2_ctrl_hevc_slice_params); break; + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS: + elem_size =3D sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps); + break; + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS: + elem_size =3D sizeof(struct v4l2_ctrl_hevc_ext_sps_lt_rps); + break; case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: elem_size =3D sizeof(struct v4l2_ctrl_hevc_scaling_matrix); break; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2= -core/v4l2-ctrls-defs.c index ad41f65374e2..167286c9e424 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1233,6 +1233,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return "HEVC Decode Mode"; case V4L2_CID_STATELESS_HEVC_START_CODE: return "HEVC Start Code"; case V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS: return "HEVC Entry Poin= t Offsets"; + case V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS: return "HEVC Short Term Ref= Sets"; + case V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS: return "HEVC Long Term Ref = Sets"; case V4L2_CID_STATELESS_AV1_SEQUENCE: return "AV1 Sequence Parameters"; case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: return "AV1 Tile Group Ent= ry"; case V4L2_CID_STATELESS_AV1_FRAME: return "AV1 Frame Parameters"; @@ -1578,6 +1580,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum = v4l2_ctrl_type *type, *type =3D V4L2_CTRL_TYPE_U32; *flags |=3D V4L2_CTRL_FLAG_DYNAMIC_ARRAY; break; + case V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS: + *type =3D V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS; + *flags |=3D V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; + case V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS: + *type =3D V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS; + *flags |=3D V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; case V4L2_CID_STATELESS_VP9_COMPRESSED_HDR: *type =3D V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR; break; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-c= ontrols.h index 2d30107e047e..dd9e29afa155 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -2093,6 +2093,8 @@ struct v4l2_ctrl_mpeg2_quantisation { #define V4L2_CID_STATELESS_HEVC_DECODE_MODE (V4L2_CID_CODEC_STATELESS_BASE= + 405) #define V4L2_CID_STATELESS_HEVC_START_CODE (V4L2_CID_CODEC_STATELESS_BASE = + 406) #define V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS (V4L2_CID_CODEC_STATEL= ESS_BASE + 407) +#define V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS (V4L2_CID_CODEC_STATELESS_= BASE + 408) +#define V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS (V4L2_CID_CODEC_STATELESS_= BASE + 409) =20 enum v4l2_stateless_hevc_decode_mode { V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, @@ -2548,6 +2550,65 @@ struct v4l2_ctrl_hevc_scaling_matrix { __u8 scaling_list_dc_coef_32x32[2]; }; =20 +#define V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED 0x1 + +/* + * struct v4l2_ctrl_hevc_ext_sps_st_rps - HEVC short term RPS parameters + * + * Dynamic size 1-dimension array for short term RPS. The number of elemen= ts + * is v4l2_ctrl_hevc_sps::num_short_term_ref_pic_sets. It can contain up t= o 65 elements. + * + * @delta_idx_minus1: Specifies the delta compare to the index. See detail= s in section 7.4.8 + * "Short-term reference picture set semantics" of the = specification. + * @delta_rps_sign: Sign of the delta as specified in section 7.4.8 "Short= -term reference picture + * set semantics" of the specification. + * @abs_delta_rps_minus1: Absolute delta RPS as specified in section 7.4.8= "Short-term reference + * picture set semantics" of the specification. + * @num_negative_pics: Number of short-term RPS entries that have picture = order count values less + * than the picture order count value of the current p= icture. + * @num_positive_pics: Number of short-term RPS entries that have picture = order count values + * greater than the picture order count value of the c= urrent picture. + * @used_by_curr_pic: Bit j specifies if short-term RPS j is used by the c= urrent picture. + * @use_delta_flag: Bit j equals to 1 specifies that the j-th entry in the= source candidate + * short-term RPS is included in this candidate short-ter= m RPS. + * @delta_poc_s0_minus1: Specifies the negative picture order count delta = for the i-th entry in + * the short-term RPS. See details in section 7.4.8 = "Short-term reference + * picture set semantics" of the specification. + * @delta_poc_s1_minus1: Specifies the positive picture order count delta = for the i-th entry in + * the short-term RPS. See details in section 7.4.8 = "Short-term reference + * picture set semantics" of the specification. + * @flags: See V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_{} + */ +struct v4l2_ctrl_hevc_ext_sps_st_rps { + __u8 delta_idx_minus1; + __u8 delta_rps_sign; + __u16 abs_delta_rps_minus1; + __u8 num_negative_pics; + __u8 num_positive_pics; + __u32 used_by_curr_pic; + __u32 use_delta_flag; + __u16 delta_poc_s0_minus1[16]; + __u16 delta_poc_s1_minus1[16]; + __u8 flags; +}; + +#define V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT 0x1 + +/* + * struct v4l2_ctrl_hevc_ext_sps_lt_rps - HEVC long term RPS parameters + * + * Dynamic size 1-dimension array for long term RPS. The number of elements + * is v4l2_ctrl_hevc_sps::num_long_term_ref_pics_sps. It can contain up to= 65 elements. + * + * @lt_ref_pic_poc_lsb_sps: picture order count modulo MaxPicOrderCntLsb o= f the i-th candidate + * long-term reference picture. + * @flags: See V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_{} + */ +struct v4l2_ctrl_hevc_ext_sps_lt_rps { + __u16 lt_ref_pic_poc_lsb_sps; + __u8 flags; +}; + /* Stateless VP9 controls */ =20 #define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index becd08fdbddb..ae1d33fd37b7 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1981,6 +1981,8 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS =3D 0x0272, V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX =3D 0x0273, V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS =3D 0x0274, + V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS =3D 0x0275, + V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS =3D 0x0276, =20 V4L2_CTRL_TYPE_AV1_SEQUENCE =3D 0x280, V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY =3D 0x281, --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 142242D2498; Wed, 22 Oct 2025 16:25:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150343; cv=none; b=rc5nVMvc+Sd9YNjYsUI0jjTw9rD4VWov1nZ7yfqKP6FDzV3cWzUfx861wwll41UjaOLYy6OhA1YoPL8m+jqTbzu1PDG18vrq8R3sx+UdkALRYpq04IjMzgPmWyV68VBWV1A2xIjh0l37GHZaCxB30qnainvli0/fGxp29On4l0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150343; c=relaxed/simple; bh=f2fEBCZrGOsWKvCfquS/+GiEeUzkrxlGZ7e62F4CnQQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mrG5FeDGF168aqBiQHmtgDpkhLYkSCoLsYLZzalKpLedW1Ex7vzOrw81wt4eB3wtwvWwiPw64WGV2tS5kbKEB9OJhTtQkfzh0NWlq6mnH+vLydODiVApJMCrjo2ANojYRrXYb96mmNCOPv1GsDjT4SIkqaxqA+9L5XbNy9ktzeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=UdCDSI0V; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="UdCDSI0V" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150338; bh=f2fEBCZrGOsWKvCfquS/+GiEeUzkrxlGZ7e62F4CnQQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UdCDSI0VrP3PPdAYBmKNaEYtihzx+N6HsuzPws3+7wS1X0xkgpQPrLebJ+ntbiWWc somfR4/rUgU2yr8WP5r6qRL2cqFFUBKpmT2ylbYh7zemAGJQAJR5erjonwTG5JPoFp rsrWvZfg0NQW5TQeuKZ46GeZAuyjePXlDoJ8LROvb4s4o/5jptU8n0ANdkY63sxPg8 WRfNZ8Pm+OrcQZ8OdJgb6/QjwTlw3hNjA7CPnHgRKu/pqHmZMtbSUOXUQuDyJY9MN6 PI6hDEHe2AVCJeRAyZ9WCtRMIlcgzJvALO2d+v8+m4mnqRf0F5N9wbJj8PuHN94Dia ef2fp6hUuts5w== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 11C2C17E1413; Wed, 22 Oct 2025 18:25:35 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 03/15] media: rkvdec: Switch to using structs instead of writel Date: Wed, 22 Oct 2025 12:22:02 -0400 Message-ID: <20251022162459.271603-4-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In an effort to merge the rkvdec2 driver [1] with this one, switch from writel() calls to using structs to represent the register mappings. This is done in order to have all supported decoders use the same format in the future and ease reading of the code. Using structs also improves stability as the hardware is tested and validated downstream using a similar method. It was noticed, on decoders, that: - Some registers require to be writen in increasing order [2] - Some registers, even if unrelated, need to be written to their reset values (it was the case here for axi_ddr_[rw]data). Using structs can also help improving performance later when, e.g. multicore support is added on RK3588. Performance seems to be slightly improved, but at least, not made worse. Running fluster's JVT-AVC_V1 test suite with GStreamer on the Radxa ROCK PI 4 SE gives the following times: Before this patch: - --jobs 1: Ran 129/135 tests successfully in 77.167 secs - --jobs 6: Ran 129/135 tests successfully in 23.046 secs With this patch: - --jobs 1: Ran 129/135 tests successfully in 70.698 secs - --jobs 6: Ran 129/135 tests successfully in 22.917 secs This also shows that the fluster score hasn't changed. [1]: https://lore.kernel.org/all/20250325213303.826925-1-detlev.casanova@co= llabora.com/ [2]: https://lore.kernel.org/all/20200127143009.15677-5-andrzej.p@collabora= .com/ Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../platform/rockchip/rkvdec/rkvdec-h264.c | 165 +++-- .../platform/rockchip/rkvdec/rkvdec-hevc.c | 63 +- .../platform/rockchip/rkvdec/rkvdec-regs.h | 571 ++++++++++++------ .../platform/rockchip/rkvdec/rkvdec-vp9.c | 231 +++---- .../media/platform/rockchip/rkvdec/rkvdec.c | 10 +- .../media/platform/rockchip/rkvdec/rkvdec.h | 1 + 6 files changed, 587 insertions(+), 454 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-h264.c index d14b4d173448..116e7b1076b7 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c @@ -115,6 +115,7 @@ struct rkvdec_h264_run { struct rkvdec_h264_ctx { struct rkvdec_aux_buf priv_tbl; struct rkvdec_h264_reflists reflists; + struct rkvdec_regs regs; }; =20 #define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \ @@ -841,45 +842,41 @@ static void assemble_hw_scaling_list(struct rkvdec_ct= x *ctx, } =20 /* - * dpb poc related registers table + * Set the ref POC in the correct register. + * + * The 32 registers are spread across 3 regions, each alternating top and = bottom ref POCs: + * - 1: ref 0 to 14 contain top 0 to 7 and bottoms 0 to 6 + * - 2: ref 15 to 29 contain top 8 to 14 and bottoms 7 to 14 + * - 3: ref 30 and 31 which correspond to top 15 and bottom 15 respective= ly. */ -static const u32 poc_reg_tbl_top_field[16] =3D { - RKVDEC_REG_H264_POC_REFER0(0), - RKVDEC_REG_H264_POC_REFER0(2), - RKVDEC_REG_H264_POC_REFER0(4), - RKVDEC_REG_H264_POC_REFER0(6), - RKVDEC_REG_H264_POC_REFER0(8), - RKVDEC_REG_H264_POC_REFER0(10), - RKVDEC_REG_H264_POC_REFER0(12), - RKVDEC_REG_H264_POC_REFER0(14), - RKVDEC_REG_H264_POC_REFER1(1), - RKVDEC_REG_H264_POC_REFER1(3), - RKVDEC_REG_H264_POC_REFER1(5), - RKVDEC_REG_H264_POC_REFER1(7), - RKVDEC_REG_H264_POC_REFER1(9), - RKVDEC_REG_H264_POC_REFER1(11), - RKVDEC_REG_H264_POC_REFER1(13), - RKVDEC_REG_H264_POC_REFER2(0) -}; - -static const u32 poc_reg_tbl_bottom_field[16] =3D { - RKVDEC_REG_H264_POC_REFER0(1), - RKVDEC_REG_H264_POC_REFER0(3), - RKVDEC_REG_H264_POC_REFER0(5), - RKVDEC_REG_H264_POC_REFER0(7), - RKVDEC_REG_H264_POC_REFER0(9), - RKVDEC_REG_H264_POC_REFER0(11), - RKVDEC_REG_H264_POC_REFER0(13), - RKVDEC_REG_H264_POC_REFER1(0), - RKVDEC_REG_H264_POC_REFER1(2), - RKVDEC_REG_H264_POC_REFER1(4), - RKVDEC_REG_H264_POC_REFER1(6), - RKVDEC_REG_H264_POC_REFER1(8), - RKVDEC_REG_H264_POC_REFER1(10), - RKVDEC_REG_H264_POC_REFER1(12), - RKVDEC_REG_H264_POC_REFER1(14), - RKVDEC_REG_H264_POC_REFER2(1) -}; +static void set_poc_reg(struct rkvdec_regs *regs, uint32_t poc, int id, bo= ol bottom) +{ + if (!bottom) { + switch (id) { + case 0 ... 7: + regs->h26x.ref0_14_poc[id * 2] =3D poc; + break; + case 8 ... 14: + regs->h26x.ref15_29_poc[(id - 8) * 2 + 1] =3D poc; + break; + case 15: + regs->h26x.ref30_poc =3D poc; + break; + } + } else { + switch (id) { + case 0 ... 6: + regs->h26x.ref0_14_poc[id * 2 + 1] =3D poc; + break; + case 7 ... 14: + regs->h26x.ref15_29_poc[(id - 7) * 2] =3D poc; + break; + case 15: + regs->h26x.ref31_poc =3D poc; + break; + } + } +} =20 static void config_registers(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run) @@ -894,6 +891,7 @@ static void config_registers(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; const struct v4l2_format *f; + struct rkvdec_regs *regs =3D &h264_ctx->regs; dma_addr_t rlc_addr; dma_addr_t refer_addr; u32 rlc_len; @@ -903,10 +901,11 @@ static void config_registers(struct rkvdec_ctx *ctx, u32 yuv_virstride =3D 0; u32 offset; dma_addr_t dst_addr; - u32 reg, i; + u32 i; =20 - reg =3D RKVDEC_MODE(RKVDEC_MODE_H264); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL); + memset(regs, 0, sizeof(*regs)); + + regs->common.reg02.dec_mode =3D RKVDEC_MODE_H264; =20 f =3D &ctx->decoded_fmt; dst_fmt =3D &f->fmt.pix_mp; @@ -921,39 +920,35 @@ static void config_registers(struct rkvdec_ctx *ctx, else if (sps->chroma_format_idc =3D=3D 2) yuv_virstride =3D 2 * y_virstride; =20 - reg =3D RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) | - RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) | - RKVDEC_SLICE_NUM_HIGHBIT | - RKVDEC_SLICE_NUM_LOWBITS(0x7ff); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR); + regs->common.reg03.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg03.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg03.slice_num_highbit =3D 1; + regs->common.reg03.slice_num_lowbits =3D 0x7ff; =20 /* config rlc base address */ rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); - writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); - writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_RLCWRITE_BASE); + regs->common.strm_rlc_base =3D rlc_addr; + regs->h26x.rlcwrite_base =3D rlc_addr; =20 rlc_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); - reg =3D RKVDEC_STRM_LEN(rlc_len); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN); + regs->common.stream_len =3D rlc_len; =20 /* config cabac table */ offset =3D offsetof(struct rkvdec_h264_priv_tbl, cabac_table); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); + regs->common.cabactbl_base =3D priv_start_addr + offset; =20 /* config output base address */ dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); - writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); + regs->common.decout_base =3D dst_addr; =20 - reg =3D RKVDEC_Y_VIRSTRIDE(y_virstride / 16); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); + regs->common.reg08.y_virstride =3D y_virstride / 16; =20 - reg =3D RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); + regs->common.reg09.yuv_virstride =3D yuv_virstride / 16; =20 /* config ref pic address & poc */ for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { struct vb2_buffer *vb_buf =3D run->ref_buf[i]; + struct ref_base *base; =20 /* * If a DPB entry is unused or invalid, address of current destination @@ -963,54 +958,36 @@ static void config_registers(struct rkvdec_ctx *ctx, vb_buf =3D &dst_buf->vb2_buf; refer_addr =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); =20 - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) - refer_addr |=3D RKVDEC_COLMV_USED_FLAG_REF; - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD) - refer_addr |=3D RKVDEC_FIELD_REF; - - if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF) - refer_addr |=3D RKVDEC_TOPFIELD_USED_REF; - if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) - refer_addr |=3D RKVDEC_BOTFIELD_USED_REF; - - writel_relaxed(dpb[i].top_field_order_cnt, - rkvdec->regs + poc_reg_tbl_top_field[i]); - writel_relaxed(dpb[i].bottom_field_order_cnt, - rkvdec->regs + poc_reg_tbl_bottom_field[i]); - if (i < V4L2_H264_NUM_DPB_ENTRIES - 1) - writel_relaxed(refer_addr, - rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i)); + base =3D ®s->h26x.ref0_14_base[i]; else - writel_relaxed(refer_addr, - rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15); - } + base =3D ®s->h26x.ref15_base; =20 - reg =3D RKVDEC_CUR_POC(dec_params->top_field_order_cnt); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); + base->field_ref =3D !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD); + base->colmv_used_flag_ref =3D !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG= _ACTIVE); + base->topfield_used_ref =3D !!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF); + base->botfield_used_ref =3D !!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_RE= F); + base->base_addr =3D refer_addr >> 4; =20 - reg =3D RKVDEC_CUR_POC(dec_params->bottom_field_order_cnt); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC1); + set_poc_reg(regs, dpb[i].top_field_order_cnt, i, false); + set_poc_reg(regs, dpb[i].bottom_field_order_cnt, i, true); + } + + regs->h26x.cur_poc =3D dec_params->top_field_order_cnt; + regs->h26x.cur_poc1 =3D dec_params->bottom_field_order_cnt; =20 /* config hw pps address */ offset =3D offsetof(struct rkvdec_h264_priv_tbl, param_set); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_PPS_BASE); + regs->h26x.pps_base =3D priv_start_addr + offset; =20 /* config hw rps address */ offset =3D offsetof(struct rkvdec_h264_priv_tbl, rps); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_RPS_BASE); - - reg =3D RKVDEC_AXI_DDR_RDATA(0); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA); - - reg =3D RKVDEC_AXI_DDR_WDATA(0); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA); + regs->h26x.rps_base =3D priv_start_addr + offset; =20 offset =3D offsetof(struct rkvdec_h264_priv_tbl, err_info); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_H264_ERRINFO_BASE); + regs->h26x.errorinfo_base =3D priv_start_addr + offset; + + rkvdec_memcpy_toio(rkvdec->regs, regs, MIN(sizeof(*regs), 4 * rkvdec->var= iant->num_regs)); } =20 #define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2 @@ -1181,8 +1158,6 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) =20 schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); =20 - writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); - writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E); writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); =20 diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-hevc.c index fc7e6a260b0a..01f92fa27356 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -129,6 +129,7 @@ struct rkvdec_hevc_run { struct rkvdec_hevc_ctx { struct rkvdec_aux_buf priv_tbl; struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; + struct rkvdec_regs regs; }; =20 struct scaling_factor { @@ -548,6 +549,7 @@ static void config_registers(struct rkvdec_ctx *ctx, const struct v4l2_ctrl_hevc_slice_params *sl_params =3D &run->slices_para= ms[0]; const struct v4l2_hevc_dpb_entry *dpb =3D decode_params->dpb; struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_regs *regs =3D &hevc_ctx->regs; dma_addr_t priv_start_addr =3D hevc_ctx->priv_tbl.dma; const struct v4l2_pix_format_mplane *dst_fmt; struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; @@ -564,8 +566,9 @@ static void config_registers(struct rkvdec_ctx *ctx, dma_addr_t dst_addr; u32 reg, i; =20 - reg =3D RKVDEC_MODE(RKVDEC_MODE_HEVC); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL); + memset(regs, 0, sizeof(*regs)); + + regs->common.reg02.dec_mode =3D RKVDEC_MODE_HEVC; =20 f =3D &ctx->decoded_fmt; dst_fmt =3D &f->fmt.pix_mp; @@ -580,33 +583,27 @@ static void config_registers(struct rkvdec_ctx *ctx, else if (sps->chroma_format_idc =3D=3D 2) yuv_virstride =3D 2 * y_virstride; =20 - reg =3D RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) | - RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) | - RKVDEC_SLICE_NUM_LOWBITS(run->num_slices); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR); + regs->common.reg03.slice_num_lowbits =3D run->num_slices; + regs->common.reg03.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg03.y_hor_virstride =3D hor_virstride / 16; =20 /* config rlc base address */ rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); - writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); + regs->common.strm_rlc_base =3D rlc_addr; =20 rlc_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); - reg =3D RKVDEC_STRM_LEN(round_up(rlc_len, 16) + 64); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN); + regs->common.stream_len =3D round_up(rlc_len, 16) + 64; =20 /* config cabac table */ offset =3D offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); + regs->common.cabactbl_base =3D priv_start_addr + offset; =20 /* config output base address */ dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); - writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); - - reg =3D RKVDEC_Y_VIRSTRIDE(y_virstride / 16); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); + regs->common.decout_base =3D dst_addr; =20 - reg =3D RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); + regs->common.reg08.y_virstride =3D y_virstride / 16; + regs->common.reg09.yuv_virstride =3D yuv_virstride / 16; =20 /* config ref pic address */ for (i =3D 0; i < 15; i++) { @@ -620,33 +617,29 @@ static void config_registers(struct rkvdec_ctx *ctx, } =20 refer_addr =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); - writel_relaxed(refer_addr | reg, - rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i)); =20 - reg =3D RKVDEC_POC_REFER(i < decode_params->num_active_dpb_entries ? - dpb[i].pic_order_cnt_val : 0); - writel_relaxed(reg, - rkvdec->regs + RKVDEC_REG_H264_POC_REFER0(i)); + regs->h26x.ref0_14_base[i].base_addr =3D refer_addr >> 4; + regs->h26x.ref0_14_base[i].field_ref =3D !!(reg & 1); + regs->h26x.ref0_14_base[i].topfield_used_ref =3D !!(reg & 2); + regs->h26x.ref0_14_base[i].botfield_used_ref =3D !!(reg & 4); + regs->h26x.ref0_14_base[i].colmv_used_flag_ref =3D !!(reg & 8); + + regs->h26x.ref0_14_poc[i] =3D i < decode_params->num_active_dpb_entries + ? dpb[i].pic_order_cnt_val + : 0; } =20 - reg =3D RKVDEC_CUR_POC(sl_params->slice_pic_order_cnt); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); + regs->h26x.cur_poc =3D sl_params->slice_pic_order_cnt; =20 /* config hw pps address */ offset =3D offsetof(struct rkvdec_hevc_priv_tbl, param_set); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_PPS_BASE); + regs->h26x.pps_base =3D priv_start_addr + offset; =20 /* config hw rps address */ offset =3D offsetof(struct rkvdec_hevc_priv_tbl, rps); - writel_relaxed(priv_start_addr + offset, - rkvdec->regs + RKVDEC_REG_RPS_BASE); - - reg =3D RKVDEC_AXI_DDR_RDATA(0); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA); + regs->h26x.rps_base =3D priv_start_addr + offset; =20 - reg =3D RKVDEC_AXI_DDR_WDATA(0); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA); + rkvdec_memcpy_toio(rkvdec->regs, regs, MIN(sizeof(*regs), 4 * rkvdec->var= iant->num_regs)); } =20 #define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 @@ -784,8 +777,6 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) =20 schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); =20 - writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); - writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E); writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); =20 diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h b/drivers= /media/platform/rockchip/rkvdec/rkvdec-regs.h index c627b6b6f53a..7745ea257148 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h @@ -3,7 +3,12 @@ #ifndef RKVDEC_REGS_H_ #define RKVDEC_REGS_H_ =20 -/* rkvcodec registers */ +#include + +/* + * REG_INTERRUPT is accessed via writel to enable the decoder after + * configuring it and clear interrupt strmd_error_status + */ #define RKVDEC_REG_INTERRUPT 0x004 #define RKVDEC_INTERRUPT_DEC_E BIT(0) #define RKVDEC_CONFIG_DEC_CLK_GATE_E BIT(1) @@ -30,198 +35,384 @@ #define RKVDEC_SOFTRESET_RDY BIT(22) #define RKVDEC_WR_DDR_ALIGN_EN BIT(23) =20 -#define RKVDEC_REG_SYSCTRL 0x008 -#define RKVDEC_IN_ENDIAN BIT(0) -#define RKVDEC_IN_SWAP32_E BIT(1) -#define RKVDEC_IN_SWAP64_E BIT(2) -#define RKVDEC_STR_ENDIAN BIT(3) -#define RKVDEC_STR_SWAP32_E BIT(4) -#define RKVDEC_STR_SWAP64_E BIT(5) -#define RKVDEC_OUT_ENDIAN BIT(6) -#define RKVDEC_OUT_SWAP32_E BIT(7) -#define RKVDEC_OUT_CBCR_SWAP BIT(8) -#define RKVDEC_RLC_MODE_DIRECT_WRITE BIT(10) -#define RKVDEC_RLC_MODE BIT(11) -#define RKVDEC_STRM_START_BIT(x) (((x) & 0x7f) << 12) -#define RKVDEC_MODE(x) (((x) & 0x03) << 20) -#define RKVDEC_MODE_HEVC 0 -#define RKVDEC_MODE_H264 1 -#define RKVDEC_MODE_VP9 2 -#define RKVDEC_RPS_MODE BIT(24) -#define RKVDEC_STRM_MODE BIT(25) -#define RKVDEC_H264_STRM_LASTPKT BIT(26) -#define RKVDEC_H264_FIRSTSLICE_FLAG BIT(27) -#define RKVDEC_H264_FRAME_ORSLICE BIT(28) -#define RKVDEC_BUSPR_SLOT_DIS BIT(29) - -#define RKVDEC_REG_PICPAR 0x00C -#define RKVDEC_Y_HOR_VIRSTRIDE(x) ((x) & 0x1ff) -#define RKVDEC_SLICE_NUM_HIGHBIT BIT(11) -#define RKVDEC_UV_HOR_VIRSTRIDE(x) (((x) & 0x1ff) << 12) -#define RKVDEC_SLICE_NUM_LOWBITS(x) (((x) & 0x7ff) << 21) - -#define RKVDEC_REG_STRM_RLC_BASE 0x010 - -#define RKVDEC_REG_STRM_LEN 0x014 -#define RKVDEC_STRM_LEN(x) ((x) & 0x7ffffff) - -#define RKVDEC_REG_CABACTBL_PROB_BASE 0x018 -#define RKVDEC_REG_DECOUT_BASE 0x01C - -#define RKVDEC_REG_Y_VIRSTRIDE 0x020 -#define RKVDEC_Y_VIRSTRIDE(x) ((x) & 0xfffff) - -#define RKVDEC_REG_YUV_VIRSTRIDE 0x024 -#define RKVDEC_YUV_VIRSTRIDE(x) ((x) & 0x1fffff) -#define RKVDEC_REG_H264_BASE_REFER(i) (((i) * 0x04) + 0x028) - -#define RKVDEC_REG_H264_BASE_REFER15 0x0C0 -#define RKVDEC_FIELD_REF BIT(0) -#define RKVDEC_TOPFIELD_USED_REF BIT(1) -#define RKVDEC_BOTFIELD_USED_REF BIT(2) -#define RKVDEC_COLMV_USED_FLAG_REF BIT(3) - -#define RKVDEC_REG_VP9_LAST_FRAME_BASE 0x02c -#define RKVDEC_REG_VP9_GOLDEN_FRAME_BASE 0x030 -#define RKVDEC_REG_VP9_ALTREF_FRAME_BASE 0x034 - -#define RKVDEC_REG_VP9_CPRHEADER_OFFSET 0x028 -#define RKVDEC_VP9_CPRHEADER_OFFSET(x) ((x) & 0xffff) - -#define RKVDEC_REG_VP9_REFERLAST_BASE 0x02C -#define RKVDEC_REG_VP9_REFERGOLDEN_BASE 0x030 -#define RKVDEC_REG_VP9_REFERALFTER_BASE 0x034 - -#define RKVDEC_REG_VP9COUNT_BASE 0x038 -#define RKVDEC_VP9COUNT_UPDATE_EN BIT(0) - -#define RKVDEC_REG_VP9_SEGIDLAST_BASE 0x03C -#define RKVDEC_REG_VP9_SEGIDCUR_BASE 0x040 -#define RKVDEC_REG_VP9_FRAME_SIZE(i) ((i) * 0x04 + 0x044) -#define RKVDEC_VP9_FRAMEWIDTH(x) (((x) & 0xffff) << 0) -#define RKVDEC_VP9_FRAMEHEIGHT(x) (((x) & 0xffff) << 16) - -#define RKVDEC_VP9_SEGID_GRP(i) ((i) * 0x04 + 0x050) -#define RKVDEC_SEGID_ABS_DELTA(x) ((x) & 0x1) -#define RKVDEC_SEGID_FRAME_QP_DELTA_EN(x) (((x) & 0x1) << 1) -#define RKVDEC_SEGID_FRAME_QP_DELTA(x) (((x) & 0x1ff) << 2) -#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(x) (((x) & 0x1) << 11) -#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(x) (((x) & 0x7f) << 12) -#define RKVDEC_SEGID_REFERINFO_EN(x) (((x) & 0x1) << 19) -#define RKVDEC_SEGID_REFERINFO(x) (((x) & 0x03) << 20) -#define RKVDEC_SEGID_FRAME_SKIP_EN(x) (((x) & 0x1) << 22) - -#define RKVDEC_VP9_CPRHEADER_CONFIG 0x070 -#define RKVDEC_VP9_TX_MODE(x) ((x) & 0x07) -#define RKVDEC_VP9_FRAME_REF_MODE(x) (((x) & 0x03) << 3) - -#define RKVDEC_VP9_REF_SCALE(i) ((i) * 0x04 + 0x074) -#define RKVDEC_VP9_REF_HOR_SCALE(x) ((x) & 0xffff) -#define RKVDEC_VP9_REF_VER_SCALE(x) (((x) & 0xffff) << 16) - -#define RKVDEC_VP9_REF_DELTAS_LASTFRAME 0x080 -#define RKVDEC_REF_DELTAS_LASTFRAME(pos, val) (((val) & 0x7f) << ((pos) *= 7)) - -#define RKVDEC_VP9_INFO_LASTFRAME 0x084 -#define RKVDEC_MODE_DELTAS_LASTFRAME(pos, val) (((val) & 0x7f) << ((pos) = * 7)) -#define RKVDEC_SEG_EN_LASTFRAME BIT(16) -#define RKVDEC_LAST_SHOW_FRAME BIT(17) -#define RKVDEC_LAST_INTRA_ONLY BIT(18) -#define RKVDEC_LAST_WIDHHEIGHT_EQCUR BIT(19) -#define RKVDEC_COLOR_SPACE_LASTKEYFRAME(x) (((x) & 0x07) << 20) - -#define RKVDEC_VP9_INTERCMD_BASE 0x088 - -#define RKVDEC_VP9_INTERCMD_NUM 0x08C -#define RKVDEC_INTERCMD_NUM(x) ((x) & 0xffffff) - -#define RKVDEC_VP9_LASTTILE_SIZE 0x090 -#define RKVDEC_LASTTILE_SIZE(x) ((x) & 0xffffff) - -#define RKVDEC_VP9_HOR_VIRSTRIDE(i) ((i) * 0x04 + 0x094) -#define RKVDEC_HOR_Y_VIRSTRIDE(x) ((x) & 0x1ff) -#define RKVDEC_HOR_UV_VIRSTRIDE(x) (((x) & 0x1ff) << 16) - -#define RKVDEC_REG_H264_POC_REFER0(i) (((i) * 0x04) + 0x064) -#define RKVDEC_REG_H264_POC_REFER1(i) (((i) * 0x04) + 0x0C4) -#define RKVDEC_REG_H264_POC_REFER2(i) (((i) * 0x04) + 0x120) -#define RKVDEC_POC_REFER(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_CUR_POC0 0x0A0 -#define RKVDEC_REG_CUR_POC1 0x128 -#define RKVDEC_CUR_POC(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_RLCWRITE_BASE 0x0A4 -#define RKVDEC_REG_PPS_BASE 0x0A8 -#define RKVDEC_REG_RPS_BASE 0x0AC - -#define RKVDEC_REG_STRMD_ERR_EN 0x0B0 -#define RKVDEC_STRMD_ERR_EN(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_STRMD_ERR_STA 0x0B4 -#define RKVDEC_STRMD_ERR_STA(x) ((x) & 0xfffffff) -#define RKVDEC_COLMV_ERR_REF_PICIDX(x) (((x) & 0x0f) << 28) - -#define RKVDEC_REG_STRMD_ERR_CTU 0x0B8 -#define RKVDEC_STRMD_ERR_CTU(x) ((x) & 0xff) -#define RKVDEC_STRMD_ERR_CTU_YOFFSET(x) (((x) & 0xff) << 8) -#define RKVDEC_STRMFIFO_SPACE2FULL(x) (((x) & 0x7f) << 16) -#define RKVDEC_VP9_ERR_EN_CTU0 BIT(24) - -#define RKVDEC_REG_SAO_CTU_POS 0x0BC -#define RKVDEC_SAOWR_XOFFSET(x) ((x) & 0x1ff) -#define RKVDEC_SAOWR_YOFFSET(x) (((x) & 0x3ff) << 16) - -#define RKVDEC_VP9_LAST_FRAME_YSTRIDE 0x0C0 -#define RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE 0x0C4 -#define RKVDEC_VP9_ALTREF_FRAME_YSTRIDE 0x0C8 -#define RKVDEC_VP9_REF_YSTRIDE(x) (((x) & 0xfffff) << 0) - -#define RKVDEC_VP9_LAST_FRAME_YUVSTRIDE 0x0CC -#define RKVDEC_VP9_REF_YUVSTRIDE(x) (((x) & 0x1fffff) << 0) - -#define RKVDEC_VP9_REF_COLMV_BASE 0x0D0 - -#define RKVDEC_REG_PERFORMANCE_CYCLE 0x100 -#define RKVDEC_PERFORMANCE_CYCLE(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_AXI_DDR_RDATA 0x104 -#define RKVDEC_AXI_DDR_RDATA(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_AXI_DDR_WDATA 0x108 -#define RKVDEC_AXI_DDR_WDATA(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_FPGADEBUG_RESET 0x10C -#define RKVDEC_BUSIFD_RESETN BIT(0) -#define RKVDEC_CABAC_RESETN BIT(1) -#define RKVDEC_DEC_CTRL_RESETN BIT(2) -#define RKVDEC_TRANSD_RESETN BIT(3) -#define RKVDEC_INTRA_RESETN BIT(4) -#define RKVDEC_INTER_RESETN BIT(5) -#define RKVDEC_RECON_RESETN BIT(6) -#define RKVDEC_FILER_RESETN BIT(7) - -#define RKVDEC_REG_PERFORMANCE_SEL 0x110 -#define RKVDEC_PERF_SEL_CNT0(x) ((x) & 0x3f) -#define RKVDEC_PERF_SEL_CNT1(x) (((x) & 0x3f) << 8) -#define RKVDEC_PERF_SEL_CNT2(x) (((x) & 0x3f) << 16) - -#define RKVDEC_REG_PERFORMANCE_CNT(i) ((i) * 0x04 + 0x114) -#define RKVDEC_PERF_CNT(x) ((x) & 0xffffffff) - -#define RKVDEC_REG_H264_ERRINFO_BASE 0x12C - -#define RKVDEC_REG_H264_ERRINFO_NUM 0x130 -#define RKVDEC_SLICEDEC_NUM(x) ((x) & 0x3fff) -#define RKVDEC_STRMD_DECT_ERR_FLAG BIT(15) -#define RKVDEC_ERR_PKT_NUM(x) (((x) & 0x3fff) << 16) - -#define RKVDEC_REG_H264_ERR_E 0x134 -#define RKVDEC_H264_ERR_EN_HIGHBITS(x) ((x) & 0x3fffffff) - #define RKVDEC_REG_QOS_CTRL 0x18C =20 +/* + * Cache configuration is not covered in the range of the register struct + */ #define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND 0x410 #define RKVDEC_REG_PREF_CHR_CACHE_COMMAND 0x450 =20 +/* + * Define the mode values + */ +#define RKVDEC_MODE_HEVC 0 +#define RKVDEC_MODE_H264 1 +#define RKVDEC_MODE_VP9 2 + +/* rkvcodec registers */ +struct rkvdec_common_regs { + struct rkvdec_id { + u32 minor_ver : 8; + u32 level : 1; + u32 dec_support : 3; + u32 profile : 1; + u32 reserved0 : 1; + u32 codec_flag : 1; + u32 reserved1 : 1; + u32 prod_num : 16; + } reg00; + + struct rkvdec_int { + u32 dec_e : 1; + u32 dec_clkgate_e : 1; + u32 reserved0 : 1; + u32 timeout_mode : 1; + u32 dec_irq_dis : 1; + u32 dec_timeout_e : 1; + u32 buf_empty_en : 1; + u32 stmerror_waitdecfifo_empty : 1; + u32 dec_irq : 1; + u32 dec_irq_raw : 1; + u32 reserved2 : 2; + u32 dec_rdy_sta : 1; + u32 dec_bus_sta : 1; + u32 dec_error_sta : 1; + u32 dec_timeout_sta : 1; + u32 dec_empty_sta : 1; + u32 colmv_ref_error_sta : 1; + u32 cabu_end_sta : 1; + u32 h264orvp9_error_mode : 1; + u32 softrst_en_p : 1; + u32 force_softreset_valid : 1; + u32 softreset_rdy : 1; + u32 reserved1 : 9; + } reg01; + + struct rkvdec_sysctrl { + u32 in_endian : 1; + u32 in_swap32_e : 1; + u32 in_swap64_e : 1; + u32 str_endian : 1; + u32 str_swap32_e : 1; + u32 str_swap64_e : 1; + u32 out_endian : 1; + u32 out_swap32_e : 1; + u32 out_cbcr_swap : 1; + u32 reserved0 : 1; + u32 rlc_mode_direct_write : 1; + u32 rlc_mode : 1; + u32 strm_start_bit : 7; + u32 reserved1 : 1; + u32 dec_mode : 2; + u32 reserved2 : 2; + u32 rps_mode : 1; + u32 stream_mode : 1; + u32 stream_lastpacket : 1; + u32 firstslice_flag : 1; + u32 frame_orslice : 1; + u32 buspr_slot_disable : 1; + u32 reserved3 : 2; + } reg02; + + struct rkvdec_picpar { + u32 y_hor_virstride : 9; + u32 reserved : 2; + u32 slice_num_highbit : 1; + u32 uv_hor_virstride : 9; + u32 slice_num_lowbits : 11; + } reg03; + + u32 strm_rlc_base; + u32 stream_len; + u32 cabactbl_base; + u32 decout_base; + + struct rkvdec_y_virstride { + u32 y_virstride : 20; + u32 reserved0 : 12; + } reg08; + + struct rkvdec_yuv_virstride { + u32 yuv_virstride : 21; + u32 reserved0 : 11; + } reg09; +} __packed; + +struct ref_base { + u32 field_ref : 1; + u32 topfield_used_ref : 1; + u32 botfield_used_ref : 1; + u32 colmv_used_flag_ref : 1; + u32 base_addr : 28; +}; + +struct rkvdec_h26x_regs { + struct ref_base ref0_14_base[15]; + u32 ref0_14_poc[15]; + + u32 cur_poc; + u32 rlcwrite_base; + u32 pps_base; + u32 rps_base; + + u32 strmd_error_e; + + struct { + u32 strmd_error_status : 28; + u32 colmv_error_ref_picidx : 4; + } reg45; + + struct { + u32 strmd_error_ctu_xoffset : 8; + u32 strmd_error_ctu_yoffset : 8; + u32 streamfifo_space2full : 7; + u32 reserved0 : 1; + u32 vp9_error_ctu0_en : 1; + u32 reserved1 : 7; + } reg46; + + struct { + u32 saowr_xoffet : 9; + u32 reserved0 : 7; + u32 saowr_yoffset : 10; + u32 reserved1 : 6; + } reg47; + + struct ref_base ref15_base; + + u32 ref15_29_poc[15]; + + u32 performance_cycle; + u32 axi_ddr_rdata; + u32 axi_ddr_wdata; + + struct { + u32 busifd_resetn : 1; + u32 cabac_resetn : 1; + u32 dec_ctrl_resetn : 1; + u32 transd_resetn : 1; + u32 intra_resetn : 1; + u32 inter_resetn : 1; + u32 recon_resetn : 1; + u32 filer_resetn : 1; + u32 reserved0 : 24; + } reg67; + + struct { + u32 perf_cnt0_sel : 6; + u32 reserved0 : 2; + u32 perf_cnt1_sel : 6; + u32 reserved1 : 2; + u32 perf_cnt2_sel : 6; + u32 reserved2 : 10; + } reg68; + + u32 perf_cnt0; + u32 perf_cnt1; + u32 perf_cnt2; + u32 ref30_poc; + u32 ref31_poc; + u32 cur_poc1; + u32 errorinfo_base; + + struct { + u32 slicedec_num : 14; + u32 reserved0 : 1; + u32 strmd_detect_error_flag : 1; + u32 error_packet_num : 14; + u32 reserved1 : 2; + } reg76; + + struct { + u32 error_en_highbits : 30; + u32 reserved : 2; + } reg77; +} __packed; + +struct rkvdec_vp9_regs { + struct cprheader_offset { + u32 cprheader_offset : 16; + u32 reserved : 16; + } reg10; + + u32 refer_bases[3]; + u32 count_base; + u32 segidlast_base; + u32 segidcur_base; + + struct frame_sizes { + u32 framewidth : 16; + u32 frameheight : 16; + } reg17_19[3]; + + struct segid_grp { + u32 segid_abs_delta : 1; + u32 segid_frame_qp_delta_en : 1; + u32 segid_frame_qp_delta : 9; + u32 segid_frame_loopfilter_value_en : 1; + u32 segid_frame_loopfilter_value : 7; + u32 segid_referinfo_en : 1; + u32 segid_referinfo : 2; + u32 segid_frame_skip_en : 1; + u32 reserved : 9; + } reg20_27[8]; + + struct cprheader_config { + u32 tx_mode : 3; + u32 frame_reference_mode : 2; + u32 reserved : 27; + } reg28; + + struct ref_scale { + u32 ref_hor_scale : 16; + u32 ref_ver_scale : 16; + } reg29_31[3]; + + struct ref_deltas_lastframe { + u32 ref_deltas_lastframe0 : 7; + u32 ref_deltas_lastframe1 : 7; + u32 ref_deltas_lastframe2 : 7; + u32 ref_deltas_lastframe3 : 7; + u32 reserved : 4; + } reg32; + + struct info_lastframe { + u32 mode_deltas_lastframe0 : 7; + u32 mode_deltas_lastframe1 : 7; + u32 reserved0 : 2; + u32 segmentation_enable_lstframe : 1; + u32 last_show_frame : 1; + u32 last_intra_only : 1; + u32 last_widthheight_eqcur : 1; + u32 color_space_lastkeyframe : 3; + u32 reserved1 : 9; + } reg33; + + u32 intercmd_base; + + struct intercmd_num { + u32 intercmd_num : 24; + u32 reserved : 8; + } reg35; + + struct lasttile_size { + u32 lasttile_size : 24; + u32 reserved : 8; + } reg36; + + struct hor_virstride { + u32 y_hor_virstride : 9; + u32 reserved0 : 7; + u32 uv_hor_virstride : 9; + u32 reserved1 : 7; + } reg37_39[3]; + + u32 cur_poc; + + struct rlcwrite_base { + u32 reserved : 3; + u32 rlcwrite_base : 29; + } reg41; + + struct pps_base { + u32 reserved : 4; + u32 pps_base : 28; + } reg42; + + struct rps_base { + u32 reserved : 4; + u32 rps_base : 28; + } reg43; + + struct strmd_error_en { + u32 strmd_error_e : 28; + u32 reserved : 4; + } reg44; + + u32 vp9_error_info0; + + struct strmd_error_ctu { + u32 strmd_error_ctu_xoffset : 8; + u32 strmd_error_ctu_yoffset : 8; + u32 streamfifo_space2full : 7; + u32 reserved0 : 1; + u32 error_ctu0_en : 1; + u32 reserved1 : 7; + } reg46; + + struct sao_ctu_position { + u32 saowr_xoffet : 9; + u32 reserved0 : 7; + u32 saowr_yoffset : 10; + u32 reserved1 : 6; + } reg47; + + struct ystride { + u32 virstride : 20; + u32 reserved : 12; + } reg48_50[3]; + + struct lastref_yuvstride { + u32 lastref_yuv_virstride : 21; + u32 reserved : 11; + } reg51; + + u32 refcolmv_base; + + u32 reserved0[11]; + + u32 performance_cycle; + u32 axi_ddr_rdata; + u32 axi_ddr_wdata; + + struct fpgadebug_reset { + u32 busifd_resetn : 1; + u32 cabac_resetn : 1; + u32 dec_ctrl_resetn : 1; + u32 transd_resetn : 1; + u32 intra_resetn : 1; + u32 inter_resetn : 1; + u32 recon_resetn : 1; + u32 filer_resetn : 1; + u32 reserved : 24; + } reg67; + + struct performance_sel { + u32 perf_cnt0_sel : 6; + u32 reserved0 : 2; + u32 perf_cnt1_sel : 6; + u32 reserved1 : 2; + u32 perf_cnt2_sel : 6; + u32 reserved : 10; + } reg68; + + u32 perf_cnt0; + u32 perf_cnt1; + u32 perf_cnt2; + + u32 reserved1[3]; + + u32 vp9_error_info1; + + struct error_ctu1 { + u32 vp9_error_ctu1_x : 6; + u32 reserved0 : 2; + u32 vp9_error_ctu1_y : 6; + u32 reserved1 : 1; + u32 vp9_error_ctu1_en : 1; + u32 reserved2 : 16; + } reg76; + + u32 reserved2; +} __packed; + +struct rkvdec_regs { + struct rkvdec_common_regs common; + union { + struct rkvdec_h26x_regs h26x; + struct rkvdec_vp9_regs vp9; + }; +} __packed; + #endif /* RKVDEC_REGS_H_ */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c b/drivers/= media/platform/rockchip/rkvdec/rkvdec-vp9.c index b4bf01e839ef..0cf5a559701c 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c @@ -163,6 +163,7 @@ struct rkvdec_vp9_ctx { struct v4l2_vp9_frame_context frame_context[4]; struct rkvdec_vp9_frame_info cur; struct rkvdec_vp9_frame_info last; + struct rkvdec_regs regs; }; =20 static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) @@ -347,38 +348,6 @@ static void init_probs(struct rkvdec_ctx *ctx, init_inter_probs(ctx, run); } =20 -struct rkvdec_vp9_ref_reg { - u32 reg_frm_size; - u32 reg_hor_stride; - u32 reg_y_stride; - u32 reg_yuv_stride; - u32 reg_ref_base; -}; - -static struct rkvdec_vp9_ref_reg ref_regs[] =3D { - { - .reg_frm_size =3D RKVDEC_REG_VP9_FRAME_SIZE(0), - .reg_hor_stride =3D RKVDEC_VP9_HOR_VIRSTRIDE(0), - .reg_y_stride =3D RKVDEC_VP9_LAST_FRAME_YSTRIDE, - .reg_yuv_stride =3D RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, - .reg_ref_base =3D RKVDEC_REG_VP9_LAST_FRAME_BASE, - }, - { - .reg_frm_size =3D RKVDEC_REG_VP9_FRAME_SIZE(1), - .reg_hor_stride =3D RKVDEC_VP9_HOR_VIRSTRIDE(1), - .reg_y_stride =3D RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, - .reg_yuv_stride =3D 0, - .reg_ref_base =3D RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, - }, - { - .reg_frm_size =3D RKVDEC_REG_VP9_FRAME_SIZE(2), - .reg_hor_stride =3D RKVDEC_VP9_HOR_VIRSTRIDE(2), - .reg_y_stride =3D RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, - .reg_yuv_stride =3D 0, - .reg_ref_base =3D RKVDEC_REG_VP9_ALTREF_FRAME_BASE, - } -}; - static struct rkvdec_decoded_buffer * get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 times= tamp) { @@ -412,18 +381,17 @@ static dma_addr_t get_mv_base_addr(struct rkvdec_deco= ded_buffer *buf) static void config_ref_registers(struct rkvdec_ctx *ctx, const struct rkvdec_vp9_run *run, struct rkvdec_decoded_buffer *ref_buf, - struct rkvdec_vp9_ref_reg *ref_reg) + int i) { unsigned int aligned_pitch, aligned_height, y_len, yuv_len; - struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_vp9_ctx *vp9_ctx =3D ctx->priv; + struct rkvdec_regs *regs =3D &vp9_ctx->regs; =20 aligned_height =3D round_up(ref_buf->vp9.height, 64); - writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) | - RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height), - rkvdec->regs + ref_reg->reg_frm_size); + regs->vp9.reg17_19[i].frameheight =3D ref_buf->vp9.height; + regs->vp9.reg17_19[i].framewidth =3D ref_buf->vp9.width; =20 - writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0= ), - rkvdec->regs + ref_reg->reg_ref_base); + regs->vp9.refer_bases[i] =3D vb2_dma_contig_plane_dma_addr(&ref_buf->base= .vb.vb2_buf, 0); =20 if (&ref_buf->base.vb =3D=3D run->base.bufs.dst) return; @@ -432,59 +400,50 @@ static void config_ref_registers(struct rkvdec_ctx *c= tx, y_len =3D aligned_height * aligned_pitch; yuv_len =3D (y_len * 3) / 2; =20 - writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | - RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), - rkvdec->regs + ref_reg->reg_hor_stride); - writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), - rkvdec->regs + ref_reg->reg_y_stride); - - if (!ref_reg->reg_yuv_stride) - return; + regs->vp9.reg37_39[i].y_hor_virstride =3D aligned_pitch / 16; + regs->vp9.reg37_39[i].uv_hor_virstride =3D aligned_pitch / 16; + regs->vp9.reg48_50[i].virstride =3D y_len / 16; =20 - writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), - rkvdec->regs + ref_reg->reg_yuv_stride); + if (!i) + regs->vp9.reg51.lastref_yuv_virstride =3D yuv_len / 16; } =20 static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segi= d) { struct rkvdec_vp9_ctx *vp9_ctx =3D ctx->priv; + struct rkvdec_regs *regs =3D &vp9_ctx->regs; const struct v4l2_vp9_segmentation *seg; - struct rkvdec_dev *rkvdec =3D ctx->dev; s16 feature_val; int feature_id; - u32 val =3D 0; =20 seg =3D vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; feature_id =3D V4L2_VP9_SEG_LVL_ALT_Q; if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { feature_val =3D seg->feature_data[segid][feature_id]; - val |=3D RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | - RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); + regs->vp9.reg20_27[segid].segid_frame_qp_delta_en =3D 1; + regs->vp9.reg20_27[segid].segid_frame_qp_delta =3D feature_val; } =20 feature_id =3D V4L2_VP9_SEG_LVL_ALT_L; if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { feature_val =3D seg->feature_data[segid][feature_id]; - val |=3D RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | - RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); + regs->vp9.reg20_27[segid].segid_frame_loopfilter_value_en =3D 1; + regs->vp9.reg20_27[segid].segid_frame_loopfilter_value =3D feature_val; } =20 feature_id =3D V4L2_VP9_SEG_LVL_REF_FRAME; if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { feature_val =3D seg->feature_data[segid][feature_id]; - val |=3D RKVDEC_SEGID_REFERINFO_EN(1) | - RKVDEC_SEGID_REFERINFO(feature_val); + regs->vp9.reg20_27[segid].segid_referinfo_en =3D 1; + regs->vp9.reg20_27[segid].segid_referinfo =3D feature_val; } =20 feature_id =3D V4L2_VP9_SEG_LVL_SKIP; - if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) - val |=3D RKVDEC_SEGID_FRAME_SKIP_EN(1); - - if (!segid && - (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) - val |=3D RKVDEC_SEGID_ABS_DELTA(1); + regs->vp9.reg20_27[segid].segid_frame_skip_en =3D + v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid); =20 - writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); + regs->vp9.reg20_27[segid].segid_abs_delta =3D !segid && + (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE); } =20 static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf, @@ -521,7 +480,8 @@ static void config_registers(struct rkvdec_ctx *ctx, struct rkvdec_decoded_buffer *ref_bufs[3]; struct rkvdec_decoded_buffer *dst, *last, *mv_ref; struct rkvdec_vp9_ctx *vp9_ctx =3D ctx->priv; - u32 val, last_frame_info =3D 0; + struct rkvdec_regs *regs =3D &vp9_ctx->regs; + u32 val; const struct v4l2_vp9_segmentation *seg; struct rkvdec_dev *rkvdec =3D ctx->dev; dma_addr_t addr; @@ -547,8 +507,7 @@ static void config_registers(struct rkvdec_ctx *ctx, (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); =20 - writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), - rkvdec->regs + RKVDEC_REG_SYSCTRL); + regs->common.reg02.dec_mode =3D RKVDEC_MODE_VP9; =20 bit_depth =3D dec_params->bit_depth; aligned_height =3D round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); @@ -560,17 +519,14 @@ static void config_registers(struct rkvdec_ctx *ctx, uv_len =3D y_len / 2; yuv_len =3D y_len + uv_len; =20 - 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); + regs->common.reg03.y_hor_virstride =3D aligned_pitch / 16; + regs->common.reg03.uv_hor_virstride =3D aligned_pitch / 16; + regs->common.reg08.y_virstride =3D y_len / 16; + regs->common.reg09.yuv_virstride =3D yuv_len / 16; =20 stream_len =3D vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); - writel_relaxed(RKVDEC_STRM_LEN(stream_len), - rkvdec->regs + RKVDEC_REG_STRM_LEN); + + regs->common.stream_len =3D stream_len; =20 /* * Reset count buffer, because decoder only output intra related syntax @@ -588,14 +544,13 @@ static void config_registers(struct rkvdec_ctx *ctx, vp9_ctx->cur.segmapid++; =20 for (i =3D 0; i < ARRAY_SIZE(ref_bufs); i++) - config_ref_registers(ctx, run, ref_bufs[i], &ref_regs[i]); + config_ref_registers(ctx, run, ref_bufs[i], i); =20 for (i =3D 0; i < 8; i++) config_seg_registers(ctx, i); =20 - writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) | - RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), - rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); + regs->vp9.reg28.tx_mode =3D vp9_ctx->cur.tx_mode; + regs->vp9.reg28.frame_reference_mode =3D dec_params->reference_mode; =20 if (!intra_only) { const struct v4l2_vp9_loop_filter *lf; @@ -609,43 +564,56 @@ static void config_registers(struct rkvdec_ctx *ctx, val =3D 0; for (i =3D 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { delta =3D lf->ref_deltas[i]; - val |=3D RKVDEC_REF_DELTAS_LASTFRAME(i, delta); + switch (i) { + case 0: + regs->vp9.reg32.ref_deltas_lastframe0 =3D delta; + break; + case 1: + regs->vp9.reg32.ref_deltas_lastframe1 =3D delta; + break; + case 2: + regs->vp9.reg32.ref_deltas_lastframe2 =3D delta; + break; + case 3: + regs->vp9.reg32.ref_deltas_lastframe3 =3D delta; + break; + } } =20 - writel_relaxed(val, - rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); - for (i =3D 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { delta =3D lf->mode_deltas[i]; - last_frame_info |=3D RKVDEC_MODE_DELTAS_LASTFRAME(i, - delta); + switch (i) { + case 0: + regs->vp9.reg33.mode_deltas_lastframe0 =3D delta; + break; + case 1: + regs->vp9.reg33.mode_deltas_lastframe1 =3D delta; + break; + } } } =20 - if (vp9_ctx->last.valid && !intra_only && - vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) - last_frame_info |=3D RKVDEC_SEG_EN_LASTFRAME; + regs->vp9.reg33.segmentation_enable_lstframe =3D + vp9_ctx->last.valid && !intra_only && + vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED; =20 - if (vp9_ctx->last.valid && - vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) - last_frame_info |=3D RKVDEC_LAST_SHOW_FRAME; + regs->vp9.reg33.last_show_frame =3D + vp9_ctx->last.valid && + vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME; =20 - if (vp9_ctx->last.valid && - vp9_ctx->last.flags & - (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) - last_frame_info |=3D RKVDEC_LAST_INTRA_ONLY; + regs->vp9.reg33.last_intra_only =3D + vp9_ctx->last.valid && + vp9_ctx->last.flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY); =20 - if (vp9_ctx->last.valid && - last->vp9.width =3D=3D dst->vp9.width && - last->vp9.height =3D=3D dst->vp9.height) - last_frame_info |=3D RKVDEC_LAST_WIDHHEIGHT_EQCUR; + regs->vp9.reg33.last_widthheight_eqcur =3D + vp9_ctx->last.valid && + last->vp9.width =3D=3D dst->vp9.width && + last->vp9.height =3D=3D dst->vp9.height; =20 - 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); + regs->vp9.reg36.lasttile_size =3D + stream_len - dec_params->compressed_header_size - + dec_params->uncompressed_header_size; =20 for (i =3D 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { unsigned int refw =3D ref_bufs[i]->vp9.width; @@ -654,29 +622,28 @@ static void config_registers(struct rkvdec_ctx *ctx, =20 hscale =3D (refw << 14) / dst->vp9.width; vscale =3D (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)); + + regs->vp9.reg29_31[i].ref_hor_scale =3D hscale; + regs->vp9.reg29_31[i].ref_ver_scale =3D vscale; } =20 addr =3D vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); - writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); + regs->common.decout_base =3D addr; addr =3D 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); + regs->common.strm_rlc_base =3D addr; + + regs->common.cabactbl_base =3D vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, probs); + + regs->vp9.count_base =3D vp9_ctx->count_tbl.dma; + + regs->vp9.segidlast_base =3D vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + + (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)); + + regs->vp9.segidcur_base =3D vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + + (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid); =20 if (!intra_only && !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && @@ -685,12 +652,14 @@ static void config_registers(struct rkvdec_ctx *ctx, else mv_ref =3D dst; =20 - writel_relaxed(get_mv_base_addr(mv_ref), - rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); + regs->vp9.refcolmv_base =3D get_mv_base_addr(mv_ref); =20 - writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | - (ctx->decoded_fmt.fmt.pix_mp.height << 16), - rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); + regs->vp9.performance_cycle =3D ctx->decoded_fmt.fmt.pix_mp.width | + (ctx->decoded_fmt.fmt.pix_mp.height << 16); + + regs->vp9.reg44.strmd_error_e =3D 0xe; + + rkvdec_memcpy_toio(rkvdec->regs, regs, MIN(sizeof(*regs), rkvdec->variant= ->num_regs)); } =20 static int validate_dec_params(struct rkvdec_ctx *ctx, @@ -823,8 +792,6 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); =20 - writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); - if (rkvdec->variant->quirks & RKVDEC_QUIRK_DISABLE_QOS) rkvdec_quirks_disable_qos(ctx); =20 diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 5af9aa5ab353..776149f871b0 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -914,6 +914,15 @@ void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx) writel(reg, rkvdec->regs + RKVDEC_REG_QOS_CTRL); } =20 +void rkvdec_memcpy_toio(void __iomem *dst, void *src, size_t len) +{ +#ifdef CONFIG_ARM64 + __iowrite32_copy(dst, src, len / 4); +#else + memcpy_toio(dst, src, len); +#endif +} + static void rkvdec_device_run(void *priv) { struct rkvdec_ctx *ctx =3D priv; @@ -1227,7 +1236,6 @@ static void rkvdec_watchdog_func(struct work_struct *= work) if (ctx) { dev_err(rkvdec->dev, "Frame processing timed out!\n"); writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT); - writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); } } diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 566e06fa2b1e..f35f6e80ea2e 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -151,6 +151,7 @@ struct rkvdec_aux_buf { =20 void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); +void rkvdec_memcpy_toio(void __iomem *dst, void *src, size_t len); =20 void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx); =20 --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43F4935581B; Wed, 22 Oct 2025 16:25:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150347; cv=none; b=MSWlurpuEFMoKfmdBZb81dn0wepJoe10ct5k94F0Lo2gkIYDkVo3aYKC5cErMv8EMoTwGpQ+Pr7ELipIQSw9emrA/14T15YJMoAbNi3jX2C3LnXXCnm5qjxZ3tCGvuBZzLWY9cMLeXb1fiWY2s8KdblsNZ9jinFS1xZEfw7LSQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150347; c=relaxed/simple; bh=Cs8lP4tys12ZhFtU1Od+kEGifjR6IAEPuhpSrnZ7dw8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FHYVphQqOgBAwYmfvosWMqrCbjHz0HB+77cPuV1g4JVR4Bft8uvmMbDK7kxNjnAIjW0qzASa7nOmwoG/mz/JBOjTxaGQSaMd4gt3kKF11Lern4K43KxhlJ7pFXZZg7DJW8BB9rZcwapSoDhXg0owA1YTIWDxRgcw0U28g8D+QVg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=nJ/g6UIT; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="nJ/g6UIT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150341; bh=Cs8lP4tys12ZhFtU1Od+kEGifjR6IAEPuhpSrnZ7dw8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nJ/g6UITzO6dRtOt+Px2qCU+6PdnjOYmGV9qeKrAnMfm23mWAZTjCNTPVsaizdCN+ R1GAPWHjiIGUqwrpfUHptG1RCWCItOLiBQcHi5gdICumh5U61pG420Nj5FMQWIZcEI XfSR5q8xvC9i24qvX+XGuJsF6bGbkNk9HEP2CGKHoFWhpORm22sGNXS3KvC9rhk0hh OgVGQTk4QnIbg4z33eut/VKQts42HNq0V48OTLCkNHfIRn8XltQ4RUmInD9iQjD5XS TtNK/rNncTu3iup7/lBYUgt//CeknKqa0V5beBuGaZUr1eVduwHVEeac5+/DfBT9XC fGsvHGnr+uzdw== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id EDE6017E108C; Wed, 22 Oct 2025 18:25:38 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 04/15] media: rkvdec: Move cabac tables to their own source file Date: Wed, 22 Oct 2025 12:22:03 -0400 Message-ID: <20251022162459.271603-5-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This is in preparation to add support for new variants that will use the same tables. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/Makefile | 7 +- .../{rkvdec-hevc-data.c =3D> rkvdec-cabac.c} | 506 +++++++++++++++++- .../platform/rockchip/rkvdec/rkvdec-h264.c | 501 +---------------- .../platform/rockchip/rkvdec/rkvdec-hevc.c | 6 +- 4 files changed, 514 insertions(+), 506 deletions(-) rename drivers/media/platform/rockchip/rkvdec/{rkvdec-hevc-data.c =3D> rkv= dec-cabac.c} (86%) diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index a77122641d14..a8ff5e3d7bec 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -1,3 +1,8 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) +=3D rockchip-vdec.o =20 -rockchip-vdec-y +=3D rkvdec.o rkvdec-h264.o rkvdec-hevc.o rkvdec-vp9.o +rockchip-vdec-y +=3D \ + rkvdec.o \ + rkvdec-cabac.o \ + rkvdec-h264.o \ + rkvdec-hevc.o \ + rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-data.c b/dr= ivers/media/platform/rockchip/rkvdec/rkvdec-cabac.c similarity index 86% rename from drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-data.c rename to drivers/media/platform/rockchip/rkvdec/rkvdec-cabac.c index eac4ea604949..bc87f59636ea 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-data.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-cabac.c @@ -1,19 +1,517 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Rockchip Video Decoder driver + * Rockchip Video Decoder CABAC tables * * Copyright (C) 2023 Collabora, Ltd. * Sebastian Fricke + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon */ =20 #include =20 -#define RKV_CABAC_TABLE_SIZE 27456 +#define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \ + idc2_m, idc2_n, intra_m, intra_n) \ + [0][(ctxidx)] =3D {idc0_m, idc0_n}, \ + [1][(ctxidx)] =3D {idc1_m, idc1_n}, \ + [2][(ctxidx)] =3D {idc2_m, idc2_n}, \ + [3][(ctxidx)] =3D {intra_m, intra_n} =20 /* - * This file is #include from rkvdec-hevc.c and not compiled. + * Constant CABAC table. + * Built from the tables described in section '9.3.1.1 Initialisation proc= ess + * for context variables' of the H264 spec. */ -static const u8 rkvdec_hevc_cabac_table[RKV_CABAC_TABLE_SIZE] =3D { +const s8 rkvdec_h264_cabac_table[4][464][2] =3D { + /* Table 9-12 =E2=80=93 Values of variables m and n for ctxIdx from 0 to = 10 */ + CABAC_ENTRY(0, 20, -15, 20, -15, 20, -15, 20, -15), + CABAC_ENTRY(1, 2, 54, 2, 54, 2, 54, 2, 54), + CABAC_ENTRY(2, 3, 74, 3, 74, 3, 74, 3, 74), + CABAC_ENTRY(3, 20, -15, 20, -15, 20, -15, 20, -15), + CABAC_ENTRY(4, 2, 54, 2, 54, 2, 54, 2, 54), + CABAC_ENTRY(5, 3, 74, 3, 74, 3, 74, 3, 74), + CABAC_ENTRY(6, -28, 127, -28, 127, -28, 127, -28, 127), + CABAC_ENTRY(7, -23, 104, -23, 104, -23, 104, -23, 104), + CABAC_ENTRY(8, -6, 53, -6, 53, -6, 53, -6, 53), + CABAC_ENTRY(9, -1, 54, -1, 54, -1, 54, -1, 54), + CABAC_ENTRY(10, 7, 51, 7, 51, 7, 51, 7, 51), + + /* Table 9-13 =E2=80=93 Values of variables m and n for ctxIdx from 11 to= 23 */ + CABAC_ENTRY(11, 23, 33, 22, 25, 29, 16, 0, 0), + CABAC_ENTRY(12, 23, 2, 34, 0, 25, 0, 0, 0), + CABAC_ENTRY(13, 21, 0, 16, 0, 14, 0, 0, 0), + CABAC_ENTRY(14, 1, 9, -2, 9, -10, 51, 0, 0), + CABAC_ENTRY(15, 0, 49, 4, 41, -3, 62, 0, 0), + CABAC_ENTRY(16, -37, 118, -29, 118, -27, 99, 0, 0), + CABAC_ENTRY(17, 5, 57, 2, 65, 26, 16, 0, 0), + CABAC_ENTRY(18, -13, 78, -6, 71, -4, 85, 0, 0), + CABAC_ENTRY(19, -11, 65, -13, 79, -24, 102, 0, 0), + CABAC_ENTRY(20, 1, 62, 5, 52, 5, 57, 0, 0), + CABAC_ENTRY(21, 12, 49, 9, 50, 6, 57, 0, 0), + CABAC_ENTRY(22, -4, 73, -3, 70, -17, 73, 0, 0), + CABAC_ENTRY(23, 17, 50, 10, 54, 14, 57, 0, 0), + + /* Table 9-14 =E2=80=93 Values of variables m and n for ctxIdx from 24 to= 39 */ + CABAC_ENTRY(24, 18, 64, 26, 34, 20, 40, 0, 0), + CABAC_ENTRY(25, 9, 43, 19, 22, 20, 10, 0, 0), + CABAC_ENTRY(26, 29, 0, 40, 0, 29, 0, 0, 0), + CABAC_ENTRY(27, 26, 67, 57, 2, 54, 0, 0, 0), + CABAC_ENTRY(28, 16, 90, 41, 36, 37, 42, 0, 0), + CABAC_ENTRY(29, 9, 104, 26, 69, 12, 97, 0, 0), + CABAC_ENTRY(30, -46, 127, -45, 127, -32, 127, 0, 0), + CABAC_ENTRY(31, -20, 104, -15, 101, -22, 117, 0, 0), + CABAC_ENTRY(32, 1, 67, -4, 76, -2, 74, 0, 0), + CABAC_ENTRY(33, -13, 78, -6, 71, -4, 85, 0, 0), + CABAC_ENTRY(34, -11, 65, -13, 79, -24, 102, 0, 0), + CABAC_ENTRY(35, 1, 62, 5, 52, 5, 57, 0, 0), + CABAC_ENTRY(36, -6, 86, 6, 69, -6, 93, 0, 0), + CABAC_ENTRY(37, -17, 95, -13, 90, -14, 88, 0, 0), + CABAC_ENTRY(38, -6, 61, 0, 52, -6, 44, 0, 0), + CABAC_ENTRY(39, 9, 45, 8, 43, 4, 55, 0, 0), + + /* Table 9-15 =E2=80=93 Values of variables m and n for ctxIdx from 40 to= 53 */ + CABAC_ENTRY(40, -3, 69, -2, 69, -11, 89, 0, 0), + CABAC_ENTRY(41, -6, 81, -5, 82, -15, 103, 0, 0), + CABAC_ENTRY(42, -11, 96, -10, 96, -21, 116, 0, 0), + CABAC_ENTRY(43, 6, 55, 2, 59, 19, 57, 0, 0), + CABAC_ENTRY(44, 7, 67, 2, 75, 20, 58, 0, 0), + CABAC_ENTRY(45, -5, 86, -3, 87, 4, 84, 0, 0), + CABAC_ENTRY(46, 2, 88, -3, 100, 6, 96, 0, 0), + CABAC_ENTRY(47, 0, 58, 1, 56, 1, 63, 0, 0), + CABAC_ENTRY(48, -3, 76, -3, 74, -5, 85, 0, 0), + CABAC_ENTRY(49, -10, 94, -6, 85, -13, 106, 0, 0), + CABAC_ENTRY(50, 5, 54, 0, 59, 5, 63, 0, 0), + CABAC_ENTRY(51, 4, 69, -3, 81, 6, 75, 0, 0), + CABAC_ENTRY(52, -3, 81, -7, 86, -3, 90, 0, 0), + CABAC_ENTRY(53, 0, 88, -5, 95, -1, 101, 0, 0), + + /* Table 9-16 =E2=80=93 Values of variables m and n for ctxIdx from 54 to= 59 */ + CABAC_ENTRY(54, -7, 67, -1, 66, 3, 55, 0, 0), + CABAC_ENTRY(55, -5, 74, -1, 77, -4, 79, 0, 0), + CABAC_ENTRY(56, -4, 74, 1, 70, -2, 75, 0, 0), + CABAC_ENTRY(57, -5, 80, -2, 86, -12, 97, 0, 0), + CABAC_ENTRY(58, -7, 72, -5, 72, -7, 50, 0, 0), + CABAC_ENTRY(59, 1, 58, 0, 61, 1, 60, 0, 0), + + /* Table 9-17 =E2=80=93 Values of variables m and n for ctxIdx from 60 to= 69 */ + CABAC_ENTRY(60, 0, 41, 0, 41, 0, 41, 0, 41), + CABAC_ENTRY(61, 0, 63, 0, 63, 0, 63, 0, 63), + CABAC_ENTRY(62, 0, 63, 0, 63, 0, 63, 0, 63), + CABAC_ENTRY(63, 0, 63, 0, 63, 0, 63, 0, 63), + CABAC_ENTRY(64, -9, 83, -9, 83, -9, 83, -9, 83), + CABAC_ENTRY(65, 4, 86, 4, 86, 4, 86, 4, 86), + CABAC_ENTRY(66, 0, 97, 0, 97, 0, 97, 0, 97), + CABAC_ENTRY(67, -7, 72, -7, 72, -7, 72, -7, 72), + CABAC_ENTRY(68, 13, 41, 13, 41, 13, 41, 13, 41), + CABAC_ENTRY(69, 3, 62, 3, 62, 3, 62, 3, 62), + + /* Table 9-18 =E2=80=93 Values of variables m and n for ctxIdx from 70 to= 104 */ + CABAC_ENTRY(70, 0, 45, 13, 15, 7, 34, 0, 11), + CABAC_ENTRY(71, -4, 78, 7, 51, -9, 88, 1, 55), + CABAC_ENTRY(72, -3, 96, 2, 80, -20, 127, 0, 69), + CABAC_ENTRY(73, -27, 126, -39, 127, -36, 127, -17, 127), + CABAC_ENTRY(74, -28, 98, -18, 91, -17, 91, -13, 102), + CABAC_ENTRY(75, -25, 101, -17, 96, -14, 95, 0, 82), + CABAC_ENTRY(76, -23, 67, -26, 81, -25, 84, -7, 74), + CABAC_ENTRY(77, -28, 82, -35, 98, -25, 86, -21, 107), + CABAC_ENTRY(78, -20, 94, -24, 102, -12, 89, -27, 127), + CABAC_ENTRY(79, -16, 83, -23, 97, -17, 91, -31, 127), + CABAC_ENTRY(80, -22, 110, -27, 119, -31, 127, -24, 127), + CABAC_ENTRY(81, -21, 91, -24, 99, -14, 76, -18, 95), + CABAC_ENTRY(82, -18, 102, -21, 110, -18, 103, -27, 127), + CABAC_ENTRY(83, -13, 93, -18, 102, -13, 90, -21, 114), + CABAC_ENTRY(84, -29, 127, -36, 127, -37, 127, -30, 127), + CABAC_ENTRY(85, -7, 92, 0, 80, 11, 80, -17, 123), + CABAC_ENTRY(86, -5, 89, -5, 89, 5, 76, -12, 115), + CABAC_ENTRY(87, -7, 96, -7, 94, 2, 84, -16, 122), + CABAC_ENTRY(88, -13, 108, -4, 92, 5, 78, -11, 115), + CABAC_ENTRY(89, -3, 46, 0, 39, -6, 55, -12, 63), + CABAC_ENTRY(90, -1, 65, 0, 65, 4, 61, -2, 68), + CABAC_ENTRY(91, -1, 57, -15, 84, -14, 83, -15, 84), + CABAC_ENTRY(92, -9, 93, -35, 127, -37, 127, -13, 104), + CABAC_ENTRY(93, -3, 74, -2, 73, -5, 79, -3, 70), + CABAC_ENTRY(94, -9, 92, -12, 104, -11, 104, -8, 93), + CABAC_ENTRY(95, -8, 87, -9, 91, -11, 91, -10, 90), + CABAC_ENTRY(96, -23, 126, -31, 127, -30, 127, -30, 127), + CABAC_ENTRY(97, 5, 54, 3, 55, 0, 65, -1, 74), + CABAC_ENTRY(98, 6, 60, 7, 56, -2, 79, -6, 97), + CABAC_ENTRY(99, 6, 59, 7, 55, 0, 72, -7, 91), + CABAC_ENTRY(100, 6, 69, 8, 61, -4, 92, -20, 127), + CABAC_ENTRY(101, -1, 48, -3, 53, -6, 56, -4, 56), + CABAC_ENTRY(102, 0, 68, 0, 68, 3, 68, -5, 82), + CABAC_ENTRY(103, -4, 69, -7, 74, -8, 71, -7, 76), + CABAC_ENTRY(104, -8, 88, -9, 88, -13, 98, -22, 125), + + /* Table 9-19 =E2=80=93 Values of variables m and n for ctxIdx from 105 t= o 165 */ + CABAC_ENTRY(105, -2, 85, -13, 103, -4, 86, -7, 93), + CABAC_ENTRY(106, -6, 78, -13, 91, -12, 88, -11, 87), + CABAC_ENTRY(107, -1, 75, -9, 89, -5, 82, -3, 77), + CABAC_ENTRY(108, -7, 77, -14, 92, -3, 72, -5, 71), + CABAC_ENTRY(109, 2, 54, -8, 76, -4, 67, -4, 63), + CABAC_ENTRY(110, 5, 50, -12, 87, -8, 72, -4, 68), + CABAC_ENTRY(111, -3, 68, -23, 110, -16, 89, -12, 84), + CABAC_ENTRY(112, 1, 50, -24, 105, -9, 69, -7, 62), + CABAC_ENTRY(113, 6, 42, -10, 78, -1, 59, -7, 65), + CABAC_ENTRY(114, -4, 81, -20, 112, 5, 66, 8, 61), + CABAC_ENTRY(115, 1, 63, -17, 99, 4, 57, 5, 56), + CABAC_ENTRY(116, -4, 70, -78, 127, -4, 71, -2, 66), + CABAC_ENTRY(117, 0, 67, -70, 127, -2, 71, 1, 64), + CABAC_ENTRY(118, 2, 57, -50, 127, 2, 58, 0, 61), + CABAC_ENTRY(119, -2, 76, -46, 127, -1, 74, -2, 78), + CABAC_ENTRY(120, 11, 35, -4, 66, -4, 44, 1, 50), + CABAC_ENTRY(121, 4, 64, -5, 78, -1, 69, 7, 52), + CABAC_ENTRY(122, 1, 61, -4, 71, 0, 62, 10, 35), + CABAC_ENTRY(123, 11, 35, -8, 72, -7, 51, 0, 44), + CABAC_ENTRY(124, 18, 25, 2, 59, -4, 47, 11, 38), + CABAC_ENTRY(125, 12, 24, -1, 55, -6, 42, 1, 45), + CABAC_ENTRY(126, 13, 29, -7, 70, -3, 41, 0, 46), + CABAC_ENTRY(127, 13, 36, -6, 75, -6, 53, 5, 44), + CABAC_ENTRY(128, -10, 93, -8, 89, 8, 76, 31, 17), + CABAC_ENTRY(129, -7, 73, -34, 119, -9, 78, 1, 51), + CABAC_ENTRY(130, -2, 73, -3, 75, -11, 83, 7, 50), + CABAC_ENTRY(131, 13, 46, 32, 20, 9, 52, 28, 19), + CABAC_ENTRY(132, 9, 49, 30, 22, 0, 67, 16, 33), + CABAC_ENTRY(133, -7, 100, -44, 127, -5, 90, 14, 62), + CABAC_ENTRY(134, 9, 53, 0, 54, 1, 67, -13, 108), + CABAC_ENTRY(135, 2, 53, -5, 61, -15, 72, -15, 100), + CABAC_ENTRY(136, 5, 53, 0, 58, -5, 75, -13, 101), + CABAC_ENTRY(137, -2, 61, -1, 60, -8, 80, -13, 91), + CABAC_ENTRY(138, 0, 56, -3, 61, -21, 83, -12, 94), + CABAC_ENTRY(139, 0, 56, -8, 67, -21, 64, -10, 88), + CABAC_ENTRY(140, -13, 63, -25, 84, -13, 31, -16, 84), + CABAC_ENTRY(141, -5, 60, -14, 74, -25, 64, -10, 86), + CABAC_ENTRY(142, -1, 62, -5, 65, -29, 94, -7, 83), + CABAC_ENTRY(143, 4, 57, 5, 52, 9, 75, -13, 87), + CABAC_ENTRY(144, -6, 69, 2, 57, 17, 63, -19, 94), + CABAC_ENTRY(145, 4, 57, 0, 61, -8, 74, 1, 70), + CABAC_ENTRY(146, 14, 39, -9, 69, -5, 35, 0, 72), + CABAC_ENTRY(147, 4, 51, -11, 70, -2, 27, -5, 74), + CABAC_ENTRY(148, 13, 68, 18, 55, 13, 91, 18, 59), + CABAC_ENTRY(149, 3, 64, -4, 71, 3, 65, -8, 102), + CABAC_ENTRY(150, 1, 61, 0, 58, -7, 69, -15, 100), + CABAC_ENTRY(151, 9, 63, 7, 61, 8, 77, 0, 95), + CABAC_ENTRY(152, 7, 50, 9, 41, -10, 66, -4, 75), + CABAC_ENTRY(153, 16, 39, 18, 25, 3, 62, 2, 72), + CABAC_ENTRY(154, 5, 44, 9, 32, -3, 68, -11, 75), + CABAC_ENTRY(155, 4, 52, 5, 43, -20, 81, -3, 71), + CABAC_ENTRY(156, 11, 48, 9, 47, 0, 30, 15, 46), + CABAC_ENTRY(157, -5, 60, 0, 44, 1, 7, -13, 69), + CABAC_ENTRY(158, -1, 59, 0, 51, -3, 23, 0, 62), + CABAC_ENTRY(159, 0, 59, 2, 46, -21, 74, 0, 65), + CABAC_ENTRY(160, 22, 33, 19, 38, 16, 66, 21, 37), + CABAC_ENTRY(161, 5, 44, -4, 66, -23, 124, -15, 72), + CABAC_ENTRY(162, 14, 43, 15, 38, 17, 37, 9, 57), + CABAC_ENTRY(163, -1, 78, 12, 42, 44, -18, 16, 54), + CABAC_ENTRY(164, 0, 60, 9, 34, 50, -34, 0, 62), + CABAC_ENTRY(165, 9, 69, 0, 89, -22, 127, 12, 72), + + /* Table 9-20 =E2=80=93 Values of variables m and n for ctxIdx from 166 t= o 226 */ + CABAC_ENTRY(166, 11, 28, 4, 45, 4, 39, 24, 0), + CABAC_ENTRY(167, 2, 40, 10, 28, 0, 42, 15, 9), + CABAC_ENTRY(168, 3, 44, 10, 31, 7, 34, 8, 25), + CABAC_ENTRY(169, 0, 49, 33, -11, 11, 29, 13, 18), + CABAC_ENTRY(170, 0, 46, 52, -43, 8, 31, 15, 9), + CABAC_ENTRY(171, 2, 44, 18, 15, 6, 37, 13, 19), + CABAC_ENTRY(172, 2, 51, 28, 0, 7, 42, 10, 37), + CABAC_ENTRY(173, 0, 47, 35, -22, 3, 40, 12, 18), + CABAC_ENTRY(174, 4, 39, 38, -25, 8, 33, 6, 29), + CABAC_ENTRY(175, 2, 62, 34, 0, 13, 43, 20, 33), + CABAC_ENTRY(176, 6, 46, 39, -18, 13, 36, 15, 30), + CABAC_ENTRY(177, 0, 54, 32, -12, 4, 47, 4, 45), + CABAC_ENTRY(178, 3, 54, 102, -94, 3, 55, 1, 58), + CABAC_ENTRY(179, 2, 58, 0, 0, 2, 58, 0, 62), + CABAC_ENTRY(180, 4, 63, 56, -15, 6, 60, 7, 61), + CABAC_ENTRY(181, 6, 51, 33, -4, 8, 44, 12, 38), + CABAC_ENTRY(182, 6, 57, 29, 10, 11, 44, 11, 45), + CABAC_ENTRY(183, 7, 53, 37, -5, 14, 42, 15, 39), + CABAC_ENTRY(184, 6, 52, 51, -29, 7, 48, 11, 42), + CABAC_ENTRY(185, 6, 55, 39, -9, 4, 56, 13, 44), + CABAC_ENTRY(186, 11, 45, 52, -34, 4, 52, 16, 45), + CABAC_ENTRY(187, 14, 36, 69, -58, 13, 37, 12, 41), + CABAC_ENTRY(188, 8, 53, 67, -63, 9, 49, 10, 49), + CABAC_ENTRY(189, -1, 82, 44, -5, 19, 58, 30, 34), + CABAC_ENTRY(190, 7, 55, 32, 7, 10, 48, 18, 42), + CABAC_ENTRY(191, -3, 78, 55, -29, 12, 45, 10, 55), + CABAC_ENTRY(192, 15, 46, 32, 1, 0, 69, 17, 51), + CABAC_ENTRY(193, 22, 31, 0, 0, 20, 33, 17, 46), + CABAC_ENTRY(194, -1, 84, 27, 36, 8, 63, 0, 89), + CABAC_ENTRY(195, 25, 7, 33, -25, 35, -18, 26, -19), + CABAC_ENTRY(196, 30, -7, 34, -30, 33, -25, 22, -17), + CABAC_ENTRY(197, 28, 3, 36, -28, 28, -3, 26, -17), + CABAC_ENTRY(198, 28, 4, 38, -28, 24, 10, 30, -25), + CABAC_ENTRY(199, 32, 0, 38, -27, 27, 0, 28, -20), + CABAC_ENTRY(200, 34, -1, 34, -18, 34, -14, 33, -23), + CABAC_ENTRY(201, 30, 6, 35, -16, 52, -44, 37, -27), + CABAC_ENTRY(202, 30, 6, 34, -14, 39, -24, 33, -23), + CABAC_ENTRY(203, 32, 9, 32, -8, 19, 17, 40, -28), + CABAC_ENTRY(204, 31, 19, 37, -6, 31, 25, 38, -17), + CABAC_ENTRY(205, 26, 27, 35, 0, 36, 29, 33, -11), + CABAC_ENTRY(206, 26, 30, 30, 10, 24, 33, 40, -15), + CABAC_ENTRY(207, 37, 20, 28, 18, 34, 15, 41, -6), + CABAC_ENTRY(208, 28, 34, 26, 25, 30, 20, 38, 1), + CABAC_ENTRY(209, 17, 70, 29, 41, 22, 73, 41, 17), + CABAC_ENTRY(210, 1, 67, 0, 75, 20, 34, 30, -6), + CABAC_ENTRY(211, 5, 59, 2, 72, 19, 31, 27, 3), + CABAC_ENTRY(212, 9, 67, 8, 77, 27, 44, 26, 22), + CABAC_ENTRY(213, 16, 30, 14, 35, 19, 16, 37, -16), + CABAC_ENTRY(214, 18, 32, 18, 31, 15, 36, 35, -4), + CABAC_ENTRY(215, 18, 35, 17, 35, 15, 36, 38, -8), + CABAC_ENTRY(216, 22, 29, 21, 30, 21, 28, 38, -3), + CABAC_ENTRY(217, 24, 31, 17, 45, 25, 21, 37, 3), + CABAC_ENTRY(218, 23, 38, 20, 42, 30, 20, 38, 5), + CABAC_ENTRY(219, 18, 43, 18, 45, 31, 12, 42, 0), + CABAC_ENTRY(220, 20, 41, 27, 26, 27, 16, 35, 16), + CABAC_ENTRY(221, 11, 63, 16, 54, 24, 42, 39, 22), + CABAC_ENTRY(222, 9, 59, 7, 66, 0, 93, 14, 48), + CABAC_ENTRY(223, 9, 64, 16, 56, 14, 56, 27, 37), + CABAC_ENTRY(224, -1, 94, 11, 73, 15, 57, 21, 60), + CABAC_ENTRY(225, -2, 89, 10, 67, 26, 38, 12, 68), + CABAC_ENTRY(226, -9, 108, -10, 116, -24, 127, 2, 97), + + /* Table 9-21 =E2=80=93 Values of variables m and n for ctxIdx from 227 t= o 275 */ + CABAC_ENTRY(227, -6, 76, -23, 112, -24, 115, -3, 71), + CABAC_ENTRY(228, -2, 44, -15, 71, -22, 82, -6, 42), + CABAC_ENTRY(229, 0, 45, -7, 61, -9, 62, -5, 50), + CABAC_ENTRY(230, 0, 52, 0, 53, 0, 53, -3, 54), + CABAC_ENTRY(231, -3, 64, -5, 66, 0, 59, -2, 62), + CABAC_ENTRY(232, -2, 59, -11, 77, -14, 85, 0, 58), + CABAC_ENTRY(233, -4, 70, -9, 80, -13, 89, 1, 63), + CABAC_ENTRY(234, -4, 75, -9, 84, -13, 94, -2, 72), + CABAC_ENTRY(235, -8, 82, -10, 87, -11, 92, -1, 74), + CABAC_ENTRY(236, -17, 102, -34, 127, -29, 127, -9, 91), + CABAC_ENTRY(237, -9, 77, -21, 101, -21, 100, -5, 67), + CABAC_ENTRY(238, 3, 24, -3, 39, -14, 57, -5, 27), + CABAC_ENTRY(239, 0, 42, -5, 53, -12, 67, -3, 39), + CABAC_ENTRY(240, 0, 48, -7, 61, -11, 71, -2, 44), + CABAC_ENTRY(241, 0, 55, -11, 75, -10, 77, 0, 46), + CABAC_ENTRY(242, -6, 59, -15, 77, -21, 85, -16, 64), + CABAC_ENTRY(243, -7, 71, -17, 91, -16, 88, -8, 68), + CABAC_ENTRY(244, -12, 83, -25, 107, -23, 104, -10, 78), + CABAC_ENTRY(245, -11, 87, -25, 111, -15, 98, -6, 77), + CABAC_ENTRY(246, -30, 119, -28, 122, -37, 127, -10, 86), + CABAC_ENTRY(247, 1, 58, -11, 76, -10, 82, -12, 92), + CABAC_ENTRY(248, -3, 29, -10, 44, -8, 48, -15, 55), + CABAC_ENTRY(249, -1, 36, -10, 52, -8, 61, -10, 60), + CABAC_ENTRY(250, 1, 38, -10, 57, -8, 66, -6, 62), + CABAC_ENTRY(251, 2, 43, -9, 58, -7, 70, -4, 65), + CABAC_ENTRY(252, -6, 55, -16, 72, -14, 75, -12, 73), + CABAC_ENTRY(253, 0, 58, -7, 69, -10, 79, -8, 76), + CABAC_ENTRY(254, 0, 64, -4, 69, -9, 83, -7, 80), + CABAC_ENTRY(255, -3, 74, -5, 74, -12, 92, -9, 88), + CABAC_ENTRY(256, -10, 90, -9, 86, -18, 108, -17, 110), + CABAC_ENTRY(257, 0, 70, 2, 66, -4, 79, -11, 97), + CABAC_ENTRY(258, -4, 29, -9, 34, -22, 69, -20, 84), + CABAC_ENTRY(259, 5, 31, 1, 32, -16, 75, -11, 79), + CABAC_ENTRY(260, 7, 42, 11, 31, -2, 58, -6, 73), + CABAC_ENTRY(261, 1, 59, 5, 52, 1, 58, -4, 74), + CABAC_ENTRY(262, -2, 58, -2, 55, -13, 78, -13, 86), + CABAC_ENTRY(263, -3, 72, -2, 67, -9, 83, -13, 96), + CABAC_ENTRY(264, -3, 81, 0, 73, -4, 81, -11, 97), + CABAC_ENTRY(265, -11, 97, -8, 89, -13, 99, -19, 117), + CABAC_ENTRY(266, 0, 58, 3, 52, -13, 81, -8, 78), + CABAC_ENTRY(267, 8, 5, 7, 4, -6, 38, -5, 33), + CABAC_ENTRY(268, 10, 14, 10, 8, -13, 62, -4, 48), + CABAC_ENTRY(269, 14, 18, 17, 8, -6, 58, -2, 53), + CABAC_ENTRY(270, 13, 27, 16, 19, -2, 59, -3, 62), + CABAC_ENTRY(271, 2, 40, 3, 37, -16, 73, -13, 71), + CABAC_ENTRY(272, 0, 58, -1, 61, -10, 76, -10, 79), + CABAC_ENTRY(273, -3, 70, -5, 73, -13, 86, -12, 86), + CABAC_ENTRY(274, -6, 79, -1, 70, -9, 83, -13, 90), + CABAC_ENTRY(275, -8, 85, -4, 78, -10, 87, -14, 97), + + /* Table 9-22 =E2=80=93 Values of variables m and n for ctxIdx from 277 t= o 337 */ + CABAC_ENTRY(277, -13, 106, -21, 126, -22, 127, -6, 93), + CABAC_ENTRY(278, -16, 106, -23, 124, -25, 127, -6, 84), + CABAC_ENTRY(279, -10, 87, -20, 110, -25, 120, -8, 79), + CABAC_ENTRY(280, -21, 114, -26, 126, -27, 127, 0, 66), + CABAC_ENTRY(281, -18, 110, -25, 124, -19, 114, -1, 71), + CABAC_ENTRY(282, -14, 98, -17, 105, -23, 117, 0, 62), + CABAC_ENTRY(283, -22, 110, -27, 121, -25, 118, -2, 60), + CABAC_ENTRY(284, -21, 106, -27, 117, -26, 117, -2, 59), + CABAC_ENTRY(285, -18, 103, -17, 102, -24, 113, -5, 75), + CABAC_ENTRY(286, -21, 107, -26, 117, -28, 118, -3, 62), + CABAC_ENTRY(287, -23, 108, -27, 116, -31, 120, -4, 58), + CABAC_ENTRY(288, -26, 112, -33, 122, -37, 124, -9, 66), + CABAC_ENTRY(289, -10, 96, -10, 95, -10, 94, -1, 79), + CABAC_ENTRY(290, -12, 95, -14, 100, -15, 102, 0, 71), + CABAC_ENTRY(291, -5, 91, -8, 95, -10, 99, 3, 68), + CABAC_ENTRY(292, -9, 93, -17, 111, -13, 106, 10, 44), + CABAC_ENTRY(293, -22, 94, -28, 114, -50, 127, -7, 62), + CABAC_ENTRY(294, -5, 86, -6, 89, -5, 92, 15, 36), + CABAC_ENTRY(295, 9, 67, -2, 80, 17, 57, 14, 40), + CABAC_ENTRY(296, -4, 80, -4, 82, -5, 86, 16, 27), + CABAC_ENTRY(297, -10, 85, -9, 85, -13, 94, 12, 29), + CABAC_ENTRY(298, -1, 70, -8, 81, -12, 91, 1, 44), + CABAC_ENTRY(299, 7, 60, -1, 72, -2, 77, 20, 36), + CABAC_ENTRY(300, 9, 58, 5, 64, 0, 71, 18, 32), + CABAC_ENTRY(301, 5, 61, 1, 67, -1, 73, 5, 42), + CABAC_ENTRY(302, 12, 50, 9, 56, 4, 64, 1, 48), + CABAC_ENTRY(303, 15, 50, 0, 69, -7, 81, 10, 62), + CABAC_ENTRY(304, 18, 49, 1, 69, 5, 64, 17, 46), + CABAC_ENTRY(305, 17, 54, 7, 69, 15, 57, 9, 64), + CABAC_ENTRY(306, 10, 41, -7, 69, 1, 67, -12, 104), + CABAC_ENTRY(307, 7, 46, -6, 67, 0, 68, -11, 97), + CABAC_ENTRY(308, -1, 51, -16, 77, -10, 67, -16, 96), + CABAC_ENTRY(309, 7, 49, -2, 64, 1, 68, -7, 88), + CABAC_ENTRY(310, 8, 52, 2, 61, 0, 77, -8, 85), + CABAC_ENTRY(311, 9, 41, -6, 67, 2, 64, -7, 85), + CABAC_ENTRY(312, 6, 47, -3, 64, 0, 68, -9, 85), + CABAC_ENTRY(313, 2, 55, 2, 57, -5, 78, -13, 88), + CABAC_ENTRY(314, 13, 41, -3, 65, 7, 55, 4, 66), + CABAC_ENTRY(315, 10, 44, -3, 66, 5, 59, -3, 77), + CABAC_ENTRY(316, 6, 50, 0, 62, 2, 65, -3, 76), + CABAC_ENTRY(317, 5, 53, 9, 51, 14, 54, -6, 76), + CABAC_ENTRY(318, 13, 49, -1, 66, 15, 44, 10, 58), + CABAC_ENTRY(319, 4, 63, -2, 71, 5, 60, -1, 76), + CABAC_ENTRY(320, 6, 64, -2, 75, 2, 70, -1, 83), + CABAC_ENTRY(321, -2, 69, -1, 70, -2, 76, -7, 99), + CABAC_ENTRY(322, -2, 59, -9, 72, -18, 86, -14, 95), + CABAC_ENTRY(323, 6, 70, 14, 60, 12, 70, 2, 95), + CABAC_ENTRY(324, 10, 44, 16, 37, 5, 64, 0, 76), + CABAC_ENTRY(325, 9, 31, 0, 47, -12, 70, -5, 74), + CABAC_ENTRY(326, 12, 43, 18, 35, 11, 55, 0, 70), + CABAC_ENTRY(327, 3, 53, 11, 37, 5, 56, -11, 75), + CABAC_ENTRY(328, 14, 34, 12, 41, 0, 69, 1, 68), + CABAC_ENTRY(329, 10, 38, 10, 41, 2, 65, 0, 65), + CABAC_ENTRY(330, -3, 52, 2, 48, -6, 74, -14, 73), + CABAC_ENTRY(331, 13, 40, 12, 41, 5, 54, 3, 62), + CABAC_ENTRY(332, 17, 32, 13, 41, 7, 54, 4, 62), + CABAC_ENTRY(333, 7, 44, 0, 59, -6, 76, -1, 68), + CABAC_ENTRY(334, 7, 38, 3, 50, -11, 82, -13, 75), + CABAC_ENTRY(335, 13, 50, 19, 40, -2, 77, 11, 55), + CABAC_ENTRY(336, 10, 57, 3, 66, -2, 77, 5, 64), + CABAC_ENTRY(337, 26, 43, 18, 50, 25, 42, 12, 70), + + /* Table 9-23 =E2=80=93 Values of variables m and n for ctxIdx from 338 t= o 398 */ + CABAC_ENTRY(338, 14, 11, 19, -6, 17, -13, 15, 6), + CABAC_ENTRY(339, 11, 14, 18, -6, 16, -9, 6, 19), + CABAC_ENTRY(340, 9, 11, 14, 0, 17, -12, 7, 16), + CABAC_ENTRY(341, 18, 11, 26, -12, 27, -21, 12, 14), + CABAC_ENTRY(342, 21, 9, 31, -16, 37, -30, 18, 13), + CABAC_ENTRY(343, 23, -2, 33, -25, 41, -40, 13, 11), + CABAC_ENTRY(344, 32, -15, 33, -22, 42, -41, 13, 15), + CABAC_ENTRY(345, 32, -15, 37, -28, 48, -47, 15, 16), + CABAC_ENTRY(346, 34, -21, 39, -30, 39, -32, 12, 23), + CABAC_ENTRY(347, 39, -23, 42, -30, 46, -40, 13, 23), + CABAC_ENTRY(348, 42, -33, 47, -42, 52, -51, 15, 20), + CABAC_ENTRY(349, 41, -31, 45, -36, 46, -41, 14, 26), + CABAC_ENTRY(350, 46, -28, 49, -34, 52, -39, 14, 44), + CABAC_ENTRY(351, 38, -12, 41, -17, 43, -19, 17, 40), + CABAC_ENTRY(352, 21, 29, 32, 9, 32, 11, 17, 47), + CABAC_ENTRY(353, 45, -24, 69, -71, 61, -55, 24, 17), + CABAC_ENTRY(354, 53, -45, 63, -63, 56, -46, 21, 21), + CABAC_ENTRY(355, 48, -26, 66, -64, 62, -50, 25, 22), + CABAC_ENTRY(356, 65, -43, 77, -74, 81, -67, 31, 27), + CABAC_ENTRY(357, 43, -19, 54, -39, 45, -20, 22, 29), + CABAC_ENTRY(358, 39, -10, 52, -35, 35, -2, 19, 35), + CABAC_ENTRY(359, 30, 9, 41, -10, 28, 15, 14, 50), + CABAC_ENTRY(360, 18, 26, 36, 0, 34, 1, 10, 57), + CABAC_ENTRY(361, 20, 27, 40, -1, 39, 1, 7, 63), + CABAC_ENTRY(362, 0, 57, 30, 14, 30, 17, -2, 77), + CABAC_ENTRY(363, -14, 82, 28, 26, 20, 38, -4, 82), + CABAC_ENTRY(364, -5, 75, 23, 37, 18, 45, -3, 94), + CABAC_ENTRY(365, -19, 97, 12, 55, 15, 54, 9, 69), + CABAC_ENTRY(366, -35, 125, 11, 65, 0, 79, -12, 109), + CABAC_ENTRY(367, 27, 0, 37, -33, 36, -16, 36, -35), + CABAC_ENTRY(368, 28, 0, 39, -36, 37, -14, 36, -34), + CABAC_ENTRY(369, 31, -4, 40, -37, 37, -17, 32, -26), + CABAC_ENTRY(370, 27, 6, 38, -30, 32, 1, 37, -30), + CABAC_ENTRY(371, 34, 8, 46, -33, 34, 15, 44, -32), + CABAC_ENTRY(372, 30, 10, 42, -30, 29, 15, 34, -18), + CABAC_ENTRY(373, 24, 22, 40, -24, 24, 25, 34, -15), + CABAC_ENTRY(374, 33, 19, 49, -29, 34, 22, 40, -15), + CABAC_ENTRY(375, 22, 32, 38, -12, 31, 16, 33, -7), + CABAC_ENTRY(376, 26, 31, 40, -10, 35, 18, 35, -5), + CABAC_ENTRY(377, 21, 41, 38, -3, 31, 28, 33, 0), + CABAC_ENTRY(378, 26, 44, 46, -5, 33, 41, 38, 2), + CABAC_ENTRY(379, 23, 47, 31, 20, 36, 28, 33, 13), + CABAC_ENTRY(380, 16, 65, 29, 30, 27, 47, 23, 35), + CABAC_ENTRY(381, 14, 71, 25, 44, 21, 62, 13, 58), + CABAC_ENTRY(382, 8, 60, 12, 48, 18, 31, 29, -3), + CABAC_ENTRY(383, 6, 63, 11, 49, 19, 26, 26, 0), + CABAC_ENTRY(384, 17, 65, 26, 45, 36, 24, 22, 30), + CABAC_ENTRY(385, 21, 24, 22, 22, 24, 23, 31, -7), + CABAC_ENTRY(386, 23, 20, 23, 22, 27, 16, 35, -15), + CABAC_ENTRY(387, 26, 23, 27, 21, 24, 30, 34, -3), + CABAC_ENTRY(388, 27, 32, 33, 20, 31, 29, 34, 3), + CABAC_ENTRY(389, 28, 23, 26, 28, 22, 41, 36, -1), + CABAC_ENTRY(390, 28, 24, 30, 24, 22, 42, 34, 5), + CABAC_ENTRY(391, 23, 40, 27, 34, 16, 60, 32, 11), + CABAC_ENTRY(392, 24, 32, 18, 42, 15, 52, 35, 5), + CABAC_ENTRY(393, 28, 29, 25, 39, 14, 60, 34, 12), + CABAC_ENTRY(394, 23, 42, 18, 50, 3, 78, 39, 11), + CABAC_ENTRY(395, 19, 57, 12, 70, -16, 123, 30, 29), + CABAC_ENTRY(396, 22, 53, 21, 54, 21, 53, 34, 26), + CABAC_ENTRY(397, 22, 61, 14, 71, 22, 56, 29, 39), + CABAC_ENTRY(398, 11, 86, 11, 83, 25, 61, 19, 66), + + /* Values of variables m and n for ctxIdx from 399 to 463 (not documented= ) */ + CABAC_ENTRY(399, 12, 40, 25, 32, 21, 33, 31, 21), + CABAC_ENTRY(400, 11, 51, 21, 49, 19, 50, 31, 31), + CABAC_ENTRY(401, 14, 59, 21, 54, 17, 61, 25, 50), + CABAC_ENTRY(402, -4, 79, -5, 85, -3, 78, -17, 120), + CABAC_ENTRY(403, -7, 71, -6, 81, -8, 74, -20, 112), + CABAC_ENTRY(404, -5, 69, -10, 77, -9, 72, -18, 114), + CABAC_ENTRY(405, -9, 70, -7, 81, -10, 72, -11, 85), + CABAC_ENTRY(406, -8, 66, -17, 80, -18, 75, -15, 92), + CABAC_ENTRY(407, -10, 68, -18, 73, -12, 71, -14, 89), + CABAC_ENTRY(408, -19, 73, -4, 74, -11, 63, -26, 71), + CABAC_ENTRY(409, -12, 69, -10, 83, -5, 70, -15, 81), + CABAC_ENTRY(410, -16, 70, -9, 71, -17, 75, -14, 80), + CABAC_ENTRY(411, -15, 67, -9, 67, -14, 72, 0, 68), + CABAC_ENTRY(412, -20, 62, -1, 61, -16, 67, -14, 70), + CABAC_ENTRY(413, -19, 70, -8, 66, -8, 53, -24, 56), + CABAC_ENTRY(414, -16, 66, -14, 66, -14, 59, -23, 68), + CABAC_ENTRY(415, -22, 65, 0, 59, -9, 52, -24, 50), + CABAC_ENTRY(416, -20, 63, 2, 59, -11, 68, -11, 74), + CABAC_ENTRY(417, 9, -2, 17, -10, 9, -2, 23, -13), + CABAC_ENTRY(418, 26, -9, 32, -13, 30, -10, 26, -13), + CABAC_ENTRY(419, 33, -9, 42, -9, 31, -4, 40, -15), + CABAC_ENTRY(420, 39, -7, 49, -5, 33, -1, 49, -14), + CABAC_ENTRY(421, 41, -2, 53, 0, 33, 7, 44, 3), + CABAC_ENTRY(422, 45, 3, 64, 3, 31, 12, 45, 6), + CABAC_ENTRY(423, 49, 9, 68, 10, 37, 23, 44, 34), + CABAC_ENTRY(424, 45, 27, 66, 27, 31, 38, 33, 54), + CABAC_ENTRY(425, 36, 59, 47, 57, 20, 64, 19, 82), + CABAC_ENTRY(426, -6, 66, -5, 71, -9, 71, -3, 75), + CABAC_ENTRY(427, -7, 35, 0, 24, -7, 37, -1, 23), + CABAC_ENTRY(428, -7, 42, -1, 36, -8, 44, 1, 34), + CABAC_ENTRY(429, -8, 45, -2, 42, -11, 49, 1, 43), + CABAC_ENTRY(430, -5, 48, -2, 52, -10, 56, 0, 54), + CABAC_ENTRY(431, -12, 56, -9, 57, -12, 59, -2, 55), + CABAC_ENTRY(432, -6, 60, -6, 63, -8, 63, 0, 61), + CABAC_ENTRY(433, -5, 62, -4, 65, -9, 67, 1, 64), + CABAC_ENTRY(434, -8, 66, -4, 67, -6, 68, 0, 68), + CABAC_ENTRY(435, -8, 76, -7, 82, -10, 79, -9, 92), + CABAC_ENTRY(436, -5, 85, -3, 81, -3, 78, -14, 106), + CABAC_ENTRY(437, -6, 81, -3, 76, -8, 74, -13, 97), + CABAC_ENTRY(438, -10, 77, -7, 72, -9, 72, -15, 90), + CABAC_ENTRY(439, -7, 81, -6, 78, -10, 72, -12, 90), + CABAC_ENTRY(440, -17, 80, -12, 72, -18, 75, -18, 88), + CABAC_ENTRY(441, -18, 73, -14, 68, -12, 71, -10, 73), + CABAC_ENTRY(442, -4, 74, -3, 70, -11, 63, -9, 79), + CABAC_ENTRY(443, -10, 83, -6, 76, -5, 70, -14, 86), + CABAC_ENTRY(444, -9, 71, -5, 66, -17, 75, -10, 73), + CABAC_ENTRY(445, -9, 67, -5, 62, -14, 72, -10, 70), + CABAC_ENTRY(446, -1, 61, 0, 57, -16, 67, -10, 69), + CABAC_ENTRY(447, -8, 66, -4, 61, -8, 53, -5, 66), + CABAC_ENTRY(448, -14, 66, -9, 60, -14, 59, -9, 64), + CABAC_ENTRY(449, 0, 59, 1, 54, -9, 52, -5, 58), + CABAC_ENTRY(450, 2, 59, 2, 58, -11, 68, 2, 59), + CABAC_ENTRY(451, 21, -13, 17, -10, 9, -2, 21, -10), + CABAC_ENTRY(452, 33, -14, 32, -13, 30, -10, 24, -11), + CABAC_ENTRY(453, 39, -7, 42, -9, 31, -4, 28, -8), + CABAC_ENTRY(454, 46, -2, 49, -5, 33, -1, 28, -1), + CABAC_ENTRY(455, 51, 2, 53, 0, 33, 7, 29, 3), + CABAC_ENTRY(456, 60, 6, 64, 3, 31, 12, 29, 9), + CABAC_ENTRY(457, 61, 17, 68, 10, 37, 23, 35, 20), + CABAC_ENTRY(458, 55, 34, 66, 27, 31, 38, 29, 36), + CABAC_ENTRY(459, 42, 62, 47, 57, 20, 64, 14, 67), +}; + +#define RKV_HEVC_CABAC_TABLE_SIZE 27456 + +const u8 rkvdec_hevc_cabac_table[RKV_HEVC_CABAC_TABLE_SIZE] =3D { 0x07, 0x0f, 0x48, 0x58, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0= x40, 0x40, 0x0f, 0x68, 0x48, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0= x40, 0x07, 0x40, 0x40, 0x68, 0x58, 0x60, 0x40, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0= x48, 0x48, 0x60, diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-h264.c index 116e7b1076b7..989379ae3a73 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c @@ -15,6 +15,8 @@ #include "rkvdec.h" #include "rkvdec-regs.h" =20 +extern const s8 rkvdec_h264_cabac_table[4][464][2]; + /* Size with u32 units. */ #define RKV_CABAC_INIT_BUFFER_SIZE (3680 + 128) #define RKV_RPS_SIZE ((128 + 128) / 4) @@ -118,505 +120,6 @@ struct rkvdec_h264_ctx { struct rkvdec_regs regs; }; =20 -#define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \ - idc2_m, idc2_n, intra_m, intra_n) \ - [0][(ctxidx)] =3D {idc0_m, idc0_n}, \ - [1][(ctxidx)] =3D {idc1_m, idc1_n}, \ - [2][(ctxidx)] =3D {idc2_m, idc2_n}, \ - [3][(ctxidx)] =3D {intra_m, intra_n} - -/* - * Constant CABAC table. - * Built from the tables described in section '9.3.1.1 Initialisation proc= ess - * for context variables' of the H264 spec. - */ -static const s8 rkvdec_h264_cabac_table[4][464][2] =3D { - /* Table 9-12 =E2=80=93 Values of variables m and n for ctxIdx from 0 to = 10 */ - CABAC_ENTRY(0, 20, -15, 20, -15, 20, -15, 20, -15), - CABAC_ENTRY(1, 2, 54, 2, 54, 2, 54, 2, 54), - CABAC_ENTRY(2, 3, 74, 3, 74, 3, 74, 3, 74), - CABAC_ENTRY(3, 20, -15, 20, -15, 20, -15, 20, -15), - CABAC_ENTRY(4, 2, 54, 2, 54, 2, 54, 2, 54), - CABAC_ENTRY(5, 3, 74, 3, 74, 3, 74, 3, 74), - CABAC_ENTRY(6, -28, 127, -28, 127, -28, 127, -28, 127), - CABAC_ENTRY(7, -23, 104, -23, 104, -23, 104, -23, 104), - CABAC_ENTRY(8, -6, 53, -6, 53, -6, 53, -6, 53), - CABAC_ENTRY(9, -1, 54, -1, 54, -1, 54, -1, 54), - CABAC_ENTRY(10, 7, 51, 7, 51, 7, 51, 7, 51), - - /* Table 9-13 =E2=80=93 Values of variables m and n for ctxIdx from 11 to= 23 */ - CABAC_ENTRY(11, 23, 33, 22, 25, 29, 16, 0, 0), - CABAC_ENTRY(12, 23, 2, 34, 0, 25, 0, 0, 0), - CABAC_ENTRY(13, 21, 0, 16, 0, 14, 0, 0, 0), - CABAC_ENTRY(14, 1, 9, -2, 9, -10, 51, 0, 0), - CABAC_ENTRY(15, 0, 49, 4, 41, -3, 62, 0, 0), - CABAC_ENTRY(16, -37, 118, -29, 118, -27, 99, 0, 0), - CABAC_ENTRY(17, 5, 57, 2, 65, 26, 16, 0, 0), - CABAC_ENTRY(18, -13, 78, -6, 71, -4, 85, 0, 0), - CABAC_ENTRY(19, -11, 65, -13, 79, -24, 102, 0, 0), - CABAC_ENTRY(20, 1, 62, 5, 52, 5, 57, 0, 0), - CABAC_ENTRY(21, 12, 49, 9, 50, 6, 57, 0, 0), - CABAC_ENTRY(22, -4, 73, -3, 70, -17, 73, 0, 0), - CABAC_ENTRY(23, 17, 50, 10, 54, 14, 57, 0, 0), - - /* Table 9-14 =E2=80=93 Values of variables m and n for ctxIdx from 24 to= 39 */ - CABAC_ENTRY(24, 18, 64, 26, 34, 20, 40, 0, 0), - CABAC_ENTRY(25, 9, 43, 19, 22, 20, 10, 0, 0), - CABAC_ENTRY(26, 29, 0, 40, 0, 29, 0, 0, 0), - CABAC_ENTRY(27, 26, 67, 57, 2, 54, 0, 0, 0), - CABAC_ENTRY(28, 16, 90, 41, 36, 37, 42, 0, 0), - CABAC_ENTRY(29, 9, 104, 26, 69, 12, 97, 0, 0), - CABAC_ENTRY(30, -46, 127, -45, 127, -32, 127, 0, 0), - CABAC_ENTRY(31, -20, 104, -15, 101, -22, 117, 0, 0), - CABAC_ENTRY(32, 1, 67, -4, 76, -2, 74, 0, 0), - CABAC_ENTRY(33, -13, 78, -6, 71, -4, 85, 0, 0), - CABAC_ENTRY(34, -11, 65, -13, 79, -24, 102, 0, 0), - CABAC_ENTRY(35, 1, 62, 5, 52, 5, 57, 0, 0), - CABAC_ENTRY(36, -6, 86, 6, 69, -6, 93, 0, 0), - CABAC_ENTRY(37, -17, 95, -13, 90, -14, 88, 0, 0), - CABAC_ENTRY(38, -6, 61, 0, 52, -6, 44, 0, 0), - CABAC_ENTRY(39, 9, 45, 8, 43, 4, 55, 0, 0), - - /* Table 9-15 =E2=80=93 Values of variables m and n for ctxIdx from 40 to= 53 */ - CABAC_ENTRY(40, -3, 69, -2, 69, -11, 89, 0, 0), - CABAC_ENTRY(41, -6, 81, -5, 82, -15, 103, 0, 0), - CABAC_ENTRY(42, -11, 96, -10, 96, -21, 116, 0, 0), - CABAC_ENTRY(43, 6, 55, 2, 59, 19, 57, 0, 0), - CABAC_ENTRY(44, 7, 67, 2, 75, 20, 58, 0, 0), - CABAC_ENTRY(45, -5, 86, -3, 87, 4, 84, 0, 0), - CABAC_ENTRY(46, 2, 88, -3, 100, 6, 96, 0, 0), - CABAC_ENTRY(47, 0, 58, 1, 56, 1, 63, 0, 0), - CABAC_ENTRY(48, -3, 76, -3, 74, -5, 85, 0, 0), - CABAC_ENTRY(49, -10, 94, -6, 85, -13, 106, 0, 0), - CABAC_ENTRY(50, 5, 54, 0, 59, 5, 63, 0, 0), - CABAC_ENTRY(51, 4, 69, -3, 81, 6, 75, 0, 0), - CABAC_ENTRY(52, -3, 81, -7, 86, -3, 90, 0, 0), - CABAC_ENTRY(53, 0, 88, -5, 95, -1, 101, 0, 0), - - /* Table 9-16 =E2=80=93 Values of variables m and n for ctxIdx from 54 to= 59 */ - CABAC_ENTRY(54, -7, 67, -1, 66, 3, 55, 0, 0), - CABAC_ENTRY(55, -5, 74, -1, 77, -4, 79, 0, 0), - CABAC_ENTRY(56, -4, 74, 1, 70, -2, 75, 0, 0), - CABAC_ENTRY(57, -5, 80, -2, 86, -12, 97, 0, 0), - CABAC_ENTRY(58, -7, 72, -5, 72, -7, 50, 0, 0), - CABAC_ENTRY(59, 1, 58, 0, 61, 1, 60, 0, 0), - - /* Table 9-17 =E2=80=93 Values of variables m and n for ctxIdx from 60 to= 69 */ - CABAC_ENTRY(60, 0, 41, 0, 41, 0, 41, 0, 41), - CABAC_ENTRY(61, 0, 63, 0, 63, 0, 63, 0, 63), - CABAC_ENTRY(62, 0, 63, 0, 63, 0, 63, 0, 63), - CABAC_ENTRY(63, 0, 63, 0, 63, 0, 63, 0, 63), - CABAC_ENTRY(64, -9, 83, -9, 83, -9, 83, -9, 83), - CABAC_ENTRY(65, 4, 86, 4, 86, 4, 86, 4, 86), - CABAC_ENTRY(66, 0, 97, 0, 97, 0, 97, 0, 97), - CABAC_ENTRY(67, -7, 72, -7, 72, -7, 72, -7, 72), - CABAC_ENTRY(68, 13, 41, 13, 41, 13, 41, 13, 41), - CABAC_ENTRY(69, 3, 62, 3, 62, 3, 62, 3, 62), - - /* Table 9-18 =E2=80=93 Values of variables m and n for ctxIdx from 70 to= 104 */ - CABAC_ENTRY(70, 0, 45, 13, 15, 7, 34, 0, 11), - CABAC_ENTRY(71, -4, 78, 7, 51, -9, 88, 1, 55), - CABAC_ENTRY(72, -3, 96, 2, 80, -20, 127, 0, 69), - CABAC_ENTRY(73, -27, 126, -39, 127, -36, 127, -17, 127), - CABAC_ENTRY(74, -28, 98, -18, 91, -17, 91, -13, 102), - CABAC_ENTRY(75, -25, 101, -17, 96, -14, 95, 0, 82), - CABAC_ENTRY(76, -23, 67, -26, 81, -25, 84, -7, 74), - CABAC_ENTRY(77, -28, 82, -35, 98, -25, 86, -21, 107), - CABAC_ENTRY(78, -20, 94, -24, 102, -12, 89, -27, 127), - CABAC_ENTRY(79, -16, 83, -23, 97, -17, 91, -31, 127), - CABAC_ENTRY(80, -22, 110, -27, 119, -31, 127, -24, 127), - CABAC_ENTRY(81, -21, 91, -24, 99, -14, 76, -18, 95), - CABAC_ENTRY(82, -18, 102, -21, 110, -18, 103, -27, 127), - CABAC_ENTRY(83, -13, 93, -18, 102, -13, 90, -21, 114), - CABAC_ENTRY(84, -29, 127, -36, 127, -37, 127, -30, 127), - CABAC_ENTRY(85, -7, 92, 0, 80, 11, 80, -17, 123), - CABAC_ENTRY(86, -5, 89, -5, 89, 5, 76, -12, 115), - CABAC_ENTRY(87, -7, 96, -7, 94, 2, 84, -16, 122), - CABAC_ENTRY(88, -13, 108, -4, 92, 5, 78, -11, 115), - CABAC_ENTRY(89, -3, 46, 0, 39, -6, 55, -12, 63), - CABAC_ENTRY(90, -1, 65, 0, 65, 4, 61, -2, 68), - CABAC_ENTRY(91, -1, 57, -15, 84, -14, 83, -15, 84), - CABAC_ENTRY(92, -9, 93, -35, 127, -37, 127, -13, 104), - CABAC_ENTRY(93, -3, 74, -2, 73, -5, 79, -3, 70), - CABAC_ENTRY(94, -9, 92, -12, 104, -11, 104, -8, 93), - CABAC_ENTRY(95, -8, 87, -9, 91, -11, 91, -10, 90), - CABAC_ENTRY(96, -23, 126, -31, 127, -30, 127, -30, 127), - CABAC_ENTRY(97, 5, 54, 3, 55, 0, 65, -1, 74), - CABAC_ENTRY(98, 6, 60, 7, 56, -2, 79, -6, 97), - CABAC_ENTRY(99, 6, 59, 7, 55, 0, 72, -7, 91), - CABAC_ENTRY(100, 6, 69, 8, 61, -4, 92, -20, 127), - CABAC_ENTRY(101, -1, 48, -3, 53, -6, 56, -4, 56), - CABAC_ENTRY(102, 0, 68, 0, 68, 3, 68, -5, 82), - CABAC_ENTRY(103, -4, 69, -7, 74, -8, 71, -7, 76), - CABAC_ENTRY(104, -8, 88, -9, 88, -13, 98, -22, 125), - - /* Table 9-19 =E2=80=93 Values of variables m and n for ctxIdx from 105 t= o 165 */ - CABAC_ENTRY(105, -2, 85, -13, 103, -4, 86, -7, 93), - CABAC_ENTRY(106, -6, 78, -13, 91, -12, 88, -11, 87), - CABAC_ENTRY(107, -1, 75, -9, 89, -5, 82, -3, 77), - CABAC_ENTRY(108, -7, 77, -14, 92, -3, 72, -5, 71), - CABAC_ENTRY(109, 2, 54, -8, 76, -4, 67, -4, 63), - CABAC_ENTRY(110, 5, 50, -12, 87, -8, 72, -4, 68), - CABAC_ENTRY(111, -3, 68, -23, 110, -16, 89, -12, 84), - CABAC_ENTRY(112, 1, 50, -24, 105, -9, 69, -7, 62), - CABAC_ENTRY(113, 6, 42, -10, 78, -1, 59, -7, 65), - CABAC_ENTRY(114, -4, 81, -20, 112, 5, 66, 8, 61), - CABAC_ENTRY(115, 1, 63, -17, 99, 4, 57, 5, 56), - CABAC_ENTRY(116, -4, 70, -78, 127, -4, 71, -2, 66), - CABAC_ENTRY(117, 0, 67, -70, 127, -2, 71, 1, 64), - CABAC_ENTRY(118, 2, 57, -50, 127, 2, 58, 0, 61), - CABAC_ENTRY(119, -2, 76, -46, 127, -1, 74, -2, 78), - CABAC_ENTRY(120, 11, 35, -4, 66, -4, 44, 1, 50), - CABAC_ENTRY(121, 4, 64, -5, 78, -1, 69, 7, 52), - CABAC_ENTRY(122, 1, 61, -4, 71, 0, 62, 10, 35), - CABAC_ENTRY(123, 11, 35, -8, 72, -7, 51, 0, 44), - CABAC_ENTRY(124, 18, 25, 2, 59, -4, 47, 11, 38), - CABAC_ENTRY(125, 12, 24, -1, 55, -6, 42, 1, 45), - CABAC_ENTRY(126, 13, 29, -7, 70, -3, 41, 0, 46), - CABAC_ENTRY(127, 13, 36, -6, 75, -6, 53, 5, 44), - CABAC_ENTRY(128, -10, 93, -8, 89, 8, 76, 31, 17), - CABAC_ENTRY(129, -7, 73, -34, 119, -9, 78, 1, 51), - CABAC_ENTRY(130, -2, 73, -3, 75, -11, 83, 7, 50), - CABAC_ENTRY(131, 13, 46, 32, 20, 9, 52, 28, 19), - CABAC_ENTRY(132, 9, 49, 30, 22, 0, 67, 16, 33), - CABAC_ENTRY(133, -7, 100, -44, 127, -5, 90, 14, 62), - CABAC_ENTRY(134, 9, 53, 0, 54, 1, 67, -13, 108), - CABAC_ENTRY(135, 2, 53, -5, 61, -15, 72, -15, 100), - CABAC_ENTRY(136, 5, 53, 0, 58, -5, 75, -13, 101), - CABAC_ENTRY(137, -2, 61, -1, 60, -8, 80, -13, 91), - CABAC_ENTRY(138, 0, 56, -3, 61, -21, 83, -12, 94), - CABAC_ENTRY(139, 0, 56, -8, 67, -21, 64, -10, 88), - CABAC_ENTRY(140, -13, 63, -25, 84, -13, 31, -16, 84), - CABAC_ENTRY(141, -5, 60, -14, 74, -25, 64, -10, 86), - CABAC_ENTRY(142, -1, 62, -5, 65, -29, 94, -7, 83), - CABAC_ENTRY(143, 4, 57, 5, 52, 9, 75, -13, 87), - CABAC_ENTRY(144, -6, 69, 2, 57, 17, 63, -19, 94), - CABAC_ENTRY(145, 4, 57, 0, 61, -8, 74, 1, 70), - CABAC_ENTRY(146, 14, 39, -9, 69, -5, 35, 0, 72), - CABAC_ENTRY(147, 4, 51, -11, 70, -2, 27, -5, 74), - CABAC_ENTRY(148, 13, 68, 18, 55, 13, 91, 18, 59), - CABAC_ENTRY(149, 3, 64, -4, 71, 3, 65, -8, 102), - CABAC_ENTRY(150, 1, 61, 0, 58, -7, 69, -15, 100), - CABAC_ENTRY(151, 9, 63, 7, 61, 8, 77, 0, 95), - CABAC_ENTRY(152, 7, 50, 9, 41, -10, 66, -4, 75), - CABAC_ENTRY(153, 16, 39, 18, 25, 3, 62, 2, 72), - CABAC_ENTRY(154, 5, 44, 9, 32, -3, 68, -11, 75), - CABAC_ENTRY(155, 4, 52, 5, 43, -20, 81, -3, 71), - CABAC_ENTRY(156, 11, 48, 9, 47, 0, 30, 15, 46), - CABAC_ENTRY(157, -5, 60, 0, 44, 1, 7, -13, 69), - CABAC_ENTRY(158, -1, 59, 0, 51, -3, 23, 0, 62), - CABAC_ENTRY(159, 0, 59, 2, 46, -21, 74, 0, 65), - CABAC_ENTRY(160, 22, 33, 19, 38, 16, 66, 21, 37), - CABAC_ENTRY(161, 5, 44, -4, 66, -23, 124, -15, 72), - CABAC_ENTRY(162, 14, 43, 15, 38, 17, 37, 9, 57), - CABAC_ENTRY(163, -1, 78, 12, 42, 44, -18, 16, 54), - CABAC_ENTRY(164, 0, 60, 9, 34, 50, -34, 0, 62), - CABAC_ENTRY(165, 9, 69, 0, 89, -22, 127, 12, 72), - - /* Table 9-20 =E2=80=93 Values of variables m and n for ctxIdx from 166 t= o 226 */ - CABAC_ENTRY(166, 11, 28, 4, 45, 4, 39, 24, 0), - CABAC_ENTRY(167, 2, 40, 10, 28, 0, 42, 15, 9), - CABAC_ENTRY(168, 3, 44, 10, 31, 7, 34, 8, 25), - CABAC_ENTRY(169, 0, 49, 33, -11, 11, 29, 13, 18), - CABAC_ENTRY(170, 0, 46, 52, -43, 8, 31, 15, 9), - CABAC_ENTRY(171, 2, 44, 18, 15, 6, 37, 13, 19), - CABAC_ENTRY(172, 2, 51, 28, 0, 7, 42, 10, 37), - CABAC_ENTRY(173, 0, 47, 35, -22, 3, 40, 12, 18), - CABAC_ENTRY(174, 4, 39, 38, -25, 8, 33, 6, 29), - CABAC_ENTRY(175, 2, 62, 34, 0, 13, 43, 20, 33), - CABAC_ENTRY(176, 6, 46, 39, -18, 13, 36, 15, 30), - CABAC_ENTRY(177, 0, 54, 32, -12, 4, 47, 4, 45), - CABAC_ENTRY(178, 3, 54, 102, -94, 3, 55, 1, 58), - CABAC_ENTRY(179, 2, 58, 0, 0, 2, 58, 0, 62), - CABAC_ENTRY(180, 4, 63, 56, -15, 6, 60, 7, 61), - CABAC_ENTRY(181, 6, 51, 33, -4, 8, 44, 12, 38), - CABAC_ENTRY(182, 6, 57, 29, 10, 11, 44, 11, 45), - CABAC_ENTRY(183, 7, 53, 37, -5, 14, 42, 15, 39), - CABAC_ENTRY(184, 6, 52, 51, -29, 7, 48, 11, 42), - CABAC_ENTRY(185, 6, 55, 39, -9, 4, 56, 13, 44), - CABAC_ENTRY(186, 11, 45, 52, -34, 4, 52, 16, 45), - CABAC_ENTRY(187, 14, 36, 69, -58, 13, 37, 12, 41), - CABAC_ENTRY(188, 8, 53, 67, -63, 9, 49, 10, 49), - CABAC_ENTRY(189, -1, 82, 44, -5, 19, 58, 30, 34), - CABAC_ENTRY(190, 7, 55, 32, 7, 10, 48, 18, 42), - CABAC_ENTRY(191, -3, 78, 55, -29, 12, 45, 10, 55), - CABAC_ENTRY(192, 15, 46, 32, 1, 0, 69, 17, 51), - CABAC_ENTRY(193, 22, 31, 0, 0, 20, 33, 17, 46), - CABAC_ENTRY(194, -1, 84, 27, 36, 8, 63, 0, 89), - CABAC_ENTRY(195, 25, 7, 33, -25, 35, -18, 26, -19), - CABAC_ENTRY(196, 30, -7, 34, -30, 33, -25, 22, -17), - CABAC_ENTRY(197, 28, 3, 36, -28, 28, -3, 26, -17), - CABAC_ENTRY(198, 28, 4, 38, -28, 24, 10, 30, -25), - CABAC_ENTRY(199, 32, 0, 38, -27, 27, 0, 28, -20), - CABAC_ENTRY(200, 34, -1, 34, -18, 34, -14, 33, -23), - CABAC_ENTRY(201, 30, 6, 35, -16, 52, -44, 37, -27), - CABAC_ENTRY(202, 30, 6, 34, -14, 39, -24, 33, -23), - CABAC_ENTRY(203, 32, 9, 32, -8, 19, 17, 40, -28), - CABAC_ENTRY(204, 31, 19, 37, -6, 31, 25, 38, -17), - CABAC_ENTRY(205, 26, 27, 35, 0, 36, 29, 33, -11), - CABAC_ENTRY(206, 26, 30, 30, 10, 24, 33, 40, -15), - CABAC_ENTRY(207, 37, 20, 28, 18, 34, 15, 41, -6), - CABAC_ENTRY(208, 28, 34, 26, 25, 30, 20, 38, 1), - CABAC_ENTRY(209, 17, 70, 29, 41, 22, 73, 41, 17), - CABAC_ENTRY(210, 1, 67, 0, 75, 20, 34, 30, -6), - CABAC_ENTRY(211, 5, 59, 2, 72, 19, 31, 27, 3), - CABAC_ENTRY(212, 9, 67, 8, 77, 27, 44, 26, 22), - CABAC_ENTRY(213, 16, 30, 14, 35, 19, 16, 37, -16), - CABAC_ENTRY(214, 18, 32, 18, 31, 15, 36, 35, -4), - CABAC_ENTRY(215, 18, 35, 17, 35, 15, 36, 38, -8), - CABAC_ENTRY(216, 22, 29, 21, 30, 21, 28, 38, -3), - CABAC_ENTRY(217, 24, 31, 17, 45, 25, 21, 37, 3), - CABAC_ENTRY(218, 23, 38, 20, 42, 30, 20, 38, 5), - CABAC_ENTRY(219, 18, 43, 18, 45, 31, 12, 42, 0), - CABAC_ENTRY(220, 20, 41, 27, 26, 27, 16, 35, 16), - CABAC_ENTRY(221, 11, 63, 16, 54, 24, 42, 39, 22), - CABAC_ENTRY(222, 9, 59, 7, 66, 0, 93, 14, 48), - CABAC_ENTRY(223, 9, 64, 16, 56, 14, 56, 27, 37), - CABAC_ENTRY(224, -1, 94, 11, 73, 15, 57, 21, 60), - CABAC_ENTRY(225, -2, 89, 10, 67, 26, 38, 12, 68), - CABAC_ENTRY(226, -9, 108, -10, 116, -24, 127, 2, 97), - - /* Table 9-21 =E2=80=93 Values of variables m and n for ctxIdx from 227 t= o 275 */ - CABAC_ENTRY(227, -6, 76, -23, 112, -24, 115, -3, 71), - CABAC_ENTRY(228, -2, 44, -15, 71, -22, 82, -6, 42), - CABAC_ENTRY(229, 0, 45, -7, 61, -9, 62, -5, 50), - CABAC_ENTRY(230, 0, 52, 0, 53, 0, 53, -3, 54), - CABAC_ENTRY(231, -3, 64, -5, 66, 0, 59, -2, 62), - CABAC_ENTRY(232, -2, 59, -11, 77, -14, 85, 0, 58), - CABAC_ENTRY(233, -4, 70, -9, 80, -13, 89, 1, 63), - CABAC_ENTRY(234, -4, 75, -9, 84, -13, 94, -2, 72), - CABAC_ENTRY(235, -8, 82, -10, 87, -11, 92, -1, 74), - CABAC_ENTRY(236, -17, 102, -34, 127, -29, 127, -9, 91), - CABAC_ENTRY(237, -9, 77, -21, 101, -21, 100, -5, 67), - CABAC_ENTRY(238, 3, 24, -3, 39, -14, 57, -5, 27), - CABAC_ENTRY(239, 0, 42, -5, 53, -12, 67, -3, 39), - CABAC_ENTRY(240, 0, 48, -7, 61, -11, 71, -2, 44), - CABAC_ENTRY(241, 0, 55, -11, 75, -10, 77, 0, 46), - CABAC_ENTRY(242, -6, 59, -15, 77, -21, 85, -16, 64), - CABAC_ENTRY(243, -7, 71, -17, 91, -16, 88, -8, 68), - CABAC_ENTRY(244, -12, 83, -25, 107, -23, 104, -10, 78), - CABAC_ENTRY(245, -11, 87, -25, 111, -15, 98, -6, 77), - CABAC_ENTRY(246, -30, 119, -28, 122, -37, 127, -10, 86), - CABAC_ENTRY(247, 1, 58, -11, 76, -10, 82, -12, 92), - CABAC_ENTRY(248, -3, 29, -10, 44, -8, 48, -15, 55), - CABAC_ENTRY(249, -1, 36, -10, 52, -8, 61, -10, 60), - CABAC_ENTRY(250, 1, 38, -10, 57, -8, 66, -6, 62), - CABAC_ENTRY(251, 2, 43, -9, 58, -7, 70, -4, 65), - CABAC_ENTRY(252, -6, 55, -16, 72, -14, 75, -12, 73), - CABAC_ENTRY(253, 0, 58, -7, 69, -10, 79, -8, 76), - CABAC_ENTRY(254, 0, 64, -4, 69, -9, 83, -7, 80), - CABAC_ENTRY(255, -3, 74, -5, 74, -12, 92, -9, 88), - CABAC_ENTRY(256, -10, 90, -9, 86, -18, 108, -17, 110), - CABAC_ENTRY(257, 0, 70, 2, 66, -4, 79, -11, 97), - CABAC_ENTRY(258, -4, 29, -9, 34, -22, 69, -20, 84), - CABAC_ENTRY(259, 5, 31, 1, 32, -16, 75, -11, 79), - CABAC_ENTRY(260, 7, 42, 11, 31, -2, 58, -6, 73), - CABAC_ENTRY(261, 1, 59, 5, 52, 1, 58, -4, 74), - CABAC_ENTRY(262, -2, 58, -2, 55, -13, 78, -13, 86), - CABAC_ENTRY(263, -3, 72, -2, 67, -9, 83, -13, 96), - CABAC_ENTRY(264, -3, 81, 0, 73, -4, 81, -11, 97), - CABAC_ENTRY(265, -11, 97, -8, 89, -13, 99, -19, 117), - CABAC_ENTRY(266, 0, 58, 3, 52, -13, 81, -8, 78), - CABAC_ENTRY(267, 8, 5, 7, 4, -6, 38, -5, 33), - CABAC_ENTRY(268, 10, 14, 10, 8, -13, 62, -4, 48), - CABAC_ENTRY(269, 14, 18, 17, 8, -6, 58, -2, 53), - CABAC_ENTRY(270, 13, 27, 16, 19, -2, 59, -3, 62), - CABAC_ENTRY(271, 2, 40, 3, 37, -16, 73, -13, 71), - CABAC_ENTRY(272, 0, 58, -1, 61, -10, 76, -10, 79), - CABAC_ENTRY(273, -3, 70, -5, 73, -13, 86, -12, 86), - CABAC_ENTRY(274, -6, 79, -1, 70, -9, 83, -13, 90), - CABAC_ENTRY(275, -8, 85, -4, 78, -10, 87, -14, 97), - - /* Table 9-22 =E2=80=93 Values of variables m and n for ctxIdx from 277 t= o 337 */ - CABAC_ENTRY(277, -13, 106, -21, 126, -22, 127, -6, 93), - CABAC_ENTRY(278, -16, 106, -23, 124, -25, 127, -6, 84), - CABAC_ENTRY(279, -10, 87, -20, 110, -25, 120, -8, 79), - CABAC_ENTRY(280, -21, 114, -26, 126, -27, 127, 0, 66), - CABAC_ENTRY(281, -18, 110, -25, 124, -19, 114, -1, 71), - CABAC_ENTRY(282, -14, 98, -17, 105, -23, 117, 0, 62), - CABAC_ENTRY(283, -22, 110, -27, 121, -25, 118, -2, 60), - CABAC_ENTRY(284, -21, 106, -27, 117, -26, 117, -2, 59), - CABAC_ENTRY(285, -18, 103, -17, 102, -24, 113, -5, 75), - CABAC_ENTRY(286, -21, 107, -26, 117, -28, 118, -3, 62), - CABAC_ENTRY(287, -23, 108, -27, 116, -31, 120, -4, 58), - CABAC_ENTRY(288, -26, 112, -33, 122, -37, 124, -9, 66), - CABAC_ENTRY(289, -10, 96, -10, 95, -10, 94, -1, 79), - CABAC_ENTRY(290, -12, 95, -14, 100, -15, 102, 0, 71), - CABAC_ENTRY(291, -5, 91, -8, 95, -10, 99, 3, 68), - CABAC_ENTRY(292, -9, 93, -17, 111, -13, 106, 10, 44), - CABAC_ENTRY(293, -22, 94, -28, 114, -50, 127, -7, 62), - CABAC_ENTRY(294, -5, 86, -6, 89, -5, 92, 15, 36), - CABAC_ENTRY(295, 9, 67, -2, 80, 17, 57, 14, 40), - CABAC_ENTRY(296, -4, 80, -4, 82, -5, 86, 16, 27), - CABAC_ENTRY(297, -10, 85, -9, 85, -13, 94, 12, 29), - CABAC_ENTRY(298, -1, 70, -8, 81, -12, 91, 1, 44), - CABAC_ENTRY(299, 7, 60, -1, 72, -2, 77, 20, 36), - CABAC_ENTRY(300, 9, 58, 5, 64, 0, 71, 18, 32), - CABAC_ENTRY(301, 5, 61, 1, 67, -1, 73, 5, 42), - CABAC_ENTRY(302, 12, 50, 9, 56, 4, 64, 1, 48), - CABAC_ENTRY(303, 15, 50, 0, 69, -7, 81, 10, 62), - CABAC_ENTRY(304, 18, 49, 1, 69, 5, 64, 17, 46), - CABAC_ENTRY(305, 17, 54, 7, 69, 15, 57, 9, 64), - CABAC_ENTRY(306, 10, 41, -7, 69, 1, 67, -12, 104), - CABAC_ENTRY(307, 7, 46, -6, 67, 0, 68, -11, 97), - CABAC_ENTRY(308, -1, 51, -16, 77, -10, 67, -16, 96), - CABAC_ENTRY(309, 7, 49, -2, 64, 1, 68, -7, 88), - CABAC_ENTRY(310, 8, 52, 2, 61, 0, 77, -8, 85), - CABAC_ENTRY(311, 9, 41, -6, 67, 2, 64, -7, 85), - CABAC_ENTRY(312, 6, 47, -3, 64, 0, 68, -9, 85), - CABAC_ENTRY(313, 2, 55, 2, 57, -5, 78, -13, 88), - CABAC_ENTRY(314, 13, 41, -3, 65, 7, 55, 4, 66), - CABAC_ENTRY(315, 10, 44, -3, 66, 5, 59, -3, 77), - CABAC_ENTRY(316, 6, 50, 0, 62, 2, 65, -3, 76), - CABAC_ENTRY(317, 5, 53, 9, 51, 14, 54, -6, 76), - CABAC_ENTRY(318, 13, 49, -1, 66, 15, 44, 10, 58), - CABAC_ENTRY(319, 4, 63, -2, 71, 5, 60, -1, 76), - CABAC_ENTRY(320, 6, 64, -2, 75, 2, 70, -1, 83), - CABAC_ENTRY(321, -2, 69, -1, 70, -2, 76, -7, 99), - CABAC_ENTRY(322, -2, 59, -9, 72, -18, 86, -14, 95), - CABAC_ENTRY(323, 6, 70, 14, 60, 12, 70, 2, 95), - CABAC_ENTRY(324, 10, 44, 16, 37, 5, 64, 0, 76), - CABAC_ENTRY(325, 9, 31, 0, 47, -12, 70, -5, 74), - CABAC_ENTRY(326, 12, 43, 18, 35, 11, 55, 0, 70), - CABAC_ENTRY(327, 3, 53, 11, 37, 5, 56, -11, 75), - CABAC_ENTRY(328, 14, 34, 12, 41, 0, 69, 1, 68), - CABAC_ENTRY(329, 10, 38, 10, 41, 2, 65, 0, 65), - CABAC_ENTRY(330, -3, 52, 2, 48, -6, 74, -14, 73), - CABAC_ENTRY(331, 13, 40, 12, 41, 5, 54, 3, 62), - CABAC_ENTRY(332, 17, 32, 13, 41, 7, 54, 4, 62), - CABAC_ENTRY(333, 7, 44, 0, 59, -6, 76, -1, 68), - CABAC_ENTRY(334, 7, 38, 3, 50, -11, 82, -13, 75), - CABAC_ENTRY(335, 13, 50, 19, 40, -2, 77, 11, 55), - CABAC_ENTRY(336, 10, 57, 3, 66, -2, 77, 5, 64), - CABAC_ENTRY(337, 26, 43, 18, 50, 25, 42, 12, 70), - - /* Table 9-23 =E2=80=93 Values of variables m and n for ctxIdx from 338 t= o 398 */ - CABAC_ENTRY(338, 14, 11, 19, -6, 17, -13, 15, 6), - CABAC_ENTRY(339, 11, 14, 18, -6, 16, -9, 6, 19), - CABAC_ENTRY(340, 9, 11, 14, 0, 17, -12, 7, 16), - CABAC_ENTRY(341, 18, 11, 26, -12, 27, -21, 12, 14), - CABAC_ENTRY(342, 21, 9, 31, -16, 37, -30, 18, 13), - CABAC_ENTRY(343, 23, -2, 33, -25, 41, -40, 13, 11), - CABAC_ENTRY(344, 32, -15, 33, -22, 42, -41, 13, 15), - CABAC_ENTRY(345, 32, -15, 37, -28, 48, -47, 15, 16), - CABAC_ENTRY(346, 34, -21, 39, -30, 39, -32, 12, 23), - CABAC_ENTRY(347, 39, -23, 42, -30, 46, -40, 13, 23), - CABAC_ENTRY(348, 42, -33, 47, -42, 52, -51, 15, 20), - CABAC_ENTRY(349, 41, -31, 45, -36, 46, -41, 14, 26), - CABAC_ENTRY(350, 46, -28, 49, -34, 52, -39, 14, 44), - CABAC_ENTRY(351, 38, -12, 41, -17, 43, -19, 17, 40), - CABAC_ENTRY(352, 21, 29, 32, 9, 32, 11, 17, 47), - CABAC_ENTRY(353, 45, -24, 69, -71, 61, -55, 24, 17), - CABAC_ENTRY(354, 53, -45, 63, -63, 56, -46, 21, 21), - CABAC_ENTRY(355, 48, -26, 66, -64, 62, -50, 25, 22), - CABAC_ENTRY(356, 65, -43, 77, -74, 81, -67, 31, 27), - CABAC_ENTRY(357, 43, -19, 54, -39, 45, -20, 22, 29), - CABAC_ENTRY(358, 39, -10, 52, -35, 35, -2, 19, 35), - CABAC_ENTRY(359, 30, 9, 41, -10, 28, 15, 14, 50), - CABAC_ENTRY(360, 18, 26, 36, 0, 34, 1, 10, 57), - CABAC_ENTRY(361, 20, 27, 40, -1, 39, 1, 7, 63), - CABAC_ENTRY(362, 0, 57, 30, 14, 30, 17, -2, 77), - CABAC_ENTRY(363, -14, 82, 28, 26, 20, 38, -4, 82), - CABAC_ENTRY(364, -5, 75, 23, 37, 18, 45, -3, 94), - CABAC_ENTRY(365, -19, 97, 12, 55, 15, 54, 9, 69), - CABAC_ENTRY(366, -35, 125, 11, 65, 0, 79, -12, 109), - CABAC_ENTRY(367, 27, 0, 37, -33, 36, -16, 36, -35), - CABAC_ENTRY(368, 28, 0, 39, -36, 37, -14, 36, -34), - CABAC_ENTRY(369, 31, -4, 40, -37, 37, -17, 32, -26), - CABAC_ENTRY(370, 27, 6, 38, -30, 32, 1, 37, -30), - CABAC_ENTRY(371, 34, 8, 46, -33, 34, 15, 44, -32), - CABAC_ENTRY(372, 30, 10, 42, -30, 29, 15, 34, -18), - CABAC_ENTRY(373, 24, 22, 40, -24, 24, 25, 34, -15), - CABAC_ENTRY(374, 33, 19, 49, -29, 34, 22, 40, -15), - CABAC_ENTRY(375, 22, 32, 38, -12, 31, 16, 33, -7), - CABAC_ENTRY(376, 26, 31, 40, -10, 35, 18, 35, -5), - CABAC_ENTRY(377, 21, 41, 38, -3, 31, 28, 33, 0), - CABAC_ENTRY(378, 26, 44, 46, -5, 33, 41, 38, 2), - CABAC_ENTRY(379, 23, 47, 31, 20, 36, 28, 33, 13), - CABAC_ENTRY(380, 16, 65, 29, 30, 27, 47, 23, 35), - CABAC_ENTRY(381, 14, 71, 25, 44, 21, 62, 13, 58), - CABAC_ENTRY(382, 8, 60, 12, 48, 18, 31, 29, -3), - CABAC_ENTRY(383, 6, 63, 11, 49, 19, 26, 26, 0), - CABAC_ENTRY(384, 17, 65, 26, 45, 36, 24, 22, 30), - CABAC_ENTRY(385, 21, 24, 22, 22, 24, 23, 31, -7), - CABAC_ENTRY(386, 23, 20, 23, 22, 27, 16, 35, -15), - CABAC_ENTRY(387, 26, 23, 27, 21, 24, 30, 34, -3), - CABAC_ENTRY(388, 27, 32, 33, 20, 31, 29, 34, 3), - CABAC_ENTRY(389, 28, 23, 26, 28, 22, 41, 36, -1), - CABAC_ENTRY(390, 28, 24, 30, 24, 22, 42, 34, 5), - CABAC_ENTRY(391, 23, 40, 27, 34, 16, 60, 32, 11), - CABAC_ENTRY(392, 24, 32, 18, 42, 15, 52, 35, 5), - CABAC_ENTRY(393, 28, 29, 25, 39, 14, 60, 34, 12), - CABAC_ENTRY(394, 23, 42, 18, 50, 3, 78, 39, 11), - CABAC_ENTRY(395, 19, 57, 12, 70, -16, 123, 30, 29), - CABAC_ENTRY(396, 22, 53, 21, 54, 21, 53, 34, 26), - CABAC_ENTRY(397, 22, 61, 14, 71, 22, 56, 29, 39), - CABAC_ENTRY(398, 11, 86, 11, 83, 25, 61, 19, 66), - - /* Values of variables m and n for ctxIdx from 399 to 463 (not documented= ) */ - CABAC_ENTRY(399, 12, 40, 25, 32, 21, 33, 31, 21), - CABAC_ENTRY(400, 11, 51, 21, 49, 19, 50, 31, 31), - CABAC_ENTRY(401, 14, 59, 21, 54, 17, 61, 25, 50), - CABAC_ENTRY(402, -4, 79, -5, 85, -3, 78, -17, 120), - CABAC_ENTRY(403, -7, 71, -6, 81, -8, 74, -20, 112), - CABAC_ENTRY(404, -5, 69, -10, 77, -9, 72, -18, 114), - CABAC_ENTRY(405, -9, 70, -7, 81, -10, 72, -11, 85), - CABAC_ENTRY(406, -8, 66, -17, 80, -18, 75, -15, 92), - CABAC_ENTRY(407, -10, 68, -18, 73, -12, 71, -14, 89), - CABAC_ENTRY(408, -19, 73, -4, 74, -11, 63, -26, 71), - CABAC_ENTRY(409, -12, 69, -10, 83, -5, 70, -15, 81), - CABAC_ENTRY(410, -16, 70, -9, 71, -17, 75, -14, 80), - CABAC_ENTRY(411, -15, 67, -9, 67, -14, 72, 0, 68), - CABAC_ENTRY(412, -20, 62, -1, 61, -16, 67, -14, 70), - CABAC_ENTRY(413, -19, 70, -8, 66, -8, 53, -24, 56), - CABAC_ENTRY(414, -16, 66, -14, 66, -14, 59, -23, 68), - CABAC_ENTRY(415, -22, 65, 0, 59, -9, 52, -24, 50), - CABAC_ENTRY(416, -20, 63, 2, 59, -11, 68, -11, 74), - CABAC_ENTRY(417, 9, -2, 17, -10, 9, -2, 23, -13), - CABAC_ENTRY(418, 26, -9, 32, -13, 30, -10, 26, -13), - CABAC_ENTRY(419, 33, -9, 42, -9, 31, -4, 40, -15), - CABAC_ENTRY(420, 39, -7, 49, -5, 33, -1, 49, -14), - CABAC_ENTRY(421, 41, -2, 53, 0, 33, 7, 44, 3), - CABAC_ENTRY(422, 45, 3, 64, 3, 31, 12, 45, 6), - CABAC_ENTRY(423, 49, 9, 68, 10, 37, 23, 44, 34), - CABAC_ENTRY(424, 45, 27, 66, 27, 31, 38, 33, 54), - CABAC_ENTRY(425, 36, 59, 47, 57, 20, 64, 19, 82), - CABAC_ENTRY(426, -6, 66, -5, 71, -9, 71, -3, 75), - CABAC_ENTRY(427, -7, 35, 0, 24, -7, 37, -1, 23), - CABAC_ENTRY(428, -7, 42, -1, 36, -8, 44, 1, 34), - CABAC_ENTRY(429, -8, 45, -2, 42, -11, 49, 1, 43), - CABAC_ENTRY(430, -5, 48, -2, 52, -10, 56, 0, 54), - CABAC_ENTRY(431, -12, 56, -9, 57, -12, 59, -2, 55), - CABAC_ENTRY(432, -6, 60, -6, 63, -8, 63, 0, 61), - CABAC_ENTRY(433, -5, 62, -4, 65, -9, 67, 1, 64), - CABAC_ENTRY(434, -8, 66, -4, 67, -6, 68, 0, 68), - CABAC_ENTRY(435, -8, 76, -7, 82, -10, 79, -9, 92), - CABAC_ENTRY(436, -5, 85, -3, 81, -3, 78, -14, 106), - CABAC_ENTRY(437, -6, 81, -3, 76, -8, 74, -13, 97), - CABAC_ENTRY(438, -10, 77, -7, 72, -9, 72, -15, 90), - CABAC_ENTRY(439, -7, 81, -6, 78, -10, 72, -12, 90), - CABAC_ENTRY(440, -17, 80, -12, 72, -18, 75, -18, 88), - CABAC_ENTRY(441, -18, 73, -14, 68, -12, 71, -10, 73), - CABAC_ENTRY(442, -4, 74, -3, 70, -11, 63, -9, 79), - CABAC_ENTRY(443, -10, 83, -6, 76, -5, 70, -14, 86), - CABAC_ENTRY(444, -9, 71, -5, 66, -17, 75, -10, 73), - CABAC_ENTRY(445, -9, 67, -5, 62, -14, 72, -10, 70), - CABAC_ENTRY(446, -1, 61, 0, 57, -16, 67, -10, 69), - CABAC_ENTRY(447, -8, 66, -4, 61, -8, 53, -5, 66), - CABAC_ENTRY(448, -14, 66, -9, 60, -14, 59, -9, 64), - CABAC_ENTRY(449, 0, 59, 1, 54, -9, 52, -5, 58), - CABAC_ENTRY(450, 2, 59, 2, 58, -11, 68, 2, 59), - CABAC_ENTRY(451, 21, -13, 17, -10, 9, -2, 21, -10), - CABAC_ENTRY(452, 33, -14, 32, -13, 30, -10, 24, -11), - CABAC_ENTRY(453, 39, -7, 42, -9, 31, -4, 28, -8), - CABAC_ENTRY(454, 46, -2, 49, -5, 33, -1, 28, -1), - CABAC_ENTRY(455, 51, 2, 53, 0, 33, 7, 29, 3), - CABAC_ENTRY(456, 60, 6, 64, 3, 31, 12, 29, 9), - CABAC_ENTRY(457, 61, 17, 68, 10, 37, 23, 35, 20), - CABAC_ENTRY(458, 55, 34, 66, 27, 31, 38, 29, 36), - CABAC_ENTRY(459, 42, 62, 47, 57, 20, 64, 14, 67), -}; - static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) { u8 bit =3D field.offset % 32, word =3D field.offset / 32; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-hevc.c index 01f92fa27356..b01c1bb52a04 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -16,7 +16,6 @@ =20 #include "rkvdec.h" #include "rkvdec-regs.h" -#include "rkvdec-hevc-data.c" =20 /* Size in u8/u32 units. */ #define RKV_SCALING_LIST_SIZE 1360 @@ -25,6 +24,9 @@ #define RKV_RPS_SIZE (32 / 4) #define RKV_RPS_LEN 600 =20 +#define RKV_HEVC_CABAC_TABLE_SIZE 27456 +extern const u8 rkvdec_hevc_cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; + struct rkvdec_sps_pps_packet { u32 info[RKV_PPS_SIZE]; }; @@ -110,7 +112,7 @@ struct rkvdec_ps_field { =20 /* Data structure describing auxiliary buffer format. */ struct rkvdec_hevc_priv_tbl { - u8 cabac_table[RKV_CABAC_TABLE_SIZE]; + u8 cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; u8 scaling_list[RKV_SCALING_LIST_SIZE]; struct rkvdec_sps_pps_packet param_set[RKV_PPS_LEN]; struct rkvdec_rps_packet rps[RKV_RPS_LEN]; --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A49B927BF7C; Wed, 22 Oct 2025 16:25:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150347; cv=none; b=RlzAaE2lS1OhXbcTRTo0nuiod78ISMglvQGLPzWosrrGQktg1DzvkwhYkYJDmywpRleLsnoxhWDMMu+nytZIdBo/E1NdBxe+A1q+y/tT0LlCWxBzaPtt1icyRAY2o37fq5zrIPLl617SRp5tsIgL9dUnlg9MQUNyWPEuOFnl+8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150347; c=relaxed/simple; bh=8LaPy/JUz4wYgtolV664kDTBF9UYYF/LY8IQ9qzL1kI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RHWbaUzufyvD2Op2KOOiaMVJmgNnGJ0T3CPt7PW7l2iigV8uP/ulL98zd/E55ywGN1S83aMoEtLm7bOh3wzwxj4dAdDLxkQUQF3Eck+aE9jfiufQZ4TWhPMrt2prDIgx/96sR16k+0jD1S3HI9GZfeY7FC2sPwq9UtIdYe8j9gg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=cBlQDUdH; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="cBlQDUdH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150344; bh=8LaPy/JUz4wYgtolV664kDTBF9UYYF/LY8IQ9qzL1kI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cBlQDUdHAruJxENUiZOYX8c+WY9a/6RpawYDlQjxS3vG/g9lWRbvECxqDQ6PxD1iw spqpAhggv1OemWYK8i+rWzwr2bF2Ito5w2ox1viLQTqt3Iv5ut5e0HrpgEi1anurpO OdAW/OMDLbwN+dE6/5tVT0zWhFKFXPnre1jfjNCvVS5MnnOd/yY+J9xUSY1vY48Fxu yi3bqqZSUqiFxMaoSAWWYQcYLCWfR8+lJ+rntMxqO8ACaVlFdegQLJlXTT+/ndBNyj EVykMJpbRQSh9rOgRzNevr7VgwEpUylKYd5d3YPp7tlQMzvUeC3Voxy91o6Yo7FVw1 nPas2jkJCC5kg== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id CE53317E1404; Wed, 22 Oct 2025 18:25:41 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 05/15] media: rkvdec: Use structs to represent the HW RPS Date: Wed, 22 Oct 2025 12:22:04 -0400 Message-ID: <20251022162459.271603-6-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This is in preparation to add support for other variants of the decoder. Moving to struct representation is mainly to prepare for multicore support that is present in e.g. rk3588. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../platform/rockchip/rkvdec/rkvdec-h264.c | 93 +++++++++++++++++-- 1 file changed, 84 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-h264.c index 989379ae3a73..cb17dfcae5ca 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c @@ -19,7 +19,6 @@ extern const s8 rkvdec_h264_cabac_table[4][464][2]; =20 /* Size with u32 units. */ #define RKV_CABAC_INIT_BUFFER_SIZE (3680 + 128) -#define RKV_RPS_SIZE ((128 + 128) / 4) #define RKV_ERROR_INFO_SIZE (256 * 144 * 4) =20 #define RKVDEC_NUM_REFLIST 3 @@ -34,6 +33,40 @@ struct rkvdec_sps_pps_packet { u32 info[8]; }; =20 +struct rkvdec_rps_entry { + u32 dpb_info0: 5; + u32 bottom_flag0: 1; + u32 view_index_off0: 1; + u32 dpb_info1: 5; + u32 bottom_flag1: 1; + u32 view_index_off1: 1; + u32 dpb_info2: 5; + u32 bottom_flag2: 1; + u32 view_index_off2: 1; + u32 dpb_info3: 5; + u32 bottom_flag3: 1; + u32 view_index_off3: 1; + u32 dpb_info4: 5; + u32 bottom_flag4: 1; + u32 view_index_off4: 1; + u32 dpb_info5: 5; + u32 bottom_flag5: 1; + u32 view_index_off5: 1; + u32 dpb_info6: 5; + u32 bottom_flag6: 1; + u32 view_index_off6: 1; + u32 dpb_info7: 5; + u32 bottom_flag7: 1; + u32 view_index_off7: 1; +} __packed; + +struct rkvdec_rps { + u16 frame_num[16]; + u32 reserved0; + struct rkvdec_rps_entry entries[12]; + u32 reserved1[66]; +} __packed; + struct rkvdec_ps_field { u16 offset; u8 len; @@ -94,7 +127,7 @@ struct rkvdec_ps_field { struct rkvdec_h264_priv_tbl { s8 cabac_table[4][464][2]; struct rkvdec_h264_scaling_list scaling_list; - u32 rps[RKV_RPS_SIZE]; + struct rkvdec_rps rps; struct rkvdec_sps_pps_packet param_set[256]; u8 err_info[RKV_ERROR_INFO_SIZE]; }; @@ -260,6 +293,51 @@ static void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, } } =20 +static void set_dpb_info(struct rkvdec_rps_entry *entries, + u8 reflist, + u8 refnum, + u8 info, + bool bottom) +{ + struct rkvdec_rps_entry *entry =3D &entries[(reflist * 4) + refnum / 8]; + u8 idx =3D refnum % 8; + + switch (idx) { + case 0: + entry->dpb_info0 =3D info; + entry->bottom_flag0 =3D bottom; + break; + case 1: + entry->dpb_info1 =3D info; + entry->bottom_flag1 =3D bottom; + break; + case 2: + entry->dpb_info2 =3D info; + entry->bottom_flag2 =3D bottom; + break; + case 3: + entry->dpb_info3 =3D info; + entry->bottom_flag3 =3D bottom; + break; + case 4: + entry->dpb_info4 =3D info; + entry->bottom_flag4 =3D bottom; + break; + case 5: + entry->dpb_info5 =3D info; + entry->bottom_flag5 =3D bottom; + break; + case 6: + entry->dpb_info6 =3D info; + entry->bottom_flag6 =3D bottom; + break; + case 7: + entry->dpb_info7 =3D info; + entry->bottom_flag7 =3D bottom; + break; + } +} + static void assemble_hw_rps(struct rkvdec_ctx *ctx, struct v4l2_h264_reflist_builder *builder, struct rkvdec_h264_run *run) @@ -269,11 +347,10 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; =20 - u32 *hw_rps =3D priv_tbl->rps; + struct rkvdec_rps *hw_rps =3D &priv_tbl->rps; u32 i, j; - u16 *p =3D (u16 *)hw_rps; =20 - memset(hw_rps, 0, sizeof(priv_tbl->rps)); + memset(hw_rps, 0, sizeof(*hw_rps)); =20 /* * Assign an invalid pic_num if DPB entry at that position is inactive. @@ -285,7 +362,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) continue; =20 - p[i] =3D builder->refs[i].frame_num; + hw_rps->frame_num[i] =3D builder->refs[i].frame_num; } =20 for (j =3D 0; j < RKVDEC_NUM_REFLIST; j++) { @@ -312,9 +389,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, dpb_valid =3D run->ref_buf[ref->index] !=3D NULL; bottom =3D ref->fields =3D=3D V4L2_H264_BOTTOM_FIELD_REF; =20 - set_ps_field(hw_rps, DPB_INFO(i, j), - ref->index | dpb_valid << 4); - set_ps_field(hw_rps, BOTTOM_FLAG(i, j), bottom); + set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bott= om); } } } --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75DD33563D5; Wed, 22 Oct 2025 16:25:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150351; cv=none; b=s0mBpL6LesmUx9yWB4xr52pUNVkOm5Qude9thr79vMp9toeYHUhlP+rw8nHlhT/MUq+tG5p4PiLwNSJ5cBcdRZb+PGZ0JHkvDjAUH7F7MOyaOH2VKENwDncoFbsblU2S3jXAI+J5yeU5iSoMI5wjZpp2oUBmJMd5YJrGHhQzTXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150351; c=relaxed/simple; bh=K/hFxLstWBVepDqhjgr+37ksdfcWBhFrOmL+ypYPFbM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TDc17xQiDKARyzJYkIA9vRm3aBz+CnE1qaoyMOvtZMPLozqy6RJ+jP0wMVxds9PgEenyZaDZ7Dit3nCaxfU4iL8hwI5Sj66fYvSAFcE1z5KOkhpI3ijSjJMn1n/arPHK7DUJCu2CEDoe63KdR6XsngUs0NP81XAQcPmqJMOfTek= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=YaqP0sEX; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="YaqP0sEX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150347; bh=K/hFxLstWBVepDqhjgr+37ksdfcWBhFrOmL+ypYPFbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YaqP0sEXygrSn5GM1LjHYiKkM0ljDPRi4oopyY8ZPgtU32RDgZVfqh3kOO0phZCdS Dt7dlEt/TeHqHXRDeoJL5+o9FTrt95As5CQwfXSSFYKE2iLFga6JwtQmPvbgAIloip 6iGF5g3Ch0X+haQGm1uXMuUllfDOnsZQuPlhCpHSL9KLGgNvGyjMO+9hKMvfkzXyIo 6CMs+/bwBnDGm17Jo4p2NKx/2doOrVlcWNCpoOLOlZMi8lIjKIAvAZmxWVuKMZgJyu hQyBthHe69ox7IzZO0N+kHTnM4L5zwDGK/S4l4wVsv1Zx4nbE2s842FpEnOZgLMBh9 OHLDlBbGErDng== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 929B517E1407; Wed, 22 Oct 2025 18:25:44 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 06/15] media: rkvdec: Move h264 functions to common file Date: Wed, 22 Oct 2025 12:22:05 -0400 Message-ID: <20251022162459.271603-7-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This is a preparation commit to add support for new variants of the decoder. The functions will later be shared with vdpu381 (rk3588) and vdpu383 (rk3576). Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-h264-common.c | 252 ++++++++++++++ .../rockchip/rkvdec/rkvdec-h264-common.h | 81 +++++ .../platform/rockchip/rkvdec/rkvdec-h264.c | 310 +----------------- 4 files changed, 338 insertions(+), 306 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-h264-comm= on.c create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-h264-comm= on.h diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index a8ff5e3d7bec..d2ba7a7c15e5 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -4,5 +4,6 @@ rockchip-vdec-y +=3D \ rkvdec.o \ rkvdec-cabac.o \ rkvdec-h264.o \ + rkvdec-h264-common.o \ rkvdec-hevc.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c b/= drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c new file mode 100644 index 000000000000..d660dd81ca6e --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip video decoder h264 common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include +#include + +#include "rkvdec.h" +#include "rkvdec-h264-common.h" + +#define RKVDEC_NUM_REFLIST 3 + +static void set_dpb_info(struct rkvdec_rps_entry *entries, + u8 reflist, + u8 refnum, + u8 info, + bool bottom) +{ + struct rkvdec_rps_entry *entry =3D &entries[(reflist * 4) + refnum / 8]; + u8 idx =3D refnum % 8; + + switch (idx) { + case 0: + entry->dpb_info0 =3D info; + entry->bottom_flag0 =3D bottom; + break; + case 1: + entry->dpb_info1 =3D info; + entry->bottom_flag1 =3D bottom; + break; + case 2: + entry->dpb_info2 =3D info; + entry->bottom_flag2 =3D bottom; + break; + case 3: + entry->dpb_info3 =3D info; + entry->bottom_flag3 =3D bottom; + break; + case 4: + entry->dpb_info4 =3D info; + entry->bottom_flag4 =3D bottom; + break; + case 5: + entry->dpb_info5 =3D info; + entry->bottom_flag5 =3D bottom; + break; + case 6: + entry->dpb_info6 =3D info; + entry->bottom_flag6 =3D bottom; + break; + case 7: + entry->dpb_info7 =3D info; + entry->bottom_flag7 =3D bottom; + break; + } +} + +void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + u32 i; + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct v4l2_m2m_ctx *m2m_ctx =3D ctx->fh.m2m_ctx; + const struct v4l2_h264_dpb_entry *dpb =3D run->decode_params->dpb; + struct vb2_queue *cap_q =3D &m2m_ctx->cap_q_ctx.q; + struct vb2_buffer *buf =3D NULL; + + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { + buf =3D vb2_find_buffer(cap_q, dpb[i].reference_ts); + if (!buf) + pr_debug("No buffer for reference_ts %llu", + dpb[i].reference_ts); + } + + run->ref_buf[i] =3D buf; + } +} + +void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder, + struct rkvdec_h264_run *run, + struct rkvdec_h264_reflists *reflists, + struct rkvdec_rps *hw_rps) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + + u32 i, j; + + memset(hw_rps, 0, sizeof(*hw_rps)); + + /* + * Assign an invalid pic_num if DPB entry at that position is inactive. + * If we assign 0 in that position hardware will treat that as a real + * reference picture with pic_num 0, triggering output picture + * corruption. + */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) + continue; + + hw_rps->frame_num[i] =3D builder->refs[i].frame_num; + } + + for (j =3D 0; j < RKVDEC_NUM_REFLIST; j++) { + for (i =3D 0; i < builder->num_valid; i++) { + struct v4l2_h264_reference *ref; + bool dpb_valid; + bool bottom; + + switch (j) { + case 0: + ref =3D &reflists->p[i]; + break; + case 1: + ref =3D &reflists->b0[i]; + break; + case 2: + ref =3D &reflists->b1[i]; + break; + } + + if (WARN_ON(ref->index >=3D ARRAY_SIZE(dec_params->dpb))) + continue; + + dpb_valid =3D !!(run->ref_buf[ref->index]); + bottom =3D ref->fields =3D=3D V4L2_H264_BOTTOM_FIELD_REF; + + set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bott= om); + } + } +} + +void assemble_hw_scaling_list(struct rkvdec_h264_run *run, + struct rkvdec_h264_scaling_list *scaling_list) +{ + const struct v4l2_ctrl_h264_scaling_matrix *scaling =3D run->scaling_matr= ix; + const struct v4l2_ctrl_h264_pps *pps =3D run->pps; + + if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) + return; + + BUILD_BUG_ON(sizeof(scaling_list->scaling_list_4x4) !=3D + sizeof(scaling->scaling_list_4x4)); + BUILD_BUG_ON(sizeof(scaling_list->scaling_list_8x8) !=3D + sizeof(scaling->scaling_list_8x8)); + + memcpy(scaling_list->scaling_list_4x4, + scaling->scaling_list_4x4, + sizeof(scaling->scaling_list_4x4)); + + memcpy(scaling_list->scaling_list_8x8, + scaling->scaling_list_8x8, + sizeof(scaling->scaling_list_8x8)); +} + +#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2 + +int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *fmt =3D &f->fmt.pix_mp; + + fmt->num_planes =3D 1; + if (!fmt->plane_fmt[0].sizeimage) + fmt->plane_fmt[0].sizeimage =3D fmt->width * fmt->height * + RKVDEC_H264_MAX_DEPTH_IN_BYTES; + return 0; +} + +enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx, + struct v4l2_ctrl *ctrl) +{ + const struct v4l2_ctrl_h264_sps *sps =3D ctrl->p_new.p_h264_sps; + + if (ctrl->id !=3D V4L2_CID_STATELESS_H264_SPS) + return RKVDEC_IMG_FMT_ANY; + + if (sps->bit_depth_luma_minus8 =3D=3D 0) { + if (sps->chroma_format_idc =3D=3D 2) + return RKVDEC_IMG_FMT_422_8BIT; + else + return RKVDEC_IMG_FMT_420_8BIT; + } else if (sps->bit_depth_luma_minus8 =3D=3D 2) { + if (sps->chroma_format_idc =3D=3D 2) + return RKVDEC_IMG_FMT_422_10BIT; + else + return RKVDEC_IMG_FMT_420_10BIT; + } + + return RKVDEC_IMG_FMT_ANY; +} + +int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_h264_sps *sps) +{ + unsigned int width, height; + + 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 !=3D sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 !=3D 0 && sps->bit_depth_luma_minus8 !=3D = 2) + /* Only 8-bit and 10-bit is supported */ + return -EINVAL; + + width =3D (sps->pic_width_in_mbs_minus1 + 1) * 16; + height =3D (sps->pic_height_in_map_units_minus1 + 1) * 16; + + /* + * When frame_mbs_only_flag is not set, this is field height, + * which is half the final height (see (7-18) in the + * specification) + */ + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) + height *=3D 2; + + if (width > ctx->coded_fmt.fmt.pix_mp.width || + height > ctx->coded_fmt.fmt.pix_mp.height) + return -EINVAL; + + return 0; +} + +void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + struct v4l2_ctrl *ctrl; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_DECODE_PARAMS); + run->decode_params =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_SPS); + run->sps =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_PPS); + run->pps =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_SCALING_MATRIX); + run->scaling_matrix =3D ctrl ? ctrl->p_cur.p : NULL; + + rkvdec_run_preamble(ctx, &run->base); +} diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h new file mode 100644 index 000000000000..aea346744e4c --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip video decoder h264 common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include + +#include "rkvdec.h" + +extern const s8 rkvdec_h264_cabac_table[4][464][2]; + +struct rkvdec_h264_scaling_list { + u8 scaling_list_4x4[6][16]; + u8 scaling_list_8x8[6][64]; + u8 padding[128]; +}; + +struct rkvdec_h264_reflists { + struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN]; + struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN]; + struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN]; +}; + +struct rkvdec_h264_run { + struct rkvdec_run base; + const struct v4l2_ctrl_h264_decode_params *decode_params; + const struct v4l2_ctrl_h264_sps *sps; + const struct v4l2_ctrl_h264_pps *pps; + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; + struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES]; +}; + +struct rkvdec_rps_entry { + u32 dpb_info0: 5; + u32 bottom_flag0: 1; + u32 view_index_off0: 1; + u32 dpb_info1: 5; + u32 bottom_flag1: 1; + u32 view_index_off1: 1; + u32 dpb_info2: 5; + u32 bottom_flag2: 1; + u32 view_index_off2: 1; + u32 dpb_info3: 5; + u32 bottom_flag3: 1; + u32 view_index_off3: 1; + u32 dpb_info4: 5; + u32 bottom_flag4: 1; + u32 view_index_off4: 1; + u32 dpb_info5: 5; + u32 bottom_flag5: 1; + u32 view_index_off5: 1; + u32 dpb_info6: 5; + u32 bottom_flag6: 1; + u32 view_index_off6: 1; + u32 dpb_info7: 5; + u32 bottom_flag7: 1; + u32 view_index_off7: 1; +} __packed; + +struct rkvdec_rps { + u16 frame_num[16]; + u32 reserved0; + struct rkvdec_rps_entry entries[12]; + u32 reserved1[66]; +} __packed; + +void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *ru= n); +void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder, + struct rkvdec_h264_run *run, + struct rkvdec_h264_reflists *reflists, + struct rkvdec_rps *hw_rps); +void assemble_hw_scaling_list(struct rkvdec_h264_run *run, + struct rkvdec_h264_scaling_list *scaling_list); +int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f); +enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx, st= ruct v4l2_ctrl *ctrl); +int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, const struct v4l2_ctr= l_h264_sps *sps); +void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_h264_r= un *run); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-h264.c index cb17dfcae5ca..e98bb69ff7f9 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c @@ -14,59 +14,16 @@ =20 #include "rkvdec.h" #include "rkvdec-regs.h" - -extern const s8 rkvdec_h264_cabac_table[4][464][2]; +#include "rkvdec-h264-common.h" =20 /* Size with u32 units. */ #define RKV_CABAC_INIT_BUFFER_SIZE (3680 + 128) #define RKV_ERROR_INFO_SIZE (256 * 144 * 4) =20 -#define RKVDEC_NUM_REFLIST 3 - -struct rkvdec_h264_scaling_list { - u8 scaling_list_4x4[6][16]; - u8 scaling_list_8x8[6][64]; - u8 padding[128]; -}; - struct rkvdec_sps_pps_packet { u32 info[8]; }; =20 -struct rkvdec_rps_entry { - u32 dpb_info0: 5; - u32 bottom_flag0: 1; - u32 view_index_off0: 1; - u32 dpb_info1: 5; - u32 bottom_flag1: 1; - u32 view_index_off1: 1; - u32 dpb_info2: 5; - u32 bottom_flag2: 1; - u32 view_index_off2: 1; - u32 dpb_info3: 5; - u32 bottom_flag3: 1; - u32 view_index_off3: 1; - u32 dpb_info4: 5; - u32 bottom_flag4: 1; - u32 view_index_off4: 1; - u32 dpb_info5: 5; - u32 bottom_flag5: 1; - u32 view_index_off5: 1; - u32 dpb_info6: 5; - u32 bottom_flag6: 1; - u32 view_index_off6: 1; - u32 dpb_info7: 5; - u32 bottom_flag7: 1; - u32 view_index_off7: 1; -} __packed; - -struct rkvdec_rps { - u16 frame_num[16]; - u32 reserved0; - struct rkvdec_rps_entry entries[12]; - u32 reserved1[66]; -} __packed; - struct rkvdec_ps_field { u16 offset; u8 len; @@ -118,11 +75,6 @@ struct rkvdec_ps_field { #define SCALING_LIST_ADDRESS PS_FIELD(184, 32) #define IS_LONG_TERM(i) PS_FIELD(216 + (i), 1) =20 -#define DPB_OFFS(i, j) (288 + ((j) * 32 * 7) + ((i) * 7)) -#define DPB_INFO(i, j) PS_FIELD(DPB_OFFS(i, j), 5) -#define BOTTOM_FLAG(i, j) PS_FIELD(DPB_OFFS(i, j) + 5, 1) -#define VIEW_INDEX_OFF(i, j) PS_FIELD(DPB_OFFS(i, j) + 6, 1) - /* Data structure describing auxiliary buffer format. */ struct rkvdec_h264_priv_tbl { s8 cabac_table[4][464][2]; @@ -132,21 +84,6 @@ struct rkvdec_h264_priv_tbl { u8 err_info[RKV_ERROR_INFO_SIZE]; }; =20 -struct rkvdec_h264_reflists { - struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN]; - struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN]; - struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN]; -}; - -struct rkvdec_h264_run { - struct rkvdec_run base; - const struct v4l2_ctrl_h264_decode_params *decode_params; - const struct v4l2_ctrl_h264_sps *sps; - const struct v4l2_ctrl_h264_pps *pps; - const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; - struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES]; -}; - struct rkvdec_h264_ctx { struct rkvdec_aux_buf priv_tbl; struct rkvdec_h264_reflists reflists; @@ -270,155 +207,6 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, } } =20 -static void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, - struct rkvdec_h264_run *run) -{ - const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; - u32 i; - - for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { - struct v4l2_m2m_ctx *m2m_ctx =3D ctx->fh.m2m_ctx; - const struct v4l2_h264_dpb_entry *dpb =3D run->decode_params->dpb; - struct vb2_queue *cap_q =3D &m2m_ctx->cap_q_ctx.q; - struct vb2_buffer *buf =3D NULL; - - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { - buf =3D vb2_find_buffer(cap_q, dpb[i].reference_ts); - if (!buf) - pr_debug("No buffer for reference_ts %llu", - dpb[i].reference_ts); - } - - run->ref_buf[i] =3D buf; - } -} - -static void set_dpb_info(struct rkvdec_rps_entry *entries, - u8 reflist, - u8 refnum, - u8 info, - bool bottom) -{ - struct rkvdec_rps_entry *entry =3D &entries[(reflist * 4) + refnum / 8]; - u8 idx =3D refnum % 8; - - switch (idx) { - case 0: - entry->dpb_info0 =3D info; - entry->bottom_flag0 =3D bottom; - break; - case 1: - entry->dpb_info1 =3D info; - entry->bottom_flag1 =3D bottom; - break; - case 2: - entry->dpb_info2 =3D info; - entry->bottom_flag2 =3D bottom; - break; - case 3: - entry->dpb_info3 =3D info; - entry->bottom_flag3 =3D bottom; - break; - case 4: - entry->dpb_info4 =3D info; - entry->bottom_flag4 =3D bottom; - break; - case 5: - entry->dpb_info5 =3D info; - entry->bottom_flag5 =3D bottom; - break; - case 6: - entry->dpb_info6 =3D info; - entry->bottom_flag6 =3D bottom; - break; - case 7: - entry->dpb_info7 =3D info; - entry->bottom_flag7 =3D bottom; - break; - } -} - -static void assemble_hw_rps(struct rkvdec_ctx *ctx, - struct v4l2_h264_reflist_builder *builder, - struct rkvdec_h264_run *run) -{ - const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; - const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; - struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; - struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; - - struct rkvdec_rps *hw_rps =3D &priv_tbl->rps; - u32 i, j; - - memset(hw_rps, 0, sizeof(*hw_rps)); - - /* - * Assign an invalid pic_num if DPB entry at that position is inactive. - * If we assign 0 in that position hardware will treat that as a real - * reference picture with pic_num 0, triggering output picture - * corruption. - */ - for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { - if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) - continue; - - hw_rps->frame_num[i] =3D builder->refs[i].frame_num; - } - - for (j =3D 0; j < RKVDEC_NUM_REFLIST; j++) { - for (i =3D 0; i < builder->num_valid; i++) { - struct v4l2_h264_reference *ref; - bool dpb_valid; - bool bottom; - - switch (j) { - case 0: - ref =3D &h264_ctx->reflists.p[i]; - break; - case 1: - ref =3D &h264_ctx->reflists.b0[i]; - break; - case 2: - ref =3D &h264_ctx->reflists.b1[i]; - break; - } - - if (WARN_ON(ref->index >=3D ARRAY_SIZE(dec_params->dpb))) - continue; - - dpb_valid =3D run->ref_buf[ref->index] !=3D NULL; - bottom =3D ref->fields =3D=3D V4L2_H264_BOTTOM_FIELD_REF; - - set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bott= om); - } - } -} - -static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, - struct rkvdec_h264_run *run) -{ - const struct v4l2_ctrl_h264_scaling_matrix *scaling =3D run->scaling_matr= ix; - const struct v4l2_ctrl_h264_pps *pps =3D run->pps; - struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; - struct rkvdec_h264_priv_tbl *tbl =3D 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) !=3D - sizeof(scaling->scaling_list_4x4)); - BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_8x8) !=3D - sizeof(scaling->scaling_list_8x8)); - - memcpy(tbl->scaling_list.scaling_list_4x4, - scaling->scaling_list_4x4, - sizeof(scaling->scaling_list_4x4)); - - memcpy(tbl->scaling_list.scaling_list_8x8, - scaling->scaling_list_8x8, - sizeof(scaling->scaling_list_8x8)); -} - /* * Set the ref POC in the correct register. * @@ -568,76 +356,6 @@ static void config_registers(struct rkvdec_ctx *ctx, rkvdec_memcpy_toio(rkvdec->regs, regs, MIN(sizeof(*regs), 4 * rkvdec->var= iant->num_regs)); } =20 -#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2 - -static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, - struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *fmt =3D &f->fmt.pix_mp; - - fmt->num_planes =3D 1; - if (!fmt->plane_fmt[0].sizeimage) - fmt->plane_fmt[0].sizeimage =3D fmt->width * fmt->height * - RKVDEC_H264_MAX_DEPTH_IN_BYTES; - return 0; -} - -static enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *= ctx, - struct v4l2_ctrl *ctrl) -{ - const struct v4l2_ctrl_h264_sps *sps =3D ctrl->p_new.p_h264_sps; - - if (ctrl->id !=3D V4L2_CID_STATELESS_H264_SPS) - return RKVDEC_IMG_FMT_ANY; - - if (sps->bit_depth_luma_minus8 =3D=3D 0) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_8BIT; - else - return RKVDEC_IMG_FMT_420_8BIT; - } else if (sps->bit_depth_luma_minus8 =3D=3D 2) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_10BIT; - else - return RKVDEC_IMG_FMT_420_10BIT; - } - - return RKVDEC_IMG_FMT_ANY; -} - -static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, - const struct v4l2_ctrl_h264_sps *sps) -{ - unsigned int width, height; - - 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 !=3D sps->bit_depth_chroma_minus8) - /* Luma and chroma bit depth mismatch */ - return -EINVAL; - if (sps->bit_depth_luma_minus8 !=3D 0 && sps->bit_depth_luma_minus8 !=3D = 2) - /* Only 8-bit and 10-bit is supported */ - return -EINVAL; - - width =3D (sps->pic_width_in_mbs_minus1 + 1) * 16; - height =3D (sps->pic_height_in_map_units_minus1 + 1) * 16; - - /* - * When frame_mbs_only_flag is not set, this is field height, - * which is half the final height (see (7-18) in the - * specification) - */ - if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) - height *=3D 2; - - if (width > ctx->coded_fmt.fmt.pix_mp.width || - height > ctx->coded_fmt.fmt.pix_mp.height) - return -EINVAL; - - return 0; -} - static int rkvdec_h264_start(struct rkvdec_ctx *ctx) { struct rkvdec_dev *rkvdec =3D ctx->dev; @@ -689,33 +407,13 @@ static void rkvdec_h264_stop(struct rkvdec_ctx *ctx) kfree(h264_ctx); } =20 -static void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, - struct rkvdec_h264_run *run) -{ - struct v4l2_ctrl *ctrl; - - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_H264_DECODE_PARAMS); - run->decode_params =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_H264_SPS); - run->sps =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_H264_PPS); - run->pps =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_H264_SCALING_MATRIX); - run->scaling_matrix =3D ctrl ? ctrl->p_cur.p : NULL; - - rkvdec_run_preamble(ctx, &run->base); -} - static int rkvdec_h264_run(struct rkvdec_ctx *ctx) { struct v4l2_h264_reflist_builder reflist_builder; struct rkvdec_dev *rkvdec =3D ctx->dev; struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; struct rkvdec_h264_run run; + struct rkvdec_h264_priv_tbl *tbl =3D h264_ctx->priv_tbl.cpu; =20 rkvdec_h264_run_preamble(ctx, &run); =20 @@ -726,10 +424,10 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, h264_ctx->reflists.b1); =20 - assemble_hw_scaling_list(ctx, &run); + assemble_hw_scaling_list(&run, &tbl->scaling_list); assemble_hw_pps(ctx, &run); lookup_ref_buf_idx(ctx, &run); - assemble_hw_rps(ctx, &reflist_builder, &run); + assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps); config_registers(ctx, &run); =20 rkvdec_run_postamble(ctx, &run.base); --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E26327BF7C; Wed, 22 Oct 2025 16:25:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150354; cv=none; b=cZex2IK7AMjYn0UfN08+jnFVwzHKS5aDQIDzBnFLw2PTH4ulItWv8TthnY6+D+mOUtyf10v1kf7KTnlPHIx+m/ukpl3Gh0M5fvh9r5wVjHSqbAo1b9pCD0n776/x5Lz8NuhvdTdsj3IQG6vav0hB+aZtx4BWvQvB7O+x0ZMrrbI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150354; c=relaxed/simple; bh=p6jGiM+GGEp9U5AHK1oND8hRojGmvlhceK8h3kX7S50=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BaMmaZeEa0ZgHYAQRL3TJGYJF4DBqhT6MkD1MWpCQGm3bxI8xpfZp/I0h3g91MAkIp6czWCjWTtWZcPBgQJnI06ovjRadHHtd2GocRaAx+ueEUaHk2abrkrF9O7X1CXPrq+tLbe+KsrV/xnkmoieNWhRxoKSTQ1Af7+1BWmdJGg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=YUQ09nmf; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="YUQ09nmf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150349; bh=p6jGiM+GGEp9U5AHK1oND8hRojGmvlhceK8h3kX7S50=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YUQ09nmfUGoMO5u/UbI2mAYfSIQSeDuGTiaVbxLN1GdoaQEAgMkIHlILkzP8FFAM+ 4dYR3H15OGr8yUihUylFINBRcCB6BE/odL28w+CF84Odj806P0S0eC9ssul42KcEpb zoN5G2vMqWnwu5KGGTWC8wLIPX+rywlUGnOf+hW7WtHg0lsVgxNeMASQuDxiidmAw0 PIJywpaXxmjZcOwAvZi+jgn2eqc1+eY7v436uDmepuLEUmV9n9zQiE4MNC/9soAIjD EM0nPyH/henkQeID/03o0VBEhWBvdQwvEFRZLyTz6U86mepuCrEhS/NLEQxDr2xf69 EGO6o3HUF/RVg== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 598B717E1413; Wed, 22 Oct 2025 18:25:47 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 07/15] media: rkvdec: Move hevc functions to common file Date: Wed, 22 Oct 2025 12:22:06 -0400 Message-ID: <20251022162459.271603-8-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This is a preparation commit to add support for new variants of the decoder. The functions will later be shared with vdpu381 (rk3588) and vdpu383 (rk3576). Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 233 +++++++++++++++++ .../rockchip/rkvdec/rkvdec-hevc-common.h | 51 ++++ .../platform/rockchip/rkvdec/rkvdec-hevc.c | 243 +----------------- 4 files changed, 291 insertions(+), 237 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-comm= on.c create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-comm= on.h diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index d2ba7a7c15e5..1b4bc44be23e 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -6,4 +6,5 @@ rockchip-vdec-y +=3D \ rkvdec-h264.o \ rkvdec-h264-common.o \ rkvdec-hevc.o \ + rkvdec-hevc-common.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c new file mode 100644 index 000000000000..d571107f2242 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip video decoder hevc common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + * + * Copyright (C) 2023 Collabora, Ltd. + * Sebastian Fricke + * + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon + * + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Jeffy Chen + */ + +#include +#include + +#include "rkvdec.h" +#include "rkvdec-hevc-common.h" + +/* + * Flip one or more matrices along their main diagonal and flatten them + * before writing it to the memory. + * Convert: + * ABCD AEIM + * EFGH =3D> BFJN =3D> AEIMBFJNCGKODHLP + * IJKL CGKO + * MNOP DHLP + */ +static void transpose_and_flatten_matrices(u8 *output, const u8 *input, + int matrices, int row_length) +{ + int i, j, row, x_offset, matrix_offset, rot_index, y_offset, matrix_size,= new_value; + + matrix_size =3D row_length * row_length; + for (i =3D 0; i < matrices; i++) { + row =3D 0; + x_offset =3D 0; + matrix_offset =3D i * matrix_size; + for (j =3D 0; j < matrix_size; j++) { + y_offset =3D j - (row * row_length); + rot_index =3D y_offset * row_length + x_offset; + new_value =3D *(input + i * matrix_size + j); + output[matrix_offset + rot_index] =3D new_value; + if ((j + 1) % row_length =3D=3D 0) { + row +=3D 1; + x_offset +=3D 1; + } + } + } +} + +static void assemble_scalingfactor0(u8 *output, const struct v4l2_ctrl_hev= c_scaling_matrix *input) +{ + int offset =3D 0; + + transpose_and_flatten_matrices(output, (const u8 *)input->scaling_list_4x= 4, 6, 4); + offset =3D 6 * 16 * sizeof(u8); + transpose_and_flatten_matrices(output + offset, (const u8 *)input->scalin= g_list_8x8, 6, 8); + offset +=3D 6 * 64 * sizeof(u8); + transpose_and_flatten_matrices(output + offset, + (const u8 *)input->scaling_list_16x16, 6, 8); + offset +=3D 6 * 64 * sizeof(u8); + /* Add a 128 byte padding with 0s between the two 32x32 matrices */ + transpose_and_flatten_matrices(output + offset, + (const u8 *)input->scaling_list_32x32, 1, 8); + offset +=3D 64 * sizeof(u8); + memset(output + offset, 0, 128); + offset +=3D 128 * sizeof(u8); + transpose_and_flatten_matrices(output + offset, + (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), + 1, 8); + offset +=3D 64 * sizeof(u8); + memset(output + offset, 0, 128); +} + +/* + * Required layout: + * A =3D scaling_list_dc_coef_16x16 + * B =3D scaling_list_dc_coef_32x32 + * 0 =3D Padding + * + * A, A, A, A, A, A, B, 0, 0, B, 0, 0 + */ +static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_sca= ling_matrix *input) +{ + u8 list_32x32[6] =3D {0}; + + memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8)); + list_32x32[0] =3D input->scaling_list_dc_coef_32x32[0]; + list_32x32[3] =3D input->scaling_list_dc_coef_32x32[1]; + memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8)); +} + +static void translate_scaling_list(struct scaling_factor *output, + const struct v4l2_ctrl_hevc_scaling_matrix *input) +{ + assemble_scalingfactor0(output->scalingfactor0, input); + memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96); + assemble_scalingdc(output->scalingdc, input); + memset(output->reserved, 0, 4 * sizeof(u8)); +} + +void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, + struct scaling_factor *scaling_factor, + struct v4l2_ctrl_hevc_scaling_matrix *cache) +{ + const struct v4l2_ctrl_hevc_scaling_matrix *scaling =3D run->scaling_matr= ix; + + if (!memcmp(cache, scaling, + sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) + return; + + translate_scaling_list(scaling_factor, scaling); + + memcpy(cache, scaling, + sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); +} + +struct vb2_buffer * +get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, + unsigned int dpb_idx) +{ + struct v4l2_m2m_ctx *m2m_ctx =3D ctx->fh.m2m_ctx; + const struct v4l2_ctrl_hevc_decode_params *decode_params =3D run->decode_= params; + const struct v4l2_hevc_dpb_entry *dpb =3D decode_params->dpb; + struct vb2_queue *cap_q =3D &m2m_ctx->cap_q_ctx.q; + struct vb2_buffer *buf =3D NULL; + + if (dpb_idx < decode_params->num_active_dpb_entries) + buf =3D vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp); + + /* + * If a DPB entry is unused or invalid, the address of current destination + * buffer is returned. + */ + if (!buf) + return &run->base.bufs.dst->vb2_buf; + + return buf; +} + +#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 + +int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *fmt =3D &f->fmt.pix_mp; + + fmt->num_planes =3D 1; + if (!fmt->plane_fmt[0].sizeimage) + fmt->plane_fmt[0].sizeimage =3D fmt->width * fmt->height * + RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; + return 0; +} + +enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, + struct v4l2_ctrl *ctrl) +{ + const struct v4l2_ctrl_hevc_sps *sps =3D ctrl->p_new.p_hevc_sps; + + if (ctrl->id !=3D V4L2_CID_STATELESS_HEVC_SPS) + return RKVDEC_IMG_FMT_ANY; + + if (sps->bit_depth_luma_minus8 =3D=3D 0) { + if (sps->chroma_format_idc =3D=3D 2) + return RKVDEC_IMG_FMT_422_8BIT; + else + return RKVDEC_IMG_FMT_420_8BIT; + } else if (sps->bit_depth_luma_minus8 =3D=3D 2) { + if (sps->chroma_format_idc =3D=3D 2) + return RKVDEC_IMG_FMT_422_10BIT; + else + return RKVDEC_IMG_FMT_420_10BIT; + } + + return RKVDEC_IMG_FMT_ANY; +} + +static int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_hevc_sps *sps) +{ + if (sps->chroma_format_idc > 1) + /* Only 4:0:0 and 4:2:0 are supported */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 !=3D sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 !=3D 0 && sps->bit_depth_luma_minus8 !=3D = 2) + /* Only 8-bit and 10-bit are supported */ + return -EINVAL; + + if (sps->pic_width_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.width || + sps->pic_height_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.height) + return -EINVAL; + + return 0; +} + +void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + struct v4l2_ctrl *ctrl; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); + run->decode_params =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_SLICE_PARAMS); + run->slices_params =3D ctrl ? ctrl->p_cur.p : NULL; + run->num_slices =3D ctrl ? ctrl->new_elems : 0; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_SPS); + run->sps =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_PPS); + run->pps =3D ctrl ? ctrl->p_cur.p : NULL; + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); + run->scaling_matrix =3D ctrl ? ctrl->p_cur.p : NULL; + + rkvdec_run_preamble(ctx, &run->base); +} + +int rkvdec_hevc_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) +{ + if (ctrl->id =3D=3D V4L2_CID_STATELESS_HEVC_SPS) + return rkvdec_hevc_validate_sps(ctx, ctrl->p_new.p_hevc_sps); + + return 0; +} diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h new file mode 100644 index 000000000000..746b1bd73c08 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip video decoder hevc common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + * + * Copyright (C) 2023 Collabora, Ltd. + * Sebastian Fricke + * + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon + * + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Jeffy Chen + */ + +#include +#include "rkvdec.h" + +#define RKV_HEVC_CABAC_TABLE_SIZE 27456 +extern const u8 rkvdec_hevc_cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; + +struct rkvdec_hevc_run { + struct rkvdec_run base; + const struct v4l2_ctrl_hevc_slice_params *slices_params; + const struct v4l2_ctrl_hevc_decode_params *decode_params; + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; + int num_slices; +}; + +struct scaling_factor { + u8 scalingfactor0[1248]; + u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ + u8 scalingdc[12]; /*N1005 Vienna Meeting*/ + u8 reserved[4]; /*16Bytes align*/ +}; + +enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, + struct v4l2_ctrl *ctrl); +void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, + struct scaling_factor *scaling_factor, + struct v4l2_ctrl_hevc_scaling_matrix *cache); +struct vb2_buffer *get_ref_buf(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run, + unsigned int dpb_idx); +int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f); +int rkvdec_hevc_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); +void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_hevc_r= un *run); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-hevc.c index b01c1bb52a04..31a979698578 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -16,6 +16,7 @@ =20 #include "rkvdec.h" #include "rkvdec-regs.h" +#include "rkvdec-hevc-common.h" =20 /* Size in u8/u32 units. */ #define RKV_SCALING_LIST_SIZE 1360 @@ -24,9 +25,6 @@ #define RKV_RPS_SIZE (32 / 4) #define RKV_RPS_LEN 600 =20 -#define RKV_HEVC_CABAC_TABLE_SIZE 27456 -extern const u8 rkvdec_hevc_cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; - struct rkvdec_sps_pps_packet { u32 info[RKV_PPS_SIZE]; }; @@ -113,34 +111,17 @@ struct rkvdec_ps_field { /* Data structure describing auxiliary buffer format. */ struct rkvdec_hevc_priv_tbl { u8 cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; - u8 scaling_list[RKV_SCALING_LIST_SIZE]; + struct scaling_factor scaling_list; struct rkvdec_sps_pps_packet param_set[RKV_PPS_LEN]; struct rkvdec_rps_packet rps[RKV_RPS_LEN]; }; =20 -struct rkvdec_hevc_run { - struct rkvdec_run base; - const struct v4l2_ctrl_hevc_slice_params *slices_params; - const struct v4l2_ctrl_hevc_decode_params *decode_params; - const struct v4l2_ctrl_hevc_sps *sps; - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; - int num_slices; -}; - struct rkvdec_hevc_ctx { struct rkvdec_aux_buf priv_tbl; struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; struct rkvdec_regs regs; }; =20 -struct scaling_factor { - u8 scalingfactor0[1248]; - u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ - u8 scalingdc[12]; /*N1005 Vienna Meeting*/ - u8 reserved[4]; /*16Bytes align*/ -}; - static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) { u8 bit =3D field.offset % 32, word =3D field.offset / 32; @@ -417,131 +398,6 @@ static void assemble_sw_rps(struct rkvdec_ctx *ctx, } } =20 -/* - * Flip one or more matrices along their main diagonal and flatten them - * before writing it to the memory. - * Convert: - * ABCD AEIM - * EFGH =3D> BFJN =3D> AEIMBFJNCGKODHLP - * IJKL CGKO - * MNOP DHLP - */ -static void transpose_and_flatten_matrices(u8 *output, const u8 *input, - int matrices, int row_length) -{ - int i, j, row, x_offset, matrix_offset, rot_index, y_offset, matrix_size,= new_value; - - matrix_size =3D row_length * row_length; - for (i =3D 0; i < matrices; i++) { - row =3D 0; - x_offset =3D 0; - matrix_offset =3D i * matrix_size; - for (j =3D 0; j < matrix_size; j++) { - y_offset =3D j - (row * row_length); - rot_index =3D y_offset * row_length + x_offset; - new_value =3D *(input + i * matrix_size + j); - output[matrix_offset + rot_index] =3D new_value; - if ((j + 1) % row_length =3D=3D 0) { - row +=3D 1; - x_offset +=3D 1; - } - } - } -} - -static void assemble_scalingfactor0(u8 *output, const struct v4l2_ctrl_hev= c_scaling_matrix *input) -{ - int offset =3D 0; - - transpose_and_flatten_matrices(output, (const u8 *)input->scaling_list_4x= 4, 6, 4); - offset =3D 6 * 16 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, (const u8 *)input->scalin= g_list_8x8, 6, 8); - offset +=3D 6 * 64 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_16x16, 6, 8); - offset +=3D 6 * 64 * sizeof(u8); - /* Add a 128 byte padding with 0s between the two 32x32 matrices */ - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_32x32, 1, 8); - offset +=3D 64 * sizeof(u8); - memset(output + offset, 0, 128); - offset +=3D 128 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), - 1, 8); - offset +=3D 64 * sizeof(u8); - memset(output + offset, 0, 128); -} - -/* - * Required layout: - * A =3D scaling_list_dc_coef_16x16 - * B =3D scaling_list_dc_coef_32x32 - * 0 =3D Padding - * - * A, A, A, A, A, A, B, 0, 0, B, 0, 0 - */ -static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_sca= ling_matrix *input) -{ - u8 list_32x32[6] =3D {0}; - - memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8)); - list_32x32[0] =3D input->scaling_list_dc_coef_32x32[0]; - list_32x32[3] =3D input->scaling_list_dc_coef_32x32[1]; - memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8)); -} - -static void translate_scaling_list(struct scaling_factor *output, - const struct v4l2_ctrl_hevc_scaling_matrix *input) -{ - assemble_scalingfactor0(output->scalingfactor0, input); - memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96); - assemble_scalingdc(output->scalingdc, input); - memset(output->reserved, 0, 4 * sizeof(u8)); -} - -static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, - struct rkvdec_hevc_run *run) -{ - const struct v4l2_ctrl_hevc_scaling_matrix *scaling =3D run->scaling_matr= ix; - struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; - struct rkvdec_hevc_priv_tbl *tbl =3D hevc_ctx->priv_tbl.cpu; - u8 *dst; - - if (!memcmp((void *)&hevc_ctx->scaling_matrix_cache, scaling, - sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) - return; - - dst =3D tbl->scaling_list; - translate_scaling_list((struct scaling_factor *)dst, scaling); - - memcpy((void *)&hevc_ctx->scaling_matrix_cache, scaling, - sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); -} - -static struct vb2_buffer * -get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, - unsigned int dpb_idx) -{ - struct v4l2_m2m_ctx *m2m_ctx =3D ctx->fh.m2m_ctx; - const struct v4l2_ctrl_hevc_decode_params *decode_params =3D run->decode_= params; - const struct v4l2_hevc_dpb_entry *dpb =3D decode_params->dpb; - struct vb2_queue *cap_q =3D &m2m_ctx->cap_q_ctx.q; - struct vb2_buffer *buf =3D NULL; - - if (dpb_idx < decode_params->num_active_dpb_entries) - buf =3D vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp); - - /* - * If a DPB entry is unused or invalid, the address of current destination - * buffer is returned. - */ - if (!buf) - return &run->base.bufs.dst->vb2_buf; - - return buf; -} - static void config_registers(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run) { @@ -644,63 +500,6 @@ static void config_registers(struct rkvdec_ctx *ctx, rkvdec_memcpy_toio(rkvdec->regs, regs, MIN(sizeof(*regs), 4 * rkvdec->var= iant->num_regs)); } =20 -#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 - -static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, - struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *fmt =3D &f->fmt.pix_mp; - - fmt->num_planes =3D 1; - if (!fmt->plane_fmt[0].sizeimage) - fmt->plane_fmt[0].sizeimage =3D fmt->width * fmt->height * - RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; - return 0; -} - -static enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *= ctx, - struct v4l2_ctrl *ctrl) -{ - const struct v4l2_ctrl_hevc_sps *sps =3D ctrl->p_new.p_hevc_sps; - - if (ctrl->id !=3D V4L2_CID_STATELESS_HEVC_SPS) - return RKVDEC_IMG_FMT_ANY; - - if (sps->bit_depth_luma_minus8 =3D=3D 0) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_8BIT; - else - return RKVDEC_IMG_FMT_420_8BIT; - } else if (sps->bit_depth_luma_minus8 =3D=3D 2) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_10BIT; - else - return RKVDEC_IMG_FMT_420_10BIT; - } - - return RKVDEC_IMG_FMT_ANY; -} - -static int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, - const struct v4l2_ctrl_hevc_sps *sps) -{ - if (sps->chroma_format_idc > 1) - /* Only 4:0:0 and 4:2:0 are supported */ - return -EINVAL; - if (sps->bit_depth_luma_minus8 !=3D sps->bit_depth_chroma_minus8) - /* Luma and chroma bit depth mismatch */ - return -EINVAL; - if (sps->bit_depth_luma_minus8 !=3D 0 && sps->bit_depth_luma_minus8 !=3D = 2) - /* Only 8-bit and 10-bit is supported */ - return -EINVAL; - - if (sps->pic_width_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.width || - sps->pic_height_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.height) - return -EINVAL; - - return 0; -} - static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) { struct rkvdec_dev *rkvdec =3D ctx->dev; @@ -737,40 +536,18 @@ static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) kfree(hevc_ctx); } =20 -static void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, - struct rkvdec_hevc_run *run) -{ - struct v4l2_ctrl *ctrl; - - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); - run->decode_params =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_HEVC_SLICE_PARAMS); - run->slices_params =3D ctrl ? ctrl->p_cur.p : NULL; - run->num_slices =3D ctrl ? ctrl->new_elems : 0; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_HEVC_SPS); - run->sps =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_HEVC_PPS); - run->pps =3D ctrl ? ctrl->p_cur.p : NULL; - ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, - V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); - run->scaling_matrix =3D ctrl ? ctrl->p_cur.p : NULL; - - rkvdec_run_preamble(ctx, &run->base); -} - static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) { struct rkvdec_dev *rkvdec =3D ctx->dev; struct rkvdec_hevc_run run; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_hevc_priv_tbl *tbl =3D hevc_ctx->priv_tbl.cpu; u32 reg; =20 rkvdec_hevc_run_preamble(ctx, &run); =20 - assemble_hw_scaling_list(ctx, &run); + rkvdec_hevc_assemble_hw_scaling_list(&run, &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); assemble_hw_pps(ctx, &run); assemble_sw_rps(ctx, &run); config_registers(ctx, &run); @@ -795,14 +572,6 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) return 0; } =20 -static int rkvdec_hevc_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *= ctrl) -{ - if (ctrl->id =3D=3D V4L2_CID_STATELESS_HEVC_SPS) - return rkvdec_hevc_validate_sps(ctx, ctrl->p_new.p_hevc_sps); - - return 0; -} - const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops =3D { .adjust_fmt =3D rkvdec_hevc_adjust_fmt, .start =3D rkvdec_hevc_start, --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D27A3570D4; Wed, 22 Oct 2025 16:25:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150356; cv=none; b=RCkG/NKxmaU2peLz7Lwt3aipiIWIs8XoShwEQUOsVLLPiFO5SEXK6i9/GSxAOk8IHotT130McYMO++Km0USf161YG31ic+40uwuygR84e5l1nKWjInh0x+GmGaMTYYzPeoFcN2JYZHQN/arOMgIkPfxTEzzsedBQSqSf3gtoWyQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150356; c=relaxed/simple; bh=5XepCE8oQ4CfIylcFNZHUx5cQS3sUUTvzh5DlZ/N4/Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pS2cjvLfAUlzbzs3zr4o1Gfr76R75dLpRrIzMevsqUdjitlIg0U3yzRtfJmvai+rKRAjfCQ6psXUkQSLzVEvopuuo0OeLyE8rno7OvCd7tiViQixh19+KSWdVpLo++EF5US4scvhJPDcDF6zletQxpEMr3jye36dpgNVK1xe7HQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=P0t+K76h; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="P0t+K76h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150352; bh=5XepCE8oQ4CfIylcFNZHUx5cQS3sUUTvzh5DlZ/N4/Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P0t+K76hJcGBebSmfvjK9UEbNi++7UBmpAvQW/+8AF78GkTIhMMq6StOEC7V/evEZ xw/KvtT/owMWWVqWo6zwoBZgd9Dc27m2niz1y5H6AIZPayww+e5zFjiAZZPGlBWgMN Xb1JyLyvPKqFiIaT3FLAmI5JMhMO1F0lJ432D3OGxUriIUZ6k8+qi2O+Zk8gyP9EGr AhDXukGy1Ara2VyuZK9ExXGjLC83Bp2k/w8kpNouLnqI0Ioc+o+O0rVR8aGQ4wKsgG 2gEUg3h1C+Sx8qNzhqo82DXpCRsYP28f/jY95xnIgYv07m14tzDF0X1LBIOK7hKzj2 BMJVcJMxrW+MQ== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 1B90E17E108C; Wed, 22 Oct 2025 18:25:50 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 08/15] media: rkvdec: Add generic configuration for variants Date: Wed, 22 Oct 2025 12:22:07 -0400 Message-ID: <20251022162459.271603-9-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This is to prepare for adding new versions of the decoder and support specific formats and ops per version. Different rkvdec_variant instances will be able to share generic decoder configs. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/rkvdec.c | 37 ++++++++++++------- .../media/platform/rockchip/rkvdec/rkvdec.h | 6 +++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 776149f871b0..a7af1e3fdebd 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -373,15 +373,16 @@ static bool rkvdec_is_capable(struct rkvdec_ctx *ctx,= unsigned int capability) static const struct rkvdec_coded_fmt_desc * rkvdec_enum_coded_fmt_desc(struct rkvdec_ctx *ctx, int index) { + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; int fmt_idx =3D -1; unsigned int i; =20 - for (i =3D 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) { - if (!rkvdec_is_capable(ctx, rkvdec_coded_fmts[i].capability)) + for (i =3D 0; i < cfg->coded_fmts_num; i++) { + if (!rkvdec_is_capable(ctx, cfg->coded_fmts[i].capability)) continue; fmt_idx++; if (index =3D=3D fmt_idx) - return &rkvdec_coded_fmts[i]; + return &cfg->coded_fmts[i]; } =20 return NULL; @@ -390,12 +391,13 @@ rkvdec_enum_coded_fmt_desc(struct rkvdec_ctx *ctx, in= t index) static const struct rkvdec_coded_fmt_desc * rkvdec_find_coded_fmt_desc(struct rkvdec_ctx *ctx, u32 fourcc) { + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; unsigned int i; =20 - for (i =3D 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) { - if (rkvdec_is_capable(ctx, rkvdec_coded_fmts[i].capability) && - rkvdec_coded_fmts[i].fourcc =3D=3D fourcc) - return &rkvdec_coded_fmts[i]; + for (i =3D 0; i < cfg->coded_fmts_num; i++) { + if (rkvdec_is_capable(ctx, cfg->coded_fmts[i].capability) && + cfg->coded_fmts[i].fourcc =3D=3D fourcc) + return &cfg->coded_fmts[i]; } =20 return NULL; @@ -1014,18 +1016,19 @@ static int rkvdec_add_ctrls(struct rkvdec_ctx *ctx, =20 static int rkvdec_init_ctrls(struct rkvdec_ctx *ctx) { + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; unsigned int i, nctrls =3D 0; int ret; =20 - for (i =3D 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) - if (rkvdec_is_capable(ctx, rkvdec_coded_fmts[i].capability)) - nctrls +=3D rkvdec_coded_fmts[i].ctrls->num_ctrls; + for (i =3D 0; i < cfg->coded_fmts_num; i++) + if (rkvdec_is_capable(ctx, cfg->coded_fmts[i].capability)) + nctrls +=3D cfg->coded_fmts[i].ctrls->num_ctrls; =20 v4l2_ctrl_handler_init(&ctx->ctrl_hdl, nctrls); =20 - for (i =3D 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) { - if (rkvdec_is_capable(ctx, rkvdec_coded_fmts[i].capability)) { - ret =3D rkvdec_add_ctrls(ctx, rkvdec_coded_fmts[i].ctrls); + for (i =3D 0; i < cfg->coded_fmts_num; i++) { + if (rkvdec_is_capable(ctx, cfg->coded_fmts[i].capability)) { + ret =3D rkvdec_add_ctrls(ctx, cfg->coded_fmts[i].ctrls); if (ret) goto err_free_handler; } @@ -1240,13 +1243,20 @@ static void rkvdec_watchdog_func(struct work_struct= *work) } } =20 +static const struct rkvdec_config config_rkvdec =3D { + .coded_fmts =3D rkvdec_coded_fmts, + .coded_fmts_num =3D ARRAY_SIZE(rkvdec_coded_fmts), +}; + static const struct rkvdec_variant rk3288_rkvdec_variant =3D { .num_regs =3D 68, + .config =3D &config_rkvdec, .capabilities =3D RKVDEC_CAPABILITY_HEVC, }; =20 static const struct rkvdec_variant rk3328_rkvdec_variant =3D { .num_regs =3D 109, + .config =3D &config_rkvdec, .capabilities =3D RKVDEC_CAPABILITY_HEVC | RKVDEC_CAPABILITY_H264 | RKVDEC_CAPABILITY_VP9, @@ -1255,6 +1265,7 @@ static const struct rkvdec_variant rk3328_rkvdec_vari= ant =3D { =20 static const struct rkvdec_variant rk3399_rkvdec_variant =3D { .num_regs =3D 78, + .config =3D &config_rkvdec, .capabilities =3D RKVDEC_CAPABILITY_HEVC | RKVDEC_CAPABILITY_H264 | RKVDEC_CAPABILITY_VP9, diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index f35f6e80ea2e..3b1cc511412e 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -71,6 +71,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) =20 struct rkvdec_variant { unsigned int num_regs; + const struct rkvdec_config *config; unsigned int capabilities; unsigned int quirks; }; @@ -113,6 +114,11 @@ struct rkvdec_coded_fmt_desc { unsigned int capability; }; =20 +struct rkvdec_config { + const struct rkvdec_coded_fmt_desc *coded_fmts; + size_t coded_fmts_num; +}; + struct rkvdec_dev { struct v4l2_device v4l2_dev; struct media_device mdev; --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E93B0357725; Wed, 22 Oct 2025 16:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150359; cv=none; b=FAHYPWuOvUeOZx/BSk7NhCcdvBj1bT19cvhGxVZqDZvkpMBhYtil5Hx4ZgTe6TtL26ttkG+m27GsuSb+JwgrfGGYvq6ieovEYVCckxFzxzF3re2lhEjDh6HOKm66jJG72lDMY2w4+nOF0ar4EDFylBDkLaoWkLmhBv3/uvm6mj4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150359; c=relaxed/simple; bh=3DNL3ewdtZ7oUDJlJifx6EL8cleCbSj+6x/r1+VSu7E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=A2tGGEHgeOEGpG8mb4Kw9PI6VE/addZNH29wx9clIMnYNfUZ3pZNY5idND/5P8VNiOtYO0Lj8Vyi0j6C0p8rKADpiLgm6PV6zV1hcnKeFHo3sObiLPynMbHO2fH4jITHrXH/wSDNdqlnHYieDLw6/xhy5FAoo0/FktTQHpJzKzc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=Qv36012g; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="Qv36012g" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150355; bh=3DNL3ewdtZ7oUDJlJifx6EL8cleCbSj+6x/r1+VSu7E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qv36012g4JiPgUqkP7c9MLqg0KEwzGzml7wTbPT7z8Jz9Zr0khSsV5bg2kXucCiF5 DI/Ukm30orSah7TT6ogJJj0ukSvAcepfknsrx9XQ42EoVF7UKymac8RmbTegSFKl6p 81X4fPUpwVseUqTqLOZGblGgWaoiCRS7E1APLUrjkZiVAxiXgKyNWKgZWoIe80/t6x XaOyp78u2xBbQknKQXkPYnZkvkYTInG2o4S91KNNrLnIe9AsASSC2sqz+7RDjqZ0wo fD6xZR8o52ycHvumCT/r4QJnLBg+k0i1nSgUrhPMcGFlkUhvwIyrw9DfZJFv8dmqsN EfIfiUDVpFmmQ== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id D596117E1404; Wed, 22 Oct 2025 18:25:52 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 09/15] media: rkvdec: Add RCB and SRAM support Date: Wed, 22 Oct 2025 12:22:08 -0400 Message-ID: <20251022162459.271603-10-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The RCB (Rows and Cols Buffers) are a set of buffers used by other variations of the decoder to store temporary data. Those variation come with a dedicated SRAM area used to store those buffers for better performances. The buffer sizes are either the width or height of the frame being decoded multiplied by a documented factor and can be stored either in SRAM or RAM. A fallback to RAM is provided if the SRAM is full (e.g.: multiple streams are being decoded at the same time). To manage the different kind of allocation, an enum is added to the rkvdec_aux_buf struct to specify how the buffer was allocated, and so, how to free it. This commit is in preparation of other variants support. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../platform/rockchip/rkvdec/rkvdec-rcb.c | 173 ++++++++++++++++++ .../platform/rockchip/rkvdec/rkvdec-rcb.h | 29 +++ .../media/platform/rockchip/rkvdec/rkvdec.c | 27 ++- .../media/platform/rockchip/rkvdec/rkvdec.h | 13 ++ 5 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index 1b4bc44be23e..3d75103e536d 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -7,4 +7,5 @@ rockchip-vdec-y +=3D \ rkvdec-h264-common.o \ rkvdec-hevc.o \ rkvdec-hevc-common.o \ + rkvdec-rcb.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c b/drivers/= media/platform/rockchip/rkvdec/rkvdec-rcb.c new file mode 100644 index 000000000000..5a4959c239e3 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip video decoder Rows and Cols Buffers manager + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include "rkvdec.h" +#include "rkvdec-rcb.h" + +#include +#include +#include + +struct rkvdec_rcb_config { + struct rkvdec_aux_buf *rcb_bufs; + size_t rcb_count; +}; + +static size_t rkvdec_rcb_size(const struct rcb_size_info *size_info, + unsigned int width, unsigned int height) +{ + return size_info->multiplier * (size_info->axis =3D=3D PIC_HEIGHT ? heigh= t : width); +} + +dma_addr_t rkvdec_rcb_buf_dma_addr(struct rkvdec_ctx *ctx, int id) +{ + return ctx->rcb_config->rcb_bufs[id].dma; +} + +size_t rkvdec_rcb_buf_size(struct rkvdec_ctx *ctx, int id) +{ + return ctx->rcb_config->rcb_bufs[id].size; +} + +int rkvdec_rcb_buf_count(struct rkvdec_ctx *ctx) +{ + return ctx->rcb_config->rcb_count; +} + +void rkvdec_free_rcb(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *dev =3D ctx->dev; + struct rkvdec_rcb_config *cfg =3D ctx->rcb_config; + unsigned long virt_addr; + int i; + + if (!cfg) + return; + + for (i =3D 0; i < cfg->rcb_count; i++) { + size_t rcb_size =3D cfg->rcb_bufs[i].size; + + if (!cfg->rcb_bufs[i].cpu) + continue; + + switch (cfg->rcb_bufs[i].type) { + case RKVDEC_ALLOC_SRAM: + virt_addr =3D (unsigned long)cfg->rcb_bufs[i].cpu; + + if (dev->iommu_domain) + iommu_unmap(dev->iommu_domain, virt_addr, rcb_size); + gen_pool_free(dev->sram_pool, virt_addr, rcb_size); + break; + case RKVDEC_ALLOC_DMA: + dma_free_coherent(dev->dev, + rcb_size, + cfg->rcb_bufs[i].cpu, + cfg->rcb_bufs[i].dma); + break; + } + } + + if (cfg->rcb_bufs) + devm_kfree(dev->dev, cfg->rcb_bufs); + + devm_kfree(dev->dev, cfg); +} + +int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx, + const struct rcb_size_info *size_info, + size_t rcb_count) +{ + int ret, i; + u32 width, height; + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_rcb_config *cfg; + + ctx->rcb_config =3D devm_kzalloc(rkvdec->dev, sizeof(*ctx->rcb_config), G= FP_KERNEL); + if (!ctx->rcb_config) + return -ENOMEM; + + cfg =3D ctx->rcb_config; + + cfg->rcb_bufs =3D devm_kzalloc(rkvdec->dev, sizeof(*cfg->rcb_bufs) * rcb_= count, GFP_KERNEL); + if (!cfg->rcb_bufs) { + ret =3D -ENOMEM; + goto err_alloc; + } + + width =3D ctx->decoded_fmt.fmt.pix_mp.width; + height =3D ctx->decoded_fmt.fmt.pix_mp.height; + + for (i =3D 0; i < rcb_count; i++) { + void *cpu =3D NULL; + dma_addr_t dma; + size_t rcb_size =3D rkvdec_rcb_size(&size_info[i], width, height); + enum rkvdec_alloc_type alloc_type =3D RKVDEC_ALLOC_SRAM; + + /* Try allocating an SRAM buffer */ + if (ctx->dev->sram_pool) { + if (rkvdec->iommu_domain) + rcb_size =3D ALIGN(rcb_size, 0x1000); + + cpu =3D gen_pool_dma_zalloc_align(ctx->dev->sram_pool, + rcb_size, + &dma, + 0x1000); + } + + /* If an IOMMU is used, map the SRAM address through it */ + if (cpu && rkvdec->iommu_domain) { + unsigned long virt_addr =3D (unsigned long)cpu; + phys_addr_t phys_addr =3D dma; + + ret =3D iommu_map(rkvdec->iommu_domain, virt_addr, phys_addr, + rcb_size, IOMMU_READ | IOMMU_WRITE, 0); + if (ret) { + gen_pool_free(ctx->dev->sram_pool, + (unsigned long)cpu, + rcb_size); + cpu =3D NULL; + goto ram_fallback; + } + + /* + * The registers will be configured with the virtual + * address so that it goes through the IOMMU + */ + dma =3D virt_addr; + } + +ram_fallback: + /* Fallback to RAM */ + if (!cpu) { + cpu =3D dma_alloc_coherent(ctx->dev->dev, + rcb_size, + &dma, + GFP_KERNEL); + alloc_type =3D RKVDEC_ALLOC_DMA; + } + + if (!cpu) { + ret =3D -ENOMEM; + goto err_alloc; + } + + cfg->rcb_bufs[i].cpu =3D cpu; + cfg->rcb_bufs[i].dma =3D dma; + cfg->rcb_bufs[i].size =3D rcb_size; + cfg->rcb_bufs[i].type =3D alloc_type; + + cfg->rcb_count +=3D 1; + } + + return 0; + +err_alloc: + rkvdec_free_rcb(ctx); + + return ret; +} diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h b/drivers/= media/platform/rockchip/rkvdec/rkvdec-rcb.h new file mode 100644 index 000000000000..30e8002555c8 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip video decoder Rows and Cols Buffers manager + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include + +struct rkvdec_ctx; + +enum rcb_axis { + PIC_WIDTH =3D 0, + PIC_HEIGHT =3D 1 +}; + +struct rcb_size_info { + u8 multiplier; + enum rcb_axis axis; +}; + +int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx, + const struct rcb_size_info *size_info, + size_t rcb_count); +dma_addr_t rkvdec_rcb_buf_dma_addr(struct rkvdec_ctx *ctx, int id); +size_t rkvdec_rcb_buf_size(struct rkvdec_ctx *ctx, int id); +int rkvdec_rcb_buf_count(struct rkvdec_ctx *ctx); +void rkvdec_free_rcb(struct rkvdec_ctx *ctx); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index a7af1e3fdebd..5dd486edd64d 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -10,6 +10,7 @@ */ =20 #include +#include #include #include #include @@ -28,6 +29,7 @@ =20 #include "rkvdec.h" #include "rkvdec-regs.h" +#include "rkvdec-rcb.h" =20 static bool rkvdec_image_fmt_match(enum rkvdec_image_fmt fmt1, enum rkvdec_image_fmt fmt2) @@ -771,6 +773,7 @@ static int rkvdec_start_streaming(struct vb2_queue *q, = unsigned int count) { struct rkvdec_ctx *ctx =3D vb2_get_drv_priv(q); const struct rkvdec_coded_fmt_desc *desc; + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; int ret; =20 if (V4L2_TYPE_IS_CAPTURE(q->type)) @@ -780,13 +783,22 @@ static int rkvdec_start_streaming(struct vb2_queue *q= , unsigned int count) if (WARN_ON(!desc)) return -EINVAL; =20 + ret =3D rkvdec_allocate_rcb(ctx, cfg->rcb_size_info, cfg->rcb_num); + if (ret) + return ret; + if (desc->ops->start) { ret =3D desc->ops->start(ctx); if (ret) - return ret; + goto err_ops_start; } =20 return 0; + +err_ops_start: + rkvdec_free_rcb(ctx); + + return ret; } =20 static void rkvdec_queue_cleanup(struct vb2_queue *vq, u32 state) @@ -822,6 +834,8 @@ static void rkvdec_stop_streaming(struct vb2_queue *q) =20 if (desc->ops->stop) desc->ops->stop(ctx); + + rkvdec_free_rcb(ctx); } =20 rkvdec_queue_cleanup(q, VB2_BUF_STATE_ERROR); @@ -1350,6 +1364,10 @@ static int rkvdec_probe(struct platform_device *pdev) return ret; } =20 + rkvdec->sram_pool =3D of_gen_pool_get(pdev->dev.of_node, "sram", 0); + if (!rkvdec->sram_pool && rkvdec->variant->config->rcb_num > 0) + dev_info(&pdev->dev, "No sram node, RCB will be stored in RAM\n"); + pm_runtime_set_autosuspend_delay(&pdev->dev, 100); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -1358,7 +1376,8 @@ static int rkvdec_probe(struct platform_device *pdev) if (ret) goto err_disable_runtime_pm; =20 - if (iommu_get_domain_for_dev(&pdev->dev)) { + rkvdec->iommu_domain =3D iommu_get_domain_for_dev(&pdev->dev); + if (rkvdec->iommu_domain) { rkvdec->empty_domain =3D iommu_paging_domain_alloc(rkvdec->dev); =20 if (IS_ERR(rkvdec->empty_domain)) { @@ -1372,6 +1391,10 @@ static int rkvdec_probe(struct platform_device *pdev) err_disable_runtime_pm: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_disable(&pdev->dev); + + if (rkvdec->sram_pool) + gen_pool_destroy(rkvdec->sram_pool); + return ret; } =20 diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 3b1cc511412e..74f71542e031 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include =20 @@ -29,6 +30,7 @@ #define RKVDEC_QUIRK_DISABLE_QOS BIT(0) =20 struct rkvdec_ctx; +struct rkvdec_rcb_config; =20 struct rkvdec_ctrl_desc { struct v4l2_ctrl_config cfg; @@ -117,6 +119,8 @@ struct rkvdec_coded_fmt_desc { struct rkvdec_config { const struct rkvdec_coded_fmt_desc *coded_fmts; size_t coded_fmts_num; + const struct rcb_size_info *rcb_size_info; + size_t rcb_num; }; =20 struct rkvdec_dev { @@ -129,6 +133,8 @@ struct rkvdec_dev { void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; + struct gen_pool *sram_pool; + struct iommu_domain *iommu_domain; struct iommu_domain *empty_domain; const struct rkvdec_variant *variant; }; @@ -141,6 +147,7 @@ struct rkvdec_ctx { struct v4l2_ctrl_handler ctrl_hdl; struct rkvdec_dev *dev; enum rkvdec_image_fmt image_fmt; + struct rkvdec_rcb_config *rcb_config; void *priv; }; =20 @@ -149,10 +156,16 @@ static inline struct rkvdec_ctx *file_to_rkvdec_ctx(s= truct file *filp) return container_of(file_to_v4l2_fh(filp), struct rkvdec_ctx, fh); } =20 +enum rkvdec_alloc_type { + RKVDEC_ALLOC_DMA =3D 0, + RKVDEC_ALLOC_SRAM =3D 1, +}; + struct rkvdec_aux_buf { void *cpu; dma_addr_t dma; size_t size; + enum rkvdec_alloc_type type; }; =20 void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD782357A32; Wed, 22 Oct 2025 16:25:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150361; cv=none; b=rBAV+uMgWgdtqXNr1W4G4ffC+O5wN9OzCDba7mkcdQ95q+JfhgoVXEHCPWiJm2HOdllcAb4JeqwRqY348aD6XOAyK5AKc+j4raSDCywDYus84y3Y6K3OKwGByzvs+G1pr3Pjc8gpFOe9dPwQLs46lXIUEiDr//Y1joU3DtMRNB4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150361; c=relaxed/simple; bh=dAFQDps3eAP+w+7ZBAZcwTH8VtKHFGKFfeZJsJy7sx0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XWuM66mlx8uBd4wqx3d9ZusiGctfoDlTVZ/odJuONbkmICd+2in0bb8gWFA0by63zm7wn9/WZ+wrh+zkyBtUKcSlV/ClHq1of7jZMpAOMAVPB8QJBOBqhxQdj2OR3+vLrVWajSmFAmI6Ufq7B1N3sjtbSLIdcwS1atd6d993P2E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=lpVGl9kx; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="lpVGl9kx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150358; bh=dAFQDps3eAP+w+7ZBAZcwTH8VtKHFGKFfeZJsJy7sx0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lpVGl9kx/30E9ellazr/4+Sc+PKcpbRIBmSqb/WJXovq8sHym+ht6G3Rc5gje7rtt cEJwqOkZepVREbBztWFTu8Cvgf+aJJLx5bW48mSZ+/J8yZt+CepAScyJswLGqVkNLW hv3wAsrPsK5CL1CI3Q1hGnO99snrHe8pmO+MHkoOt1eNMLSX8lgIthNK1SIPvu4Rod qiKWE4b5gpA4Wf5Ypx180nS4Jbg00TNm8aT7ebty0FWJ6UpSllxKY9U+rWOPEXtwP9 tz9iJ9DTC9GFv+jmmTkWgFE/0VFJ5UN6XP0T/GogDsJUCwpCUvvcwEOwoH4D6oEp54 r0+lGezxyLQ5g== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 999BD17E1407; Wed, 22 Oct 2025 18:25:55 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 10/15] media: rkvdec: Support per-variant interrupt handler Date: Wed, 22 Oct 2025 12:22:09 -0400 Message-ID: <20251022162459.271603-11-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Preparation commit for supporting different variants with different interrupt management. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- drivers/media/platform/rockchip/rkvdec/rkvdec.c | 15 ++++++++++++--- drivers/media/platform/rockchip/rkvdec/rkvdec.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 5dd486edd64d..b0e90c9b826e 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1218,10 +1218,9 @@ static void rkvdec_iommu_restore(struct rkvdec_dev *= rkvdec) } } =20 -static irqreturn_t rkvdec_irq_handler(int irq, void *priv) +static irqreturn_t rk3399_irq_handler(struct rkvdec_ctx *ctx) { - struct rkvdec_dev *rkvdec =3D priv; - struct rkvdec_ctx *ctx =3D v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + struct rkvdec_dev *rkvdec =3D ctx->dev; enum vb2_buffer_state state; u32 status; =20 @@ -1242,6 +1241,15 @@ static irqreturn_t rkvdec_irq_handler(int irq, void = *priv) return IRQ_HANDLED; } =20 +static irqreturn_t rkvdec_irq_handler(int irq, void *priv) +{ + struct rkvdec_dev *rkvdec =3D priv; + struct rkvdec_ctx *ctx =3D v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + const struct rkvdec_config *cfg =3D rkvdec->variant->config; + + return cfg->irq_handler(ctx); +} + static void rkvdec_watchdog_func(struct work_struct *work) { struct rkvdec_dev *rkvdec; @@ -1260,6 +1268,7 @@ static void rkvdec_watchdog_func(struct work_struct *= work) static const struct rkvdec_config config_rkvdec =3D { .coded_fmts =3D rkvdec_coded_fmts, .coded_fmts_num =3D ARRAY_SIZE(rkvdec_coded_fmts), + .irq_handler =3D rk3399_irq_handler, }; =20 static const struct rkvdec_variant rk3288_rkvdec_variant =3D { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 74f71542e031..dfafb2c2cbc1 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -121,6 +121,7 @@ struct rkvdec_config { size_t coded_fmts_num; const struct rcb_size_info *rcb_size_info; size_t rcb_num; + irqreturn_t (*irq_handler)(struct rkvdec_ctx *ctx); }; =20 struct rkvdec_dev { --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BB603587A3; Wed, 22 Oct 2025 16:26:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150364; cv=none; b=VOFG0pvXrBBmlge2/5D0UOMjgJhIFzmnAdiYJx5+Ip5lv+gHSJ1MimFNWlBQVB5UcNuuxAyPWy8mEt0lSuz4iQWAj1gerh38pyceu3PPvImExNKUZ7+IDdtNCw5j3ADbCxjov6AgK/S8j/rdn/VjQ5vTTftN/ntYDpv883aAhuk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150364; c=relaxed/simple; bh=5QHIAhDdNTruUVsBvBey2DnUkdbmf61aGkGJ7dtje8I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eBF8Pm1go06VHh4KfYycimxCSayv+9dgLZH0bYdAxD48pPb1ZX9XLFO/8/RU04AKvoDsSTEH/7h5ynv8z9BDUEYQuGuoqbXBqJz93/9Gp9O8ltPlqp5/jMRk5yEjAdAeqcxDV9hM5WiYf8D7hAxjFu5nd2fYfYjDI8yWtzN5lAc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=bGRLA9Yg; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="bGRLA9Yg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150360; bh=5QHIAhDdNTruUVsBvBey2DnUkdbmf61aGkGJ7dtje8I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bGRLA9YgLg3oh0ZzO8FvoGoD8rrm6rIbB0PJ6A/B967q9028W41imHDXJgyD9GGzQ +I1ur/z5uECjoKB3Yr1W3ujUgyyrj/1v2BOQWFAuO7ecvczxTNuqBoBFL338/c6kRX /lzPsrwfhIJAEc+dUD5ZiPYmi996m7aQN34j15kgKKzhvD5NWhNLEJU02F5okggXbh qHKqwqyVLaz/l/a2L8pUHDQ+QZLrOd8bBR+wDW1j7i3EY79jasW2xngzwSSX4nSFG/ KpJ8wex5wOT2O2DMbgg06VP0bBY3/3yBRaPIo8st8OKcENUaEpF0PVj1bc153l8kHO iW+Hk3Yf71NJQ== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 61D7B17E1413; Wed, 22 Oct 2025 18:25:58 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 11/15] media: rkvdec: Enable all clocks without naming them Date: Wed, 22 Oct 2025 12:22:10 -0400 Message-ID: <20251022162459.271603-12-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For other variants, the clock names and number will differ. There is no need to keep track of the clock names in the driver so drop them to avoid having a list for each variant. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/rkvdec.c | 24 +++++-------------- .../media/platform/rockchip/rkvdec/rkvdec.h | 1 + 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index b0e90c9b826e..aa92b586429e 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1311,15 +1311,10 @@ static const struct of_device_id of_rkvdec_match[] = =3D { }; MODULE_DEVICE_TABLE(of, of_rkvdec_match); =20 -static const char * const rkvdec_clk_names[] =3D { - "axi", "ahb", "cabac", "core" -}; - static int rkvdec_probe(struct platform_device *pdev) { const struct rkvdec_variant *variant; struct rkvdec_dev *rkvdec; - unsigned int i; int ret, irq; =20 variant =3D of_device_get_match_data(&pdev->dev); @@ -1336,19 +1331,12 @@ static int rkvdec_probe(struct platform_device *pde= v) mutex_init(&rkvdec->vdev_lock); INIT_DELAYED_WORK(&rkvdec->watchdog_work, rkvdec_watchdog_func); =20 - rkvdec->clocks =3D devm_kcalloc(&pdev->dev, ARRAY_SIZE(rkvdec_clk_names), - sizeof(*rkvdec->clocks), GFP_KERNEL); - if (!rkvdec->clocks) - return -ENOMEM; - - for (i =3D 0; i < ARRAY_SIZE(rkvdec_clk_names); i++) - rkvdec->clocks[i].id =3D rkvdec_clk_names[i]; - - ret =3D devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(rkvdec_clk_names), - rkvdec->clocks); - if (ret) + ret =3D devm_clk_bulk_get_all_enabled(&pdev->dev, &rkvdec->clocks); + if (ret < 0) return ret; =20 + rkvdec->clk_count =3D ret; + rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rkvdec->regs)) return PTR_ERR(rkvdec->regs); @@ -1426,7 +1414,7 @@ static int rkvdec_runtime_resume(struct device *dev) { struct rkvdec_dev *rkvdec =3D dev_get_drvdata(dev); =20 - return clk_bulk_prepare_enable(ARRAY_SIZE(rkvdec_clk_names), + return clk_bulk_prepare_enable(rkvdec->clk_count, rkvdec->clocks); } =20 @@ -1434,7 +1422,7 @@ static int rkvdec_runtime_suspend(struct device *dev) { struct rkvdec_dev *rkvdec =3D dev_get_drvdata(dev); =20 - clk_bulk_disable_unprepare(ARRAY_SIZE(rkvdec_clk_names), + clk_bulk_disable_unprepare(rkvdec->clk_count, rkvdec->clocks); return 0; } diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index dfafb2c2cbc1..4094f92f8a44 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -131,6 +131,7 @@ struct rkvdec_dev { struct v4l2_m2m_dev *m2m_dev; struct device *dev; struct clk_bulk_data *clocks; + unsigned int clk_count; void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 453743587DA; Wed, 22 Oct 2025 16:26:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150368; cv=none; b=dQEDdFDCSlIisa2fYQz7+3z0cyHTSTAyYk9+XA5lfmNmASc4sx2z3UOxjq93t/wQyyfWB+R/6wpVAaO67+TIstIUj8dSrFAnhT3sehzsKHOJdpmwJ/9AAlrtDPO55DbNMLEIhncrgmPtmYrdDYbVIhcW1L9ZL9ybbg65uYt8B94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150368; c=relaxed/simple; bh=wyo1l1OeLPxnYHXBg3dfdzxYEgHinft6T/5jKQgZwQ8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P4W43auAmAlpdil7RRiZGLoGiOFow2cJOdsJOHs7Zt7wHkcGLNiJXuSLiyyjZjSDraf1Vsum2trZ/iBGWSST3Ij92Va6BuOxAIOuXwkTJX0s8ypAsPIxgtXHE9bzeUCLMjdts+4jufzV3p0VDxAU3C82W0QVd3ez/qKGSQMf/ec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=j0e6tpkY; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="j0e6tpkY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150363; bh=wyo1l1OeLPxnYHXBg3dfdzxYEgHinft6T/5jKQgZwQ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j0e6tpkYLzcS6L/fAzU93ewmIWtFHuw975l2rJdp1esmwjQpXycCAx8Wi5phVYOTT 3H5NulTGJCi1EonT0UWdgxytDckz5Qc6O77NiAc3RAhCxmnbl97SmWi97njTzjn15E A3022wwI18M1/AajZNfSeycYfOqpt7j5gjmMfTDKilgeilDChPyH9kmZAB/L85ktno bPJ5dMotiijXJ4y0KLxAsr0txM6JeyBnQ2MYYxTYc/GQx15lqYxr86l3/QjR2nV8Bq s29nFvjhWDU31Fh9XdwddRoNfAwnRH+OfVobNC+zSPHjZAOAInXNhPs2ItDYeYGZ6I zlOIG3xyMRk0Q== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 2D8AA17E108C; Wed, 22 Oct 2025 18:26:01 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 12/15] media: rkvdec: Add H264 support for the VDPU381 variant Date: Wed, 22 Oct 2025 12:22:11 -0400 Message-ID: <20251022162459.271603-13-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This decoder variant is found in Rockchip RK3588 SoC family. Like for rkvdec on rk3399, it supports the NV12, NV15, NV16 and NV20 output formats and level up to 5.1. The maximum width and height have been significantly increased supporting up to 65520 pixels for both. Also make sure to only expose the first core and ignore the other until mutli-core is supported. Fluster score for JVT-AVC_V1 is 129/135. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-h264-common.h | 2 + .../rockchip/rkvdec/rkvdec-vdpu381-h264.c | 469 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu381-regs.h | 427 ++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 131 +++++ .../media/platform/rockchip/rkvdec/rkvdec.h | 4 + 6 files changed, 1034 insertions(+) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h= 264.c create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-r= egs.h diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index 3d75103e536d..7bfd95151e40 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -8,4 +8,5 @@ rockchip-vdec-y +=3D \ rkvdec-hevc.o \ rkvdec-hevc-common.o \ rkvdec-rcb.o \ + rkvdec-vdpu381-h264.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h index aea346744e4c..3984740e6f42 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h @@ -68,6 +68,8 @@ struct rkvdec_rps { u32 reserved1[66]; } __packed; =20 +extern const s8 rkvdec_h264_cabac_table[4][464][2]; + void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *ru= n); void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder, struct rkvdec_h264_run *run, diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h264.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h264.c new file mode 100644 index 000000000000..e65a56bc9c63 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h264.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip VDPU381 Video Decoder H264 backend + * + * Copyright (C) 2024 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include + +#include "rkvdec.h" +#include "rkvdec-rcb.h" +#include "rkvdec-h264-common.h" +#include "rkvdec-vdpu381-regs.h" + +struct rkvdec_sps { + u16 seq_parameter_set_id: 4; + u16 profile_idc: 8; + u16 constraint_set3_flag: 1; + u16 chroma_format_idc: 2; + u16 bit_depth_luma: 3; + u16 bit_depth_chroma: 3; + u16 qpprime_y_zero_transform_bypass_flag: 1; + u16 log2_max_frame_num_minus4: 4; + u16 max_num_ref_frames: 5; + u16 pic_order_cnt_type: 2; + u16 log2_max_pic_order_cnt_lsb_minus4: 4; + u16 delta_pic_order_always_zero_flag: 1; + u16 pic_width_in_mbs: 12; + u16 pic_height_in_mbs: 12; + u16 frame_mbs_only_flag: 1; + u16 mb_adaptive_frame_field_flag: 1; + u16 direct_8x8_inference_flag: 1; + u16 mvc_extension_enable: 1; + u16 num_views: 2; + + u16 reserved_bits: 12; + u16 reserved[11]; +} __packed; + +struct rkvdec_pps { + u16 pic_parameter_set_id: 8; + u16 pps_seq_parameter_set_id: 5; + u16 entropy_coding_mode_flag: 1; + u16 bottom_field_pic_order_in_frame_present_flag: 1; + u16 num_ref_idx_l0_default_active_minus1: 5; + u16 num_ref_idx_l1_default_active_minus1: 5; + u16 weighted_pred_flag: 1; + u16 weighted_bipred_idc: 2; + u16 pic_init_qp_minus26: 7; + u16 pic_init_qs_minus26: 6; + u16 chroma_qp_index_offset: 5; + u16 deblocking_filter_control_present_flag: 1; + u16 constrained_intra_pred_flag: 1; + u16 redundant_pic_cnt_present: 1; + u16 transform_8x8_mode_flag: 1; + u16 second_chroma_qp_index_offset: 5; + u16 scaling_list_enable_flag: 1; + u32 scaling_list_address; + u16 is_longterm; + + u8 reserved[3]; +} __packed; + +struct rkvdec_sps_pps { + struct rkvdec_sps sps; + struct rkvdec_pps pps; +} __packed; + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec_h264_priv_tbl { + s8 cabac_table[4][464][2]; + struct rkvdec_h264_scaling_list scaling_list; + struct rkvdec_sps_pps param_set[256]; + struct rkvdec_rps rps; +}; + +struct rkvdec_h264_ctx { + struct rkvdec_aux_buf priv_tbl; + struct rkvdec_h264_reflists reflists; + struct rkvdec_vdpu381_regs_h264 regs; +}; + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_h264_sps *sps =3D run->sps; + const struct v4l2_ctrl_h264_pps *pps =3D run->pps; + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_sps_pps *hw_ps; + dma_addr_t scaling_list_address; + u32 scaling_distance; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set[pps->pic_parameter_set_id]; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->sps.seq_parameter_set_id =3D sps->seq_parameter_set_id; + hw_ps->sps.profile_idc =3D sps->profile_idc; + hw_ps->sps.constraint_set3_flag =3D !!(sps->constraint_set_flags & (1 << = 3)); + hw_ps->sps.chroma_format_idc =3D sps->chroma_format_idc; + hw_ps->sps.bit_depth_luma =3D sps->bit_depth_luma_minus8; + hw_ps->sps.bit_depth_chroma =3D sps->bit_depth_chroma_minus8; + hw_ps->sps.qpprime_y_zero_transform_bypass_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS); + hw_ps->sps.log2_max_frame_num_minus4 =3D sps->log2_max_frame_num_minus4; + hw_ps->sps.max_num_ref_frames =3D sps->max_num_ref_frames; + hw_ps->sps.pic_order_cnt_type =3D sps->pic_order_cnt_type; + hw_ps->sps.log2_max_pic_order_cnt_lsb_minus4 =3D + sps->log2_max_pic_order_cnt_lsb_minus4; + hw_ps->sps.delta_pic_order_always_zero_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO); + hw_ps->sps.mvc_extension_enable =3D 1; + hw_ps->sps.num_views =3D 1; + + /* + * Use the SPS values since they are already in macroblocks + * dimensions, height can be field height (halved) if + * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows + * decoding smaller images into larger allocation which can be used + * to implementing SVC spatial layer support. + */ + hw_ps->sps.pic_width_in_mbs =3D sps->pic_width_in_mbs_minus1 + 1; + hw_ps->sps.pic_height_in_mbs =3D sps->pic_height_in_map_units_minus1 + 1; + hw_ps->sps.frame_mbs_only_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY); + hw_ps->sps.mb_adaptive_frame_field_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + hw_ps->sps.direct_8x8_inference_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); + + /* write pps */ + hw_ps->pps.pic_parameter_set_id =3D pps->pic_parameter_set_id; + hw_ps->pps.pps_seq_parameter_set_id =3D pps->seq_parameter_set_id; + hw_ps->pps.entropy_coding_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESE= NT); + hw_ps->pps.num_ref_idx_l0_default_active_minus1 =3D + pps->num_ref_idx_l0_default_active_minus1; + hw_ps->pps.num_ref_idx_l1_default_active_minus1 =3D + pps->num_ref_idx_l1_default_active_minus1; + hw_ps->pps.weighted_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED); + hw_ps->pps.weighted_bipred_idc =3D pps->weighted_bipred_idc; + hw_ps->pps.pic_init_qp_minus26 =3D pps->pic_init_qp_minus26; + hw_ps->pps.pic_init_qs_minus26 =3D pps->pic_init_qs_minus26; + hw_ps->pps.chroma_qp_index_offset =3D pps->chroma_qp_index_offset; + hw_ps->pps.deblocking_filter_control_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + hw_ps->pps.constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->pps.redundant_pic_cnt_present =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT); + hw_ps->pps.transform_8x8_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE); + hw_ps->pps.second_chroma_qp_index_offset =3D pps->second_chroma_qp_index_= offset; + hw_ps->pps.scaling_list_enable_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT); + + /* + * To be on the safe side, program the scaling matrix address + */ + scaling_distance =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + scaling_list_address =3D h264_ctx->priv_tbl.dma + scaling_distance; + hw_ps->pps.scaling_list_address =3D scaling_list_address; + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + hw_ps->pps.is_longterm |=3D (1 << i); + } +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS, + &h264_ctx->regs.common, + sizeof(h264_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS, + &h264_ctx->regs.h264_param, + sizeof(h264_ctx->regs.h264_param)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS, + &h264_ctx->regs.common_addr, + sizeof(h264_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS, + &h264_ctx->regs.h264_addr, + sizeof(h264_ctx->regs.h264_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_POC_HIGHBIT_REGS, + &h264_ctx->regs.h264_highpoc, + sizeof(h264_ctx->regs.h264_highpoc)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + dma_addr_t priv_start_addr =3D h264_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + struct rkvdec_vdpu381_regs_h264 *regs =3D &h264_ctx->regs; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + dma_addr_t dst_addr; + u32 hor_virstride; + u32 ver_virstride; + u32 y_virstride; + u32 offset; + u32 pixels; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set H264 mode */ + regs->common.reg009.dec_mode =3D VDPU381_MODE_H264; + + /* Set config */ + regs->common.reg011.buf_empty_en =3D 1; + regs->common.reg011.dec_clkgate_e =3D 1; + regs->common.reg011.dec_timeout_e =3D 1; + regs->common.reg011.pix_range_detection_e =3D 1; + + /* + * Even though the scan list address can be set in RPS, + * with some frames, it will try to use the address set in the register. + */ + regs->common.reg012.scanlist_addr_valid_en =3D 1; + + /* Set IDR flag */ + regs->common.reg013.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.stream_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); + + /* Set max slice number */ + regs->common.reg017.slice_num =3D MAX_SLICE_NUMBER; + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->common.reg018.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026.swreg_block_gating_e =3D 0xfffef; + regs->common.reg026.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_8K; + else + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_MAX; + + /* Set TOP and BOTTOM POCs */ + regs->h264_param.cur_top_poc =3D dec_params->top_field_order_cnt; + regs->h264_param.cur_bot_poc =3D dec_params->bottom_field_order_cnt; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf =3D run->ref_buf[i]; + dma_addr_t buf_dma; + + /* + * If a DPB entry is unused or invalid, address of current destination + * buffer is returned. + */ + if (!vb_buf) + vb_buf =3D &dst_buf->vb2_buf; + + buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + + /* Set reference addresses */ + regs->h264_addr.ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->h264_addr.colmv_base[i] =3D buf_dma + ctx->colmv_offset; + + struct rkvdec_vdpu381_h264_ref_info *ref_info =3D + ®s->h264_param.ref_info_regs[i / 4].ref_info[i % 4]; + + ref_info->ref_field =3D + !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD); + ref_info->ref_colmv_use_flag =3D + !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); + ref_info->ref_topfield_used =3D + !!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF); + ref_info->ref_botfield_used =3D + !!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF); + + regs->h264_param.ref_pocs[i * 2] =3D + dpb[i].top_field_order_cnt; + regs->h264_param.ref_pocs[i * 2 + 1] =3D + dpb[i].bottom_field_order_cnt; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.rlc_base =3D rlc_addr; + regs->common_addr.rlcwrite_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->common_addr.decout_base =3D dst_addr; + regs->common_addr.error_ref_base =3D dst_addr; + + /* Set colmv address */ + regs->common_addr.colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) + regs->common_addr.rcb_base[i] =3D rkvdec_rcb_buf_dma_addr(ctx, i); + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, param_set); + regs->h264_addr.pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, rps); + regs->h264_addr.rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, cabac_table); + regs->h264_addr.cabactbl_base =3D priv_start_addr + offset; + + offset =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + regs->h264_addr.scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_h264_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_priv_tbl *priv_tbl; + struct rkvdec_h264_ctx *h264_ctx; + struct v4l2_ctrl *ctrl; + int ret; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_SPS); + if (!ctrl) + return -EINVAL; + + ret =3D rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + if (ret) + return ret; + + h264_ctx =3D kzalloc(sizeof(*h264_ctx), GFP_KERNEL); + if (!h264_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &h264_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + h264_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + h264_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_h264_cabac_table, + sizeof(rkvdec_h264_cabac_table)); + + ctx->priv =3D h264_ctx; + return 0; + +err_free_ctx: + kfree(h264_ctx); + return ret; +} + +static void rkvdec_h264_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, h264_ctx->priv_tbl.size, + h264_ctx->priv_tbl.cpu, h264_ctx->priv_tbl.dma); + kfree(h264_ctx); +} + +static int rkvdec_h264_run(struct rkvdec_ctx *ctx) +{ + struct v4l2_h264_reflist_builder reflist_builder; + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_h264_priv_tbl *tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_h264_run run; + u32 watchdog_time; + + rkvdec_h264_run_preamble(ctx, &run); + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, + run.sps, run.decode_params->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); + + assemble_hw_scaling_list(&run, &tbl->scaling_list); + assemble_hw_pps(ctx, &run); + lookup_ref_buf_idx(ctx, &run); + assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + u64 timeout_threshold =3D h264_ctx->regs.common.timeout_threshold; + unsigned long axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); + + return 0; +} + +static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *= ctrl) +{ + if (ctrl->id =3D=3D V4L2_CID_STATELESS_H264_SPS) + return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops =3D { + .adjust_fmt =3D rkvdec_h264_adjust_fmt, + .get_image_fmt =3D rkvdec_h264_get_image_fmt, + .start =3D rkvdec_h264_start, + .stop =3D rkvdec_h264_stop, + .run =3D rkvdec_h264_run, + .try_ctrl =3D rkvdec_h264_try_ctrl, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h new file mode 100644 index 000000000000..11b545e9ee7e --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h @@ -0,0 +1,427 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip VDPU381 Video Decoder driver registers description + * + * Copyright (C) 2024 Collabora, Ltd. + * Detlev Casanova + */ + +#include + +#ifndef _RKVDEC_REGS_H_ +#define _RKVDEC_REGS_H_ + +#define OFFSET_COMMON_REGS (8 * sizeof(u32)) +#define OFFSET_CODEC_PARAMS_REGS (64 * sizeof(u32)) +#define OFFSET_COMMON_ADDR_REGS (128 * sizeof(u32)) +#define OFFSET_CODEC_ADDR_REGS (160 * sizeof(u32)) +#define OFFSET_POC_HIGHBIT_REGS (200 * sizeof(u32)) + +#define VDPU381_MODE_HEVC 0 +#define VDPU381_MODE_H264 1 +#define VDPU381_MODE_VP9 2 +#define VDPU381_MODE_AVS2 3 + +#define MAX_SLICE_NUMBER 0x3fff + +#define RKVDEC_1080P_PIXELS (1920 * 1080) +#define RKVDEC_4K_PIXELS (4096 * 2304) +#define RKVDEC_8K_PIXELS (7680 * 4320) +#define RKVDEC_TIMEOUT_1080p (0xefffff) +#define RKVDEC_TIMEOUT_4K (0x2cfffff) +#define RKVDEC_TIMEOUT_8K (0x4ffffff) +#define RKVDEC_TIMEOUT_MAX (0xffffffff) + +#define VDPU381_REG_DEC_E 0x028 +#define VDPU381_DEC_E_BIT 1 + +#define VDPU381_REG_IMPORTANT_EN 0x02c +#define VDPU381_DEC_IRQ_DISABLE BIT(4) + +#define VDPU381_REG_STA_INT 0x380 +#define VDPU381_STA_INT_DEC_RDY_STA BIT(2) +#define VDPU381_STA_INT_ERROR BIT(4) +#define VDPU381_STA_INT_TIMEOUT BIT(5) +#define VDPU381_STA_INT_SOFTRESET_RDY BIT(9) + +/* base: OFFSET_COMMON_REGS */ +struct rkvdec_vdpu381_regs_common { + struct rkvdec_vdpu381_in_out { + u32 in_endian : 1; + u32 in_swap32_e : 1; + u32 in_swap64_e : 1; + u32 str_endian : 1; + u32 str_swap32_e : 1; + u32 str_swap64_e : 1; + u32 out_endian : 1; + u32 out_swap32_e : 1; + u32 out_cbcr_swap : 1; + u32 out_swap64_e : 1; + u32 reserved : 22; + } reg008; + + struct rkvdec_vdpu381_dec_mode { + u32 dec_mode : 10; + u32 reserved : 22; + } reg009; + + struct rkvdec_vdpu381_dec_e { + u32 dec_e : 1; + u32 reserved : 31; + } reg010; + + struct rkvdec_vdpu381_important_en { + u32 reserved : 1; + u32 dec_clkgate_e : 1; + u32 dec_e_strmd_clkgate_dis : 1; + u32 reserved0 : 1; + + u32 dec_irq_dis : 1; + u32 dec_timeout_e : 1; + u32 buf_empty_en : 1; + u32 reserved1 : 3; + + u32 dec_e_rewrite_valid : 1; + u32 reserved2 : 9; + u32 softrst_en_p : 1; + u32 force_softreset_valid : 1; + u32 reserved3 : 2; + u32 pix_range_detection_e : 1; + u32 reserved4 : 7; + } reg011; + + struct rkvdec_vdpu381_sencodary_en { + u32 wr_ddr_align_en : 1; + u32 colmv_compress_en : 1; + u32 fbc_e : 1; + u32 reserved0 : 1; + + u32 buspr_slot_disable : 1; + u32 error_info_en : 1; + u32 info_collect_en : 1; + u32 wait_reset_en : 1; + + u32 scanlist_addr_valid_en : 1; + u32 scale_down_en : 1; + u32 error_cfg_wr_disable : 1; + u32 reserved1 : 21; + } reg012; + + struct rkvdec_vdpu381_en_mode_set { + u32 timeout_mode : 1; + u32 req_timeout_rst_sel : 1; + u32 reserved0 : 1; + u32 dec_commonirq_mode : 1; + u32 reserved1 : 2; + u32 stmerror_waitdecfifo_empty : 1; + u32 reserved2 : 2; + u32 h26x_streamd_error_mode : 1; + u32 reserved3 : 2; + u32 allow_not_wr_unref_bframe : 1; + u32 fbc_output_wr_disable : 1; + u32 reserved4 : 1; + u32 colmv_error_mode : 1; + + u32 reserved5 : 2; + u32 h26x_error_mode : 1; + u32 reserved6 : 2; + u32 ycacherd_prior : 1; + u32 reserved7 : 2; + u32 cur_pic_is_idr : 1; + u32 reserved8 : 1; + u32 right_auto_rst_disable : 1; + u32 frame_end_err_rst_flag : 1; + u32 rd_prior_mode : 1; + u32 rd_ctrl_prior_mode : 1; + u32 reserved9 : 1; + u32 filter_outbuf_mode : 1; + } reg013; + + struct rkvdec_vdpu381_fbc_param_set { + u32 fbc_force_uncompress : 1; + + u32 reserved0 : 2; + u32 allow_16x8_cp_flag : 1; + u32 reserved1 : 2; + + u32 fbc_h264_exten_4or8_flag : 1; + u32 reserved2 : 25; + } reg014; + + struct rkvdec_vdpu381_stream_param_set { + u32 rlc_mode_direct_write : 1; + u32 rlc_mode : 1; + u32 reserved0 : 3; + + u32 strm_start_bit : 7; + u32 reserved1 : 20; + } reg015; + + u32 stream_len; + + struct rkvdec_vdpu381_slice_number { + u32 slice_num : 25; + u32 reserved : 7; + } reg017; + + struct rkvdec_vdpu381_y_hor_stride { + u32 y_hor_virstride : 16; + u32 reserved : 16; + } reg018; + + struct rkvdec_vdpu381_uv_hor_stride { + u32 uv_hor_virstride : 16; + u32 reserved : 16; + } reg019; + + struct rkvdec_vdpu381_y_stride { + u32 y_virstride : 28; + u32 reserved : 4; + } reg020; + + struct rkvdec_vdpu381_error_ctrl_set { + u32 inter_error_prc_mode : 1; + u32 error_intra_mode : 1; + u32 error_deb_en : 1; + u32 picidx_replace : 5; + u32 error_spread_e : 1; + u32 reserved0 : 3; + u32 error_inter_pred_cross_slice : 1; + u32 reserved1 : 11; + u32 roi_error_ctu_cal_en : 1; + u32 reserved2 : 7; + } reg021; + + struct rkvdec_vdpu381_err_roi_ctu_offset_start { + u32 roi_x_ctu_offset_st : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserved1 : 4; + } reg022; + + struct rkvdec_vdpu381_err_roi_ctu_offset_end { + u32 roi_x_ctu_offset_end : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserved1 : 4; + } reg023; + + struct rkvdec_vdpu381_cabac_error_en_lowbits { + u32 cabac_err_en_lowbits : 32; + } reg024; + + struct rkvdec_vdpu381_cabac_error_en_highbits { + u32 cabac_err_en_highbits : 30; + u32 reserved : 2; + } reg025; + + struct rkvdec_vdpu381_block_gating_en { + u32 swreg_block_gating_e : 20; + u32 reserved : 11; + u32 reg_cfg_gating_en : 1; + } reg026; + + struct SW027_CORE_SAFE_PIXELS { + u32 core_safe_x_pixels : 16; + u32 core_safe_y_pixels : 16; + } reg027; + + struct rkvdec_vdpu381_multiply_core_ctrl { + u32 swreg_vp9_wr_prob_idx : 3; + u32 reserved0 : 1; + u32 swreg_vp9_rd_prob_idx : 3; + u32 reserved1 : 1; + + u32 swreg_ref_req_advance_flag : 1; + u32 sw_colmv_req_advance_flag : 1; + u32 sw_poc_only_highbit_flag : 1; + u32 sw_poc_arb_flag : 1; + + u32 reserved2 : 4; + u32 sw_film_idx : 10; + u32 reserved3 : 2; + u32 sw_pu_req_mismatch_dis : 1; + u32 sw_colmv_req_mismatch_dis : 1; + u32 reserved4 : 2; + } reg028; + + struct SW029_SCALE_DOWN_CTRL { + u32 scale_down_hor_ratio : 2; + u32 reserved0 : 6; + u32 scale_down_vrz_ratio : 2; + u32 reserved1 : 22; + } reg029; + + struct SW032_Y_SCALE_DOWN_TILE8x8_HOR_STRIDE { + u32 y_scale_down_hor_stride : 20; + u32 reserved0 : 12; + } reg030; + + struct SW031_UV_SCALE_DOWN_TILE8x8_HOR_STRIDE { + u32 uv_scale_down_hor_stride : 20; + u32 reserved0 : 12; + } reg031; + + u32 timeout_threshold; +} __packed; + +/* base: OFFSET_COMMON_ADDR_REGS */ +struct rkvdec_vdpu381_regs_common_addr { + u32 rlc_base; + u32 rlcwrite_base; + u32 decout_base; + u32 colmv_cur_base; + u32 error_ref_base; + u32 rcb_base[10]; +} __packed; + +struct rkvdec_vdpu381_h26x_set { + u32 h26x_frame_orslice : 1; + u32 h26x_rps_mode : 1; + u32 h26x_stream_mode : 1; + u32 h26x_stream_lastpacket : 1; + u32 h264_firstslice_flag : 1; + u32 reserved : 27; +} __packed; + +/* base: OFFSET_CODEC_PARAMS_REGS */ +struct rkvdec_vdpu381_regs_h264_params { + struct rkvdec_vdpu381_h26x_set reg064; + + u32 cur_top_poc; + u32 cur_bot_poc; + u32 ref_pocs[32]; + + struct rkvdec_vdpu381_h264_info { + struct rkvdec_vdpu381_h264_ref_info { + u32 ref_field : 1; + u32 ref_topfield_used : 1; + u32 ref_botfield_used : 1; + u32 ref_colmv_use_flag : 1; + u32 ref_reserved : 4; + } __packed ref_info[4]; + } __packed ref_info_regs[4]; + + u32 reserved_103_111[9]; + + struct rkvdec_vdpu381_error_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserved : 28; + } reg112; +} __packed; + +struct rkvdec_vdpu381_regs_hevc_params { + struct rkvdec_vdpu381_h26x_set reg064; + + u32 cur_top_poc; + u32 cur_bot_poc; + + u32 reg067_082_ref_poc[16]; + + u32 reserved_083_098[16]; + + struct rkvdec_vdpu381_hevc_ref_valid { + u32 hevc_ref_valid_0 : 1; + u32 hevc_ref_valid_1 : 1; + u32 hevc_ref_valid_2 : 1; + u32 hevc_ref_valid_3 : 1; + u32 reserve0 : 4; + u32 hevc_ref_valid_4 : 1; + u32 hevc_ref_valid_5 : 1; + u32 hevc_ref_valid_6 : 1; + u32 hevc_ref_valid_7 : 1; + u32 reserve1 : 4; + u32 hevc_ref_valid_8 : 1; + u32 hevc_ref_valid_9 : 1; + u32 hevc_ref_valid_10 : 1; + u32 hevc_ref_valid_11 : 1; + u32 reserve2 : 4; + u32 hevc_ref_valid_12 : 1; + u32 hevc_ref_valid_13 : 1; + u32 hevc_ref_valid_14 : 1; + u32 reserve3 : 5; + } reg099; + + u32 reserved_100_102[3]; + + struct rkvdec_vdpu381_hevc_mvc0 { + u32 ref_pic_layer_same_with_cur : 16; + u32 reserve : 16; + } reg103; + + struct rkvdec_vdpu381_hevc_mvc1 { + u32 poc_lsb_not_present_flag : 1; + u32 num_direct_ref_layers : 6; + u32 reserve0 : 1; + + u32 num_reflayer_pics : 6; + u32 default_ref_layers_active_flag : 1; + u32 max_one_active_ref_layer_flag : 1; + + u32 poc_reset_info_present_flag : 1; + u32 vps_poc_lsb_aligned_flag : 1; + u32 mvc_poc15_valid_flag : 1; + u32 reserve1 : 13; + } reg104; + + u32 reserved_105_111[7]; + + struct rkvdec_vdpu381_hevc_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserve : 28; + } reg112; + +} __packed; + +/* base: OFFSET_CODEC_ADDR_REGS */ +struct rkvdec_vdpu381_regs_h26x_addr { + u32 reserved_160; + u32 pps_base; + u32 reserved_162; + u32 rps_base; + u32 ref_base[16]; + u32 scanlist_addr; + u32 colmv_base[16]; + u32 cabactbl_base; +} __packed; + +struct rkvdec_vdpu381_regs_h26x_highpoc { + struct rkvdec_vdpu381_ref_poc_highbit { + u32 ref0_poc_highbit : 4; + u32 ref1_poc_highbit : 4; + u32 ref2_poc_highbit : 4; + u32 ref3_poc_highbit : 4; + u32 ref4_poc_highbit : 4; + u32 ref5_poc_highbit : 4; + u32 ref6_poc_highbit : 4; + u32 ref7_poc_highbit : 4; + } reg200[4]; + struct rkvdec_vdpu381_cur_poc_highbit { + u32 cur_poc_highbit : 4; + u32 reserved : 28; + } reg204; +} __packed; + +struct rkvdec_vdpu381_regs_h264 { + struct rkvdec_vdpu381_regs_common common; + struct rkvdec_vdpu381_regs_h264_params h264_param; + struct rkvdec_vdpu381_regs_common_addr common_addr; + struct rkvdec_vdpu381_regs_h26x_addr h264_addr; + struct rkvdec_vdpu381_regs_h26x_highpoc h264_highpoc; +} __packed; + +struct rkvdec_vdpu381_regs_hevc { + struct rkvdec_vdpu381_regs_common common; + struct rkvdec_vdpu381_regs_hevc_params hevc_param; + struct rkvdec_vdpu381_regs_common_addr common_addr; + struct rkvdec_vdpu381_regs_h26x_addr hevc_addr; + struct rkvdec_vdpu381_regs_h26x_highpoc hevc_highpoc; +} __packed; + +#endif /* __RKVDEC_REGS_H__ */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index aa92b586429e..ecf6b9051543 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -29,6 +29,7 @@ =20 #include "rkvdec.h" #include "rkvdec-regs.h" +#include "rkvdec-vdpu381-regs.h" #include "rkvdec-rcb.h" =20 static bool rkvdec_image_fmt_match(enum rkvdec_image_fmt fmt1, @@ -90,6 +91,9 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx = *ctx, { v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width, pix_mp->height); + + ctx->colmv_offset =3D pix_mp->plane_fmt[0].sizeimage; + pix_mp->plane_fmt[0].sizeimage +=3D 128 * DIV_ROUND_UP(pix_mp->width, 16) * DIV_ROUND_UP(pix_mp->height, 16); @@ -367,6 +371,26 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded= _fmts[] =3D { } }; =20 +static const struct rkvdec_coded_fmt_desc vdpu381_coded_fmts[] =3D { + { + .fourcc =3D V4L2_PIX_FMT_H264_SLICE, + .frmsize =3D { + .min_width =3D 64, + .max_width =3D 65520, + .step_width =3D 64, + .min_height =3D 64, + .max_height =3D 65520, + .step_height =3D 16, + }, + .ctrls =3D &rkvdec_h264_ctrls, + .ops =3D &rkvdec_vdpu381_h264_fmt_ops, + .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts =3D rkvdec_h264_decoded_fmts, + .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, + .capability =3D RKVDEC_CAPABILITY_H264, + }, +}; + static bool rkvdec_is_capable(struct rkvdec_ctx *ctx, unsigned int capabil= ity) { return (ctx->dev->variant->capabilities & capability) =3D=3D capability; @@ -1241,6 +1265,35 @@ static irqreturn_t rk3399_irq_handler(struct rkvdec_= ctx *ctx) return IRQ_HANDLED; } =20 +static irqreturn_t vdpu381_irq_handler(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + enum vb2_buffer_state state; + bool need_reset =3D 0; + u32 status; + + status =3D readl(rkvdec->regs + VDPU381_REG_STA_INT); + writel(0, rkvdec->regs + VDPU381_REG_STA_INT); + + if (status & VDPU381_STA_INT_DEC_RDY_STA) { + state =3D VB2_BUF_STATE_DONE; + } else { + state =3D VB2_BUF_STATE_ERROR; + if (status & (VDPU381_STA_INT_SOFTRESET_RDY | + VDPU381_STA_INT_TIMEOUT | + VDPU381_STA_INT_ERROR)) + rkvdec_iommu_restore(rkvdec); + } + + if (need_reset) + rkvdec_iommu_restore(rkvdec); + + if (cancel_delayed_work(&rkvdec->watchdog_work)) + rkvdec_job_finish(ctx, state); + + return IRQ_HANDLED; +} + static irqreturn_t rkvdec_irq_handler(int irq, void *priv) { struct rkvdec_dev *rkvdec =3D priv; @@ -1265,12 +1318,76 @@ static void rkvdec_watchdog_func(struct work_struct= *work) } } =20 +/* + * Some SoCs, like RK3588 have multiple identical VDPU cores, but the + * kernel is currently missing support for multi-core handling. Exposing + * separate devices for each core to userspace is bad, since that does + * not allow scheduling tasks properly (and creates ABI). With this workar= ound + * the driver will only probe for the first core and early exit for the ot= her + * cores. Once the driver gains multi-core support, the same technique + * for detecting the first core can be used to cluster all cores together. + */ +static int rkvdec_disable_multicore(struct rkvdec_dev *rkvdec) +{ + struct device_node *node =3D NULL; + const char *compatible; + bool is_first_core; + int ret; + + /* Intentionally ignores the fallback strings */ + ret =3D of_property_read_string(rkvdec->dev->of_node, "compatible", &comp= atible); + if (ret) + return ret; + + /* The first compatible and available node found is considered the main c= ore */ + do { + node =3D of_find_compatible_node(node, NULL, compatible); + if (of_device_is_available(node)) + break; + } while (node); + + if (!node) + return -EINVAL; + + is_first_core =3D (rkvdec->dev->of_node =3D=3D node); + + of_node_put(node); + + if (!is_first_core) { + dev_info(rkvdec->dev, "missing multi-core support, ignoring this instanc= e\n"); + return -ENODEV; + } + + return 0; +} + static const struct rkvdec_config config_rkvdec =3D { .coded_fmts =3D rkvdec_coded_fmts, .coded_fmts_num =3D ARRAY_SIZE(rkvdec_coded_fmts), .irq_handler =3D rk3399_irq_handler, }; =20 +static const struct rcb_size_info vdpu381_rcb_sizes[] =3D { + {6, PIC_WIDTH}, // intrar + {1, PIC_WIDTH}, // transdr (Is actually 0.4*pic_width) + {1, PIC_HEIGHT}, // transdc (Is actually 0.1*pic_height) + {3, PIC_WIDTH}, // streamdr + {6, PIC_WIDTH}, // interr + {3, PIC_HEIGHT}, // interc + {22, PIC_WIDTH}, // dblkr + {6, PIC_WIDTH}, // saor + {11, PIC_WIDTH}, // fbcr + {67, PIC_HEIGHT}, // filtc col +}; + +static const struct rkvdec_config config_vdpu381 =3D { + .coded_fmts =3D vdpu381_coded_fmts, + .coded_fmts_num =3D ARRAY_SIZE(vdpu381_coded_fmts), + .rcb_size_info =3D vdpu381_rcb_sizes, + .rcb_num =3D ARRAY_SIZE(vdpu381_rcb_sizes), + .irq_handler =3D vdpu381_irq_handler, +}; + static const struct rkvdec_variant rk3288_rkvdec_variant =3D { .num_regs =3D 68, .config =3D &config_rkvdec, @@ -1294,6 +1411,11 @@ static const struct rkvdec_variant rk3399_rkvdec_var= iant =3D { RKVDEC_CAPABILITY_VP9, }; =20 +static const struct rkvdec_variant rk3588_vdpu381_variant =3D { + .config =3D &config_vdpu381, + .capabilities =3D RKVDEC_CAPABILITY_H264, +}; + static const struct of_device_id of_rkvdec_match[] =3D { { .compatible =3D "rockchip,rk3288-vdec", @@ -1307,6 +1429,10 @@ static const struct of_device_id of_rkvdec_match[] = =3D { .compatible =3D "rockchip,rk3399-vdec", .data =3D &rk3399_rkvdec_variant, }, + { + .compatible =3D "rockchip,rk3588-vdec", + .data =3D &rk3588_vdpu381_variant, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_rkvdec_match); @@ -1331,11 +1457,16 @@ static int rkvdec_probe(struct platform_device *pde= v) mutex_init(&rkvdec->vdev_lock); INIT_DELAYED_WORK(&rkvdec->watchdog_work, rkvdec_watchdog_func); =20 + ret =3D rkvdec_disable_multicore(rkvdec); + if (ret) + return ret; + ret =3D devm_clk_bulk_get_all_enabled(&pdev->dev, &rkvdec->clocks); if (ret < 0) return ret; =20 rkvdec->clk_count =3D ret; + rkvdec->axi_clk =3D devm_clk_get(&pdev->dev, "axi"); =20 rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rkvdec->regs)) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 4094f92f8a44..5b86f5b85d20 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -132,6 +132,7 @@ struct rkvdec_dev { struct device *dev; struct clk_bulk_data *clocks; unsigned int clk_count; + struct clk *axi_clk; void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; @@ -150,6 +151,7 @@ struct rkvdec_ctx { struct rkvdec_dev *dev; enum rkvdec_image_fmt image_fmt; struct rkvdec_rcb_config *rcb_config; + u32 colmv_offset; void *priv; }; =20 @@ -180,4 +182,6 @@ extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fm= t_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; =20 +extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops; + #endif /* RKVDEC_H_ */ --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0516C358D10; Wed, 22 Oct 2025 16:26:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150371; cv=none; b=fYwQ24XeUOL4SfcBoOjp/qeusO5yDbVTp2ylm/pmR2iV8XsCFYz3Dj1UUlZzcGcwBhwIXV90hkhw/QTlbrXU5ushEEYGGKP9O3Tzt0EdHgMlADhn6QWPKwgnXvw692fNrrODzzoPYvCvJk2Fl8lhCgT3IPbZ5Dbmspuvz3h9gOc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150371; c=relaxed/simple; bh=F7yGgie9aFsTMe3YNKjhKGh/Yly8eVXZqp5tbl9ZwIQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XfpG65YDio+P3quXjjmCnOYWZ38Iv7IB5BdOsAMRxyLzsu/dkYjd1KCMG1Z9kV5L8GATnv4nzmFUM5ka6sxE8mWxuwRey/BNcpzR2qK+4B2TC3A+7CBVzfYnVO3yncF6y1Z4yTq+3AeEDLJf5U5EskLLTDJ22e8Yg2dugsH0ebc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=qQgYU79G; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="qQgYU79G" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150366; bh=F7yGgie9aFsTMe3YNKjhKGh/Yly8eVXZqp5tbl9ZwIQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qQgYU79GPKg1+uZaWeBYSm9ia0Rhk8FK5EBM63XShCnwzwoe7brZMF9Q09nU/Fzkg iP9LXU5i3mrlgYCjfWmhDje6wWgKt1X59TyB3dL8sNWJvqAJ/7Y4iw+o7SyUme9Nzs rHO23qrqHWiKo245MDyZ+lrs100ibfxf9rkbepzjZxOjYA7qDSGmhQWMzRHyra92gO g3OqwLB8k5RRcu9247y9rGEmiOTGOp/7/Tw7jrGIHg4bHxAGY5zjwW/De0Ga8jsuAs imR0zcA3o0T4u1+dV6q2KcRVnCqmhAUWq4ztWvmGkaQvFtRz2it/utg8pZyWlgRPBE Xir3Ski/MG6tg== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id E61FE17E1414; Wed, 22 Oct 2025 18:26:03 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne Subject: [PATCH v3 13/15] media: rkvdec: Add H264 support for the VDPU383 variant Date: Wed, 22 Oct 2025 12:22:12 -0400 Message-ID: <20251022162459.271603-14-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This variant is used on the RK3576 SoC. The moving vectors size requirements are slightly different so support for a colmv_size function per variant is added. Also, the link registers are used to start the decoder and read IRQ status. Per variant support for named register sections is added. The fluster score is 128/135 for JVT-AVC_V1, with MPS_MW_A failing in addition to the usual ones. The other test suites are not supported yet. Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-vdpu383-h264.c | 582 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu383-regs.h | 284 +++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 118 +++- .../media/platform/rockchip/rkvdec/rkvdec.h | 8 + 5 files changed, 987 insertions(+), 6 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h= 264.c create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-r= egs.h diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index 7bfd95151e40..a58d4aede2fe 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -9,4 +9,5 @@ rockchip-vdec-y +=3D \ rkvdec-hevc-common.o \ rkvdec-rcb.o \ rkvdec-vdpu381-h264.o \ + rkvdec-vdpu383-h264.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h264.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h264.c new file mode 100644 index 000000000000..bb2c62d9c3d4 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h264.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip Video Decoder VDPU383 H264 backend + * + * Copyright (C) 2024 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include + +#include + +#include "rkvdec-rcb.h" +#include "rkvdec-vdpu383-regs.h" +#include "rkvdec-h264-common.h" + +struct rkvdec_sps { + u16 seq_parameter_set_id: 4; + u16 profile_idc: 8; + u16 constraint_set3_flag: 1; + u16 chroma_format_idc: 2; + u16 bit_depth_luma: 3; + u16 bit_depth_chroma: 3; + u16 qpprime_y_zero_transform_bypass_flag: 1; + u16 log2_max_frame_num_minus4: 4; + u16 max_num_ref_frames: 5; + u16 pic_order_cnt_type: 2; + u16 log2_max_pic_order_cnt_lsb_minus4: 4; + u16 delta_pic_order_always_zero_flag: 1; + + u16 pic_width_in_mbs: 16; + u16 pic_height_in_mbs: 16; + + u16 frame_mbs_only_flag: 1; + u16 mb_adaptive_frame_field_flag: 1; + u16 direct_8x8_inference_flag: 1; + u16 mvc_extension_enable: 1; + u16 num_views: 2; + u16 view_id0: 10; + u16 view_id1: 10; +} __packed; + +struct rkvdec_pps { + u32 pic_parameter_set_id: 8; + u32 pps_seq_parameter_set_id: 5; + u32 entropy_coding_mode_flag: 1; + u32 bottom_field_pic_order_in_frame_present_flag: 1; + u32 num_ref_idx_l0_default_active_minus1: 5; + u32 num_ref_idx_l1_default_active_minus1: 5; + u32 weighted_pred_flag: 1; + u32 weighted_bipred_idc: 2; + u32 pic_init_qp_minus26: 7; + u32 pic_init_qs_minus26: 6; + u32 chroma_qp_index_offset: 5; + u32 deblocking_filter_control_present_flag: 1; + u32 constrained_intra_pred_flag: 1; + u32 redundant_pic_cnt_present: 1; + u32 transform_8x8_mode_flag: 1; + u32 second_chroma_qp_index_offset: 5; + u32 scaling_list_enable_flag: 1; + u32 is_longterm: 16; + u32 voidx: 16; + + // dpb + u32 pic_field_flag: 1; + u32 pic_associated_flag: 1; + u32 cur_top_field: 32; + u32 cur_bot_field: 32; + + u32 top_field_order_cnt0: 32; + u32 bot_field_order_cnt0: 32; + u32 top_field_order_cnt1: 32; + u32 bot_field_order_cnt1: 32; + u32 top_field_order_cnt2: 32; + u32 bot_field_order_cnt2: 32; + u32 top_field_order_cnt3: 32; + u32 bot_field_order_cnt3: 32; + u32 top_field_order_cnt4: 32; + u32 bot_field_order_cnt4: 32; + u32 top_field_order_cnt5: 32; + u32 bot_field_order_cnt5: 32; + u32 top_field_order_cnt6: 32; + u32 bot_field_order_cnt6: 32; + u32 top_field_order_cnt7: 32; + u32 bot_field_order_cnt7: 32; + u32 top_field_order_cnt8: 32; + u32 bot_field_order_cnt8: 32; + u32 top_field_order_cnt9: 32; + u32 bot_field_order_cnt9: 32; + u32 top_field_order_cnt10: 32; + u32 bot_field_order_cnt10: 32; + u32 top_field_order_cnt11: 32; + u32 bot_field_order_cnt11: 32; + u32 top_field_order_cnt12: 32; + u32 bot_field_order_cnt12: 32; + u32 top_field_order_cnt13: 32; + u32 bot_field_order_cnt13: 32; + u32 top_field_order_cnt14: 32; + u32 bot_field_order_cnt14: 32; + u32 top_field_order_cnt15: 32; + u32 bot_field_order_cnt15: 32; + + u32 ref_field_flags: 16; + u32 ref_topfield_used: 16; + u32 ref_botfield_used: 16; + u32 ref_colmv_use_flag: 16; + + u32 reserved0: 30; + u32 reserved[3]; +} __packed; + +struct rkvdec_sps_pps { + struct rkvdec_sps sps; + struct rkvdec_pps pps; +} __packed; + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec_h264_priv_tbl { + s8 cabac_table[4][464][2]; + struct rkvdec_h264_scaling_list scaling_list; + struct rkvdec_sps_pps param_set[256]; + struct rkvdec_rps rps; +} __packed; + +struct rkvdec_h264_ctx { + struct rkvdec_aux_buf priv_tbl; + struct rkvdec_h264_reflists reflists; + struct vdpu383_regs_h26x regs; +}; + +static void set_field_order_cnt(struct rkvdec_sps_pps *hw_ps, int id, u32 = top, u32 bottom) +{ + switch (id) { + case 0: + hw_ps->pps.top_field_order_cnt0 =3D top; + hw_ps->pps.bot_field_order_cnt0 =3D bottom; + break; + case 1: + hw_ps->pps.top_field_order_cnt1 =3D top; + hw_ps->pps.bot_field_order_cnt1 =3D bottom; + break; + case 2: + hw_ps->pps.top_field_order_cnt2 =3D top; + hw_ps->pps.bot_field_order_cnt2 =3D bottom; + break; + case 3: + hw_ps->pps.top_field_order_cnt3 =3D top; + hw_ps->pps.bot_field_order_cnt3 =3D bottom; + break; + case 4: + hw_ps->pps.top_field_order_cnt4 =3D top; + hw_ps->pps.bot_field_order_cnt4 =3D bottom; + break; + case 5: + hw_ps->pps.top_field_order_cnt5 =3D top; + hw_ps->pps.bot_field_order_cnt5 =3D bottom; + break; + case 6: + hw_ps->pps.top_field_order_cnt6 =3D top; + hw_ps->pps.bot_field_order_cnt6 =3D bottom; + break; + case 7: + hw_ps->pps.top_field_order_cnt7 =3D top; + hw_ps->pps.bot_field_order_cnt7 =3D bottom; + break; + case 8: + hw_ps->pps.top_field_order_cnt8 =3D top; + hw_ps->pps.bot_field_order_cnt8 =3D bottom; + break; + case 9: + hw_ps->pps.top_field_order_cnt9 =3D top; + hw_ps->pps.bot_field_order_cnt9 =3D bottom; + break; + case 10: + hw_ps->pps.top_field_order_cnt10 =3D top; + hw_ps->pps.bot_field_order_cnt10 =3D bottom; + break; + case 11: + hw_ps->pps.top_field_order_cnt11 =3D top; + hw_ps->pps.bot_field_order_cnt11 =3D bottom; + break; + case 12: + hw_ps->pps.top_field_order_cnt12 =3D top; + hw_ps->pps.bot_field_order_cnt12 =3D bottom; + break; + case 13: + hw_ps->pps.top_field_order_cnt13 =3D top; + hw_ps->pps.bot_field_order_cnt13 =3D bottom; + break; + case 14: + hw_ps->pps.top_field_order_cnt14 =3D top; + hw_ps->pps.bot_field_order_cnt14 =3D bottom; + break; + case 15: + hw_ps->pps.top_field_order_cnt15 =3D top; + hw_ps->pps.bot_field_order_cnt15 =3D bottom; + break; + } +} + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_h264_sps *sps =3D run->sps; + const struct v4l2_ctrl_h264_pps *pps =3D run->pps; + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_sps_pps *hw_ps; + u32 pic_width, pic_height; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set[pps->pic_parameter_set_id]; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->sps.seq_parameter_set_id =3D sps->seq_parameter_set_id; + hw_ps->sps.profile_idc =3D sps->profile_idc; + hw_ps->sps.constraint_set3_flag =3D !!(sps->constraint_set_flags & (1 << = 3)); + hw_ps->sps.chroma_format_idc =3D sps->chroma_format_idc; + hw_ps->sps.bit_depth_luma =3D sps->bit_depth_luma_minus8; + hw_ps->sps.bit_depth_chroma =3D sps->bit_depth_chroma_minus8; + hw_ps->sps.qpprime_y_zero_transform_bypass_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS); + hw_ps->sps.log2_max_frame_num_minus4 =3D sps->log2_max_frame_num_minus4; + hw_ps->sps.max_num_ref_frames =3D sps->max_num_ref_frames; + hw_ps->sps.pic_order_cnt_type =3D sps->pic_order_cnt_type; + hw_ps->sps.log2_max_pic_order_cnt_lsb_minus4 =3D + sps->log2_max_pic_order_cnt_lsb_minus4; + hw_ps->sps.delta_pic_order_always_zero_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO); + hw_ps->sps.mvc_extension_enable =3D 0; + hw_ps->sps.num_views =3D 0; + + /* + * Use the SPS values since they are already in macroblocks + * dimensions, height can be field height (halved) if + * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows + * decoding smaller images into larger allocation which can be used + * to implementing SVC spatial layer support. + */ + pic_width =3D 16 * (sps->pic_width_in_mbs_minus1 + 1); + pic_height =3D 16 * (sps->pic_height_in_map_units_minus1 + 1); + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) + pic_height *=3D 2; + if (!!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + pic_height /=3D 2; + + hw_ps->sps.pic_width_in_mbs =3D pic_width; + hw_ps->sps.pic_height_in_mbs =3D pic_height; + + hw_ps->sps.frame_mbs_only_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY); + hw_ps->sps.mb_adaptive_frame_field_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + hw_ps->sps.direct_8x8_inference_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); + + /* write pps */ + hw_ps->pps.pic_parameter_set_id =3D pps->pic_parameter_set_id; + hw_ps->pps.pps_seq_parameter_set_id =3D pps->seq_parameter_set_id; + hw_ps->pps.entropy_coding_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESE= NT); + hw_ps->pps.num_ref_idx_l0_default_active_minus1 =3D + pps->num_ref_idx_l0_default_active_minus1; + hw_ps->pps.num_ref_idx_l1_default_active_minus1 =3D + pps->num_ref_idx_l1_default_active_minus1; + hw_ps->pps.weighted_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED); + hw_ps->pps.weighted_bipred_idc =3D pps->weighted_bipred_idc; + hw_ps->pps.pic_init_qp_minus26 =3D pps->pic_init_qp_minus26; + hw_ps->pps.pic_init_qs_minus26 =3D pps->pic_init_qs_minus26; + hw_ps->pps.chroma_qp_index_offset =3D pps->chroma_qp_index_offset; + hw_ps->pps.deblocking_filter_control_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + hw_ps->pps.constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->pps.redundant_pic_cnt_present =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT); + hw_ps->pps.transform_8x8_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE); + hw_ps->pps.second_chroma_qp_index_offset =3D pps->second_chroma_qp_index_= offset; + hw_ps->pps.scaling_list_enable_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT); + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + hw_ps->pps.is_longterm |=3D (1 << i); + + set_field_order_cnt(hw_ps, i, dpb[i].top_field_order_cnt, + dpb[i].bottom_field_order_cnt); + + hw_ps->pps.ref_field_flags |=3D + (!!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) << i; + hw_ps->pps.ref_colmv_use_flag |=3D + (!!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) << i; + hw_ps->pps.ref_topfield_used |=3D + (!!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF)) << i; + hw_ps->pps.ref_botfield_used |=3D + (!!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)) << i; + } + + hw_ps->pps.pic_field_flag =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC); + hw_ps->pps.pic_associated_flag =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD); + + hw_ps->pps.cur_top_field =3D dec_params->top_field_order_cnt; + hw_ps->pps.cur_bot_field =3D dec_params->bottom_field_order_cnt; +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_REGS, + &h264_ctx->regs.common, + sizeof(h264_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_ADDR_REGS, + &h264_ctx->regs.common_addr, + sizeof(h264_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_PARAMS_REGS, + &h264_ctx->regs.h26x_params, + sizeof(h264_ctx->regs.h26x_params)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_ADDR_REGS, + &h264_ctx->regs.h26x_addr, + sizeof(h264_ctx->regs.h26x_addr)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + dma_addr_t priv_start_addr =3D h264_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + struct vdpu383_regs_h26x *regs =3D &h264_ctx->regs; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + dma_addr_t dst_addr; + u32 hor_virstride; + u32 ver_virstride; + u32 y_virstride; + u32 offset; + u32 pixels; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set H264 mode */ + regs->common.reg008_dec_mode =3D VDPU383_MODE_H264; + + /* Set input stream length */ + regs->h26x_params.reg066_stream_len =3D vb2_get_plane_payload(&src_buf->v= b2_buf, 0); + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->h26x_params.reg068_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg069_raster_uv_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg070_y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg010.strmd_auto_gating_e =3D 1; + regs->common.reg010.inter_auto_gating_e =3D 1; + regs->common.reg010.intra_auto_gating_e =3D 1; + regs->common.reg010.transd_auto_gating_e =3D 1; + regs->common.reg010.recon_auto_gating_e =3D 1; + regs->common.reg010.filterd_auto_gating_e =3D 1; + regs->common.reg010.bus_auto_gating_e =3D 1; + regs->common.reg010.ctrl_auto_gating_e =3D 1; + regs->common.reg010.rcb_auto_gating_e =3D 1; + regs->common.reg010.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < VDPU383_1080P_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_1080p; + else if (pixels < VDPU383_4K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_4K; + else if (pixels < VDPU383_8K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_8K; + else + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_MAX; + + regs->common.reg016.error_proc_disable =3D 1; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf =3D run->ref_buf[i]; + dma_addr_t buf_dma; + + /* + * If a DPB entry is unused or invalid, address of current destination + * buffer is returned. + */ + if (!vb_buf) + vb_buf =3D &dst_buf->vb2_buf; + + buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + + /* Set reference addresses */ + regs->h26x_addr.reg170_185_ref_base[i] =3D buf_dma; + regs->h26x_addr.reg195_210_payload_st_ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->h26x_addr.reg217_232_colmv_ref_base[i] =3D buf_dma + ctx->colmv_of= fset; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.reg128_strm_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->h26x_addr.reg168_decout_base =3D dst_addr; + regs->h26x_addr.reg169_error_ref_base =3D dst_addr; + regs->h26x_addr.reg192_payload_st_cur_base =3D dst_addr; + + /* Set colmv address */ + regs->h26x_addr.reg216_colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) { + regs->common_addr.reg140_162_rcb_info[i].offset =3D rkvdec_rcb_buf_dma_a= ddr(ctx, i); + regs->common_addr.reg140_162_rcb_info[i].size =3D rkvdec_rcb_buf_size(ct= x, i); + } + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, param_set); + regs->common_addr.reg131_gbl_base =3D priv_start_addr + offset; + regs->h26x_params.reg067_global_len =3D sizeof(struct rkvdec_sps_pps) / 1= 6; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, rps); + regs->common_addr.reg129_rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, cabac_table); + regs->common_addr.reg130_cabactbl_base =3D priv_start_addr + offset; + + /* Set scaling list address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + regs->common_addr.reg132_scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_h264_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_priv_tbl *priv_tbl; + struct rkvdec_h264_ctx *h264_ctx; + struct v4l2_ctrl *ctrl; + int ret; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_SPS); + if (!ctrl) + return -EINVAL; + + ret =3D rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + if (ret) + return ret; + + h264_ctx =3D kzalloc(sizeof(*h264_ctx), GFP_KERNEL); + if (!h264_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &h264_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + h264_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + h264_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_h264_cabac_table, + sizeof(rkvdec_h264_cabac_table)); + + ctx->priv =3D h264_ctx; + + return 0; + +err_free_ctx: + kfree(h264_ctx); + return ret; +} + +static void rkvdec_h264_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, h264_ctx->priv_tbl.size, + h264_ctx->priv_tbl.cpu, h264_ctx->priv_tbl.dma); + kfree(h264_ctx); +} + +static int rkvdec_h264_run(struct rkvdec_ctx *ctx) +{ + struct v4l2_h264_reflist_builder reflist_builder; + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_h264_run run; + struct rkvdec_h264_priv_tbl *tbl =3D h264_ctx->priv_tbl.cpu; + u32 watchdog_time; + u64 timeout_threshold; + unsigned long axi_rate; + + rkvdec_h264_run_preamble(ctx, &run); + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, + run.sps, run.decode_params->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); + + assemble_hw_scaling_list(&run, &tbl->scaling_list); + assemble_hw_pps(ctx, &run); + lookup_ref_buf_idx(ctx, &run); + assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + timeout_threshold =3D h264_ctx->regs.common.reg013_core_timeout_threshold; + axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(timeout_threshold, rkvdec->link + VDPU383_LINK_TIMEOUT_THRESHOLD); + writel(0, rkvdec->link + VDPU383_LINK_IP_ENABLE); + writel(VDPU383_DEC_E_BIT, rkvdec->link + VDPU383_LINK_DEC_ENABLE); + + return 0; +} + +static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *= ctrl) +{ + if (ctrl->id =3D=3D V4L2_CID_STATELESS_H264_SPS) + return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops =3D { + .adjust_fmt =3D rkvdec_h264_adjust_fmt, + .get_image_fmt =3D rkvdec_h264_get_image_fmt, + .start =3D rkvdec_h264_start, + .stop =3D rkvdec_h264_stop, + .run =3D rkvdec_h264_run, + .try_ctrl =3D rkvdec_h264_try_ctrl, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h new file mode 100644 index 000000000000..2b614393a3af --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip Video Decoder VDPU383 driver registers description + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#ifndef _RKVDEC_VDPU838_REGS_H_ +#define _RKVDEC_VDPU838_REGS_H_ + +#include + +#define VDPU383_OFFSET_COMMON_REGS (8 * sizeof(u32)) +#define VDPU383_OFFSET_CODEC_PARAMS_REGS (64 * sizeof(u32)) +#define VDPU383_OFFSET_COMMON_ADDR_REGS (128 * sizeof(u32)) +#define VDPU383_OFFSET_CODEC_ADDR_REGS (168 * sizeof(u32)) +#define VDPU383_OFFSET_POC_HIGHBIT_REGS (200 * sizeof(u32)) + +#define VDPU383_MODE_HEVC 0 +#define VDPU383_MODE_H264 1 + +#define VDPU383_1080P_PIXELS (1920 * 1080) +#define VDPU383_4K_PIXELS (4096 * 2304) +#define VDPU383_8K_PIXELS (7680 * 4320) +#define VDPU383_TIMEOUT_1080p (0xffffff) +#define VDPU383_TIMEOUT_4K (0x2cfffff) +#define VDPU383_TIMEOUT_8K (0x4ffffff) +#define VDPU383_TIMEOUT_MAX (0xffffffff) + +#define VDPU383_LINK_TIMEOUT_THRESHOLD 0x54 + +#define VDPU383_LINK_IP_ENABLE 0x58 +#define VDPU383_IP_CRU_MODE BIT(24) + +#define VDPU383_LINK_DEC_ENABLE 0x40 +#define VDPU383_DEC_E_BIT BIT(0) + +#define VDPU383_LINK_INT_EN 0x048 +#define VDPU383_INT_EN_IRQ BIT(0) +#define VDPU383_INT_EN_LINE_IRQ BIT(1) + +#define VDPU383_LINK_STA_INT 0x04c +#define VDPU383_STA_INT_DEC_RDY_STA BIT(0) +#define VDPU383_STA_INT_SOFTRESET_RDY (BIT(10) | BIT(11)) +#define VDPU383_STA_INT_ALL 0x3ff + +struct vdpu383_regs_common { + u32 reg008_dec_mode; + + struct swreg9_important_en { + u32 fbc_e : 1; + u32 tile_e : 1; + u32 reserve0 : 2; + u32 buf_empty_en : 1; + u32 scale_down_en : 1; + u32 reserve1 : 1; + u32 pix_range_det_e : 1; + u32 av1_fgs_en : 1; + u32 reserve2 : 7; + u32 line_irq_en : 1; + u32 out_cbcr_swap : 1; + u32 fbc_force_uncompress : 1; + u32 fbc_sparse_mode : 1; + u32 reserve3 : 12; + } reg009; + + struct swreg010_block_gating_en { + u32 strmd_auto_gating_e : 1; + u32 inter_auto_gating_e : 1; + u32 intra_auto_gating_e : 1; + u32 transd_auto_gating_e : 1; + u32 recon_auto_gating_e : 1; + u32 filterd_auto_gating_e : 1; + u32 bus_auto_gating_e : 1; + u32 ctrl_auto_gating_e : 1; + u32 rcb_auto_gating_e : 1; + u32 err_prc_auto_gating_e : 1; + u32 reserve0 : 22; + } reg010; + + struct swreg011_cfg_para { + u32 reserve0 : 9; + u32 dec_timeout_dis : 1; + u32 reserve1 : 22; + } reg011; + + struct swreg012_cache_hash_mask { + u32 reserve0 : 7; + u32 cache_hash_mask : 25; + } reg012; + + u32 reg013_core_timeout_threshold; + + struct swreg014_line_irq_ctrl { + u32 dec_line_irq_step : 16; + u32 dec_line_offset_y_st : 16; + } reg014; + + struct swreg015_irq_sta { + u32 rkvdec_frame_rdy_sta : 1; + u32 rkvdec_strm_error_sta : 1; + u32 rkvdec_core_timeout_sta : 1; + u32 rkvdec_ip_timeout_sta : 1; + u32 rkvdec_bus_error_sta : 1; + u32 rkvdec_buffer_empty_sta : 1; + u32 rkvdec_colmv_ref_error_sta : 1; + u32 rkvdec_error_spread_sta : 1; + u32 create_core_timeout_sta : 1; + u32 wlast_miss_match_sta : 1; + u32 rkvdec_core_rst_rdy_sta : 1; + u32 rkvdec_ip_rst_rdy_sta : 1; + u32 force_busidle_rdy_sta : 1; + u32 ltb_pause_rdy_sta : 1; + u32 ltb_end_flag : 1; + u32 unsupport_decmode_error_sta : 1; + u32 wmask_bits : 15; + u32 reserve0 : 1; + } reg015; + + struct swreg016_error_ctrl_set { + u32 error_proc_disable : 1; + u32 reserve0 : 7; + u32 error_spread_disable : 1; + u32 reserve1 : 15; + u32 roi_error_ctu_cal_en : 1; + u32 reserve2 : 7; + } reg016; + + struct swreg017_err_roi_ctu_offset_start { + u32 roi_x_ctu_offset_st : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserve1 : 4; + } reg017; + + struct swreg018_err_roi_ctu_offset_end { + u32 roi_x_ctu_offset_end : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserve1 : 4; + } reg018; + + struct swreg019_error_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserve0 : 28; + } reg019; + + u32 reg020_cabac_error_en_lowbits; + u32 reg021_cabac_error_en_highbits; + + u32 reg022_reserved; + + struct swreg023_invalid_pixel_fill { + u32 fill_y : 10; + u32 fill_u : 10; + u32 fill_v : 10; + u32 reserve0 : 2; + } reg023; + + u32 reg024_026_reserved[3]; + + struct swreg027_align_en { + u32 reserve0 : 4; + u32 ctu_align_wr_en : 1; + u32 reserve1 : 27; + } reg027; + + struct swreg028_debug_perf_latency_ctrl0 { + u32 axi_perf_work_e : 1; + u32 reserve0 : 2; + u32 axi_cnt_type : 1; + u32 rd_latency_id : 8; + u32 reserve1 : 4; + u32 rd_latency_thr : 12; + u32 reserve2 : 4; + } reg028; + + struct swreg029_debug_perf_latency_ctrl1 { + u32 addr_align_type : 2; + u32 ar_cnt_id_type : 1; + u32 aw_cnt_id_type : 1; + u32 ar_count_id : 8; + u32 reserve0 : 4; + u32 aw_count_id : 8; + u32 rd_band_width_mode : 1; + u32 reserve1 : 7; + } reg029; + + struct swreg030_qos_ctrl { + u32 axi_wr_qos_level : 4; + u32 reserve0 : 4; + u32 axi_wr_qos : 4; + u32 reserve1 : 4; + u32 axi_rd_qos_level : 4; + u32 reserve2 : 4; + u32 axi_rd_qos : 4; + u32 reserve3 : 4; + } reg030; +}; + +struct vdpu383_regs_common_addr { + u32 reg128_strm_base; + u32 reg129_rps_base; + u32 reg130_cabactbl_base; + u32 reg131_gbl_base; + u32 reg132_scanlist_addr; + u32 reg133_scale_down_base; + u32 reg134_fgs_base; + u32 reg135_139_reserved[5]; + + struct rcb_info { + u32 offset; + u32 size; + } reg140_162_rcb_info[11]; +}; + +struct vdpu383_regs_h26x_addr { + u32 reg168_decout_base; + u32 reg169_error_ref_base; + u32 reg170_185_ref_base[16]; + u32 reg186_191_reserved[6]; + u32 reg192_payload_st_cur_base; + u32 reg193_fbc_payload_offset; + u32 reg194_payload_st_error_ref_base; + u32 reg195_210_payload_st_ref_base[16]; + u32 reg211_215_reserved[5]; + u32 reg216_colmv_cur_base; + u32 reg217_232_colmv_ref_base[16]; +}; + +struct vdpu383_regs_h26x_params { + u32 reg064_start_decoder; + u32 reg065_strm_start_bit; + u32 reg066_stream_len; + u32 reg067_global_len; + u32 reg068_hor_virstride; + u32 reg069_raster_uv_hor_virstride; + u32 reg070_y_virstride; + u32 reg071_scl_ref_hor_virstride; + u32 reg072_scl_ref_raster_uv_hor_virstride; + u32 reg073_scl_ref_virstride; + u32 reg074_fgs_ref_hor_virstride; + u32 reg075_079_reserved[5]; + u32 reg080_error_ref_hor_virstride; + u32 reg081_error_ref_raster_uv_hor_virstride; + u32 reg082_error_ref_virstride; + u32 reg083_ref0_hor_virstride; + u32 reg084_ref0_raster_uv_hor_virstride; + u32 reg085_ref0_virstride; + u32 reg086_ref1_hor_virstride; + u32 reg087_ref1_raster_uv_hor_virstride; + u32 reg088_ref1_virstride; + u32 reg089_ref2_hor_virstride; + u32 reg090_ref2_raster_uv_hor_virstride; + u32 reg091_ref2_virstride; + u32 reg092_ref3_hor_virstride; + u32 reg093_ref3_raster_uv_hor_virstride; + u32 reg094_ref3_virstride; + u32 reg095_ref4_hor_virstride; + u32 reg096_ref4_raster_uv_hor_virstride; + u32 reg097_ref4_virstride; + u32 reg098_ref5_hor_virstride; + u32 reg099_ref5_raster_uv_hor_virstride; + u32 reg100_ref5_virstride; + u32 reg101_ref6_hor_virstride; + u32 reg102_ref6_raster_uv_hor_virstride; + u32 reg103_ref6_virstride; + u32 reg104_ref7_hor_virstride; + u32 reg105_ref7_raster_uv_hor_virstride; + u32 reg106_ref7_virstride; +}; + +struct vdpu383_regs_h26x { + struct vdpu383_regs_common common; /* 8-30 */ + struct vdpu383_regs_h26x_params h26x_params; /* 64-74, 80-106 */ + struct vdpu383_regs_common_addr common_addr; /* 128-134, 140-161 */ + struct vdpu383_regs_h26x_addr h26x_addr; /* 168-185, 192-210, 216-232 */ +} __packed; + +#endif /* __RKVDEC_VDPU838_REGS_H__ */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index ecf6b9051543..1837f12f1aa1 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -9,6 +9,7 @@ * Copyright (C) 2011 Samsung Electronics Co., Ltd. */ =20 +#include #include #include #include @@ -30,6 +31,7 @@ #include "rkvdec.h" #include "rkvdec-regs.h" #include "rkvdec-vdpu381-regs.h" +#include "rkvdec-vdpu383-regs.h" #include "rkvdec-rcb.h" =20 static bool rkvdec_image_fmt_match(enum rkvdec_image_fmt fmt1, @@ -86,17 +88,27 @@ static bool rkvdec_is_valid_fmt(struct rkvdec_ctx *ctx,= u32 fourcc, return false; } =20 +static u32 rkvdec_colmv_size(u16 width, u16 height) +{ + return 128 * DIV_ROUND_UP(width, 16) * DIV_ROUND_UP(height, 16); +} + +static u32 rkvdec_vdpu383_colmv_size(u16 width, u16 height) +{ + return ALIGN(width, 64) * ALIGN(height, 16); +} + static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp) { + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width, pix_mp->height); =20 ctx->colmv_offset =3D pix_mp->plane_fmt[0].sizeimage; =20 - pix_mp->plane_fmt[0].sizeimage +=3D 128 * - DIV_ROUND_UP(pix_mp->width, 16) * - DIV_ROUND_UP(pix_mp->height, 16); + pix_mp->plane_fmt[0].sizeimage +=3D cfg->colmv_size(pix_mp->width, pix_mp= ->height); } =20 static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f, @@ -391,6 +403,26 @@ static const struct rkvdec_coded_fmt_desc vdpu381_code= d_fmts[] =3D { }, }; =20 +static const struct rkvdec_coded_fmt_desc vdpu383_coded_fmts[] =3D { + { + .fourcc =3D V4L2_PIX_FMT_H264_SLICE, + .frmsize =3D { + .min_width =3D 64, + .max_width =3D 65520, + .step_width =3D 64, + .min_height =3D 64, + .max_height =3D 65520, + .step_height =3D 16, + }, + .ctrls =3D &rkvdec_h264_ctrls, + .ops =3D &rkvdec_vdpu383_h264_fmt_ops, + .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts =3D rkvdec_h264_decoded_fmts, + .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, + .capability =3D RKVDEC_CAPABILITY_H264, + }, +}; + static bool rkvdec_is_capable(struct rkvdec_ctx *ctx, unsigned int capabil= ity) { return (ctx->dev->variant->capabilities & capability) =3D=3D capability; @@ -1294,6 +1326,35 @@ static irqreturn_t vdpu381_irq_handler(struct rkvdec= _ctx *ctx) return IRQ_HANDLED; } =20 +static irqreturn_t vdpu383_irq_handler(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + enum vb2_buffer_state state; + bool need_reset =3D 0; + u32 status; + + status =3D readl(rkvdec->link + VDPU383_LINK_STA_INT); + writel(FIELD_PREP_WM16(VDPU383_STA_INT_ALL, 0), rkvdec->link + VDPU383_LI= NK_STA_INT); + /* On vdpu383, the interrupts must be disabled */ + writel(FIELD_PREP_WM16(VDPU383_INT_EN_IRQ | VDPU383_INT_EN_LINE_IRQ, 0), + rkvdec->link + VDPU383_LINK_INT_EN); + + if (status & VDPU383_STA_INT_DEC_RDY_STA) { + state =3D VB2_BUF_STATE_DONE; + } else { + state =3D VB2_BUF_STATE_ERROR; + rkvdec_iommu_restore(rkvdec); + } + + if (need_reset) + rkvdec_iommu_restore(rkvdec); + + if (cancel_delayed_work(&rkvdec->watchdog_work)) + rkvdec_job_finish(ctx, state); + + return IRQ_HANDLED; +} + static irqreturn_t rkvdec_irq_handler(int irq, void *priv) { struct rkvdec_dev *rkvdec =3D priv; @@ -1365,6 +1426,7 @@ static const struct rkvdec_config config_rkvdec =3D { .coded_fmts =3D rkvdec_coded_fmts, .coded_fmts_num =3D ARRAY_SIZE(rkvdec_coded_fmts), .irq_handler =3D rk3399_irq_handler, + .colmv_size =3D rkvdec_colmv_size, }; =20 static const struct rcb_size_info vdpu381_rcb_sizes[] =3D { @@ -1386,6 +1448,31 @@ static const struct rkvdec_config config_vdpu381 =3D= { .rcb_size_info =3D vdpu381_rcb_sizes, .rcb_num =3D ARRAY_SIZE(vdpu381_rcb_sizes), .irq_handler =3D vdpu381_irq_handler, + .colmv_size =3D rkvdec_colmv_size, + .named_regs =3D true, +}; + +static const struct rcb_size_info vdpu383_rcb_sizes[] =3D { + {6, PIC_WIDTH}, // streamd + {6, PIC_WIDTH}, // streamd_tile + {12, PIC_WIDTH}, // inter + {12, PIC_WIDTH}, // inter_tile + {16, PIC_WIDTH}, // intra + {10, PIC_WIDTH}, // intra_tile + {120, PIC_WIDTH}, // filterd + {120, PIC_WIDTH}, // filterd_protect + {120, PIC_WIDTH}, // filterd_tile_row + {180, PIC_HEIGHT}, // filterd_tile_col +}; + +static const struct rkvdec_config config_vdpu383 =3D { + .coded_fmts =3D vdpu383_coded_fmts, + .coded_fmts_num =3D ARRAY_SIZE(vdpu383_coded_fmts), + .rcb_size_info =3D vdpu383_rcb_sizes, + .rcb_num =3D ARRAY_SIZE(vdpu383_rcb_sizes), + .irq_handler =3D vdpu383_irq_handler, + .colmv_size =3D rkvdec_vdpu383_colmv_size, + .named_regs =3D true, }; =20 static const struct rkvdec_variant rk3288_rkvdec_variant =3D { @@ -1416,6 +1503,11 @@ static const struct rkvdec_variant rk3588_vdpu381_va= riant =3D { .capabilities =3D RKVDEC_CAPABILITY_H264, }; =20 +static const struct rkvdec_variant rk3576_vdpu383_variant =3D { + .config =3D &config_vdpu383, + .capabilities =3D RKVDEC_CAPABILITY_H264, +}; + static const struct of_device_id of_rkvdec_match[] =3D { { .compatible =3D "rockchip,rk3288-vdec", @@ -1433,6 +1525,10 @@ static const struct of_device_id of_rkvdec_match[] = =3D { .compatible =3D "rockchip,rk3588-vdec", .data =3D &rk3588_vdpu381_variant, }, + { + .compatible =3D "rockchip,rk3576-vdec", + .data =3D &rk3576_vdpu383_variant, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_rkvdec_match); @@ -1468,9 +1564,19 @@ static int rkvdec_probe(struct platform_device *pdev) rkvdec->clk_count =3D ret; rkvdec->axi_clk =3D devm_clk_get(&pdev->dev, "axi"); =20 - rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(rkvdec->regs)) - return PTR_ERR(rkvdec->regs); + if (rkvdec->variant->config->named_regs) { + rkvdec->regs =3D devm_platform_ioremap_resource_byname(pdev, "function"); + if (IS_ERR(rkvdec->regs)) + return PTR_ERR(rkvdec->regs); + + rkvdec->link =3D devm_platform_ioremap_resource_byname(pdev, "link"); + if (IS_ERR(rkvdec->link)) + return PTR_ERR(rkvdec->link); + } else { + rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(rkvdec->regs)) + return PTR_ERR(rkvdec->regs); + } =20 ret =3D dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 5b86f5b85d20..e752706e9f5c 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -122,6 +122,8 @@ struct rkvdec_config { const struct rcb_size_info *rcb_size_info; size_t rcb_num; irqreturn_t (*irq_handler)(struct rkvdec_ctx *ctx); + u32 (*colmv_size)(u16 width, u16 height); + bool named_regs; }; =20 struct rkvdec_dev { @@ -134,6 +136,7 @@ struct rkvdec_dev { unsigned int clk_count; struct clk *axi_clk; void __iomem *regs; + void __iomem *link; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; struct gen_pool *sram_pool; @@ -178,10 +181,15 @@ void rkvdec_memcpy_toio(void __iomem *dst, void *src,= size_t len); =20 void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx); =20 +/* RKVDEC ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; =20 +/* VDPU381 ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops; =20 +/* VDPU383 ops */ +extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops; + #endif /* RKVDEC_H_ */ --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAE28358D3A; Wed, 22 Oct 2025 16:26:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150374; cv=none; b=OJASR6a2ZdOVCVhoJ/TthHwh5x/aw1PH9MnpNKlNSiNzvo9GOzDQTIUy0IW9Dnim9wkQt8CuSUA1CJxrdfpbdmZoLMcZc/rgk4ahxy6u8zaxo/vdQxqXu16cqT0zXq5EUjlPAe+M3Xfe2xZFiTG75qUUpZiYnzSAmCnIUOnqraA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150374; c=relaxed/simple; bh=KcUtQpTjceRQb92EgPDjZ/AQiUMhFwBADYecoGiPUM0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OkeynBFlIlg0X9rzte1YASdAxRth15ZtAMF3ZREu4rCvzEVXRKBd44Xpu5tvlYVVRHRLPqAbH4qNGVyAMWB2noLwj19vYqo2op0oCFXw1s5yV7/A90O1TUBwo2E78s2nMDZYJL+eidQ2vacKlJU+EhzMtryNr4zwugZiSq3R794= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=LfIADKRA; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="LfIADKRA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150369; bh=KcUtQpTjceRQb92EgPDjZ/AQiUMhFwBADYecoGiPUM0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LfIADKRARrkSYxa+QDGszBMLrLKpnMFPc92FSxuDPUQecSvv1NFlHs+DeVmXIcBmT U0MhezLE/ywesS74AaYlBfXaAuUU6A4Lyy3QXUgwR9Rt59AiKraPw51maiR5kqvJdS zK3qKIh7IWIN6SnMTN7j4enSdon99LYwV2hIL9WZB1t7d1J43xQeWrAC259TnN+5pH f/6RiGRg0wnaEY5DnNNA0VRSHxK8yEsUHK+hz8LSB1iGZE5o1V5Q0uonegclOqeArR MY9MSmb0O9/HPCxTQRekQoxhHqVaCQD/lZ/CsC74hzzAoUP27DDGCR4rOhiV1ZIOQh vu7Owaank4e4g== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 87D8117E1404; Wed, 22 Oct 2025 18:26:06 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne , Diederik de Haas Subject: [PATCH v3 14/15] media: rkvdec: Add HEVC support for the VDPU381 variant Date: Wed, 22 Oct 2025 12:22:13 -0400 Message-ID: <20251022162459.271603-15-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The VDPU381 supports HEVC decoding up to 7680x4320@30fps. It could double that when using both decoder cores. It support YUV420 (8 and 10 bits) as well as AFBC (not implemented here) The fluster score is 146/147 for JCT-VC-HEVC_V1, tested on ROCK 5B. None of the other test suites works. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Kconfig | 1 + .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 392 +++++++++++- .../rockchip/rkvdec/rkvdec-hevc-common.h | 74 ++- .../rockchip/rkvdec/rkvdec-vdpu381-hevc.c | 596 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 86 ++- .../media/platform/rockchip/rkvdec/rkvdec.h | 3 + 7 files changed, 1114 insertions(+), 39 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h= evc.c diff --git a/drivers/media/platform/rockchip/rkvdec/Kconfig b/drivers/media= /platform/rockchip/rkvdec/Kconfig index 5f3bdd848a2c..3303b0ce3280 100644 --- a/drivers/media/platform/rockchip/rkvdec/Kconfig +++ b/drivers/media/platform/rockchip/rkvdec/Kconfig @@ -8,6 +8,7 @@ config VIDEO_ROCKCHIP_VDEC select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 + select V4L2_HEVC select V4L2_VP9 help Support for the Rockchip Video Decoder IP present on Rockchip SoCs, diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index a58d4aede2fe..e30fdd7d51c3 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -9,5 +9,6 @@ rockchip-vdec-y +=3D \ rkvdec-hevc-common.o \ rkvdec-rcb.o \ rkvdec-vdpu381-h264.o \ + rkvdec-vdpu381-hevc.o \ rkvdec-vdpu383-h264.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c index d571107f2242..4b21b3ea67fd 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -21,6 +21,143 @@ #include "rkvdec.h" #include "rkvdec-hevc-common.h" =20 +#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 + +/* Store the Short term ref pic set calculated values */ +struct calculated_rps_st_set { + u8 num_delta_pocs; + u8 num_negative_pics; + u8 num_positive_pics; + u8 used_by_curr_pic_s0[16]; + u8 used_by_curr_pic_s1[16]; + s32 delta_poc_s0[16]; + s32 delta_poc_s1[16]; +}; + +enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, + struct v4l2_ctrl *ctrl) +{ + const struct v4l2_ctrl_hevc_sps *sps =3D ctrl->p_new.p_hevc_sps; + + if (ctrl->id !=3D V4L2_CID_STATELESS_HEVC_SPS) + return RKVDEC_IMG_FMT_ANY; + + if (sps->bit_depth_luma_minus8 =3D=3D 0) + return RKVDEC_IMG_FMT_420_8BIT; + else if (sps->bit_depth_luma_minus8 =3D=3D 2) + return RKVDEC_IMG_FMT_420_10BIT; + + return RKVDEC_IMG_FMT_ANY; +} + +void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_si= ze, + u16 width, u16 height, s32 pic_in_cts_width, + s32 pic_in_cts_height, u16 *column_width, u16 *row_height) +{ + const struct v4l2_ctrl_hevc_pps *pps =3D run->pps; + int i; + + for (i =3D 0; i < pps->num_tile_columns_minus1 + 1; i++) + column_width[i] =3D ((i + 1) * pic_in_cts_width) / + (pps->num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / + (pps->num_tile_columns_minus1 + 1); + + for (i =3D 0; i < pps->num_tile_rows_minus1 + 1; i++) + row_height[i] =3D ((i + 1) * pic_in_cts_height) / + (pps->num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / + (pps->num_tile_rows_minus1 + 1); +} + +void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_c= b_size, + u16 width, u16 height, s32 pic_in_cts_width, + s32 pic_in_cts_height, u16 *column_width, u16 *row_height) +{ + const struct v4l2_ctrl_hevc_pps *pps =3D run->pps; + s32 sum =3D 0; + int i; + + for (i =3D 0; i < pps->num_tile_columns_minus1; i++) { + column_width[i] =3D pps->column_width_minus1[i] + 1; + sum +=3D column_width[i]; + } + column_width[i] =3D pic_in_cts_width - sum; + + sum =3D 0; + for (i =3D 0; i < pps->num_tile_rows_minus1; i++) { + row_height[i] =3D pps->row_height_minus1[i] + 1; + sum +=3D row_height[i]; + } + row_height[i] =3D pic_in_cts_height - sum; +} + +static void set_ref_poc(struct rkvdec_rps_short_term_ref_set *set, int poc= , int value, int flag) +{ + switch (poc) { + case 0: + set->delta_poc0 =3D value; + set->used_flag0 =3D flag; + break; + case 1: + set->delta_poc1 =3D value; + set->used_flag1 =3D flag; + break; + case 2: + set->delta_poc2 =3D value; + set->used_flag2 =3D flag; + break; + case 3: + set->delta_poc3 =3D value; + set->used_flag3 =3D flag; + break; + case 4: + set->delta_poc4 =3D value; + set->used_flag4 =3D flag; + break; + case 5: + set->delta_poc5 =3D value; + set->used_flag5 =3D flag; + break; + case 6: + set->delta_poc6 =3D value; + set->used_flag6 =3D flag; + break; + case 7: + set->delta_poc7 =3D value; + set->used_flag7 =3D flag; + break; + case 8: + set->delta_poc8 =3D value; + set->used_flag8 =3D flag; + break; + case 9: + set->delta_poc9 =3D value; + set->used_flag9 =3D flag; + break; + case 10: + set->delta_poc10 =3D value; + set->used_flag10 =3D flag; + break; + case 11: + set->delta_poc11 =3D value; + set->used_flag11 =3D flag; + break; + case 12: + set->delta_poc12 =3D value; + set->used_flag12 =3D flag; + break; + case 13: + set->delta_poc13 =3D value; + set->used_flag13 =3D flag; + break; + case 14: + set->delta_poc14 =3D value; + set->used_flag14 =3D flag; + break; + } +} + /* * Flip one or more matrices along their main diagonal and flatten them * before writing it to the memory. @@ -105,7 +242,7 @@ static void translate_scaling_list(struct scaling_facto= r *output, } =20 void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, - struct scaling_factor *scaling_factor, + struct scaling_factor *scaling_list, struct v4l2_ctrl_hevc_scaling_matrix *cache) { const struct v4l2_ctrl_hevc_scaling_matrix *scaling =3D run->scaling_matr= ix; @@ -114,15 +251,220 @@ void rkvdec_hevc_assemble_hw_scaling_list(struct rkv= dec_hevc_run *run, sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) return; =20 - translate_scaling_list(scaling_factor, scaling); + translate_scaling_list(scaling_list, scaling); =20 memcpy(cache, scaling, sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); } =20 -struct vb2_buffer * -get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, - unsigned int dpb_idx) +static void rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run *run, st= ruct rkvdec_rps *rps) +{ + const struct v4l2_ctrl_hevc_sps *sps =3D run->sps; + + if (!run->ext_sps_lt_rps) + return; + + for (int i =3D 0; i < sps->num_long_term_ref_pics_sps; i++) { + rps->refs[i].lt_ref_pic_poc_lsb =3D + run->ext_sps_lt_rps[i].lt_ref_pic_poc_lsb_sps; + rps->refs[i].used_by_curr_pic_lt_flag =3D + !!(run->ext_sps_lt_rps[i].flags & V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT= ); + } +} + +static void rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run *run, st= ruct rkvdec_rps *rps, + struct calculated_rps_st_set *calculated_rps_st_sets) +{ + const struct v4l2_ctrl_hevc_sps *sps =3D run->sps; + + for (int i =3D 0; i < sps->num_short_term_ref_pic_sets; i++) { + int poc =3D 0; + int j =3D 0; + const struct calculated_rps_st_set *set =3D &calculated_rps_st_sets[i]; + + rps->short_term_ref_sets[i].num_negative =3D set->num_negative_pics; + rps->short_term_ref_sets[i].num_positive =3D set->num_positive_pics; + + for (; j < set->num_negative_pics; j++) { + set_ref_poc(&rps->short_term_ref_sets[i], j, + set->delta_poc_s0[j], set->used_by_curr_pic_s0[j]); + } + poc =3D j; + + for (j =3D 0; j < set->num_positive_pics; j++) { + set_ref_poc(&rps->short_term_ref_sets[i], poc + j, + set->delta_poc_s1[j], set->used_by_curr_pic_s1[j]); + } + } +} + +/* + * Compute the short term ref pic set parameters based on its reference sh= ort term ref pic + */ +static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx, + struct calculated_rps_st_set *calculated_rps_st_sets) +{ + const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data =3D &run->ext_sps_st= _rps[idx]; + struct calculated_rps_st_set *st_rps =3D &calculated_rps_st_sets[idx]; + struct calculated_rps_st_set *ref_rps; + u8 st_rps_idx =3D idx; + u8 ref_rps_idx =3D 0; + s16 delta_rps =3D 0; + u8 use_delta_flag[16] =3D { 0 }; + u8 used_by_curr_pic_flag[16] =3D { 0 }; + int i, j; + int dPoc; + + ref_rps_idx =3D st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */ + delta_rps =3D (1 - 2 * rps_data->delta_rps_sign) * + (rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */ + + ref_rps =3D &calculated_rps_st_sets[ref_rps_idx]; + + for (j =3D 0; j <=3D ref_rps->num_delta_pocs; j++) { + used_by_curr_pic_flag[j] =3D !!(rps_data->used_by_curr_pic & (1 << j)); + use_delta_flag[j] =3D !!(rps_data->use_delta_flag & (1 << j)); + } + + /* 7-61: calculate num_negative_pics, delta_poc_s0 and used_by_curr_pic_s= 0 */ + i =3D 0; + for (j =3D (ref_rps->num_positive_pics - 1); j >=3D 0; j--) { + dPoc =3D ref_rps->delta_poc_s1[j] + delta_rps; + if (dPoc < 0 && use_delta_flag[ref_rps->num_negative_pics + j]) { + st_rps->delta_poc_s0[i] =3D dPoc; + st_rps->used_by_curr_pic_s0[i++] =3D + used_by_curr_pic_flag[ref_rps->num_negative_pics + j]; + } + } + if (delta_rps < 0 && use_delta_flag[ref_rps->num_delta_pocs]) { + st_rps->delta_poc_s0[i] =3D delta_rps; + st_rps->used_by_curr_pic_s0[i++] =3D used_by_curr_pic_flag[ref_rps->num_= delta_pocs]; + } + for (j =3D 0; j < ref_rps->num_negative_pics; j++) { + dPoc =3D ref_rps->delta_poc_s0[j] + delta_rps; + if (dPoc < 0 && use_delta_flag[j]) { + st_rps->delta_poc_s0[i] =3D dPoc; + st_rps->used_by_curr_pic_s0[i++] =3D used_by_curr_pic_flag[j]; + } + } + st_rps->num_negative_pics =3D i; + + /* 7-62: calculate num_positive_pics, delta_poc_s1 and used_by_curr_pic_s= 1 */ + i =3D 0; + for (j =3D (ref_rps->num_negative_pics - 1); j >=3D 0; j--) { + dPoc =3D ref_rps->delta_poc_s0[j] + delta_rps; + if (dPoc > 0 && use_delta_flag[j]) { + st_rps->delta_poc_s1[i] =3D dPoc; + st_rps->used_by_curr_pic_s1[i++] =3D used_by_curr_pic_flag[j]; + } + } + if (delta_rps > 0 && use_delta_flag[ref_rps->num_delta_pocs]) { + st_rps->delta_poc_s1[i] =3D delta_rps; + st_rps->used_by_curr_pic_s1[i++] =3D used_by_curr_pic_flag[ref_rps->num_= delta_pocs]; + } + for (j =3D 0; j < ref_rps->num_positive_pics; j++) { + dPoc =3D ref_rps->delta_poc_s1[j] + delta_rps; + if (dPoc > 0 && use_delta_flag[ref_rps->num_negative_pics + j]) { + st_rps->delta_poc_s1[i] =3D dPoc; + st_rps->used_by_curr_pic_s1[i++] =3D + used_by_curr_pic_flag[ref_rps->num_negative_pics + j]; + } + } + st_rps->num_positive_pics =3D i; + + st_rps->num_delta_pocs =3D st_rps->num_positive_pics + st_rps->num_negati= ve_pics; +} + +/* + * Compute the short term ref pic set parameters based on the control's da= ta. + */ +static void st_ref_pic_set_calculate(struct rkvdec_hevc_run *run, int idx, + struct calculated_rps_st_set *calculated_rps_st_sets) +{ + const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data =3D &run->ext_sps_st= _rps[idx]; + struct calculated_rps_st_set *st_rps =3D &calculated_rps_st_sets[idx]; + int j, i =3D 0; + + /* 7-63 */ + st_rps->num_negative_pics =3D rps_data->num_negative_pics; + /* 7-64 */ + st_rps->num_positive_pics =3D rps_data->num_positive_pics; + + for (i =3D 0; i < st_rps->num_negative_pics; i++) { + /* 7-65 */ + st_rps->used_by_curr_pic_s0[i] =3D !!(rps_data->used_by_curr_pic & (1 <<= i)); + + if (i =3D=3D 0) { + /* 7-67 */ + st_rps->delta_poc_s0[i] =3D -(rps_data->delta_poc_s0_minus1[i] + 1); + } else { + /* 7-69 */ + st_rps->delta_poc_s0[i] =3D + st_rps->delta_poc_s0[i - 1] - + (rps_data->delta_poc_s0_minus1[i] + 1); + } + } + + for (j =3D 0; j < st_rps->num_positive_pics; j++) { + /* 7-66 */ + st_rps->used_by_curr_pic_s1[j] =3D !!(rps_data->used_by_curr_pic & (1 <<= (i + j))); + + if (j =3D=3D 0) { + /* 7-68 */ + st_rps->delta_poc_s1[j] =3D rps_data->delta_poc_s1_minus1[j] + 1; + } else { + /* 7-70 */ + st_rps->delta_poc_s1[j] =3D + st_rps->delta_poc_s1[j - 1] + + (rps_data->delta_poc_s1_minus1[j] + 1); + } + } + + /* 7-71 */ + st_rps->num_delta_pocs =3D st_rps->num_positive_pics + st_rps->num_negati= ve_pics; +} + +static void rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run *run, str= uct rkvdec_rps *rps, + struct v4l2_ctrl_hevc_ext_sps_st_rps *cache) +{ + int idx; + + if (!run->ext_sps_st_rps) + return; + + if (!memcmp(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_= sps_st_rps))) + return; + + struct calculated_rps_st_set *calculated_rps_st_sets =3D + kzalloc(sizeof(struct calculated_rps_st_set) * + run->sps->num_short_term_ref_pic_sets, GFP_KERNEL); + + for (idx =3D 0; idx < run->sps->num_short_term_ref_pic_sets; idx++) { + const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data =3D &run->ext_sps_s= t_rps[idx]; + + if (rps_data->flags & V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PR= ED) + st_ref_pic_set_prediction(run, idx, calculated_rps_st_sets); + else + st_ref_pic_set_calculate(run, idx, calculated_rps_st_sets); + } + + rkvdec_hevc_assemble_hw_st_rps(run, rps, calculated_rps_st_sets); + + kfree(calculated_rps_st_sets); + + memcpy(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_s= t_rps)); +} + +void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvde= c_rps *rps, + struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache) +{ + rkvdec_hevc_prepare_hw_st_rps(run, rps, st_cache); + rkvdec_hevc_assemble_hw_lt_rps(run, rps); +} + +struct vb2_buffer *get_ref_buf(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run, + unsigned int dpb_idx) { struct v4l2_m2m_ctx *m2m_ctx =3D ctx->fh.m2m_ctx; const struct v4l2_ctrl_hevc_decode_params *decode_params =3D run->decode_= params; @@ -143,8 +485,6 @@ get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_= run *run, return buf; } =20 -#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 - int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f) { struct v4l2_pix_format_mplane *fmt =3D &f->fmt.pix_mp; @@ -156,38 +496,17 @@ int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, st= ruct v4l2_format *f) return 0; } =20 -enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, - struct v4l2_ctrl *ctrl) -{ - const struct v4l2_ctrl_hevc_sps *sps =3D ctrl->p_new.p_hevc_sps; - - if (ctrl->id !=3D V4L2_CID_STATELESS_HEVC_SPS) - return RKVDEC_IMG_FMT_ANY; - - if (sps->bit_depth_luma_minus8 =3D=3D 0) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_8BIT; - else - return RKVDEC_IMG_FMT_420_8BIT; - } else if (sps->bit_depth_luma_minus8 =3D=3D 2) { - if (sps->chroma_format_idc =3D=3D 2) - return RKVDEC_IMG_FMT_422_10BIT; - else - return RKVDEC_IMG_FMT_420_10BIT; - } - - return RKVDEC_IMG_FMT_ANY; -} - -static int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, +int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, const struct v4l2_ctrl_hevc_sps *sps) { if (sps->chroma_format_idc > 1) /* Only 4:0:0 and 4:2:0 are supported */ return -EINVAL; + if (sps->bit_depth_luma_minus8 !=3D sps->bit_depth_chroma_minus8) /* Luma and chroma bit depth mismatch */ return -EINVAL; + if (sps->bit_depth_luma_minus8 !=3D 0 && sps->bit_depth_luma_minus8 !=3D = 2) /* Only 8-bit and 10-bit are supported */ return -EINVAL; @@ -221,6 +540,17 @@ void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); run->scaling_matrix =3D ctrl ? ctrl->p_cur.p : NULL; =20 + if (ctx->has_sps_st_rps) { + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS); + run->ext_sps_st_rps =3D ctrl ? ctrl->p_cur.p : NULL; + } + if (ctx->has_sps_lt_rps) { + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS); + run->ext_sps_lt_rps =3D ctrl ? ctrl->p_cur.p : NULL; + } + rkvdec_run_preamble(ctx, &run->base); } =20 diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h index 746b1bd73c08..0005b80bad79 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -16,19 +16,70 @@ */ =20 #include +#include #include "rkvdec.h" =20 #define RKV_HEVC_CABAC_TABLE_SIZE 27456 extern const u8 rkvdec_hevc_cabac_table[RKV_HEVC_CABAC_TABLE_SIZE]; =20 +struct rkvdec_rps_refs { + u16 lt_ref_pic_poc_lsb; + u16 used_by_curr_pic_lt_flag : 1; + u16 reserved : 15; +} __packed; + +struct rkvdec_rps_short_term_ref_set { + u32 num_negative : 4; + u32 num_positive : 4; + u32 delta_poc0 : 16; + u32 used_flag0 : 1; + u32 delta_poc1 : 16; + u32 used_flag1 : 1; + u32 delta_poc2 : 16; + u32 used_flag2 : 1; + u32 delta_poc3 : 16; + u32 used_flag3 : 1; + u32 delta_poc4 : 16; + u32 used_flag4 : 1; + u32 delta_poc5 : 16; + u32 used_flag5 : 1; + u32 delta_poc6 : 16; + u32 used_flag6 : 1; + u32 delta_poc7 : 16; + u32 used_flag7 : 1; + u32 delta_poc8 : 16; + u32 used_flag8 : 1; + u32 delta_poc9 : 16; + u32 used_flag9 : 1; + u32 delta_poc10 : 16; + u32 used_flag10 : 1; + u32 delta_poc11 : 16; + u32 used_flag11 : 1; + u32 delta_poc12 : 16; + u32 used_flag12 : 1; + u32 delta_poc13 : 16; + u32 used_flag13 : 1; + u32 delta_poc14 : 16; + u32 used_flag14 : 1; + u32 reserved_bits : 25; + u32 reserved[3]; +} __packed; + +struct rkvdec_rps { + struct rkvdec_rps_refs refs[32]; + struct rkvdec_rps_short_term_ref_set short_term_ref_sets[64]; +} __packed; + struct rkvdec_hevc_run { - struct rkvdec_run base; - const struct v4l2_ctrl_hevc_slice_params *slices_params; - const struct v4l2_ctrl_hevc_decode_params *decode_params; - const struct v4l2_ctrl_hevc_sps *sps; - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; - int num_slices; + struct rkvdec_run base; + const struct v4l2_ctrl_hevc_decode_params *decode_params; + const struct v4l2_ctrl_hevc_slice_params *slices_params; + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; + const struct v4l2_ctrl_hevc_ext_sps_st_rps *ext_sps_st_rps; + const struct v4l2_ctrl_hevc_ext_sps_lt_rps *ext_sps_lt_rps; + int num_slices; }; =20 struct scaling_factor { @@ -40,6 +91,14 @@ struct scaling_factor { =20 enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); +void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_si= ze, + u16 width, u16 height, s32 pic_in_cts_width, + s32 pic_in_cts_height, u16 *column_width, u16 *row_height); +void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_c= b_size, + u16 width, u16 height, s32 pic_in_cts_width, + s32 pic_in_cts_height, u16 *column_width, u16 *row_height); +void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvde= c_rps *rps, + struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache); void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, struct scaling_factor *scaling_factor, struct v4l2_ctrl_hevc_scaling_matrix *cache); @@ -47,5 +106,6 @@ struct vb2_buffer *get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, unsigned int dpb_idx); int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f); +int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, const struct v4l2_ctr= l_hevc_sps *sps); int rkvdec_hevc_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_hevc_r= un *run); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c new file mode 100644 index 000000000000..278f1dbf0910 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -0,0 +1,596 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip VDPU381 HEVC backend + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include + +#include "rkvdec.h" +#include "rkvdec-rcb.h" +#include "rkvdec-hevc-common.h" +#include "rkvdec-vdpu381-regs.h" + +// SPS +struct rkvdec_hevc_sps { + u16 video_parameters_set_id : 4; + u16 seq_parameters_set_id_sps : 4; + u16 chroma_format_idc : 2; + u16 width : 16; + u16 height : 16; + u16 bit_depth_luma : 4; + u16 bit_depth_chroma : 4; + u16 max_pic_order_count_lsb : 5; + u16 diff_max_min_luma_coding_block_size : 2; + u16 min_luma_coding_block_size : 3; + u16 min_transform_block_size : 3; + u16 diff_max_min_transform_block_size : 2; + u16 max_transform_hierarchy_depth_inter : 3; + u16 max_transform_hierarchy_depth_intra : 3; + u16 scaling_list_enabled_flag : 1; + u16 amp_enabled_flag : 1; + u16 sample_adaptive_offset_enabled_flag : 1; + u16 pcm_enabled_flag : 1; + u16 pcm_sample_bit_depth_luma : 4; + u16 pcm_sample_bit_depth_chroma : 4; + u16 pcm_loop_filter_disabled_flag : 1; + u16 diff_max_min_pcm_luma_coding_block_size : 3; + u16 min_pcm_luma_coding_block_size : 3; + u16 num_short_term_ref_pic_sets : 7; + u16 long_term_ref_pics_present_flag : 1; + u16 num_long_term_ref_pics_sps : 6; + u16 sps_temporal_mvp_enabled_flag : 1; + u16 strong_intra_smoothing_enabled_flag : 1; + u16 reserved_0 : 7; + u16 sps_max_dec_pic_buffering_minus1 : 4; + u16 reserved_0_2 : 3; + u16 reserved_f : 8; +} __packed; + +//PPS +struct rkvdec_hevc_pps { + u16 picture_parameters_set_id : 6; + u16 seq_parameters_set_id_pps : 4; + u16 dependent_slice_segments_enabled_flag : 1; + u16 output_flag_present_flag : 1; + u16 num_extra_slice_header_bits : 13; + u16 sign_data_hiding_enabled_flag : 1; + u16 cabac_init_present_flag : 1; + u16 num_ref_idx_l0_default_active : 4; + u16 num_ref_idx_l1_default_active : 4; + u16 init_qp_minus26 : 7; + u16 constrained_intra_pred_flag : 1; + u16 transform_skip_enabled_flag : 1; + u16 cu_qp_delta_enabled_flag : 1; + u16 log2_min_cb_size : 3; + u16 pps_cb_qp_offset : 5; + u16 pps_cr_qp_offset : 5; + u16 pps_slice_chroma_qp_offsets_present_flag : 1; + u16 weighted_pred_flag : 1; + u16 weighted_bipred_flag : 1; + u16 transquant_bypass_enabled_flag : 1; + u16 tiles_enabled_flag : 1; + u16 entropy_coding_sync_enabled_flag : 1; + u16 pps_loop_filter_across_slices_enabled_flag : 1; + u16 loop_filter_across_tiles_enabled_flag : 1; + u16 deblocking_filter_override_enabled_flag : 1; + u16 pps_deblocking_filter_disabled_flag : 1; + u16 pps_beta_offset_div2 : 4; + u16 pps_tc_offset_div2 : 4; + u16 lists_modification_present_flag : 1; + u16 log2_parallel_merge_level : 3; + u16 slice_segment_header_extension_present_flag : 1; + u16 zeroes : 3; + u16 num_tile_columns : 5; + u16 num_tile_rows : 5; + u16 sps_pps_mode : 4; + u16 reserved_bits : 14; + u16 reserved; +} __packed; + +struct rkvdec_hevc_tile { + u16 value0 : 12; + u16 value1 : 12; +} __packed; + +struct rkvdec_sps_pps_packet { + struct rkvdec_hevc_sps sps; + struct rkvdec_hevc_pps pps; + struct rkvdec_hevc_tile column_width[10]; + struct rkvdec_hevc_tile row_height[11]; + u32 zeroes[3]; + u32 zeroes_bits : 6; + u32 padding_bits : 2; + u32 padding; +} __packed; + +struct rkvdec_hevc_priv_tbl { + struct rkvdec_sps_pps_packet param_set[64]; + struct rkvdec_rps rps; + struct scaling_factor scaling_list; + u8 cabac_table[27456]; +}; + +struct rkvdec_hevc_ctx { + struct rkvdec_aux_buf priv_tbl; + struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; + struct v4l2_ctrl_hevc_ext_sps_st_rps st_cache; + struct rkvdec_vdpu381_regs_hevc regs; +}; + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + struct rkvdec_hevc_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_hevc_sps *sps =3D run->sps; + const struct v4l2_ctrl_hevc_pps *pps =3D run->pps; + struct rkvdec_hevc_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_sps_pps_packet *hw_ps; + bool tiles_enabled; + s32 max_cu_width; + s32 pic_in_cts_width; + s32 pic_in_cts_height; + u16 log2_min_cb_size, width, height; + u16 column_width[20]; + u16 row_height[22]; + u8 pcm_enabled; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set[pps->pic_parameter_set_id]; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->sps.video_parameters_set_id =3D sps->video_parameter_set_id; + hw_ps->sps.seq_parameters_set_id_sps =3D sps->seq_parameter_set_id; + hw_ps->sps.chroma_format_idc =3D sps->chroma_format_idc; + + log2_min_cb_size =3D sps->log2_min_luma_coding_block_size_minus3 + 3; + width =3D sps->pic_width_in_luma_samples; + height =3D sps->pic_height_in_luma_samples; + hw_ps->sps.width =3D width; + hw_ps->sps.height =3D height; + hw_ps->sps.bit_depth_luma =3D sps->bit_depth_luma_minus8 + 8; + hw_ps->sps.bit_depth_chroma =3D sps->bit_depth_chroma_minus8 + 8; + hw_ps->sps.max_pic_order_count_lsb =3D sps->log2_max_pic_order_cnt_lsb_mi= nus4 + 4; + hw_ps->sps.diff_max_min_luma_coding_block_size =3D + sps->log2_diff_max_min_luma_coding_block_size; + hw_ps->sps.min_luma_coding_block_size =3D sps->log2_min_luma_coding_block= _size_minus3 + 3; + hw_ps->sps.min_transform_block_size =3D sps->log2_min_luma_transform_bloc= k_size_minus2 + 2; + hw_ps->sps.diff_max_min_transform_block_size =3D + sps->log2_diff_max_min_luma_transform_block_size; + hw_ps->sps.max_transform_hierarchy_depth_inter =3D sps->max_transform_hie= rarchy_depth_inter; + hw_ps->sps.max_transform_hierarchy_depth_intra =3D sps->max_transform_hie= rarchy_depth_intra; + hw_ps->sps.scaling_list_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED); + hw_ps->sps.amp_enabled_flag =3D !!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_EN= ABLED); + hw_ps->sps.sample_adaptive_offset_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET); + + pcm_enabled =3D !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED); + hw_ps->sps.pcm_enabled_flag =3D pcm_enabled; + hw_ps->sps.pcm_sample_bit_depth_luma =3D + pcm_enabled ? sps->pcm_sample_bit_depth_luma_minus1 + 1 : 0; + hw_ps->sps.pcm_sample_bit_depth_chroma =3D + pcm_enabled ? sps->pcm_sample_bit_depth_chroma_minus1 + 1 : 0; + hw_ps->sps.pcm_loop_filter_disabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED); + hw_ps->sps.diff_max_min_pcm_luma_coding_block_size =3D + sps->log2_diff_max_min_pcm_luma_coding_block_size; + hw_ps->sps.min_pcm_luma_coding_block_size =3D + pcm_enabled ? sps->log2_min_pcm_luma_coding_block_size_minus3 + 3 : 0; + hw_ps->sps.num_short_term_ref_pic_sets =3D sps->num_short_term_ref_pic_se= ts; + hw_ps->sps.long_term_ref_pics_present_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT); + hw_ps->sps.num_long_term_ref_pics_sps =3D sps->num_long_term_ref_pics_sps; + hw_ps->sps.sps_temporal_mvp_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED); + hw_ps->sps.strong_intra_smoothing_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED); + hw_ps->sps.sps_max_dec_pic_buffering_minus1 =3D sps->sps_max_dec_pic_buff= ering_minus1; + hw_ps->sps.reserved_f =3D 0xff; + + /* write pps */ + hw_ps->pps.picture_parameters_set_id =3D pps->pic_parameter_set_id; + hw_ps->pps.seq_parameters_set_id_pps =3D sps->seq_parameter_set_id; + hw_ps->pps.dependent_slice_segments_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED); + hw_ps->pps.output_flag_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT); + hw_ps->pps.num_extra_slice_header_bits =3D pps->num_extra_slice_header_bi= ts; + hw_ps->pps.sign_data_hiding_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED); + hw_ps->pps.cabac_init_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT); + hw_ps->pps.num_ref_idx_l0_default_active =3D pps->num_ref_idx_l0_default_= active_minus1 + 1; + hw_ps->pps.num_ref_idx_l1_default_active =3D pps->num_ref_idx_l1_default_= active_minus1 + 1; + hw_ps->pps.init_qp_minus26 =3D pps->init_qp_minus26; + hw_ps->pps.constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->pps.transform_skip_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED); + hw_ps->pps.cu_qp_delta_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED); + hw_ps->pps.log2_min_cb_size =3D log2_min_cb_size + + sps->log2_diff_max_min_luma_coding_block_size - + pps->diff_cu_qp_delta_depth; + hw_ps->pps.pps_cb_qp_offset =3D pps->pps_cb_qp_offset; + hw_ps->pps.pps_cr_qp_offset =3D pps->pps_cr_qp_offset; + hw_ps->pps.pps_slice_chroma_qp_offsets_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT); + hw_ps->pps.weighted_pred_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIG= HTED_PRED); + hw_ps->pps.weighted_bipred_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_WE= IGHTED_BIPRED); + hw_ps->pps.transquant_bypass_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED); + + tiles_enabled =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED); + hw_ps->pps.tiles_enabled_flag =3D tiles_enabled; + hw_ps->pps.entropy_coding_sync_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED); + hw_ps->pps.pps_loop_filter_across_slices_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED= ); + hw_ps->pps.loop_filter_across_tiles_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED); + hw_ps->pps.deblocking_filter_override_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED); + hw_ps->pps.pps_deblocking_filter_disabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER); + hw_ps->pps.pps_beta_offset_div2 =3D pps->pps_beta_offset_div2; + hw_ps->pps.pps_tc_offset_div2 =3D pps->pps_tc_offset_div2; + hw_ps->pps.lists_modification_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT); + hw_ps->pps.log2_parallel_merge_level =3D pps->log2_parallel_merge_level_m= inus2 + 2; + hw_ps->pps.slice_segment_header_extension_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESEN= T); + hw_ps->pps.num_tile_columns =3D tiles_enabled ? pps->num_tile_columns_min= us1 + 1 : 0; + hw_ps->pps.num_tile_rows =3D tiles_enabled ? pps->num_tile_rows_minus1 + = 1 : 0; + hw_ps->pps.sps_pps_mode =3D 0; + hw_ps->pps.reserved_bits =3D 0x3fff; + hw_ps->pps.reserved =3D 0xffff; + + // Setup tiles information + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + max_cu_width =3D 1 << (sps->log2_diff_max_min_luma_coding_block_size + lo= g2_min_cb_size); + pic_in_cts_width =3D (width + max_cu_width - 1) / max_cu_width; + pic_in_cts_height =3D (height + max_cu_width - 1) / max_cu_width; + + if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) { + if (pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING) { + compute_tiles_uniform(run, log2_min_cb_size, width, height, + pic_in_cts_width, pic_in_cts_height, + column_width, row_height); + } else { + compute_tiles_non_uniform(run, log2_min_cb_size, width, height, + pic_in_cts_width, pic_in_cts_height, + column_width, row_height); + } + } else { + column_width[0] =3D (width + max_cu_width - 1) / max_cu_width; + row_height[0] =3D (height + max_cu_width - 1) / max_cu_width; + } + + for (i =3D 0; i < 20; i++) { + if (column_width[i] > 0) + column_width[i]--; + + if (i & 1) + hw_ps->column_width[i / 2].value1 =3D column_width[i]; + else + hw_ps->column_width[i / 2].value0 =3D column_width[i]; + } + + for (i =3D 0; i < 22; i++) { + if (row_height[i] > 0) + row_height[i]--; + + if (i & 1) + hw_ps->row_height[i / 2].value1 =3D row_height[i]; + else + hw_ps->row_height[i / 2].value0 =3D row_height[i]; + } + + hw_ps->padding =3D 0xffffffff; + hw_ps->padding_bits =3D 0x3; +} + +static void set_ref_valid(struct rkvdec_vdpu381_regs_hevc *regs, int id, u= 32 valid) +{ + switch (id) { + case 0: + regs->hevc_param.reg099.hevc_ref_valid_0 =3D valid; + break; + case 1: + regs->hevc_param.reg099.hevc_ref_valid_1 =3D valid; + break; + case 2: + regs->hevc_param.reg099.hevc_ref_valid_2 =3D valid; + break; + case 3: + regs->hevc_param.reg099.hevc_ref_valid_3 =3D valid; + break; + case 4: + regs->hevc_param.reg099.hevc_ref_valid_4 =3D valid; + break; + case 5: + regs->hevc_param.reg099.hevc_ref_valid_5 =3D valid; + break; + case 6: + regs->hevc_param.reg099.hevc_ref_valid_6 =3D valid; + break; + case 7: + regs->hevc_param.reg099.hevc_ref_valid_7 =3D valid; + break; + case 8: + regs->hevc_param.reg099.hevc_ref_valid_8 =3D valid; + break; + case 9: + regs->hevc_param.reg099.hevc_ref_valid_9 =3D valid; + break; + case 10: + regs->hevc_param.reg099.hevc_ref_valid_10 =3D valid; + break; + case 11: + regs->hevc_param.reg099.hevc_ref_valid_11 =3D valid; + break; + case 12: + regs->hevc_param.reg099.hevc_ref_valid_12 =3D valid; + break; + case 13: + regs->hevc_param.reg099.hevc_ref_valid_13 =3D valid; + break; + case 14: + regs->hevc_param.reg099.hevc_ref_valid_14 =3D valid; + break; + } +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS, + &hevc_ctx->regs.common, + sizeof(hevc_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS, + &hevc_ctx->regs.hevc_param, + sizeof(hevc_ctx->regs.hevc_param)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS, + &hevc_ctx->regs.common_addr, + sizeof(hevc_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS, + &hevc_ctx->regs.hevc_addr, + sizeof(hevc_ctx->regs.hevc_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_POC_HIGHBIT_REGS, + &hevc_ctx->regs.hevc_highpoc, + sizeof(hevc_ctx->regs.hevc_highpoc)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + const struct v4l2_ctrl_hevc_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_hevc_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_vdpu381_regs_hevc *regs =3D &hevc_ctx->regs; + dma_addr_t priv_start_addr =3D hevc_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + u32 hor_virstride =3D 0; + u32 ver_virstride =3D 0; + u32 y_virstride =3D 0; + u32 offset; + u32 pixels; + dma_addr_t dst_addr; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set HEVC mode */ + regs->common.reg009.dec_mode =3D VDPU381_MODE_HEVC; + + /* Set config */ + regs->common.reg011.buf_empty_en =3D 1; + regs->common.reg011.dec_clkgate_e =3D 1; + regs->common.reg011.dec_timeout_e =3D 1; + regs->common.reg011.pix_range_detection_e =3D 1; + + /* Set IDR flag */ + regs->common.reg013.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.stream_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); + + /* Set max slice number */ + regs->common.reg017.slice_num =3D 1; + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->common.reg018.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026.swreg_block_gating_e =3D 0xfffef; + regs->common.reg026.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_8K; + + /* Set POC val */ + regs->hevc_param.cur_top_poc =3D dec_params->pic_order_cnt_val; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf =3D get_ref_buf(ctx, run, i); + dma_addr_t buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + u32 valid =3D !!(dec_params->num_active_dpb_entries > i); + + /* Set reference addresses */ + regs->hevc_addr.ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->hevc_addr.colmv_base[i] =3D buf_dma + ctx->colmv_offset; + + regs->hevc_param.reg067_082_ref_poc[i] =3D + dpb[i].pic_order_cnt_val; + + set_ref_valid(regs, i, valid); + regs->hevc_param.reg103.ref_pic_layer_same_with_cur |=3D 1 << i; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.rlc_base =3D rlc_addr; + regs->common_addr.rlcwrite_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->common_addr.decout_base =3D dst_addr; + regs->common_addr.error_ref_base =3D dst_addr; + + /* Set colmv address */ + regs->common_addr.colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) + regs->common_addr.rcb_base[i] =3D rkvdec_rcb_buf_dma_addr(ctx, i); + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, param_set); + regs->hevc_addr.pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, rps); + regs->hevc_addr.rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); + regs->hevc_addr.cabactbl_base =3D priv_start_addr + offset; + + /* Set scaling matrix */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); + regs->hevc_addr.scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_priv_tbl *priv_tbl; + struct rkvdec_hevc_ctx *hevc_ctx; + struct v4l2_ctrl *ctrl; + int ret; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_SPS); + if (!ctrl) + return -EINVAL; + + ret =3D rkvdec_hevc_validate_sps(ctx, ctrl->p_new.p_hevc_sps); + if (ret) + return ret; + + hevc_ctx =3D kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); + if (!hevc_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &hevc_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + hevc_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + hevc_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, + sizeof(rkvdec_hevc_cabac_table)); + + ctx->priv =3D hevc_ctx; + return 0; + +err_free_ctx: + kfree(hevc_ctx); + return ret; +} + +static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, hevc_ctx->priv_tbl.size, + hevc_ctx->priv_tbl.cpu, hevc_ctx->priv_tbl.dma); + kfree(hevc_ctx); +} + +static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_run run; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_hevc_priv_tbl *tbl =3D hevc_ctx->priv_tbl.cpu; + + rkvdec_hevc_run_preamble(ctx, &run); + + /* + * On vdpu381, not setting the long and short term ref sets will just out= put wrong frames. + * Let's just warn about it and let the decoder run anyway. + */ + if ((!ctx->has_sps_lt_rps && run.sps->num_long_term_ref_pics_sps) || + (!ctx->has_sps_st_rps && run.sps->num_short_term_ref_pic_sets)) { + dev_warn_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); + } + + rkvdec_hevc_assemble_hw_scaling_list(&run, + &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); + assemble_hw_pps(ctx, &run); + rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); + + /* Start decoding! */ + writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_hevc_fmt_ops =3D { + .adjust_fmt =3D rkvdec_hevc_adjust_fmt, + .start =3D rkvdec_hevc_start, + .stop =3D rkvdec_hevc_stop, + .run =3D rkvdec_hevc_run, + .try_ctrl =3D rkvdec_hevc_try_ctrl, + .get_image_fmt =3D rkvdec_hevc_get_image_fmt, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 1837f12f1aa1..b72cb07de70e 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -154,6 +154,16 @@ static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) enum rkvdec_image_fmt image_fmt; struct vb2_queue *vq; =20 + if (ctrl->id =3D=3D V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS) { + ctx->has_sps_st_rps |=3D !!(ctrl->has_changed); + return 0; + } + + if (ctrl->id =3D=3D V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS) { + ctx->has_sps_lt_rps |=3D !!(ctrl->has_changed); + return 0; + } + /* Check if this change requires a capture format reset */ if (!desc->ops->get_image_fmt) return 0; @@ -285,6 +295,62 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls =3D= { .num_ctrls =3D ARRAY_SIZE(rkvdec_h264_ctrl_descs), }; =20 +static const struct rkvdec_ctrl_desc vdpu38x_hevc_ctrl_descs[] =3D { + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_SPS, + .cfg.ops =3D &rkvdec_ctrl_ops, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_PPS, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .cfg.min =3D V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .cfg.max =3D V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .cfg.def =3D V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_START_CODE, + .cfg.min =3D V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .cfg.def =3D V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .cfg.max =3D V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + }, + { + .cfg.id =3D V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, + .cfg.min =3D V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .cfg.max =3D V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .cfg.menu_skip_mask =3D + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .cfg.def =3D V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + }, + { + .cfg.id =3D V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, + .cfg.min =3D V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .cfg.max =3D V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS, + .cfg.ops =3D &rkvdec_ctrl_ops, + .cfg.dims =3D { 65 }, + }, + { + .cfg.id =3D V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS, + .cfg.ops =3D &rkvdec_ctrl_ops, + .cfg.dims =3D { 65 }, + }, +}; + +static const struct rkvdec_ctrls vdpu38x_hevc_ctrls =3D { + .ctrls =3D vdpu38x_hevc_ctrl_descs, + .num_ctrls =3D ARRAY_SIZE(vdpu38x_hevc_ctrl_descs), +}; + static const struct rkvdec_decoded_fmt_desc rkvdec_h264_decoded_fmts[] =3D= { { .fourcc =3D V4L2_PIX_FMT_NV12, @@ -401,6 +467,23 @@ static const struct rkvdec_coded_fmt_desc vdpu381_code= d_fmts[] =3D { .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, .capability =3D RKVDEC_CAPABILITY_H264, }, + { + .fourcc =3D V4L2_PIX_FMT_HEVC_SLICE, + .frmsize =3D { + .min_width =3D 64, + .max_width =3D 65472, + .step_width =3D 64, + .min_height =3D 64, + .max_height =3D 65472, + .step_height =3D 16, + }, + .ctrls =3D &vdpu38x_hevc_ctrls, + .ops =3D &rkvdec_vdpu381_hevc_fmt_ops, + .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_hevc_decoded_fmts), + .decoded_fmts =3D rkvdec_hevc_decoded_fmts, + .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, + .capability =3D RKVDEC_CAPABILITY_HEVC, + }, }; =20 static const struct rkvdec_coded_fmt_desc vdpu383_coded_fmts[] =3D { @@ -1500,7 +1583,8 @@ static const struct rkvdec_variant rk3399_rkvdec_vari= ant =3D { =20 static const struct rkvdec_variant rk3588_vdpu381_variant =3D { .config =3D &config_vdpu381, - .capabilities =3D RKVDEC_CAPABILITY_H264, + .capabilities =3D RKVDEC_CAPABILITY_H264 | + RKVDEC_CAPABILITY_HEVC, }; =20 static const struct rkvdec_variant rk3576_vdpu383_variant =3D { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index e752706e9f5c..94e2e6429992 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -156,6 +156,8 @@ struct rkvdec_ctx { struct rkvdec_rcb_config *rcb_config; u32 colmv_offset; void *priv; + u8 has_sps_st_rps: 1; + u8 has_sps_lt_rps: 1; }; =20 static inline struct rkvdec_ctx *file_to_rkvdec_ctx(struct file *filp) @@ -188,6 +190,7 @@ extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt= _ops; =20 /* VDPU381 ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops; +extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_hevc_fmt_ops; =20 /* VDPU383 ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops; --=20 2.51.1.dirty From nobody Sat Feb 7 05:01:17 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 543FB357735; Wed, 22 Oct 2025 16:26:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150376; cv=none; b=PYJw0xzCGiL19ko2ga/1ILf73ed71ErcYrpujGau+aQUkg/3JE9+K7ksvsDFWWbLf1cqRMB3MygVNmf2A/HgFJKEL7dFTzJP5LAAyvLs0I+DfB3J8jVlW/K3+FY3FONQzPm+nN/TJORoPMQiGaJEYojc7hCAN1jA1wCTqHr4n2w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761150376; c=relaxed/simple; bh=WXGIZPAvZ99cpQQw92aHBlTwVwXL4wjYSBT42EOVBPQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=STIJD6X3dQytLd6dZtEbqmMtdiLV4lJ09Z/uGOeFyz1qGYZotjUVQUb1HCK/62pP6lrxR6xd3xLhjj9DE85Xk0c/C9/sTnhmgUGodA6dlK3xBbb0MqRSkBNTRrebB+U8gEEM+x5LUuID7X7QyOiVvmrEnWoDwlTfxDf4o2cUafI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=morugFfF; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="morugFfF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1761150371; bh=WXGIZPAvZ99cpQQw92aHBlTwVwXL4wjYSBT42EOVBPQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=morugFfFZxC4A80EDrfPoLVsLz5rCB1Wrv0ELs8I99DK31BqHxH+eCwxE4ZZVwM67 yJJPsDXj8qJI4qDf8JZgq2TjS8hbk5zfagZ/6da/strsEW2ZHNCT24NmZdrkCkS4nP FalUhuWQv4sMaqwtOT6BdzqekywM3dROmGr1wp9S0hg5THcGOhCC4Iqt5z3S1vKcmB NYPElV4Nk0AMoM0nvd+5VXah6Ngu8I46VvuE3NsI6zTTFqnLJr+WM9swpA+L+wO/Tp wJx0W63mjU4s8NIPLKVp5JFqBPSdqTw0bkiKVcRSxeTxpIHg7UDsBd5Hv43X9zrN2T x4ZEAaWTi3k1w== Received: from trenzalore (unknown [23.233.251.139]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: detlev) by bali.collaboradmins.com (Postfix) with ESMTPSA id 4D11617E108C; Wed, 22 Oct 2025 18:26:09 +0200 (CEST) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Ricardo Ribalda , Hans Verkuil , Hans de Goede , Yunke Cao , Jonathan Corbet , Laurent Pinchart , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Nicolas Dufresne Subject: [PATCH v3 15/15] media: rkvdec: Add HEVC support for the VDPU383 variant Date: Wed, 22 Oct 2025 12:22:14 -0400 Message-ID: <20251022162459.271603-16-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.51.1.dirty In-Reply-To: <20251022162459.271603-1-detlev.casanova@collabora.com> References: <20251022162459.271603-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The VDPU383 decoder is used on the RK3576 SoC and has support for HEVC. This patch also moves some functions to a common rkvdec-hevc-common.c file and adds a specific scaling matrix flatten function. The fluster score for JCT-VC-HEVC_V1 is 146/147. Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 60 +- .../rockchip/rkvdec/rkvdec-hevc-common.h | 3 +- .../platform/rockchip/rkvdec/rkvdec-hevc.c | 2 +- .../rockchip/rkvdec/rkvdec-vdpu381-hevc.c | 3 +- .../rockchip/rkvdec/rkvdec-vdpu383-hevc.c | 690 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 94 ++- .../media/platform/rockchip/rkvdec/rkvdec.h | 2 + 8 files changed, 804 insertions(+), 51 deletions(-) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h= evc.c diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/medi= a/platform/rockchip/rkvdec/Makefile index e30fdd7d51c3..e629d571e4d8 100644 --- a/drivers/media/platform/rockchip/rkvdec/Makefile +++ b/drivers/media/platform/rockchip/rkvdec/Makefile @@ -11,4 +11,5 @@ rockchip-vdec-y +=3D \ rkvdec-vdpu381-h264.o \ rkvdec-vdpu381-hevc.o \ rkvdec-vdpu383-h264.o \ + rkvdec-vdpu383-hevc.o \ rkvdec-vp9.o diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c index 4b21b3ea67fd..8f1dc2d1e463 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -158,58 +158,25 @@ static void set_ref_poc(struct rkvdec_rps_short_term_= ref_set *set, int poc, int } } =20 -/* - * Flip one or more matrices along their main diagonal and flatten them - * before writing it to the memory. - * Convert: - * ABCD AEIM - * EFGH =3D> BFJN =3D> AEIMBFJNCGKODHLP - * IJKL CGKO - * MNOP DHLP - */ -static void transpose_and_flatten_matrices(u8 *output, const u8 *input, - int matrices, int row_length) -{ - int i, j, row, x_offset, matrix_offset, rot_index, y_offset, matrix_size,= new_value; - - matrix_size =3D row_length * row_length; - for (i =3D 0; i < matrices; i++) { - row =3D 0; - x_offset =3D 0; - matrix_offset =3D i * matrix_size; - for (j =3D 0; j < matrix_size; j++) { - y_offset =3D j - (row * row_length); - rot_index =3D y_offset * row_length + x_offset; - new_value =3D *(input + i * matrix_size + j); - output[matrix_offset + rot_index] =3D new_value; - if ((j + 1) % row_length =3D=3D 0) { - row +=3D 1; - x_offset +=3D 1; - } - } - } -} - -static void assemble_scalingfactor0(u8 *output, const struct v4l2_ctrl_hev= c_scaling_matrix *input) +static void assemble_scalingfactor0(struct rkvdec_ctx *ctx, u8 *output, + const struct v4l2_ctrl_hevc_scaling_matrix *input) { + const struct rkvdec_config *cfg =3D ctx->dev->variant->config; int offset =3D 0; =20 - transpose_and_flatten_matrices(output, (const u8 *)input->scaling_list_4x= 4, 6, 4); + cfg->flatten_matrices(output, (const u8 *)input->scaling_list_4x4, 6, 4); offset =3D 6 * 16 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, (const u8 *)input->scalin= g_list_8x8, 6, 8); + cfg->flatten_matrices(output + offset, (const u8 *)input->scaling_list_8x= 8, 6, 8); offset +=3D 6 * 64 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_16x16, 6, 8); + cfg->flatten_matrices(output + offset, (const u8 *)input->scaling_list_16= x16, 6, 8); offset +=3D 6 * 64 * sizeof(u8); /* Add a 128 byte padding with 0s between the two 32x32 matrices */ - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_32x32, 1, 8); + cfg->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32= x32, 1, 8); offset +=3D 64 * sizeof(u8); memset(output + offset, 0, 128); offset +=3D 128 * sizeof(u8); - transpose_and_flatten_matrices(output + offset, - (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), - 1, 8); + cfg->flatten_matrices(output + offset, + (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), 1, 8); offset +=3D 64 * sizeof(u8); memset(output + offset, 0, 128); } @@ -232,16 +199,17 @@ static void assemble_scalingdc(u8 *output, const stru= ct v4l2_ctrl_hevc_scaling_m memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8)); } =20 -static void translate_scaling_list(struct scaling_factor *output, +static void translate_scaling_list(struct rkvdec_ctx *ctx, struct scaling_= factor *output, const struct v4l2_ctrl_hevc_scaling_matrix *input) { - assemble_scalingfactor0(output->scalingfactor0, input); + assemble_scalingfactor0(ctx, output->scalingfactor0, input); memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96); assemble_scalingdc(output->scalingdc, input); memset(output->reserved, 0, 4 * sizeof(u8)); } =20 -void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, +void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run, struct scaling_factor *scaling_list, struct v4l2_ctrl_hevc_scaling_matrix *cache) { @@ -251,7 +219,7 @@ void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec= _hevc_run *run, sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) return; =20 - translate_scaling_list(scaling_list, scaling); + translate_scaling_list(ctx, scaling_list, scaling); =20 memcpy(cache, scaling, sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h index 0005b80bad79..c4947d2b983d 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -99,7 +99,8 @@ void compute_tiles_non_uniform(struct rkvdec_hevc_run *ru= n, u16 log2_min_cb_size s32 pic_in_cts_height, u16 *column_width, u16 *row_height); void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvde= c_rps *rps, struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache); -void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run, +void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run, struct scaling_factor *scaling_factor, struct v4l2_ctrl_hevc_scaling_matrix *cache); struct vb2_buffer *get_ref_buf(struct rkvdec_ctx *ctx, diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-hevc.c index 31a979698578..eb18f7c2bb0c 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -546,7 +546,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) =20 rkvdec_hevc_run_preamble(ctx, &run); =20 - rkvdec_hevc_assemble_hw_scaling_list(&run, &tbl->scaling_list, + rkvdec_hevc_assemble_hw_scaling_list(ctx, &run, &tbl->scaling_list, &hevc_ctx->scaling_matrix_cache); assemble_hw_pps(ctx, &run); assemble_sw_rps(ctx, &run); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c index 278f1dbf0910..0798d68f1af2 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -568,8 +568,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) dev_warn_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); } =20 - rkvdec_hevc_assemble_hw_scaling_list(&run, - &tbl->scaling_list, + rkvdec_hevc_assemble_hw_scaling_list(ctx, &run, &tbl->scaling_list, &hevc_ctx->scaling_matrix_cache); assemble_hw_pps(ctx, &run); rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c new file mode 100644 index 000000000000..ef29f0ee6c31 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip VDPU383 HEVC backend + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + */ + +#include + +#include "rkvdec.h" +#include "rkvdec-rcb.h" +#include "rkvdec-hevc-common.h" +#include "rkvdec-vdpu383-regs.h" + +struct rkvdec_hevc_sps_pps { + // SPS + u16 video_parameters_set_id : 4; + u16 seq_parameters_set_id_sps : 4; + u16 chroma_format_idc : 2; + u16 width : 16; + u16 height : 16; + u16 bit_depth_luma : 3; + u16 bit_depth_chroma : 3; + u16 max_pic_order_count_lsb : 5; + u16 diff_max_min_luma_coding_block_size : 2; + u16 min_luma_coding_block_size : 3; + u16 min_transform_block_size : 3; + u16 diff_max_min_transform_block_size : 2; + u16 max_transform_hierarchy_depth_inter : 3; + u16 max_transform_hierarchy_depth_intra : 3; + u16 scaling_list_enabled_flag : 1; + u16 amp_enabled_flag : 1; + u16 sample_adaptive_offset_enabled_flag : 1; + u16 pcm_enabled_flag : 1; + u16 pcm_sample_bit_depth_luma : 4; + u16 pcm_sample_bit_depth_chroma : 4; + u16 pcm_loop_filter_disabled_flag : 1; + u16 diff_max_min_pcm_luma_coding_block_size : 3; + u16 min_pcm_luma_coding_block_size : 3; + u16 num_short_term_ref_pic_sets : 7; + u16 long_term_ref_pics_present_flag : 1; + u16 num_long_term_ref_pics_sps : 6; + u16 sps_temporal_mvp_enabled_flag : 1; + u16 strong_intra_smoothing_enabled_flag : 1; + u16 reserved0 : 7; + u16 sps_max_dec_pic_buffering_minus1 : 4; + u16 separate_colour_plane_flag : 1; + u16 high_precision_offsets_enabled_flag : 1; + u16 persistent_rice_adaptation_enabled_flag : 1; + + // PPS + u16 picture_parameters_set_id : 6; + u16 seq_parameters_set_id_pps : 4; + u16 dependent_slice_segments_enabled_flag : 1; + u16 output_flag_present_flag : 1; + u16 num_extra_slice_header_bits : 13; + u16 sign_data_hiding_enabled_flag : 1; + u16 cabac_init_present_flag : 1; + u16 num_ref_idx_l0_default_active : 4; + u16 num_ref_idx_l1_default_active : 4; + u16 init_qp_minus26 : 7; + u16 constrained_intra_pred_flag : 1; + u16 transform_skip_enabled_flag : 1; + u16 cu_qp_delta_enabled_flag : 1; + u16 log2_min_cb_size : 3; + u16 pps_cb_qp_offset : 5; + u16 pps_cr_qp_offset : 5; + u16 pps_slice_chroma_qp_offsets_present_flag : 1; + u16 weighted_pred_flag : 1; + u16 weighted_bipred_flag : 1; + u16 transquant_bypass_enabled_flag : 1; + u16 tiles_enabled_flag : 1; + u16 entropy_coding_sync_enabled_flag : 1; + u16 pps_loop_filter_across_slices_enabled_flag : 1; + u16 loop_filter_across_tiles_enabled_flag : 1; + u16 deblocking_filter_override_enabled_flag : 1; + u16 pps_deblocking_filter_disabled_flag : 1; + u16 pps_beta_offset_div2 : 4; + u16 pps_tc_offset_div2 : 4; + u16 lists_modification_present_flag : 1; + u16 log2_parallel_merge_level : 3; + u16 slice_segment_header_extension_present_flag : 1; + u16 reserved1 : 3; + + // pps extensions + u16 log2_max_transform_skip_block_size : 2; + u16 cross_component_prediction_enabled_flag : 1; + u16 chroma_qp_offset_list_enabled_flag : 1; + u16 log2_min_cu_chroma_qp_delta_size : 3; + u16 cb_qp_offset_list0 : 5; + u16 cb_qp_offset_list1 : 5; + u16 cb_qp_offset_list2 : 5; + u16 cb_qp_offset_list3 : 5; + u16 cb_qp_offset_list4 : 5; + u16 cb_qp_offset_list5 : 5; + u16 cb_cr_offset_list0 : 5; + u16 cb_cr_offset_list1 : 5; + u16 cb_cr_offset_list2 : 5; + u16 cb_cr_offset_list3 : 5; + u16 cb_cr_offset_list4 : 5; + u16 cb_cr_offset_list5 : 5; + u16 chroma_qp_offset_list_len_minus1 : 3; + + /* mvc0 && mvc1 */ + u16 mvc_ff : 16; + u16 mvc_00 : 9; + + /* poc info */ + u16 reserved2 : 3; + u32 current_poc : 32; + u32 ref_pic_poc0 : 32; + u32 ref_pic_poc1 : 32; + u32 ref_pic_poc2 : 32; + u32 ref_pic_poc3 : 32; + u32 ref_pic_poc4 : 32; + u32 ref_pic_poc5 : 32; + u32 ref_pic_poc6 : 32; + u32 ref_pic_poc7 : 32; + u32 ref_pic_poc8 : 32; + u32 ref_pic_poc9 : 32; + u32 ref_pic_poc10 : 32; + u32 ref_pic_poc11 : 32; + u32 ref_pic_poc12 : 32; + u32 ref_pic_poc13 : 32; + u32 ref_pic_poc14 : 32; + u32 reserved3 : 32; + u32 ref_is_valid : 15; + u32 reserved4 : 1; + + /* tile info*/ + u16 num_tile_columns : 5; + u16 num_tile_rows : 5; + u32 column_width0 : 24; + u32 column_width1 : 24; + u32 column_width2 : 24; + u32 column_width3 : 24; + u32 column_width4 : 24; + u32 column_width5 : 24; + u32 column_width6 : 24; + u32 column_width7 : 24; + u32 column_width8 : 24; + u32 column_width9 : 24; + u32 row_height0 : 24; + u32 row_height1 : 24; + u32 row_height2 : 24; + u32 row_height3 : 24; + u32 row_height4 : 24; + u32 row_height5 : 24; + u32 row_height6 : 24; + u32 row_height7 : 24; + u32 row_height8 : 24; + u32 row_height9 : 24; + u32 row_height10 : 24; + u32 reserved5 : 2; + u32 padding; +} __packed; + +struct rkvdec_hevc_priv_tbl { + struct rkvdec_hevc_sps_pps param_set; + struct rkvdec_rps rps; + struct scaling_factor scaling_list; + u8 cabac_table[27456]; +} __packed; + +struct rkvdec_hevc_ctx { + struct rkvdec_aux_buf priv_tbl; + struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; + struct v4l2_ctrl_hevc_ext_sps_st_rps st_cache; + struct vdpu383_regs_h26x regs; +}; + +static void set_column_row(struct rkvdec_hevc_sps_pps *hw_ps, u16 column, = u16 row, int i) +{ + int shift =3D (i & 1) ? 12 : 0; + + switch (i / 2) { + case 0: + hw_ps->column_width0 |=3D column << shift; + hw_ps->row_height0 |=3D row << shift; + break; + case 1: + hw_ps->column_width1 |=3D column << shift; + hw_ps->row_height1 |=3D row << shift; + break; + case 2: + hw_ps->column_width2 |=3D column << shift; + hw_ps->row_height2 |=3D row << shift; + break; + case 3: + hw_ps->column_width3 |=3D column << shift; + hw_ps->row_height3 |=3D row << shift; + break; + case 4: + hw_ps->column_width4 |=3D column << shift; + hw_ps->row_height4 |=3D row << shift; + break; + case 5: + hw_ps->column_width5 |=3D column << shift; + hw_ps->row_height5 |=3D row << shift; + break; + case 6: + hw_ps->column_width6 |=3D column << shift; + hw_ps->row_height6 |=3D row << shift; + break; + case 7: + hw_ps->column_width7 |=3D column << shift; + hw_ps->row_height7 |=3D row << shift; + break; + case 8: + hw_ps->column_width8 |=3D column << shift; + hw_ps->row_height8 |=3D row << shift; + break; + case 9: + hw_ps->column_width9 |=3D column << shift; + hw_ps->row_height9 |=3D row << shift; + break; + case 10: + hw_ps->row_height10 |=3D row << shift; + break; + } +} + +static void set_pps_ref_pic_poc(struct rkvdec_hevc_sps_pps *hw_ps, u32 poc= , int i) +{ + switch (i) { + case 0: + hw_ps->ref_pic_poc0 =3D poc; + break; + case 1: + hw_ps->ref_pic_poc1 =3D poc; + break; + case 2: + hw_ps->ref_pic_poc2 =3D poc; + break; + case 3: + hw_ps->ref_pic_poc3 =3D poc; + break; + case 4: + hw_ps->ref_pic_poc4 =3D poc; + break; + case 5: + hw_ps->ref_pic_poc5 =3D poc; + break; + case 6: + hw_ps->ref_pic_poc6 =3D poc; + break; + case 7: + hw_ps->ref_pic_poc7 =3D poc; + break; + case 8: + hw_ps->ref_pic_poc8 =3D poc; + break; + case 9: + hw_ps->ref_pic_poc9 =3D poc; + break; + case 10: + hw_ps->ref_pic_poc10 =3D poc; + break; + case 11: + hw_ps->ref_pic_poc11 =3D poc; + break; + case 12: + hw_ps->ref_pic_poc12 =3D poc; + break; + case 13: + hw_ps->ref_pic_poc13 =3D poc; + break; + case 14: + hw_ps->ref_pic_poc14 =3D poc; + break; + } +} + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + struct rkvdec_hevc_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_hevc_sps *sps =3D run->sps; + const struct v4l2_ctrl_hevc_pps *pps =3D run->pps; + const struct v4l2_ctrl_hevc_decode_params *dec_params =3D run->decode_par= ams; + struct rkvdec_hevc_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_hevc_sps_pps *hw_ps; + bool tiles_enabled; + s32 max_cu_width; + s32 pic_in_cts_width; + s32 pic_in_cts_height; + u16 log2_min_cb_size, width, height; + u16 column_width[22]; + u16 row_height[22]; + u8 pcm_enabled; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->video_parameters_set_id =3D sps->video_parameter_set_id; + hw_ps->seq_parameters_set_id_sps =3D sps->seq_parameter_set_id; + hw_ps->chroma_format_idc =3D sps->chroma_format_idc; + + log2_min_cb_size =3D sps->log2_min_luma_coding_block_size_minus3 + 3; + width =3D sps->pic_width_in_luma_samples; + height =3D sps->pic_height_in_luma_samples; + hw_ps->width =3D width; + hw_ps->height =3D height; + hw_ps->bit_depth_luma =3D sps->bit_depth_luma_minus8 + 8; + hw_ps->bit_depth_chroma =3D sps->bit_depth_chroma_minus8 + 8; + hw_ps->max_pic_order_count_lsb =3D sps->log2_max_pic_order_cnt_lsb_minus4= + 4; + hw_ps->diff_max_min_luma_coding_block_size =3D sps->log2_diff_max_min_lum= a_coding_block_size; + hw_ps->min_luma_coding_block_size =3D sps->log2_min_luma_coding_block_siz= e_minus3 + 3; + hw_ps->min_transform_block_size =3D sps->log2_min_luma_transform_block_si= ze_minus2 + 2; + hw_ps->diff_max_min_transform_block_size =3D + sps->log2_diff_max_min_luma_transform_block_size; + hw_ps->max_transform_hierarchy_depth_inter =3D sps->max_transform_hierarc= hy_depth_inter; + hw_ps->max_transform_hierarchy_depth_intra =3D sps->max_transform_hierarc= hy_depth_intra; + hw_ps->scaling_list_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED); + hw_ps->amp_enabled_flag =3D !!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLE= D); + hw_ps->sample_adaptive_offset_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET); + + pcm_enabled =3D !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED); + hw_ps->pcm_enabled_flag =3D pcm_enabled; + hw_ps->pcm_sample_bit_depth_luma =3D + pcm_enabled ? sps->pcm_sample_bit_depth_luma_minus1 + 1 : 0; + hw_ps->pcm_sample_bit_depth_chroma =3D + pcm_enabled ? sps->pcm_sample_bit_depth_chroma_minus1 + 1 : 0; + hw_ps->pcm_loop_filter_disabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED); + hw_ps->diff_max_min_pcm_luma_coding_block_size =3D + sps->log2_diff_max_min_pcm_luma_coding_block_size; + hw_ps->min_pcm_luma_coding_block_size =3D + pcm_enabled ? sps->log2_min_pcm_luma_coding_block_size_minus3 + 3 : 0; + hw_ps->num_short_term_ref_pic_sets =3D sps->num_short_term_ref_pic_sets; + hw_ps->long_term_ref_pics_present_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT); + hw_ps->num_long_term_ref_pics_sps =3D sps->num_long_term_ref_pics_sps; + hw_ps->sps_temporal_mvp_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED); + hw_ps->strong_intra_smoothing_enabled_flag =3D + !!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED); + hw_ps->sps_max_dec_pic_buffering_minus1 =3D sps->sps_max_dec_pic_bufferin= g_minus1; + + /* write pps */ + hw_ps->picture_parameters_set_id =3D pps->pic_parameter_set_id; + hw_ps->seq_parameters_set_id_pps =3D sps->seq_parameter_set_id; + hw_ps->dependent_slice_segments_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED); + hw_ps->output_flag_present_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_OU= TPUT_FLAG_PRESENT); + hw_ps->num_extra_slice_header_bits =3D pps->num_extra_slice_header_bits; + hw_ps->sign_data_hiding_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED); + hw_ps->cabac_init_present_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_CAB= AC_INIT_PRESENT); + hw_ps->num_ref_idx_l0_default_active =3D pps->num_ref_idx_l0_default_acti= ve_minus1 + 1; + hw_ps->num_ref_idx_l1_default_active =3D pps->num_ref_idx_l1_default_acti= ve_minus1 + 1; + hw_ps->init_qp_minus26 =3D pps->init_qp_minus26; + hw_ps->constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->transform_skip_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED); + hw_ps->cu_qp_delta_enabled_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_CU= _QP_DELTA_ENABLED); + hw_ps->log2_min_cb_size =3D log2_min_cb_size + + sps->log2_diff_max_min_luma_coding_block_size - + pps->diff_cu_qp_delta_depth; + hw_ps->pps_cb_qp_offset =3D pps->pps_cb_qp_offset; + hw_ps->pps_cr_qp_offset =3D pps->pps_cr_qp_offset; + hw_ps->pps_slice_chroma_qp_offsets_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT); + hw_ps->weighted_pred_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED= _PRED); + hw_ps->weighted_bipred_flag =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHT= ED_BIPRED); + hw_ps->transquant_bypass_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED); + tiles_enabled =3D !!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED); + hw_ps->tiles_enabled_flag =3D tiles_enabled; + hw_ps->entropy_coding_sync_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED); + hw_ps->pps_loop_filter_across_slices_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED= ); + hw_ps->loop_filter_across_tiles_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED); + hw_ps->deblocking_filter_override_enabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED); + hw_ps->pps_deblocking_filter_disabled_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER); + hw_ps->pps_beta_offset_div2 =3D pps->pps_beta_offset_div2; + hw_ps->pps_tc_offset_div2 =3D pps->pps_tc_offset_div2; + hw_ps->lists_modification_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT); + hw_ps->log2_parallel_merge_level =3D pps->log2_parallel_merge_level_minus= 2 + 2; + hw_ps->slice_segment_header_extension_present_flag =3D + !!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESEN= T); + hw_ps->num_tile_columns =3D tiles_enabled ? pps->num_tile_columns_minus1 = + 1 : 1; + hw_ps->num_tile_rows =3D tiles_enabled ? pps->num_tile_rows_minus1 + 1 : = 1; + hw_ps->mvc_ff =3D 0xffff; + + // Setup tiles information + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + max_cu_width =3D 1 << (sps->log2_diff_max_min_luma_coding_block_size + lo= g2_min_cb_size); + pic_in_cts_width =3D (width + max_cu_width - 1) / max_cu_width; + pic_in_cts_height =3D (height + max_cu_width - 1) / max_cu_width; + + if (tiles_enabled) { + if (pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING) { + compute_tiles_uniform(run, log2_min_cb_size, width, height, + pic_in_cts_width, pic_in_cts_height, + column_width, row_height); + } else { + compute_tiles_non_uniform(run, log2_min_cb_size, width, height, + pic_in_cts_width, pic_in_cts_height, + column_width, row_height); + } + } else { + column_width[0] =3D (width + max_cu_width - 1) / max_cu_width; + row_height[0] =3D (height + max_cu_width - 1) / max_cu_width; + } + + for (i =3D 0; i < 22; i++) + set_column_row(hw_ps, column_width[i], row_height[i], i); + + // Setup POC information + hw_ps->current_poc =3D dec_params->pic_order_cnt_val; + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + u32 valid =3D !!(dec_params->num_active_dpb_entries > i); + + set_pps_ref_pic_poc(hw_ps, dec_params->dpb[i].pic_order_cnt_val, i); + hw_ps->ref_is_valid |=3D valid << i; + } +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_ctx *h265_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_REGS, + &h265_ctx->regs.common, + sizeof(h265_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_ADDR_REGS, + &h265_ctx->regs.common_addr, + sizeof(h265_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_PARAMS_REGS, + &h265_ctx->regs.h26x_params, + sizeof(h265_ctx->regs.h26x_params)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_ADDR_REGS, + &h265_ctx->regs.h26x_addr, + sizeof(h265_ctx->regs.h26x_addr)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + const struct v4l2_ctrl_hevc_decode_params *dec_params =3D run->decode_par= ams; + struct rkvdec_hevc_ctx *h265_ctx =3D ctx->priv; + const struct v4l2_ctrl_hevc_sps *sps =3D run->sps; + dma_addr_t priv_start_addr =3D h265_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + struct vdpu383_regs_h26x *regs =3D &h265_ctx->regs; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + dma_addr_t dst_addr; + u32 hor_virstride; + u32 ver_virstride; + u32 y_virstride; + u32 offset; + u32 pixels; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set H264 mode */ + regs->common.reg008_dec_mode =3D VDPU383_MODE_HEVC; + + /* Set input stream length */ + regs->h26x_params.reg066_stream_len =3D vb2_get_plane_payload(&src_buf->v= b2_buf, 0); + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->h26x_params.reg068_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg069_raster_uv_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg070_y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg010.strmd_auto_gating_e =3D 1; + regs->common.reg010.inter_auto_gating_e =3D 1; + regs->common.reg010.intra_auto_gating_e =3D 1; + regs->common.reg010.transd_auto_gating_e =3D 1; + regs->common.reg010.recon_auto_gating_e =3D 1; + regs->common.reg010.filterd_auto_gating_e =3D 1; + regs->common.reg010.bus_auto_gating_e =3D 1; + regs->common.reg010.ctrl_auto_gating_e =3D 1; + regs->common.reg010.rcb_auto_gating_e =3D 1; + regs->common.reg010.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < VDPU383_1080P_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_1080p; + else if (pixels < VDPU383_4K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_4K; + else if (pixels < VDPU383_8K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_8K; + else + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_MAX; + + regs->common.reg016.error_proc_disable =3D 1; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb) - 1; i++) { + struct vb2_buffer *vb_buf =3D get_ref_buf(ctx, run, i); + dma_addr_t buf_dma; + + buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + + /* Set reference addresses */ + regs->h26x_addr.reg170_185_ref_base[i] =3D buf_dma; + regs->h26x_addr.reg195_210_payload_st_ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->h26x_addr.reg217_232_colmv_ref_base[i] =3D buf_dma + ctx->colmv_of= fset; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.reg128_strm_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->h26x_addr.reg168_decout_base =3D dst_addr; + regs->h26x_addr.reg169_error_ref_base =3D dst_addr; + regs->h26x_addr.reg192_payload_st_cur_base =3D dst_addr; + + /* Set colmv address */ + regs->h26x_addr.reg216_colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) { + regs->common_addr.reg140_162_rcb_info[i].offset =3D rkvdec_rcb_buf_dma_a= ddr(ctx, i); + regs->common_addr.reg140_162_rcb_info[i].size =3D rkvdec_rcb_buf_size(ct= x, i); + } + + if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { + /* Set scaling matrix */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); + regs->common_addr.reg132_scanlist_addr =3D priv_start_addr + offset; + } + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, param_set); + regs->common_addr.reg131_gbl_base =3D priv_start_addr + offset; + regs->h26x_params.reg067_global_len =3D sizeof(struct rkvdec_hevc_sps_pps= ) / 16; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, rps); + regs->common_addr.reg129_rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); + regs->common_addr.reg130_cabactbl_base =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_priv_tbl *priv_tbl; + struct rkvdec_hevc_ctx *hevc_ctx; + struct v4l2_ctrl *ctrl; + int ret; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_HEVC_SPS); + if (!ctrl) + return -EINVAL; + + ret =3D rkvdec_hevc_validate_sps(ctx, ctrl->p_new.p_hevc_sps); + if (ret) + return ret; + + hevc_ctx =3D kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); + if (!hevc_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &hevc_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + hevc_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + hevc_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, + sizeof(rkvdec_hevc_cabac_table)); + + ctx->priv =3D hevc_ctx; + return 0; + +err_free_ctx: + kfree(hevc_ctx); + return ret; +} + +static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, hevc_ctx->priv_tbl.size, + hevc_ctx->priv_tbl.cpu, hevc_ctx->priv_tbl.dma); + kfree(hevc_ctx); +} + +static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_run run; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_hevc_priv_tbl *tbl =3D hevc_ctx->priv_tbl.cpu; + u32 watchdog_time; + u64 timeout_threshold; + unsigned long axi_rate; + + rkvdec_hevc_run_preamble(ctx, &run); + + /* + * On vdpu383, not setting the long and short term ref sets leads to IOMM= U page faults. + * To be on the safe side for this new v4l2 control, write an error in th= e log and mark + * the buffer as failed by returning an error here. + */ + if ((!ctx->has_sps_lt_rps && run.sps->num_long_term_ref_pics_sps) || + (!ctx->has_sps_st_rps && run.sps->num_short_term_ref_pic_sets)) { + dev_err_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); + return -EINVAL; + } + + rkvdec_hevc_assemble_hw_scaling_list(ctx, &run, &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); + assemble_hw_pps(ctx, &run); + rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + timeout_threshold =3D hevc_ctx->regs.common.reg013_core_timeout_threshold; + axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(timeout_threshold, rkvdec->link + VDPU383_LINK_TIMEOUT_THRESHOLD); + writel(VDPU383_IP_CRU_MODE, rkvdec->link + VDPU383_LINK_IP_ENABLE); + writel(VDPU383_DEC_E_BIT, rkvdec->link + VDPU383_LINK_DEC_ENABLE); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_hevc_fmt_ops =3D { + .adjust_fmt =3D rkvdec_hevc_adjust_fmt, + .start =3D rkvdec_hevc_start, + .stop =3D rkvdec_hevc_stop, + .run =3D rkvdec_hevc_run, + .try_ctrl =3D rkvdec_hevc_try_ctrl, + .get_image_fmt =3D rkvdec_hevc_get_image_fmt, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index b72cb07de70e..326ee8f307bc 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -504,6 +504,22 @@ static const struct rkvdec_coded_fmt_desc vdpu383_code= d_fmts[] =3D { .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, .capability =3D RKVDEC_CAPABILITY_H264, }, + { + .fourcc =3D V4L2_PIX_FMT_HEVC_SLICE, + .frmsize =3D { + .min_width =3D 64, + .max_width =3D 65472, + .step_width =3D 64, + .min_height =3D 64, + .max_height =3D 65472, + .step_height =3D 16, + }, + .ctrls =3D &vdpu38x_hevc_ctrls, + .ops =3D &rkvdec_vdpu383_hevc_fmt_ops, + .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_hevc_decoded_fmts), + .decoded_fmts =3D rkvdec_hevc_decoded_fmts, + .subsystem_flags =3D VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, + }, }; =20 static bool rkvdec_is_capable(struct rkvdec_ctx *ctx, unsigned int capabil= ity) @@ -1447,6 +1463,78 @@ static irqreturn_t rkvdec_irq_handler(int irq, void = *priv) return cfg->irq_handler(ctx); } =20 +/* + * Flip one or more matrices along their main diagonal and flatten them + * before writing it to the memory. + * Convert: + * ABCD AEIM + * EFGH =3D> BFJN =3D> AEIMBFJNCGKODHLP + * IJKL CGKO + * MNOP DHLP + */ +static void transpose_and_flatten_matrices(u8 *output, const u8 *input, + int matrices, int row_length) +{ + int i, j, row, x_offset, matrix_offset, rot_index, y_offset, matrix_size,= new_value; + + matrix_size =3D row_length * row_length; + for (i =3D 0; i < matrices; i++) { + row =3D 0; + x_offset =3D 0; + matrix_offset =3D i * matrix_size; + for (j =3D 0; j < matrix_size; j++) { + y_offset =3D j - (row * row_length); + rot_index =3D y_offset * row_length + x_offset; + new_value =3D *(input + i * matrix_size + j); + output[matrix_offset + rot_index] =3D new_value; + if ((j + 1) % row_length =3D=3D 0) { + row +=3D 1; + x_offset +=3D 1; + } + } + } +} + +/* + * VDPU383 needs a specific order: + * The 8x8 flatten matrix is based on 4x4 blocks. + * Each 4x4 block is written separately in order. + * + * Base data =3D> Transposed VDPU383 transposed + * + * ABCDEFGH AIQYaiqy AIQYBJRZ + * IJKLMNOP BJRZbjrz CKS0DLT1 + * QRSTUVWX CKS0cks6 aiqybjrz + * YZ012345 =3D> DLT1dlt7 cks6dlt7 + * abcdefgh EMU2emu8 EMU2FNV3 + * ijklmnop FNV3fnv9 GOW4HPX5 + * qrstuvwx GOW4gow# emu8fnv9 + * yz6789#$ HPX5hpx$ gow#hpx$ + * + * As the function reads block of 4x4 it can be used for both 4x4 and 8x8 = matrices. + * + */ +static void vdpu383_flatten_matrices(u8 *output, const u8 *input, int matr= ices, int row_length) +{ + u8 block; + int i, j, matrix_offset, matrix_size, new_value, input_idx, line_offset, = block_offset; + + matrix_size =3D row_length * row_length; + for (i =3D 0; i < matrices; i++) { + matrix_offset =3D i * matrix_size; + for (j =3D 0; j < matrix_size; j++) { + block =3D j / 16; + line_offset =3D (j % 16) / 4; + block_offset =3D (block & 1) * 32 + (block & 2) * 2; + input_idx =3D ((j % 4) * row_length) + line_offset + block_offset; + + new_value =3D *(input + i * matrix_size + input_idx); + + output[matrix_offset + j] =3D new_value; + } + } +} + static void rkvdec_watchdog_func(struct work_struct *work) { struct rkvdec_dev *rkvdec; @@ -1510,6 +1598,7 @@ static const struct rkvdec_config config_rkvdec =3D { .coded_fmts_num =3D ARRAY_SIZE(rkvdec_coded_fmts), .irq_handler =3D rk3399_irq_handler, .colmv_size =3D rkvdec_colmv_size, + .flatten_matrices =3D transpose_and_flatten_matrices, }; =20 static const struct rcb_size_info vdpu381_rcb_sizes[] =3D { @@ -1532,6 +1621,7 @@ static const struct rkvdec_config config_vdpu381 =3D { .rcb_num =3D ARRAY_SIZE(vdpu381_rcb_sizes), .irq_handler =3D vdpu381_irq_handler, .colmv_size =3D rkvdec_colmv_size, + .flatten_matrices =3D transpose_and_flatten_matrices, .named_regs =3D true, }; =20 @@ -1555,6 +1645,7 @@ static const struct rkvdec_config config_vdpu383 =3D { .rcb_num =3D ARRAY_SIZE(vdpu383_rcb_sizes), .irq_handler =3D vdpu383_irq_handler, .colmv_size =3D rkvdec_vdpu383_colmv_size, + .flatten_matrices =3D vdpu383_flatten_matrices, .named_regs =3D true, }; =20 @@ -1589,7 +1680,8 @@ static const struct rkvdec_variant rk3588_vdpu381_var= iant =3D { =20 static const struct rkvdec_variant rk3576_vdpu383_variant =3D { .config =3D &config_vdpu383, - .capabilities =3D RKVDEC_CAPABILITY_H264, + .capabilities =3D RKVDEC_CAPABILITY_H264 | + RKVDEC_CAPABILITY_HEVC, }; =20 static const struct of_device_id of_rkvdec_match[] =3D { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 94e2e6429992..aed684f14766 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -123,6 +123,7 @@ struct rkvdec_config { size_t rcb_num; irqreturn_t (*irq_handler)(struct rkvdec_ctx *ctx); u32 (*colmv_size)(u16 width, u16 height); + void (*flatten_matrices)(u8 *output, const u8 *input, int matrices, int r= ow_length); bool named_regs; }; =20 @@ -194,5 +195,6 @@ extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381= _hevc_fmt_ops; =20 /* VDPU383 ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops; +extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_hevc_fmt_ops; =20 #endif /* RKVDEC_H_ */ --=20 2.51.1.dirty