From nobody Sun Feb 8 02:56:14 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 D6083316904; Fri, 9 Jan 2026 16:15:49 +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=1767975351; cv=none; b=TqQfuB3wM9xmhqtg1J4dFLXYkcPwK5tnT7hcxsJQlbnkFbX3wUweE9H1tz1zUBql//lcSToO0St/r7Lw58oX5+TNVGIORf/bNu6RK+bxvB4VzzJiF3+NKv1byKJlTHE/WsnGdQ+vNFEltnnkRRWv3SS18Gl2wWrhjImtDM2lOWs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975351; c=relaxed/simple; bh=p+kuCGdXK/6j2iTBeIRSLPfGIialDQlPSZDcqO4rm2Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u3TETcObgo2Q4HooBZ8JZ2id7kYqtQHfULZUF6MG8cLyff5gaKdN/lrcWFfXg0Xn4mS2YX6n3aR28+QOOeM0Mmz8rX5zAagFo8lFzQ9yQxTWIQmBCE0agpSd6QfcvtZ1VorCx5QWdqFgsar33GFVF+94YD0AMHoU5Nf58og++bs= 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=E1lSKjyz; 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="E1lSKjyz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975348; bh=p+kuCGdXK/6j2iTBeIRSLPfGIialDQlPSZDcqO4rm2Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E1lSKjyz9/8GolqdFLydMGYfLFYfLWtAVBpMcbyqLncwJ+uJRtb/Fj1LA2LZuq1Sm mgxmH0z7FFFHKxIVj/Ci8OPullbidzm8f7c0YoGT9SXzYHjxoxWEWNGpgrGh36QFsj FFOzbjxFrYPlV73AurmsDJANh91mvcZhBcAbQGqatkidD8FnQKKWeaIbxq+OQzwVWi hoYP5cYw2qiuvVGZiOIasXHkcptScN1YPBOR0YSb1VoIMYbvjD+JFW25gv5q6G6Nw+ 6o8+Up3UGp5LeWHdLU0w86r4VdkYb9UB3VHGhfN36+qHtG8wZmDi8ANWpDI1sSg/a/ +8azVmznjg7ig== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 C5B5217E13E0; Fri, 9 Jan 2026 17:15:45 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 01/17] media: uapi: HEVC: Add v4l2_ctrl_hevc_ext_sps_[ls]t_rps controls Date: Fri, 9 Jan 2026 11:15:17 -0500 Message-ID: <20260109161538.1294449-2-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 to fully parse the slice header, which cannot be passed with the current controls. There is also no skip method similar as to what can be found in verisilicon HW. The SPS is therefore extended through these 2 new controls, providing the long and short term reference information from the slice header for HEVC decoding. These now controls are similar as what is passed in the Vulkan Video API with the StdVideoH265ShortTermRefPicSet and StdVideoH265LongTermRefPicsSps structures embedded in the SPS struct. Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/v4l/ext-ctrls-codec-stateless.rst | 120 ++++++++++++++++++ .../media/v4l/videodev2.h.rst.exceptions | 2 + .../media/v4l/vidioc-queryctrl.rst | 12 ++ 3 files changed, 134 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 497ae74379f6..3b1e05c6eb13 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -2959,6 +2959,126 @@ This structure contains all loop filter related par= ameters. See sections - 0x00000004 - =20 +``V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS (struct)`` + Subset of the :c:type:`v4l2_ctrl_hevc_sps` control. + It extends it with the list of Long-term reference sets parameters. + 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. + The values in the array should be ignored when either + num_long_term_ref_pics_sps is 0 or the + V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT flag is not set in + :c:type:`v4l2_ctrl_hevc_sps`. + +.. 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. + * - __u16 + - ``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)`` + Subset of the :c:type:`v4l2_ctrl_hevc_sps` control. + It extends it with the list of Short-term reference sets parameters. + 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. + The values in the array should be ignored when + num_short_term_ref_pic_sets is 0. + +.. 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. + * - __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 + - ``abs_delta_rps_minus1`` + - Absolute delta RPS as specified in section 7.4.8 "Short-term refer= ence picture set + semantics" of the specification. + * - __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. + * - __u16 + - ``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 c41693115db6..6182b4e2d2ee 100644 --- a/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions @@ -150,6 +150,8 @@ replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:ty= pe:`V4L.v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_H264_PRED_WEIGHTS :c:type:`V4L.v4l2_ctrl_typ= e` replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`V4L.v4l2_ctrl_typ= e` replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`V4L.v4l2_ctrl_ty= pe` +replace symbol V4L2_CTRL_TYPE_HEVC_EXT_SPS_ST_RPS :c:type:`V4L.v4l2_ctrl_t= ype` +replace symbol V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS :c:type:`V4L.v4l2_ctrl_t= ype` replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`V4L.v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`V4L.v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`V4L.v4l2_ctrl_typ= e` diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/D= ocumentation/userspace-api/media/v4l/vidioc-queryctrl.rst index c8baa9430c14..82c8b52e771c 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -531,6 +531,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.52.0 From nobody Sun Feb 8 02:56:14 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 A190E363C74; Fri, 9 Jan 2026 16:15:52 +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=1767975354; cv=none; b=Hu/x2FUm3Iny8QXqHTaOSZxcc6d40ekJqmAv4G2RoKioW/WeK5uPCQj4tnfC8aTgofYaoka7vGfpPtNeIReGp8gnN3ghQHxg0UUE0R0qnbDqhpMNYz2iSl1cRWxTd3L/GHucqIZWPyws4NH34eKOPl5QnJNs9ezyxNedig8wQ8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975354; c=relaxed/simple; bh=Sa/VjM/KZ9jAThGl1We6tM8KCFSvVQkMC7R1+/6lI8o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MY+vaoJZaeEXE/of5ck1mpSJe1LSm5VLfJVYIt4oDlqH/MuBtBGwScSyjQnxi3kS/t0+An/wuRngqhK9nIkkOStK7GqWZYSxFdftzqiSxCK3vdxFaxHlew4sL2Lq5X8l0ulVvPIkICNmn+16Z+P3Zwq8igantn5k98ye1PoyOiM= 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=jci8dueT; 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="jci8dueT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975351; bh=Sa/VjM/KZ9jAThGl1We6tM8KCFSvVQkMC7R1+/6lI8o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jci8dueT8rH9hLBgGzGMfK2skln+yvnv1aPHLQGrztTWlsGdo/sBrPE2/wuAJZRCq ecMn6cYOZCCy3W6F1+4V9SIIxhPMz0MKCSGUc/qIo8y+SGKX+lZ/vg4YjeVcp1y69v 7F2f/z3IJJHkj4fN3ugCofpyiJOt44Lp74vqXke75IanbeGjzLr4dKcD2L/Ob2+Q1w R9nMs3iarPzHf9zwKyla17anT4/NZPBIjXiIxCpS3TGM8/zLYfVuBr+1oyhM89HfnG pfMrPZEglFlpUXNfRGsviHwdKMmZgPqAREuF8c43Qo2ji5S6GgfoLHp0kMLvUhPbv5 LoZLm6jaGMZ8A== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 9807D17E1523; Fri, 9 Jan 2026 17:15:48 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 02/17] media: v4l2-ctrls: Add hevc_ext_sps_[ls]t_rps controls Date: Fri, 9 Jan 2026 11:15:18 -0500 Message-ID: <20260109161538.1294449-3-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne --- drivers/media/v4l2-core/v4l2-ctrls-core.c | 28 +++++++++++ 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, 101 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2= -core/v4l2-ctrls-core.c index 209bc05883bb..f11255255c74 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -424,6 +424,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; @@ -961,6 +967,8 @@ static int std_validate_compound(const struct v4l2_ctrl= *ctrl, u32 idx, struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights; struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; + struct v4l2_ctrl_hevc_ext_sps_lt_rps *p_hevc_lt_rps; + struct v4l2_ctrl_hevc_ext_sps_st_rps *p_hevc_st_rps; struct v4l2_ctrl_hevc_sps *p_hevc_sps; struct v4l2_ctrl_hevc_pps *p_hevc_pps; struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; @@ -1254,6 +1262,20 @@ 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: + p_hevc_st_rps =3D p; + + if (p_hevc_st_rps->flags & ~V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_= SET_PRED) + return -EINVAL; + break; + + case V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS: + p_hevc_lt_rps =3D p; + + if (p_hevc_lt_rps->flags & ~V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT) + return -EINVAL; + break; + case V4L2_CTRL_TYPE_HDR10_CLL_INFO: break; =20 @@ -2006,6 +2028,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 f84ed133a6c9..e9f1fcc4f840 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -2099,6 +2099,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, @@ -2554,6 +2556,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; + __u8 num_negative_pics; + __u8 num_positive_pics; + __u32 used_by_curr_pic; + __u32 use_delta_flag; + __u16 abs_delta_rps_minus1; + __u16 delta_poc_s0_minus1[16]; + __u16 delta_poc_s1_minus1[16]; + __u16 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; + __u16 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 add08188f068..5efaeb74ef92 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1985,6 +1985,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.52.0 From nobody Sun Feb 8 02:56:15 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 73E91364038; Fri, 9 Jan 2026 16:15:55 +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=1767975356; cv=none; b=AbltOe/M9YKDTyUVM6bVksnxW72nOhrEbfGpAYvYlsN2j42WG0sUAtw527nyljaGiSW8Dz7jYGAUPIAv4NjZpVwCwsx7tVTPpzTxgkEMxnlN+ELZVlJpYhuuyczgQd5sIT7sTcyBeZ3Tuj2gMbj0GsxsIGJxG8eEu2sw4PGF+PI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975356; c=relaxed/simple; bh=zMs773gNTyCmVsfKZpLbcuvnRPqQol+69Xi60PFt49c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LXSXSgvNJ2zNdE7IiyHVbBQ9dWBjjUwQg50DjPzFhR1SomGah5NVOxKMeHrNX2QiGHSwfGVeWDH7naSp5qV6GmfD0xr3BfrLkwS9V6L2amlysddY+Iq9Zeh0so+wdQuCUEAHKozmYgS8EvEn3cZUe8OL7T65K4cnxIz7NUi1Xv4= 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=Pl7R+Ie3; 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="Pl7R+Ie3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975353; bh=zMs773gNTyCmVsfKZpLbcuvnRPqQol+69Xi60PFt49c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Pl7R+Ie3KhApOr6fbThardVdh/JZEDJrkS9oA7rRMavTTCpJfu+TDXSrbtU+wnGwy k5zlSKTAWWu96EwDSd3p1Ne732AvaLA5bU7FSpCW3ymnUNM0D56Zu2zPLHsXTi3qIa qJMJxm8fddx7S4jfcoqJxsGMaM2pgYJ8Pvre8ozW4DGeK5r6B1KseE6Ct3Jr5TD/RQ plndtx4a3/GBp7CM/ltVK4SQHyZ0CwxsmUTGE8kC0lc2vMQmVRt+bNBlc28PO0A+25 xuzT3d8AnV6BqrYmJXWdD0dnfiDMU9TGMQkW1rw6xbrnu2z11mpM5ogTFopf94s4vH pBSr0SnM5WU7Q== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 6ADE017E1580; Fri, 9 Jan 2026 17:15:51 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 03/17] media: visl: Add HEVC short and long term RPS sets Date: Fri, 9 Jan 2026 11:15:19 -0500 Message-ID: <20260109161538.1294449-4-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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" Log the recently added v4l2 controls to set HEVC short and long term RPS sets with 2 new ftrace entries. Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- drivers/media/test-drivers/visl/visl-dec.c | 7 +++ drivers/media/test-drivers/visl/visl-dec.h | 3 + .../media/test-drivers/visl/visl-trace-hevc.h | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/tes= t-drivers/visl/visl-dec.c index d90b79de8384..6bbf93757047 100644 --- a/drivers/media/test-drivers/visl/visl-dec.c +++ b/drivers/media/test-drivers/visl/visl-dec.c @@ -547,6 +547,9 @@ static void visl_trace_ctrls(struct visl_ctx *ctx, stru= ct visl_run *run) trace_v4l2_hevc_dpb_entry(&run->hevc.dpram->dpb[i]); =20 trace_v4l2_hevc_pred_weight_table(&run->hevc.spram->pred_weight_table); + trace_v4l2_ctrl_hevc_ext_sps_lt_rps(run->hevc.rps_lt); + trace_v4l2_ctrl_hevc_ext_sps_st_rps(run->hevc.rps_st); + break; case VISL_CODEC_AV1: trace_v4l2_ctrl_av1_sequence(run->av1.seq); @@ -611,6 +614,10 @@ void visl_device_run(void *priv) run.hevc.spram =3D visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_S= LICE_PARAMS); run.hevc.sm =3D visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SCAL= ING_MATRIX); run.hevc.dpram =3D visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_D= ECODE_PARAMS); + run.hevc.rps_lt =3D visl_find_control_data(ctx, + V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS); + run.hevc.rps_st =3D visl_find_control_data(ctx, + V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS); break; case VISL_CODEC_AV1: run.av1.seq =3D visl_find_control_data(ctx, V4L2_CID_STATELESS_AV1_SEQUE= NCE); diff --git a/drivers/media/test-drivers/visl/visl-dec.h b/drivers/media/tes= t-drivers/visl/visl-dec.h index c2c2ef3a8798..6e7562e555bb 100644 --- a/drivers/media/test-drivers/visl/visl-dec.h +++ b/drivers/media/test-drivers/visl/visl-dec.h @@ -7,6 +7,7 @@ #ifndef _VISL_DEC_H_ #define _VISL_DEC_H_ =20 +#include "linux/v4l2-controls.h" #include "visl.h" =20 struct visl_fwht_run { @@ -43,6 +44,8 @@ struct visl_hevc_run { const struct v4l2_ctrl_hevc_slice_params *spram; const struct v4l2_ctrl_hevc_scaling_matrix *sm; const struct v4l2_ctrl_hevc_decode_params *dpram; + const struct v4l2_ctrl_hevc_ext_sps_lt_rps *rps_lt; + const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_st; }; =20 struct visl_av1_run { diff --git a/drivers/media/test-drivers/visl/visl-trace-hevc.h b/drivers/me= dia/test-drivers/visl/visl-trace-hevc.h index 837b8ec12e97..963914c463db 100644 --- a/drivers/media/test-drivers/visl/visl-trace-hevc.h +++ b/drivers/media/test-drivers/visl/visl-trace-hevc.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0+ */ +#include "linux/v4l2-controls.h" #if !defined(_VISL_TRACE_HEVC_H_) || defined(TRACE_HEADER_MULTI_READ) #define _VISL_TRACE_HEVC_H_ =20 @@ -343,6 +344,54 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl, )) ); =20 +DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl, + TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt), + TP_ARGS(lt), + TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_lt_rps, lt)= ), + TP_fast_assign(__entry->lt =3D *lt), + TP_printk("\nflags %s\n" + "lt_ref_pic_poc_lsb_sps %x\n", + __print_flags(__entry->lt.flags, "|", + {V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT, "USED_LT"} + ), + __entry->lt.lt_ref_pic_poc_lsb_sps + ) +) + +DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl, + TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st), + TP_ARGS(st), + TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_st_rps, st)= ), + TP_fast_assign(__entry->st =3D *st), + TP_printk("\nflags %s\n" + "delta_idx_minus1: %u\n" + "delta_rps_sign: %u\n" + "abs_delta_rps_minus1: %u\n" + "num_negative_pics: %u\n" + "num_positive_pics: %u\n" + "used_by_curr_pic: %08x\n" + "use_delta_flag: %08x\n" + "delta_poc_s0_minus1: %s\n" + "delta_poc_s1_minus1: %s\n", + __print_flags(__entry->st.flags, "|", + {V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED, "INTER_REF_PIC_= SET_PRED"} + ), + __entry->st.delta_idx_minus1, + __entry->st.delta_rps_sign, + __entry->st.abs_delta_rps_minus1, + __entry->st.num_negative_pics, + __entry->st.num_positive_pics, + __entry->st.used_by_curr_pic, + __entry->st.use_delta_flag, + __print_array(__entry->st.delta_poc_s0_minus1, + ARRAY_SIZE(__entry->st.delta_poc_s0_minus1), + sizeof(__entry->st.delta_poc_s0_minus1[0])), + __print_array(__entry->st.delta_poc_s1_minus1, + ARRAY_SIZE(__entry->st.delta_poc_s1_minus1), + sizeof(__entry->st.delta_poc_s1_minus1[0])) + ) +) + =20 DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl, TP_PROTO(const struct v4l2_hevc_dpb_entry *e), @@ -391,6 +440,16 @@ DEFINE_EVENT(v4l2_ctrl_hevc_decode_params_tmpl, v4l2_c= trl_hevc_decode_params, TP_ARGS(d) ); =20 +DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl, v4l2_ctrl_hevc_ext_sps_lt= _rps, + TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt), + TP_ARGS(lt) +); + +DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl, v4l2_ctrl_hevc_ext_sps_st= _rps, + TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st), + TP_ARGS(st) +); + DEFINE_EVENT(v4l2_hevc_dpb_entry_tmpl, v4l2_hevc_dpb_entry, TP_PROTO(const struct v4l2_hevc_dpb_entry *e), TP_ARGS(e) --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 5799E363C7F; Fri, 9 Jan 2026 16:15:58 +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=1767975361; cv=none; b=lWAc+/3PjSXqV+3dDnFYG6Jiu1EirjmfbaRwmNGo8ulSHuUiYNv+nIZrJjB4GjyBvqwskNMj80FAawJRn6LbeER3lkR3biYUFzYNB1Lcu1Z68GIzeVHNRwIgaIMyYP4d8h7yy+9DUYPKuhj7COhxgVB/yZAhQ82b4P38o110XmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975361; c=relaxed/simple; bh=RHLgCJx1whSsXoB8vOEtA2/P7pcrz1Rv7mZguY4FscA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MKP7AO2GdUDRs+w2v/V+Y61p2J95AjtO0FJMcJBvaDFA+ryLglioUtQfDd/UHNaNSSs9yuM0ROZTWaGhFriO1429vyqDnzdi8TdsVOegg+GUMOw3q+Qc7CeQwIpJLaIcl20Xra+EIA62y+BQF+viezziXpaLUVjTFBtY4CpdZD8= 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=kDgeV6Ve; 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="kDgeV6Ve" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975356; bh=RHLgCJx1whSsXoB8vOEtA2/P7pcrz1Rv7mZguY4FscA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kDgeV6VeCkXVnaoRyibxyK/bOAEzFQlMQ0qJyOTs5cYKHKrFnCrSD/afi+ydlfoYf QLQSQ3hjfbXDiviJ7Zdf+9mG9Ech/7g6KNM1nQSx4guPwwX+pqa3G5vUeiU3JFKgd+ MoaL/ZeOPTvE6HM2YO2coSA/hXtBGp8oo03b8FuJ3UYXFSnrpb7/p0d24vzXyFAek1 m6mqjkKI2HerULWO9Hr41bYhmh6M4xb5ChKe25atgEPq/X2O/vYUAXe1iSWrSJp8MM y3I+9t+meg8MvQVLSqBsEj8IJTPcBGlvEkUsNMd4+glD0xSLpPrLtD/d3BZ/69npMc ZKDSGUlq9G2mw== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 3B31917E35D2; Fri, 9 Jan 2026 17:15:54 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 04/17] media: rkvdec: Switch to using structs instead of writel Date: Fri, 9 Jan 2026 11:15:20 -0500 Message-ID: <20260109161538.1294449-5-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../platform/rockchip/rkvdec/rkvdec-h264.c | 166 +++-- .../platform/rockchip/rkvdec/rkvdec-hevc.c | 64 +- .../platform/rockchip/rkvdec/rkvdec-regs.h | 586 ++++++++++++------ .../platform/rockchip/rkvdec/rkvdec-vp9.c | 232 +++---- .../media/platform/rockchip/rkvdec/rkvdec.c | 10 +- .../media/platform/rockchip/rkvdec/rkvdec.h | 1 + 6 files changed, 604 insertions(+), 455 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c b/drivers= /media/platform/rockchip/rkvdec/rkvdec-h264.c index d14b4d173448..68e20cb81a88 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,37 @@ 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->base_addr =3D refer_addr >> 4; + base->field_ref =3D !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD); + base->colmv_use_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); =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), sizeof(u32) * rkvdec->variant->num_regs)); } =20 #define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2 @@ -1181,8 +1159,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..2d9e0e947a6d 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,30 @@ 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_use_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), sizeof(u32) * rkvdec->variant->num_regs)); } =20 #define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 @@ -784,8 +778,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..1af66c5f1c9b 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,399 @@ #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 dec_e_strmd_clkgate_dis : 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 wr_ddr_align_en : 1; + u32 scl_down_en : 1; + u32 allow_not_wr_unref_bframe : 1; + u32 reserved1 : 6; + } 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 colmv_mode : 1; + u32 ycacherd_prior : 1; + } 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_use_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 strmd_error_slice_en : 1; + u32 strmd_error_frame_en : 1; + } reg77; + + u32 colmv_cur_base; + u32 colmv_ref_base[16]; + u32 scanlist_addr; + u32 reg96_sd_decout_base; + u32 sd_y_virstride; + u32 sd_hor_stride; + u32 qos_ctrl; + u32 perf[8]; + u32 qos1; +} __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..ba51a7c2fe55 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,7 @@ 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; const struct v4l2_vp9_segmentation *seg; struct rkvdec_dev *rkvdec =3D ctx->dev; dma_addr_t addr; @@ -547,8 +506,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 +518,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 +543,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; @@ -606,46 +560,58 @@ static void config_registers(struct rkvdec_ctx *ctx, else lf =3D &vp9_ctx->cur.lf; =20 - 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 +620,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 +650,15 @@ 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), sizeof(u32) * rkvdec->variant->num_regs)); } =20 static int validate_dec_params(struct rkvdec_ctx *ctx, @@ -823,8 +791,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.52.0 From nobody Sun Feb 8 02:56:15 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 1F49030AAC9; Fri, 9 Jan 2026 16:16:01 +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=1767975365; cv=none; b=Iu5cz3I2frUFDeDdl2YpkEtm3Z1Jv0IswCJQf33F/1BVlkJydhxKNAVK16c5a+qqjp5/1mkxP9noUPrgSL8P4Ka4oDwiz1N5IHXQVZ8q6dPCOZu4qSbcDek4286W8ke2dkF9KJqZINplnLdtClAVGf402dkAxybQb/AFFJhCoJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975365; c=relaxed/simple; bh=bYUdjzkOdKWIeD/iDLusXB7gdL1SfCJNFj1eRqNBLaA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=caUWl0Pz9XzmPJAfJ4b8npiWdVgTMIurRcxiA3tEeoUWnBy1LyL+4tzxOkEyqQUEU1OQYeNTc8kOmVFwMercj6O+osS552QhaHsmb2CCFLrrdvZtEE1Idz0reYGW06IWaMLZqTPoxsnNLcN4WjINIS1MRllzR7Bzs/s+U8AQSsA= 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=kZnNkM0z; 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="kZnNkM0z" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975359; bh=bYUdjzkOdKWIeD/iDLusXB7gdL1SfCJNFj1eRqNBLaA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kZnNkM0zgBSbn0ADx7ZSfhFofQli4u5SeUpI7/DJLWtZNThQMekbvwqPLA/VxqaiX S8oULBMOsfjq70uDUf4dWuXXIwTxl8JoqjvSB3CbPhBKuAjiZBDwUE2dGv5/G3hRIw zPL03OCsmkEh4vu1xsHymx3NPyuXwCx1Z1y8bFgyPPH7GRuZpUbypA3bmhcOcnbZUa 0TFgJxFuo/K6dJ3/Ydg1eNbBKBZqmCPJxG8aUtS9CrmN4t/V5ijkISTKBhczRXl7YS r63y8ncRsF7hBY439DN+GgtaRYBVYIun/mU72CAYS3XrQEwk39jkOR1pQFPU+6Fazp dY6VYAczuIMig== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 2A64317E369F; Fri, 9 Jan 2026 17:15:57 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 05/17] media: rkvdec: Move cabac tables to their own source file Date: Fri, 9 Jan 2026 11:15:21 -0500 Message-ID: <20260109161538.1294449-6-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../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 68e20cb81a88..088840248a76 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 2d9e0e947a6d..dfadb9a13c9a 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.52.0 From nobody Sun Feb 8 02:56:15 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 3C80D236A73; Fri, 9 Jan 2026 16:16:04 +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=1767975366; cv=none; b=mFILF1ZXkO+bunds/s6JhbzkQlFc53RCkf0oM8Yrf/HCkgG9XxgqV0GQpqr91YGKDuBHQuKeJP8oHYEIiWmB+L0bJAWewQLLWxqSHcb51I6zPldVN5SrMbopNo/W2RByn1MvaqHnk5aNOlH03iJp4qmJNerFhzOK7Iv7TV6fgyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975366; c=relaxed/simple; bh=7y2GP2KySbAPGPVY5CRJkpvqGn5pMjCV2cFM/TZaslE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uwBXmEpZGWjH05NGYcXprdOEFfCbLghEdE82/R6E6gnw5f5RBunzUnIy8INiRCiapLRni/8HTyb2dF3ah8WUo7zvticQl25N3EyrR6a9pJr6CQcj82USndzvJfAHdL7eiyTfIoICHYVzXiOZAIAQKEimQEx2+F2YOAT+RMl1yxA= 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=SPeq/+wv; 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="SPeq/+wv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975362; bh=7y2GP2KySbAPGPVY5CRJkpvqGn5pMjCV2cFM/TZaslE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SPeq/+wvYUs2XSeVRrpDwWo84VuqxB2A2V74Cd9CnUI4jZQ8RhUBST0NTzoqblC0a IVVhqWI+G4RpOv6GeOB5QFVKjML89umfYnxka4I8M1Jw6Vyk3VDbFuOj2U7JDdtRkV 9ijtTo9rxF1yt1vOKuXVXvT/Aq0ThldEaNo2i9PEEkImEpmEIuRwtpl6MonAfiZd7I Jscx39zH/jfbmciE/bFNxloSkPnj3+SumoT/qE3Bm6UV/jZ/OZ4l3OeWVPd/Z3f6K1 oRWvWOea15mdEnApYjJX17S6iziaLVRjBJrZA3ts2WZ31u0DOMxLtH78DOsaBtLlt8 IRF3hwhtLVkbQ== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 0C82617E36A3; Fri, 9 Jan 2026 17:15:59 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 06/17] media: rkvdec: Use structs to represent the HW RPS Date: Fri, 9 Jan 2026 11:15:22 -0500 Message-ID: <20260109161538.1294449-7-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne 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 088840248a76..fd941e926279 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.52.0 From nobody Sun Feb 8 02:56:15 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 F2C0B316904; Fri, 9 Jan 2026 16:16:06 +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=1767975370; cv=none; b=YBACwOmdwjzSoaQTtnxonSOaqdZ57kcCF+9BsiUq+3ir1nN1JmHorAdnHsKqX7CxhIyR12Ge/ztId0ffFq35AQK6dqCLnbfTkPEXxZSNVtxPsA4H8/NhPgSkSLcQ3QhltUFx3LqlOA+K+TaQLxATDrjjwbHglGbaWrZuq3BY5Bw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975370; c=relaxed/simple; bh=e1gOZ9cU9mLV+oqrfg2LnfBGNXOro7soqCP508mtx+I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b/cZtXWnLLLYWf+7HHdWn4MOc5Q86AbFnGi57PtDg7KRdV0yAfl9Vexu0MLHVUtKr/0FQCVWpP+bRafG9h/pYUVcem3Nm+9cE1qRRXShjs31QyQONZPxvsgzW87yqittb6xPlmPeB1+NQB/TQJz2Y55U0wzmhubFwQ5PCu/HUEQ= 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=EVWnHyQC; 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="EVWnHyQC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975365; bh=e1gOZ9cU9mLV+oqrfg2LnfBGNXOro7soqCP508mtx+I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EVWnHyQCopMHKk+Gz8sGYlZgtGqYLwPFsQS/EJ4r3Y95o1J1y3KlCHFTaQtKC+3tO s4EQ3LzZt6rGt2LjvtAKXpkzmZPbXzUqIYg+K5eC1FLSescSj3Q2+ijrF4JZ07RPQj LXkbOx0EtE2SrOyDl1rfNe/q9zh07/tj0fUkjXKC6GkUYkbDJur94Ey/LPmgFrLtUv 7WrRf0X/Z3l1677X5CXtdOhoDJSPShURQB+9dwOoFvmKpmZHNsvayG/vjaklbbm7HE AdF8+hxH31XTh+iYKegm0fGYAy9jtUojW1wDCn+r3HvSoYneKbLGsZNraLQVeqmdzV UxkCqOqUvEmWg== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 CB83A17E36AC; Fri, 9 Jan 2026 17:16:02 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 07/17] media: rkvdec: Move h264 functions to common file Date: Fri, 9 Jan 2026 11:15:23 -0500 Message-ID: <20260109161538.1294449-8-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-h264-common.c | 258 +++++++++++++++ .../rockchip/rkvdec/rkvdec-h264-common.h | 87 +++++ .../platform/rockchip/rkvdec/rkvdec-h264.c | 310 +----------------- 4 files changed, 350 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..e28f06394470 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip video decoder h264 common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + * + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon + * + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Jeffy Chen + */ + +#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..bd0c0081365b --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip video decoder h264 common functions + * + * Copyright (C) 2025 Collabora, Ltd. + * Detlev Casanova + * + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon + * + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Jeffy Chen + */ + +#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 fd941e926279..d93c7953692d 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. * @@ -569,76 +357,6 @@ static void config_registers(struct rkvdec_ctx *ctx, MIN(sizeof(*regs), sizeof(u32) * rkvdec->variant->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; @@ -690,33 +408,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 @@ -727,10 +425,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.52.0 From nobody Sun Feb 8 02:56:15 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 AFD52364053; Fri, 9 Jan 2026 16:16:09 +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=1767975371; cv=none; b=S6I9DrXhLYchME4HWia8mu01E/eBzCVfQgdTKiL1rv2XUCxVJmqD/DsoiuiplWgKYotibPajbeiYfpElE4iS6E8L1YsVETzxePM/YetyicOPhIX+u2j0Xwj/uaEAMQt7J8u3kX2/xd5HWlFkUw92CyVNCXXP7gsPImLs0dirgSU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975371; c=relaxed/simple; bh=ZVz9iyDYQ+BmX6JlDG6BFIQ9CSF2WshyZlQ/8+tMrMk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RcL4xkDVXdP4hrZ+sa5H/Gnaa/7kWrY+HzVsjsdGF8XaUeNOCrqUqKNrqSG0cvj5RdyeC5YyNKs+/o/GlH4dbZFvyQAy0SedZaQZ7cebKeEn6/23GWBufcIOHxO8yxvSOWfsmlEkR8qj+9NTL6ISq+nVF9a7PtZf0yOPPY545Mo= 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=MHLiYI8m; 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="MHLiYI8m" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975368; bh=ZVz9iyDYQ+BmX6JlDG6BFIQ9CSF2WshyZlQ/8+tMrMk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MHLiYI8mPZVrCHnRZT0WushAH4FKtCK2Vf8GO6nJfnVzKNQq7FL8RxUP4wNRY7m4o YQPB7l7ojkYM0PUDCk90HFan+Kcch+Xt8X+oTuZ8/qLpa+s9cODPkDKtpouLhW+yyn bhc+kG2D3k+iAKcISqbxPzYX8XnP4kA6BevWtJg4IKTfZZBCMTtbXfoteG0Io07pNw HCA9bwV7BAxjfigbZA6y2R+MnQoowEUoiMvkbcDw7Li3XM/6r5du2chuJPhDKabOwf EgnZvtlTMjfWew+11Gez9sSKeuHxR4i1oJFt4gJu9hZVrAA/VOgV/YZbZkzdSdgLN8 r+/T7b1CRYcVQ== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 92FAA17E3722; Fri, 9 Jan 2026 17:16:05 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 08/17] media: rkvdec: Move hevc functions to common file Date: Fri, 9 Jan 2026 11:15:24 -0500 Message-ID: <20260109161538.1294449-9-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 206 +++++++++++++++++ .../rockchip/rkvdec/rkvdec-hevc-common.h | 49 ++++ .../platform/rockchip/rkvdec/rkvdec-hevc.c | 217 +----------------- 4 files changed, 263 insertions(+), 210 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..cb56a9a24392 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -0,0 +1,206 @@ +// 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; +} + + +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); +} 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..e3099fdd784b --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -0,0 +1,49 @@ +/* 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*/ +}; + +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); +enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, st= ruct 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 dfadb9a13c9a..156ce381f068 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) { @@ -645,43 +501,6 @@ static void config_registers(struct rkvdec_ctx *ctx, MIN(sizeof(*regs), sizeof(u32) * rkvdec->variant->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) { @@ -692,7 +511,7 @@ static int rkvdec_hevc_validate_sps(struct rkvdec_ctx *= ctx, /* 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 */ + /* Only 8-bit and 10-bit are supported */ return -EINVAL; =20 if (sps->pic_width_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.width || @@ -738,40 +557,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); --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 9D26B364024; Fri, 9 Jan 2026 16:16:12 +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=1767975374; cv=none; b=eqUsw/ZqLYFfhTtvvWPEhyorrOXbh1K1Nagpg32SdGb2srgD5RSPQM8L8s+bPATe0x42lxy1Khxf0/6aWfPxyaNvXs55tOx/AcJSPZ8gnTBX8pWMrRV9Fg8HCQ3TSrUsfIXvgj4Z5Qz/yalRyYdVwmhIJSE+bF8CSFjZrJrt1e4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975374; c=relaxed/simple; bh=AAcKqp1ylkAC240pSTWqd8H+tnWyz3uLdrsFl0fLhxE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iLX7HPt8K5bTfTCVUxha9df9MqEDsrUXziGI1PxtWfGk9i6WKLyHm4tf5guTmhcopS6qhG1JR9T2F5g3N8BFR4bKyFyfX7ujQ9swAeeMeon10L48TqAnb11JAPT/lwSvEwEqFSxKYZmtAdHLJHedkGwIlviF0bn/BHMfeojYHpA= 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=QTn2jLVv; 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="QTn2jLVv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975370; bh=AAcKqp1ylkAC240pSTWqd8H+tnWyz3uLdrsFl0fLhxE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QTn2jLVvdF4TyKt1Y3RAApvMb3NlsI6/HVUB6XBbjK1qtB8zQcD2zkjFhyoPUs7hA x06vuGUnBPdcvYtPIPOdQz073QaYV2KSv8/OHNwMuqi9OrfWULeum2a0FeOAA7cizk 80cPceYiVTaDiXfMwlLFWYJDd/q6YWdWiiw0tscsN/KSKytl+hKuOj1/JTG2okPPa2 6TyFS0tbkt+HaGny91/EEvLZsLJC8HrOTvbueSCstB07sY2riiWKOGBH1Rtf6ty/Bb KTo4x+4774Vs/iiYUxttSGQ1IMXNn8LtkIdlMNLHqlvVfOrD5BHdId8hhK8+2gS3iL 2jcDr/3vnnCBw== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 676D517E3819; Fri, 9 Jan 2026 17:16:08 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 09/17] media: rkvdec: Add variant specific coded formats list Date: Fri, 9 Jan 2026 11:15:25 -0500 Message-ID: <20260109161538.1294449-10-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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" Prepare for adding new variants of the decoder and support specific formats and format ops per variant. This removes the need of capability flags for variants, so remove them. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/rkvdec.c | 68 ++++++++++--------- .../media/platform/rockchip/rkvdec/rkvdec.h | 8 +-- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 776149f871b0..92b1c7b62bd2 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -328,7 +328,6 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_= fmts[] =3D { .ops =3D &rkvdec_hevc_fmt_ops, .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_hevc_decoded_fmts), .decoded_fmts =3D rkvdec_hevc_decoded_fmts, - .capability =3D RKVDEC_CAPABILITY_HEVC, }, { .fourcc =3D V4L2_PIX_FMT_H264_SLICE, @@ -345,7 +344,6 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_= fmts[] =3D { .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, }, { .fourcc =3D V4L2_PIX_FMT_VP9_FRAME, @@ -361,27 +359,38 @@ static const struct rkvdec_coded_fmt_desc rkvdec_code= d_fmts[] =3D { .ops =3D &rkvdec_vp9_fmt_ops, .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_vp9_decoded_fmts), .decoded_fmts =3D rkvdec_vp9_decoded_fmts, - .capability =3D RKVDEC_CAPABILITY_VP9, } }; =20 -static bool rkvdec_is_capable(struct rkvdec_ctx *ctx, unsigned int capabil= ity) -{ - return (ctx->dev->variant->capabilities & capability) =3D=3D capability; -} +static const struct rkvdec_coded_fmt_desc rk3288_coded_fmts[] =3D { + { + .fourcc =3D V4L2_PIX_FMT_HEVC_SLICE, + .frmsize =3D { + .min_width =3D 64, + .max_width =3D 4096, + .step_width =3D 64, + .min_height =3D 64, + .max_height =3D 2304, + .step_height =3D 16, + }, + .ctrls =3D &rkvdec_hevc_ctrls, + .ops =3D &rkvdec_hevc_fmt_ops, + .num_decoded_fmts =3D ARRAY_SIZE(rkvdec_hevc_decoded_fmts), + .decoded_fmts =3D rkvdec_hevc_decoded_fmts, + } +}; =20 static const struct rkvdec_coded_fmt_desc * rkvdec_enum_coded_fmt_desc(struct rkvdec_ctx *ctx, int index) { + const struct rkvdec_variant *variant =3D ctx->dev->variant; 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)) - continue; + for (i =3D 0; i < variant->num_coded_fmts; i++) { fmt_idx++; if (index =3D=3D fmt_idx) - return &rkvdec_coded_fmts[i]; + return &variant->coded_fmts[i]; } =20 return NULL; @@ -390,12 +399,12 @@ 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_variant *variant =3D ctx->dev->variant; 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 < variant->num_coded_fmts; i++) { + if (variant->coded_fmts[i].fourcc =3D=3D fourcc) + return &variant->coded_fmts[i]; } =20 return NULL; @@ -1014,21 +1023,19 @@ static int rkvdec_add_ctrls(struct rkvdec_ctx *ctx, =20 static int rkvdec_init_ctrls(struct rkvdec_ctx *ctx) { + const struct rkvdec_variant *variant =3D ctx->dev->variant; 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 < variant->num_coded_fmts; i++) + nctrls +=3D variant->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); - if (ret) - goto err_free_handler; - } + for (i =3D 0; i < variant->num_coded_fmts; i++) { + ret =3D rkvdec_add_ctrls(ctx, variant->coded_fmts[i].ctrls); + if (ret) + goto err_free_handler; } =20 ret =3D v4l2_ctrl_handler_setup(&ctx->ctrl_hdl); @@ -1242,22 +1249,21 @@ static void rkvdec_watchdog_func(struct work_struct= *work) =20 static const struct rkvdec_variant rk3288_rkvdec_variant =3D { .num_regs =3D 68, - .capabilities =3D RKVDEC_CAPABILITY_HEVC, + .coded_fmts =3D rk3288_coded_fmts, + .num_coded_fmts =3D ARRAY_SIZE(rk3288_coded_fmts), }; =20 static const struct rkvdec_variant rk3328_rkvdec_variant =3D { .num_regs =3D 109, - .capabilities =3D RKVDEC_CAPABILITY_HEVC | - RKVDEC_CAPABILITY_H264 | - RKVDEC_CAPABILITY_VP9, + .coded_fmts =3D rkvdec_coded_fmts, + .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), .quirks =3D RKVDEC_QUIRK_DISABLE_QOS, }; =20 static const struct rkvdec_variant rk3399_rkvdec_variant =3D { .num_regs =3D 78, - .capabilities =3D RKVDEC_CAPABILITY_HEVC | - RKVDEC_CAPABILITY_H264 | - RKVDEC_CAPABILITY_VP9, + .coded_fmts =3D rkvdec_coded_fmts, + .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), }; =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 f35f6e80ea2e..8c4f96ba5cde 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -22,10 +22,6 @@ #include #include =20 -#define RKVDEC_CAPABILITY_HEVC BIT(0) -#define RKVDEC_CAPABILITY_H264 BIT(1) -#define RKVDEC_CAPABILITY_VP9 BIT(2) - #define RKVDEC_QUIRK_DISABLE_QOS BIT(0) =20 struct rkvdec_ctx; @@ -71,7 +67,8 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) =20 struct rkvdec_variant { unsigned int num_regs; - unsigned int capabilities; + const struct rkvdec_coded_fmt_desc *coded_fmts; + size_t num_coded_fmts; unsigned int quirks; }; =20 @@ -110,7 +107,6 @@ struct rkvdec_coded_fmt_desc { unsigned int num_decoded_fmts; const struct rkvdec_decoded_fmt_desc *decoded_fmts; u32 subsystem_flags; - unsigned int capability; }; =20 struct rkvdec_dev { --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 185BB364EA2; Fri, 9 Jan 2026 16:16:15 +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=1767975377; cv=none; b=WjDt1LJPt/YKX+uXKjruqFEVKeJTDka/19WeH5Wy3S8mfmQ+aVVaBPe6XXHCtGIL/ZchbQOyqi7ZFoBb9LHgKXExh7/ZHkKx6gGpz41D+X6f1Q5PVgnn6HoLHqni/6QCNSCQb8+vBrIzux3Hj4uYvStF8Znv8q/5kR50icSSU4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975377; c=relaxed/simple; bh=9GO7WxSqqrgfmcX4/V76MCBDlnt/OjvdUGwpVq7Ce00=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X7DI2s39L6seOztg7XsCQmmJ2Y5pvBgJSCicsoeXqMeMbCyNWoDZDI7paxNucHbSwbMn8fiSbRCwGlOGk5r2FDz/pFfOyGbsXV6oqHQo/W5K0Sq+uuunuAWcKJOZ2UxR7CFcj3ER5QQhb2e0inQFPzVEqvVewVXYz3+ouL0cGGU= 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=critu8zP; 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="critu8zP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975373; bh=9GO7WxSqqrgfmcX4/V76MCBDlnt/OjvdUGwpVq7Ce00=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=critu8zPaRGi1EfZ/CZ7q4PRMQIjQnbpNou8q3NZqlLDQRhw9//PixqXaBHUkLRrQ spz5pvjbJxZHPuHyeMlThbk6PGaUbLw3xIJ0xuyDj+RztjyySv5hCcLR+rVgKFdYot DW3aY5d7kYX6jooVMvaM1sH/0Z0IpWl3fr4grJ6rWCRpy0YOcb+CB/BYNxGLWbfqeL KUYYkcCWEZvAy6StTNsEjY5pODEdf208J2g3Lv7zG5AMOAwxtXI/setm98oMA8mvZG MY573VbAndGHghLIgFjCn31+zajoNEO63nqj6lbGjuyz4Zb9lkJQSxFxQ+01AoaZwz U6GOeCgNhvhrg== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 35D4C17E3846; Fri, 9 Jan 2026 17:16:11 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 10/17] media: rkvdec: Add RCB and SRAM support Date: Fri, 9 Jan 2026 11:15:26 -0500 Message-ID: <20260109161538.1294449-11-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../platform/rockchip/rkvdec/rkvdec-rcb.c | 179 ++++++++++++++++++ .../platform/rockchip/rkvdec/rkvdec-rcb.h | 29 +++ .../media/platform/rockchip/rkvdec/rkvdec.c | 27 ++- .../media/platform/rockchip/rkvdec/rkvdec.h | 13 ++ 5 files changed, 247 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..fdcf1f177379 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c @@ -0,0 +1,179 @@ +// 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 +#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; + + if (!size_info || !rcb_count) { + ctx->rcb_config =3D NULL; + return 0; + } + + 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, SZ_4K); + + cpu =3D gen_pool_dma_zalloc_align(ctx->dev->sram_pool, + rcb_size, + &dma, + SZ_4K); + } + + /* 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 92b1c7b62bd2..ff6a09e45462 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) @@ -778,6 +780,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_variant *variant =3D ctx->dev->variant; int ret; =20 if (V4L2_TYPE_IS_CAPTURE(q->type)) @@ -787,13 +790,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, variant->rcb_sizes, variant->num_rcb_siz= es); + 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) @@ -829,6 +841,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); @@ -1345,6 +1359,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->num_rcb_sizes > 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); @@ -1353,7 +1371,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)) { @@ -1367,6 +1386,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 8c4f96ba5cde..751f39afe7e2 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -19,12 +19,14 @@ #include #include #include +#include #include #include =20 #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; @@ -69,6 +71,8 @@ struct rkvdec_variant { unsigned int num_regs; const struct rkvdec_coded_fmt_desc *coded_fmts; size_t num_coded_fmts; + const struct rcb_size_info *rcb_sizes; + size_t num_rcb_sizes; unsigned int quirks; }; =20 @@ -119,6 +123,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; }; @@ -131,6 +137,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 @@ -139,10 +146,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.52.0 From nobody Sun Feb 8 02:56:15 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 49783365A18; Fri, 9 Jan 2026 16:16:18 +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=1767975380; cv=none; b=VkoMcHjtlc0HTxUivLvXksyKRt09tAX0AK3OcISfv8ia6GQdn3KKWqu+5S47yWky/Yqf7sTquBNowmoR0OWpd3C3O0vOfMsmS1LHNMJaRwcWOokuSK+iI7Dz7hvRQrI0VG6EDF9vBXKdjATaLtT5vCji4aZiKt7A0gQ1DVHI3yM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975380; c=relaxed/simple; bh=gmpTefIfPlF4I8DgMdzcgz2ylhV7PMm7hs/HGAhZC44=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kaOYOSoK7ofZWTU+siWgL+xkcx6H1ucre9v5q+U8Xcn+WwooiRyUzoAVoBs0pH6gUlPR2+C2SgAVC196au1mo33ZJDifP8SRzLxQhnbqr1XzDWzcSAzmsYpkYurqx7I5DcCtc4HZEdngdZodALGyDI0k+ZaN0butOxBYJ1/Byi4= 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=FqOEhDdV; 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="FqOEhDdV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975376; bh=gmpTefIfPlF4I8DgMdzcgz2ylhV7PMm7hs/HGAhZC44=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FqOEhDdVbn+Y68rgKs4Q2Su4nyJGrWAFlAP6P/oxitD1agrRF/RS+wlyPpvr3BaNa x/BSRQvjcQNz0kPm2UIMGlTn44AANy0KG1EK9HOxcM/JAcubhhOHo0PZSZfYz9fXwm 7cWtQ92vY5dS1q85m6JOEIR+q7rHuCGsee0FT2z6hWpg7bh7o2YX82KzA4lhXHAEM/ BnSMeZa2FlesrFwymhEVhotL9QK6lWI3bPcL/mJt1EwPkNf8B+JA9G26pOVtaC5OhA jmG8ZFuVjrZSmAnv+adA4uAzTNsl5q/ocG9K5WVzhpBveagUP+H72s037eNm5Oc/fR A1XfrKQYVE9ag== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 F3B3F17E3856; Fri, 9 Jan 2026 17:16:13 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 11/17] media: rkvdec: Support per-variant interrupt handler Date: Fri, 9 Jan 2026 11:15:27 -0500 Message-ID: <20260109161538.1294449-12-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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" Prepare for supporting different variants with different interrupt managers. To support other variants specific function type later, introduce the rkvdec_variant_ops struct. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/rkvdec.c | 21 ++++++++++++++++--- .../media/platform/rockchip/rkvdec/rkvdec.h | 5 +++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index ff6a09e45462..174536ebdcc7 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1222,10 +1222,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 @@ -1246,6 +1245,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_variant *variant =3D rkvdec->variant; + + return variant->ops->irq_handler(ctx); +} + static void rkvdec_watchdog_func(struct work_struct *work) { struct rkvdec_dev *rkvdec; @@ -1261,16 +1269,22 @@ static void rkvdec_watchdog_func(struct work_struct= *work) } } =20 +static const struct rkvdec_variant_ops rk3399_variant_ops =3D { + .irq_handler =3D rk3399_irq_handler, +}; + static const struct rkvdec_variant rk3288_rkvdec_variant =3D { .num_regs =3D 68, .coded_fmts =3D rk3288_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rk3288_coded_fmts), + .ops =3D &rk3399_variant_ops, }; =20 static const struct rkvdec_variant rk3328_rkvdec_variant =3D { .num_regs =3D 109, .coded_fmts =3D rkvdec_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), + .ops =3D &rk3399_variant_ops, .quirks =3D RKVDEC_QUIRK_DISABLE_QOS, }; =20 @@ -1278,6 +1292,7 @@ static const struct rkvdec_variant rk3399_rkvdec_vari= ant =3D { .num_regs =3D 78, .coded_fmts =3D rkvdec_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), + .ops =3D &rk3399_variant_ops, }; =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 751f39afe7e2..faabedd2b9d8 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -67,12 +67,17 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) base.vb.vb2_buf); } =20 +struct rkvdec_variant_ops { + irqreturn_t (*irq_handler)(struct rkvdec_ctx *ctx); +}; + struct rkvdec_variant { unsigned int num_regs; const struct rkvdec_coded_fmt_desc *coded_fmts; size_t num_coded_fmts; const struct rcb_size_info *rcb_sizes; size_t num_rcb_sizes; + const struct rkvdec_variant_ops *ops; unsigned int quirks; }; =20 --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 3DC30366562; Fri, 9 Jan 2026 16:16:21 +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=1767975386; cv=none; b=M2ERpHFpUTDQsAUig8wA6t/I/pjeYJL381cCo8nAAZMPFtEIO17RPN1oRPtAWwBcCisSevt5yrGWDdTLUq/kVlschvMXomjJjX0g5w8k1ONOfvJjDy1hPCIdx3ea9BA2XfPng0/1lq6uBFDhtg1RBglLLZYYHQpPs1iLTlYjC3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975386; c=relaxed/simple; bh=FcMjdGO9DiOb6B60v+9UXIBuak2u519S7MLxvub3bdw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NPz17x/NXPL9Dlr+OLVWfL2vnOnjuaKa7sVWJ2m8zM2jPpv6iLpah2qLjJZXWrmr/v7qwZ/1HRcPt8BMnS60+DmM6H2f0VXC/mbJL9tCAG0tHX/a7d2KCx+k3hwoIVJbx3LyT7i/fc+HIDVqlOon3RstFY1uswKJlGzrOAtEB5U= 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=Ve2Sjk8S; 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="Ve2Sjk8S" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975379; bh=FcMjdGO9DiOb6B60v+9UXIBuak2u519S7MLxvub3bdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ve2Sjk8SupcW2//JqvsMdvhVXYNsJVeMqiCkaXPbadHnQJsz5SvDC9QZ6CnbChy4O iNqsIgUD/6kC+peoTOKHa25gcv0lOdKCpHWqJYCQGn5UCu9kFd0yOvPhhDoiGpRTJR ULG/A+3/EXnLKgl8SJfw3yArkzTFbzkkvUsVY4HviZ+aEE2pSL1jFfrVdrPw8U1s0m szgRUSnI1zqxtCM8VZUNSBf2yyNzbr646a5E4b1mIAuNa0/pvpnOXBSEl7EPsHNQxR XA/AT+BCetVEUCtWdpj0b9I0TAJhQ4JY357KytlaDELfB01wWP0Wm00AS0f6LgAQib Hx21FQ8gQQ0UA== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 2093117E3859; Fri, 9 Jan 2026 17:16:17 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 12/17] media: rkvdec: Enable all clocks without naming them Date: Fri, 9 Jan 2026 11:15:28 -0500 Message-ID: <20260109161538.1294449-13-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/rkvdec.c | 26 +++++-------------- .../media/platform/rockchip/rkvdec/rkvdec.h | 1 + 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 174536ebdcc7..ce96a0470d4d 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1312,15 +1312,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); @@ -1337,19 +1332,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->num_clocks =3D ret; + rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rkvdec->regs)) return PTR_ERR(rkvdec->regs); @@ -1427,16 +1415,14 @@ 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), - rkvdec->clocks); + return clk_bulk_prepare_enable(rkvdec->num_clocks, rkvdec->clocks); } =20 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), - rkvdec->clocks); + clk_bulk_disable_unprepare(rkvdec->num_clocks, rkvdec->clocks); return 0; } #endif diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index faabedd2b9d8..7766a79caf68 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -125,6 +125,7 @@ struct rkvdec_dev { struct v4l2_m2m_dev *m2m_dev; struct device *dev; struct clk_bulk_data *clocks; + unsigned int num_clocks; void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 0B3E936404A; Fri, 9 Jan 2026 16:16:23 +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=1767975385; cv=none; b=mWN3beV8/MxAt0DaH1WUBA4w37oM28FefpGXmCYY/KztBYCemZXAQjlcxDvAAhTv6TK5TT+PD0KWrOBkqQAg79GNic6jwnPrH+OHnXm2tCGV1pJ8J1UecwuiKhrXas0ShuMxkQmx/Clu3np6K38R9MukQumXgrfFDTI1S9ARaUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975385; c=relaxed/simple; bh=2cfBe2HMjZ1TVCyq7yRqYr5Xf8tgJn9wnLlQqFOVpSk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I6s2g0vqJf3WwCdL+nsISwNAZDlDiPr7K9JAIgaeEo4S+qwdjIOHdF8z/FVy/xkQBTvQpw5IRyPDLhhTOdPwuzFezLw4uHSokGiSR34pLn8lDpwX4KyX+nML4GsDvtfnQpR9A0Y/yqdPd5IMnHtrMA1ONPWC6hkw7zzpim4t6l8= 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=DUzfcDnG; 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="DUzfcDnG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975382; bh=2cfBe2HMjZ1TVCyq7yRqYr5Xf8tgJn9wnLlQqFOVpSk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DUzfcDnG7flTDX5MHJ0SaSz0mj816vvHeKbsvK40vO39QvDjXQBeG0Guk6fY5K5Yu 06G1t1Mgx8jV+68vYajhe3DNwhcWVoZIbCLMkJerPfyQ0D5okczqZINBWLi/zvxb9V vH0jS7hAaphyOMk2pnkU6X1mF0LLPpK45r5XCttRHswIYJWdkdqQiVVsu5n8/n7IEt 5K+JeE+MVe2iStyAzvbTTUoXYQXn9tfhfM/wX53jiXz0w7UbrpH21XHofpkog1ivqD ukhAqvB3OP/08/Bxw3ZFvXaj9y9UtkSqzLAb4zJezijZQqk1cXTiWV7QmjKRD7uNLD 24jyoB9y5C5Gg== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 F245617E385E; Fri, 9 Jan 2026 17:16:19 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 13/17] media: rkvdec: Disable multicore support Date: Fri, 9 Jan 2026 11:15:29 -0500 Message-ID: <20260109161538.1294449-14-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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" Similarly to what is done in Hantro, avoid exposing equal video codecs to userspace. Equal video codecs allow scheduling work between the cores. For that kernel support is required, which does not yet exist. Until that is implemented, avoid exposing each core separately to userspace so that multicore can be added in the future without breaking userspace ABI. This currently applies only to RK3588 which has 2 equal VDPU381 decoders, but will be applied for all SoC supported by rkvdec that has multiple DTS nodes with the same compatible. Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/rkvdec.c | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index ce96a0470d4d..af2eced90026 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1269,6 +1269,49 @@ 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_variant_ops rk3399_variant_ops =3D { .irq_handler =3D rk3399_irq_handler, }; @@ -1332,6 +1375,10 @@ static int rkvdec_probe(struct platform_device *pdev) 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 2.52.0 From nobody Sun Feb 8 02:56:15 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 9AB94366573; Fri, 9 Jan 2026 16:16:26 +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=1767975389; cv=none; b=IflZ6835RX/ReITphDbPj+g1LJzojeWYXfSJfOffNBqmRi320kcifOCCQjTUtu35IIc29E6gsiypHQwQXoxPMPYpewdp5zfRxCOl9HRxLvgpOMMCbg5OdH/h/ZMDU+tDIK+vB4aWUN4iHg/c5aMmGh5gTjiU6fUgBbv/07tXs9Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975389; c=relaxed/simple; bh=3uqXu8t/9MiFu2JopOn2/t5CwUPPq0DfwC8FMp27N4c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TuBL/gjk/2MU1H+r/YN/9C5DSiy9Sxn0inHDeT/PmNgGtCTEUEaRopQ1Vxq984PbUvaQFH7QizNSrtntTCRs3H7sgzinaYvhzLBpzSoNRT9PGXzqnMSPmxWT2sks6+V0N7/i46UzV02cPuCQ/xByx15tBFHtEdNOP08YKOS4+k0= 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=m9LF6mMr; 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="m9LF6mMr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975385; bh=3uqXu8t/9MiFu2JopOn2/t5CwUPPq0DfwC8FMp27N4c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m9LF6mMraVUHuWIHF5e6GoCXFox01uQxxl4sWWBbzQa+D3uFZE8QbeVDajr7neLHM GuHrSuS4vR2MAIDkWtnJNLEnkuiCyR4PfFqfcc8Yw0LTOc/XI2evBMFrM61LY8AFvz 5V3KlHjVaPSg1CnHsrmjfz8jJpL4rRM+/hpkAVkKLVFv24Bl3AaBc4AAqfjsygKfTV Hncen/xioTCZpzCO1CkvllY4R2+7k9OwbdA8/zZJmMkFoeAoD4fo6nhHFHDgPKVKDb NShxhlIDSisH8i0D3B1m2kZGMmkfKH3SvMEOtArACxw/scF24DYYUzQCKRzwgmmTw2 tgj7igxQrTvbw== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 C067717E3865; Fri, 9 Jan 2026 17:16:22 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 14/17] media: rkvdec: Add H264 support for the VDPU381 variant Date: Fri, 9 Jan 2026 11:15:30 -0500 Message-ID: <20260109161538.1294449-15-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 6.0. The maximum width and height have been significantly increased supporting up to 65520 pixels for both. Support for named register sections is added for this variant and future ones. Fluster score for JVT-AVC_V1 is 129/135. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova Reviewed-by: Nicolas Dufresne --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-h264-common.h | 2 + .../rockchip/rkvdec/rkvdec-vdpu381-h264.c | 468 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu381-regs.h | 430 ++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 111 ++++- .../media/platform/rockchip/rkvdec/rkvdec.h | 12 + 6 files changed, 1021 insertions(+), 3 deletions(-) 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 bd0c0081365b..3be6cea3a758 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h @@ -74,6 +74,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..0a89ebcab7ab --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h264.c @@ -0,0 +1,468 @@ +// 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.dec_mode =3D VDPU381_MODE_H264; + + /* Set config */ + regs->common.reg011_important_en.buf_empty_en =3D 1; + regs->common.reg011_important_en.dec_clkgate_e =3D 1; + regs->common.reg011_important_en.dec_timeout_e =3D 1; + regs->common.reg011_important_en.pix_range_det_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_secondary_en.scanlist_addr_valid_en =3D 1; + + /* Set IDR flag */ + regs->common.reg013_en_mode_set.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.reg016_stream_len =3D vb2_get_plane_payload(&src_buf->vb2_bu= f, 0); + + /* Set max slice number */ + regs->common.reg017_slice_number.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; + + regs->common.reg018_y_hor_stride.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019_uv_hor_stride.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020_y_stride.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026_block_gating_en.inter_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.filterd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.strmd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.mcp_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.busifd_auto_gating_e =3D 0; + regs->common.reg026_block_gating_en.dec_ctrl_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.intra_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.mc_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.transd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.sram_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.cru_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + pixels =3D dst_fmt->height * dst_fmt->width; + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_8K; + else + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_MAX; + + /* Set TOP and BOTTOM POCs */ + regs->h264_param.reg065_cur_top_poc =3D dec_params->top_field_order_cnt; + regs->h264_param.reg066_cur_bot_poc =3D dec_params->bottom_field_order_cn= t; + + /* 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.reg164_180_ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->h264_addr.reg182_198_colmv_base[i] =3D buf_dma + ctx->colmv_offset; + + struct rkvdec_vdpu381_h264_ref_info *ref_info =3D + ®s->h264_param.reg099_102_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.reg067_098_ref_poc[i * 2] =3D + dpb[i].top_field_order_cnt; + regs->h264_param.reg067_098_ref_poc[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.reg161_pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, rps); + regs->h264_addr.reg163_rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, cabac_table); + regs->h264_addr.reg199_cabactbl_base =3D priv_start_addr + offset; + + offset =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + regs->h264_addr.reg181_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; + + 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); + + rkvdec_schedule_watchdog(rkvdec, h264_ctx->regs.common.reg032_timeout_thr= eshold); + + /* 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..6da36031df2d --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h @@ -0,0 +1,430 @@ +/* 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_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 { + 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_in_out; + + struct { + u32 dec_mode : 10; + u32 reserved : 22; + } reg009_dec_mode; + + struct { + u32 dec_e : 1; + u32 reserved : 31; + } reg010_dec_e; + + struct { + u32 reserved0 : 1; + u32 dec_clkgate_e : 1; + u32 dec_e_strmd_clkgate_dis : 1; + u32 reserved1 : 1; + + u32 dec_irq_dis : 1; + u32 dec_timeout_e : 1; + u32 buf_empty_en : 1; + u32 reserved2 : 3; + + u32 dec_e_rewrite_valid : 1; + u32 reserved3 : 9; + u32 softrst_en_p : 1; + u32 force_softreset_valid : 1; + u32 reserved4 : 2; + u32 pix_range_det_e : 1; + u32 reserved5 : 7; + } reg011_important_en; + + struct { + u32 reserved0 : 1; + u32 colmv_compress_en : 1; + u32 fbc_e : 1; + u32 reserved1 : 1; + + u32 buspr_slot_disable : 1; + u32 error_info_en : 1; + u32 collect_info_en : 1; + u32 error_auto_rst_disable : 1; + + u32 scanlist_addr_valid_en : 1; + u32 scale_down_en : 1; + u32 error_cfg_wr_disable : 1; + u32 reserved2 : 21; + } reg012_secondary_en; + + struct { + u32 reserved0 : 1; + u32 req_timeout_rst_sel : 1; + u32 reserved1 : 1; + u32 dec_commonirq_mode : 1; + u32 reserved2 : 2; + u32 stmerror_waitdecfifo_empty : 1; + u32 reserved3 : 5; + u32 allow_not_wr_unref_bframe : 1; + u32 fbc_output_wr_disable : 1; + u32 reserved4 : 4; + u32 error_mode : 1; + u32 reserved5 : 2; + u32 ycacherd_prior : 1; + u32 reserved6 : 2; + u32 cur_pic_is_idr : 1; + u32 reserved7 : 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 reserved8 : 1; + u32 filter_outbuf_mode : 1; + } reg013_en_mode_set; + + struct { + 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_fbc_param_set; + + struct { + u32 rlc_mode_direct_write : 1; + u32 rlc_mode : 1; + u32 reserved0 : 3; + + u32 strm_start_bit : 7; + u32 reserved1 : 20; + } reg015_stream_param_set; + + u32 reg016_stream_len; + + struct { + u32 slice_num : 25; + u32 reserved : 7; + } reg017_slice_number; + + struct { + u32 y_hor_virstride : 16; + u32 reserved : 16; + } reg018_y_hor_stride; + + struct { + u32 uv_hor_virstride : 16; + u32 reserved : 16; + } reg019_uv_hor_stride; + + struct { + u32 y_virstride : 28; + u32 reserved : 4; + } reg020_y_stride; + + struct { + 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_error_ctrl_set; + + struct { + u32 roi_x_ctu_offset_st : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserved1 : 4; + } reg022_err_roi_ctu_offset_start; + + struct { + u32 roi_x_ctu_offset_end : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserved1 : 4; + } reg023_err_roi_ctu_offset_end; + + struct { + u32 cabac_err_en_lowbits : 32; + } reg024_cabac_error_en_lowbits; + + struct { + u32 cabac_err_en_highbits : 30; + u32 reserved : 2; + } reg025_cabac_error_en_highbits; + + struct { + u32 inter_auto_gating_e : 1; + u32 filterd_auto_gating_e : 1; + u32 strmd_auto_gating_e : 1; + u32 mcp_auto_gating_e : 1; + u32 busifd_auto_gating_e : 1; + u32 reserved0 : 3; + u32 dec_ctrl_auto_gating_e : 1; + u32 intra_auto_gating_e : 1; + u32 mc_auto_gating_e : 1; + u32 transd_auto_gating_e : 1; + u32 reserved1 : 4; + u32 sram_auto_gating_e : 1; + u32 cru_auto_gating_e : 1; + u32 reserved2 : 13; + u32 reg_cfg_gating_en : 1; + } reg026_block_gating_en; + + struct { + u32 core_safe_x_pixels : 16; + u32 core_safe_y_pixels : 16; + } reg027_core_safe_pixels; + + struct { + u32 vp9_wr_prob_idx : 3; + u32 reserved0 : 1; + u32 vp9_rd_prob_idx : 3; + u32 reserved1 : 1; + + u32 ref_req_advance_flag : 1; + u32 colmv_req_advance_flag : 1; + u32 poc_only_highbit_flag : 1; + u32 poc_arb_flag : 1; + + u32 reserved2 : 4; + u32 film_idx : 10; + u32 reserved3 : 2; + u32 pu_req_mismatch_dis : 1; + u32 colmv_req_mismatch_dis : 1; + u32 reserved4 : 2; + } reg028_multiply_core_ctrl; + + struct { + u32 scale_down_hor_ratio : 2; + u32 reserved0 : 6; + u32 scale_down_vrz_ratio : 2; + u32 reserved1 : 22; + } reg029_scale_down_ctrl; + + struct { + u32 y_scale_down_tile8x8_hor_stride : 20; + u32 reserved0 : 12; + } reg030_y_scale_down_tile8x8_hor_stride; + + struct { + u32 uv_scale_down8x8_tile_hor_stride : 20; + u32 reserved0 : 12; + } reg031_uv_scale_down_tile8x8_hor_stride; + + u32 reg032_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_h26x_set; + + u32 reg065_cur_top_poc; + u32 reg066_cur_bot_poc; + u32 reg067_098_ref_poc[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 reserved : 4; + } __packed ref_info[4]; + } __packed reg099_102_ref_info_regs[4]; + + u32 reserved_103_111[9]; + + struct { + 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_error_ref_info; +} __packed; + +struct rkvdec_vdpu381_regs_hevc_params { + struct rkvdec_vdpu381_h26x_set reg064_h26x_set; + + u32 reg065_cur_top_poc; + u32 reg066_cur_bot_poc; + u32 reg067_082_ref_poc[16]; + + u32 reserved_083_098[16]; + + struct { + 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_hevc_ref_valid; + + u32 reserved_100_102[3]; + + struct { + u32 ref_pic_layer_same_with_cur : 16; + u32 reserve : 16; + } reg103_hevc_mvc0; + + struct { + 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_hevc_mvc1; + + u32 reserved_105_111[7]; + + struct { + 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_hevc_ref_info; + +} __packed; + +/* base: OFFSET_CODEC_ADDR_REGS */ +struct rkvdec_vdpu381_regs_h26x_addr { + u32 reserved_160; + u32 reg161_pps_base; + u32 reserved_162; + u32 reg163_rps_base; + u32 reg164_180_ref_base[16]; + u32 reg181_scanlist_addr; + u32 reg182_198_colmv_base[16]; + u32 reg199_cabactbl_base; +} __packed; + +struct rkvdec_vdpu381_regs_h26x_highpoc { + struct { + 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_203_ref_poc_highbit[4]; + struct { + u32 cur_poc_highbit : 4; + u32 reserved : 28; + } reg204_cur_poc_highbit; +} __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 af2eced90026..c6877dfb0549 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); @@ -382,6 +386,25 @@ static const struct rkvdec_coded_fmt_desc rk3288_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, + }, +}; + static const struct rkvdec_coded_fmt_desc * rkvdec_enum_coded_fmt_desc(struct rkvdec_ctx *ctx, int index) { @@ -946,6 +969,20 @@ void rkvdec_memcpy_toio(void __iomem *dst, void *src, = size_t len) #endif } =20 +void rkvdec_schedule_watchdog(struct rkvdec_dev *rkvdec, u32 timeout_thres= hold) +{ + /* Set watchdog at 2 times the hardware timeout threshold */ + u32 watchdog_time; + unsigned long axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * div_u64(1000 * (u64)timeout_threshold, axi_rate); + else + watchdog_time =3D 2000; + + schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(watchdog_t= ime)); +} + static void rkvdec_device_run(void *priv) { struct rkvdec_ctx *ctx =3D priv; @@ -1245,6 +1282,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; @@ -1321,6 +1387,7 @@ static const struct rkvdec_variant rk3288_rkvdec_vari= ant =3D { .coded_fmts =3D rk3288_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rk3288_coded_fmts), .ops =3D &rk3399_variant_ops, + .has_single_reg_region =3D true, }; =20 static const struct rkvdec_variant rk3328_rkvdec_variant =3D { @@ -1328,6 +1395,7 @@ static const struct rkvdec_variant rk3328_rkvdec_vari= ant =3D { .coded_fmts =3D rkvdec_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), .ops =3D &rk3399_variant_ops, + .has_single_reg_region =3D true, .quirks =3D RKVDEC_QUIRK_DISABLE_QOS, }; =20 @@ -1336,6 +1404,32 @@ static const struct rkvdec_variant rk3399_rkvdec_var= iant =3D { .coded_fmts =3D rkvdec_coded_fmts, .num_coded_fmts =3D ARRAY_SIZE(rkvdec_coded_fmts), .ops =3D &rk3399_variant_ops, + .has_single_reg_region =3D true, +}; + +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_variant_ops vdpu381_variant_ops =3D { + .irq_handler =3D vdpu381_irq_handler, +}; + +static const struct rkvdec_variant vdpu381_variant =3D { + .coded_fmts =3D vdpu381_coded_fmts, + .num_coded_fmts =3D ARRAY_SIZE(vdpu381_coded_fmts), + .rcb_sizes =3D vdpu381_rcb_sizes, + .num_rcb_sizes =3D ARRAY_SIZE(vdpu381_rcb_sizes), + .ops =3D &vdpu381_variant_ops, }; =20 static const struct of_device_id of_rkvdec_match[] =3D { @@ -1351,6 +1445,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 &vdpu381_variant, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_rkvdec_match); @@ -1384,10 +1482,17 @@ static int rkvdec_probe(struct platform_device *pde= v) return ret; =20 rkvdec->num_clocks =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->has_single_reg_region) { + rkvdec->regs =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(rkvdec->regs)) + return PTR_ERR(rkvdec->regs); + } else { + rkvdec->regs =3D devm_platform_ioremap_resource_byname(pdev, "function"); + 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 7766a79caf68..4afa9cd690d5 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -25,6 +25,10 @@ =20 #define RKVDEC_QUIRK_DISABLE_QOS BIT(0) =20 +#define RKVDEC_1080P_PIXELS (1920 * 1088) +#define RKVDEC_4K_PIXELS (4096 * 2304) +#define RKVDEC_8K_PIXELS (7680 * 4320) + struct rkvdec_ctx; struct rkvdec_rcb_config; =20 @@ -78,6 +82,7 @@ struct rkvdec_variant { const struct rcb_size_info *rcb_sizes; size_t num_rcb_sizes; const struct rkvdec_variant_ops *ops; + bool has_single_reg_region; unsigned int quirks; }; =20 @@ -126,6 +131,7 @@ struct rkvdec_dev { struct device *dev; struct clk_bulk_data *clocks; unsigned int num_clocks; + struct clk *axi_clk; void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; @@ -144,6 +150,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 @@ -167,11 +174,16 @@ struct rkvdec_aux_buf { 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); +void rkvdec_schedule_watchdog(struct rkvdec_dev *rkvdec, u32 timeout_thres= hold); =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; + #endif /* RKVDEC_H_ */ --=20 2.52.0 From nobody Sun Feb 8 02:56:15 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 6B9E2364055; Fri, 9 Jan 2026 16:16:29 +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=1767975392; cv=none; b=LGNVhWdmdut93CDQsHLxFO/ichsBWYlo95o9OuYffsBNtD51GBHMD/PzFNUTK8TrH/++bIt1/4VEXcqPuPJWpfY4EV3GP0bpcsJ/022vfrO7XnswCWiYKD15+N3pLzphRrxUOxnMz+izlOcT9AyhDSJQ8nXpkXiPYIuV3i5vx8c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975392; c=relaxed/simple; bh=tVROxTzRxCDkB0td/j7QhQM/nJAgvF9F7aexdhFU+48=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eAkq1tVXCNXzYeOY+yTSgjFKgszqt1tZMhQjMkvlcPTcdtrqysXeAQ8C/s2/Kk8+gUUcIb0cW3w9mM8wVWPQQUHqgiZkQHwL3E5XbvTH3ogg2tvX+lm+e0HjL6XqptEBMI7xtF0gS3usAi0QUCAPEDZo3+1iiKt191pE66g5DlA= 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=MeP4KqHf; 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="MeP4KqHf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975388; bh=tVROxTzRxCDkB0td/j7QhQM/nJAgvF9F7aexdhFU+48=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MeP4KqHfB4Z/dp/JC4pJuMbOxX54vEbH3OHb7MbN4GDV2il8EqhwA24KXZmS3mq4L VQFXNT6JhSbNNHqB7tw3TKtJa9VZUg9dbsVmJf4Yjp84TBv2ikm2gaKKecNqHjVG// ArM0H0jzJyFmUjWx0kkpC3YDb5YC1wuZ7TeG5YxfQch1Qiryksn+PZSRfSxQxKh20I NZg4n0dv2sDzCw/Lsf8nf+mdqbXq2+ifdifyERgh+hA+mCchppvQJHXL5cm+AyEL+7 2Oikq2HH8lyAdj2WAcAibM4DJMLckrx9iLFsFbpNs7BGAJrYL6w/66LM4xvw11S3XB KAgLSMu74leHQ== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 8667317E3867; Fri, 9 Jan 2026 17:16:25 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 15/17] media: rkvdec: Add H264 support for the VDPU383 variant Date: Fri, 9 Jan 2026 11:15:31 -0500 Message-ID: <20260109161538.1294449-16-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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. 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. Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-vdpu383-h264.c | 572 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu383-regs.h | 281 +++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 105 +++- .../media/platform/rockchip/rkvdec/rkvdec.h | 5 + 5 files changed, 959 insertions(+), 5 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..c7ba01fa8876 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h264.c @@ -0,0 +1,572 @@ +// 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_block_gating_en.strmd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.inter_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.intra_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.transd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.recon_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.filterd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.bus_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.ctrl_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.rcb_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_4K; + else if (pixels < RKVDEC_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_ctrl_set.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 timeout_threshold; + + 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); + + timeout_threshold =3D h264_ctx->regs.common.reg013_core_timeout_threshold; + rkvdec_schedule_watchdog(rkvdec, timeout_threshold); + + /* 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..04eb23297e37 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h @@ -0,0 +1,281 @@ +/* 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_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 { + 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_important_en; + + struct { + 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_block_gating_en; + + struct { + u32 reserve0 : 9; + u32 dec_timeout_dis : 1; + u32 reserve1 : 22; + } reg011_cfg_para; + + struct { + u32 reserve0 : 7; + u32 cache_hash_mask : 25; + } reg012_cache_hash_mask; + + u32 reg013_core_timeout_threshold; + + struct { + u32 dec_line_irq_step : 16; + u32 dec_line_offset_y_st : 16; + } reg014_line_irq_ctrl; + + struct { + 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_irq_sta; + + struct { + 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_error_ctrl_set; + + struct { + u32 roi_x_ctu_offset_st : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserve1 : 4; + } reg017_err_roi_ctu_offset_start; + + struct { + u32 roi_x_ctu_offset_end : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserve1 : 4; + } reg018_err_roi_ctu_offset_end; + + struct { + 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_error_ref_info; + + u32 reg020_cabac_error_en_lowbits; + u32 reg021_cabac_error_en_highbits; + + u32 reg022_reserved; + + struct { + u32 fill_y : 10; + u32 fill_u : 10; + u32 fill_v : 10; + u32 reserve0 : 2; + } reg023_invalid_pixel_fill; + + u32 reg024_026_reserved[3]; + + struct { + u32 reserve0 : 4; + u32 ctu_align_wr_en : 1; + u32 reserve1 : 27; + } reg027_align_en; + + struct { + 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_debug_perf_latency_ctrl0; + + struct { + 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_debug_perf_latency_ctrl1; + + struct { + 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_qos_ctrl; +}; + +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 c6877dfb0549..804381d36bc4 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,26 @@ 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 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) { - v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, - pix_mp->width, pix_mp->height); + const struct rkvdec_variant *variant =3D ctx->dev->variant; + + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width, pix_mp->h= eight); =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 variant->ops->colmv_size(pix_mp->widt= h, pix_mp->height); } =20 static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f, @@ -405,6 +416,25 @@ 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, + }, +}; + static const struct rkvdec_coded_fmt_desc * rkvdec_enum_coded_fmt_desc(struct rkvdec_ctx *ctx, int index) { @@ -1311,6 +1341,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; @@ -1380,6 +1439,7 @@ static int rkvdec_disable_multicore(struct rkvdec_dev= *rkvdec) =20 static const struct rkvdec_variant_ops rk3399_variant_ops =3D { .irq_handler =3D rk3399_irq_handler, + .colmv_size =3D rkvdec_colmv_size, }; =20 static const struct rkvdec_variant rk3288_rkvdec_variant =3D { @@ -1422,6 +1482,7 @@ static const struct rcb_size_info vdpu381_rcb_sizes[]= =3D { =20 static const struct rkvdec_variant_ops vdpu381_variant_ops =3D { .irq_handler =3D vdpu381_irq_handler, + .colmv_size =3D rkvdec_colmv_size, }; =20 static const struct rkvdec_variant vdpu381_variant =3D { @@ -1432,6 +1493,32 @@ static const struct rkvdec_variant vdpu381_variant = =3D { .ops =3D &vdpu381_variant_ops, }; =20 +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_variant_ops vdpu383_variant_ops =3D { + .irq_handler =3D vdpu383_irq_handler, + .colmv_size =3D vdpu383_colmv_size, +}; + +static const struct rkvdec_variant vdpu383_variant =3D { + .coded_fmts =3D vdpu383_coded_fmts, + .num_coded_fmts =3D ARRAY_SIZE(vdpu383_coded_fmts), + .rcb_sizes =3D vdpu383_rcb_sizes, + .num_rcb_sizes =3D ARRAY_SIZE(vdpu383_rcb_sizes), + .ops =3D &vdpu383_variant_ops, +}; + static const struct of_device_id of_rkvdec_match[] =3D { { .compatible =3D "rockchip,rk3288-vdec", @@ -1449,6 +1536,10 @@ static const struct of_device_id of_rkvdec_match[] = =3D { .compatible =3D "rockchip,rk3588-vdec", .data =3D &vdpu381_variant, }, + { + .compatible =3D "rockchip,rk3576-vdec", + .data =3D &vdpu383_variant, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_rkvdec_match); @@ -1492,6 +1583,10 @@ static int rkvdec_probe(struct platform_device *pdev) 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); } =20 ret =3D dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 4afa9cd690d5..4e9cd12fba3b 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -73,6 +73,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) =20 struct rkvdec_variant_ops { irqreturn_t (*irq_handler)(struct rkvdec_ctx *ctx); + u32 (*colmv_size)(u16 width, u16 height); }; =20 struct rkvdec_variant { @@ -133,6 +134,7 @@ struct rkvdec_dev { unsigned int num_clocks; 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; @@ -186,4 +188,7 @@ extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt= _ops; /* 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.52.0 From nobody Sun Feb 8 02:56:15 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 5B1E83009E4; Fri, 9 Jan 2026 16:16:32 +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=1767975395; cv=none; b=Mw0SGqTpASQ3bjEhHdFseEIaO+58XtZpkOreQhsUYWDabIQL60AWZmDxE1ycAzSitnHwXsKM/FNB40weKeJSpk5NE7JfvdGpk4RgRlR8yrd2ZBx4ch33oCTZVPDul78uSBFu+lpBRj7HJLct1bizxuPlOnGdgdDXlAS62RLM5xw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975395; c=relaxed/simple; bh=Ge/9oXz5DJQ8HLTC68fGNfAGFkRkrp5zUzm5z1E9p8w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f20/F9jgK7M6f+0ssTBNdYXjuZgzOtLsYQSjJu9KPq3eNS8a9gHkPfW0O41B0qzndNoumAIEfHzg4kHhbZST6zIG4P7b30qvO2TbHukhtikGS7Q0hMpfTT1469jnAwg+NA6VFteW7i6smKJPLdFFTsznNdMbV/au3FTLALrvNtY= 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=HT9eBIaF; 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="HT9eBIaF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975390; bh=Ge/9oXz5DJQ8HLTC68fGNfAGFkRkrp5zUzm5z1E9p8w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HT9eBIaFMnga9SjWIKmAs/EkAs0Hy+wPWBkure1oKeS6nj4pFxN0kF1zztNjkWWQ5 zXgc4NmfvxocYzJ/nlla0PT3bQ9RB9vwMRF7rBtmwzHACQLtfTzxc+UZcLFsJc/k82 drX2UbbjRkB3aZbJRkXJfzj0PsvJJ8PkezP3o9RGQM/H2kHA1fYXTpcq8iH61hqTaD wvaF20lh+uCCabBsBDm/qtp0ppZW9n5RKe5/I1+k5dcTIZ4u1aL8VlclBKFtsswCNR qhG5ANfjNlh/zEQpmJ1xIilcnxi//VjI3wclF72frYosLCi+I1WfoG/RngRKIqcSka a/1Dc4xyfoyIg== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 5CC5B17E386A; Fri, 9 Jan 2026 17:16:28 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 16/17] media: rkvdec: Add HEVC support for the VDPU381 variant Date: Fri, 9 Jan 2026 11:15:32 -0500 Message-ID: <20260109161538.1294449-17-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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 Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 335 +++++++++ .../rockchip/rkvdec/rkvdec-hevc-common.h | 59 ++ .../rockchip/rkvdec/rkvdec-vdpu381-hevc.c | 639 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 82 +++ .../media/platform/rockchip/rkvdec/rkvdec.h | 3 + 6 files changed, 1119 insertions(+) create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h= evc.c 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 cb56a9a24392..52926c67d018 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -21,6 +21,125 @@ #include "rkvdec.h" #include "rkvdec-hevc-common.h" =20 +/* 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]; +}; + +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. @@ -120,6 +239,211 @@ void rkvdec_hevc_assemble_hw_scaling_list(struct rkvd= ec_hevc_run *run, sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); } =20 +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) @@ -202,5 +526,16 @@ 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); } diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h b/= drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h index e3099fdd784b..0d7498e6a112 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -16,11 +16,60 @@ */ =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; @@ -28,6 +77,8 @@ struct rkvdec_hevc_run { 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 @@ -38,6 +89,14 @@ struct scaling_factor { u8 reserved[4]; /*16Bytes align*/ }; =20 +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); 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..f4cbe402df24 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -0,0 +1,639 @@ +// 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 *hevc_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 hevc_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.hevc_ref_valid_0 =3D valid; + break; + case 1: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_1 =3D valid; + break; + case 2: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_2 =3D valid; + break; + case 3: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_3 =3D valid; + break; + case 4: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_4 =3D valid; + break; + case 5: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_5 =3D valid; + break; + case 6: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_6 =3D valid; + break; + case 7: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_7 =3D valid; + break; + case 8: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_8 =3D valid; + break; + case 9: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_9 =3D valid; + break; + case 10: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_10 =3D valid; + break; + case 11: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_11 =3D valid; + break; + case 12: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_12 =3D valid; + break; + case 13: + regs->hevc_param.reg099_hevc_ref_valid.hevc_ref_valid_13 =3D valid; + break; + case 14: + regs->hevc_param.reg099_hevc_ref_valid.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.dec_mode =3D VDPU381_MODE_HEVC; + + /* Set config */ + regs->common.reg011_important_en.buf_empty_en =3D 1; + regs->common.reg011_important_en.dec_clkgate_e =3D 1; + regs->common.reg011_important_en.dec_timeout_e =3D 1; + regs->common.reg011_important_en.pix_range_det_e =3D 1; + + /* Set IDR flag */ + regs->common.reg013_en_mode_set.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.reg016_stream_len =3D vb2_get_plane_payload(&src_buf->vb2_bu= f, 0); + + /* Set max slice number */ + regs->common.reg017_slice_number.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; + + regs->common.reg018_y_hor_stride.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019_uv_hor_stride.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020_y_stride.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026_block_gating_en.inter_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.filterd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.strmd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.mcp_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.busifd_auto_gating_e =3D 0; + regs->common.reg026_block_gating_en.dec_ctrl_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.intra_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.mc_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.transd_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.sram_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.cru_auto_gating_e =3D 1; + regs->common.reg026_block_gating_en.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + pixels =3D dst_fmt->height * dst_fmt->width; + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_8K; + else + regs->common.reg032_timeout_threshold =3D RKVDEC_TIMEOUT_MAX; + + /* Set POC val */ + regs->hevc_param.reg065_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.reg164_180_ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->hevc_addr.reg182_198_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_hevc_mvc0.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.reg161_pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, rps); + regs->hevc_addr.reg163_rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); + regs->hevc_addr.reg199_cabactbl_base =3D priv_start_addr + offset; + + /* Set scaling matrix */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); + regs->hevc_addr.reg181_scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_hevc_validate_sps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_hevc_sps *sps) +{ + if (sps->chroma_format_idc !=3D 1) + /* Only 4:2:0 is 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; +} + +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); + + rkvdec_hevc_assemble_hw_scaling_list(&run, + &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); + assemble_hw_pps(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"); + } else { + rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); + } + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + rkvdec_schedule_watchdog(rkvdec, hevc_ctx->regs.common.reg032_timeout_thr= eshold); + + /* Start decoding! */ + writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); + + return 0; +} + +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_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 804381d36bc4..395ecdc15a45 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -153,6 +153,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; @@ -226,6 +236,62 @@ static const struct rkvdec_ctrls rkvdec_hevc_ctrls =3D= { .num_ctrls =3D ARRAY_SIZE(rkvdec_hevc_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_hevc_decoded_fmts[] =3D= { { .fourcc =3D V4L2_PIX_FMT_NV12, @@ -398,6 +464,22 @@ static const struct rkvdec_coded_fmt_desc rk3288_coded= _fmts[] =3D { }; =20 static const struct rkvdec_coded_fmt_desc vdpu381_coded_fmts[] =3D { + { + .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, + }, { .fourcc =3D V4L2_PIX_FMT_H264_SLICE, .frmsize =3D { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index 4e9cd12fba3b..c723eaaef982 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -154,6 +154,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) @@ -187,6 +189,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.52.0 From nobody Sun Feb 8 02:56:15 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 29F14366DC9; Fri, 9 Jan 2026 16:16:35 +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=1767975398; cv=none; b=UThYAVETALXtktckVyAXb/U0x1QLy5qtntv07okwU3YNdQj/qpNMIKdbGpmTOeSMIOOp6/K1VhfvO0K4AjkFcMee+Vd2qtdBLAUy3CkeWFdTXY7X0Z1DoK8TLoSHca9C7qlpqMuNNnIb/e5VGAjxhgNH3dzlPBkkQcnPJw++Xf0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767975398; c=relaxed/simple; bh=6gWjg7AiFOPec1fFGRZNqldgNXs320oMu+YA6lBbOYo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pURp1uWrEQWMr0JGaOVU0f1lJhBr/5kG6up10kJgdOAlRVguqHk/iuPk8IxOTjkqitI5MZeu4Vw7wxaO57UTfM70HCxiPJsR3Lt1Izbhgf02MQnSyRzXXfPd/akAI5b0ygg3F3sbthWAY+tXSM1Ja3fhYmNpW5aBjC/ANHQxsyk= 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=CPVmVTf8; 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="CPVmVTf8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1767975393; bh=6gWjg7AiFOPec1fFGRZNqldgNXs320oMu+YA6lBbOYo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CPVmVTf8cPIORfzcUo4K8x4HWGuUxkKNFZilhONwiskc3Ts4Ck7yaoThOj96PC4ko RmVGHc6pVxbV8l0QTrGVNIYXkpIaSoggbUDWa8qmdwkNXJHnrovYuhtGDxs8vw/ytv Iz93cdopMXpmDmpGkzdi7HqcPSOsus8K/fcNcZ/Uir9BE3oWVseVnguq+r3hpGVwXI 6E8m0HGdrRM6Z9gc6E6fPr8g4wJmua0wl2doDgWWVe9IM8gxt99vgMsE0OqPRpDfl3 WAlbYeKHpm28TQD4XTEnGO3zUe0iDxFWGRjjp0HZ96w+OEDhVyh1VysFbqy20RFUGo IvhebT5Wt93JQ== Received: from trenzalore (modemcable014.2-22-96.mc.videotron.ca [96.22.2.14]) (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 3335117E386C; Fri, 9 Jan 2026 17:16:31 +0100 (CET) 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 , Jonas Karlman , Diederik de Haas Subject: [PATCH v8 17/17] media: rkvdec: Add HEVC support for the VDPU383 variant Date: Fri, 9 Jan 2026 11:15:33 -0500 Message-ID: <20260109161538.1294449-18-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260109161538.1294449-1-detlev.casanova@collabora.com> References: <20260109161538.1294449-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. Reviewed-by: Nicolas Dufresne Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-hevc-common.c | 59 +- .../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 | 710 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 91 +++ .../media/platform/rockchip/rkvdec/rkvdec.h | 2 + 8 files changed, 823 insertions(+), 48 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 52926c67d018..81f41bf661d3 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -140,56 +140,26 @@ 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_variant *variant =3D ctx->dev->variant; int offset =3D 0; =20 - transpose_and_flatten_matrices(output, (const u8 *)input->scaling_list_4x= 4, 6, 4); + variant->ops->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); + variant->ops->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); + variant->ops->flatten_matrices(output + offset, (const u8 *)input->scalin= g_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); + variant->ops->flatten_matrices(output + offset, (const u8 *)input->scalin= g_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, + variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), 1, 8); offset +=3D 64 * sizeof(u8); @@ -214,16 +184,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_factor, struct v4l2_ctrl_hevc_scaling_matrix *cache) { @@ -233,7 +204,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_factor, scaling); + translate_scaling_list(ctx, scaling_factor, 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 0d7498e6a112..96521d723477 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.h @@ -97,7 +97,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 156ce381f068..89b70ca27127 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -567,7 +567,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 f4cbe402df24..4fbb30c7af65 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -593,8 +593,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); =20 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..408374107423 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c @@ -0,0 +1,710 @@ +// 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 HEVC 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_block_gating_en.strmd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.inter_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.intra_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.transd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.recon_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.filterd_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.bus_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.ctrl_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.rcb_auto_gating_e =3D 1; + regs->common.reg010_block_gating_en.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.reg013_core_timeout_threshold =3D VDPU383_TIMEOUT_4K; + else if (pixels < RKVDEC_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_ctrl_set.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_validate_sps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_hevc_sps *sps) +{ + if (sps->chroma_format_idc !=3D 1) + /* Only 4:2:0 is 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; +} + +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 timeout_threshold; + + 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); + + timeout_threshold =3D hevc_ctx->regs.common.reg013_core_timeout_threshold; + rkvdec_schedule_watchdog(rkvdec, timeout_threshold); + + /* 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; +} + +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_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 395ecdc15a45..a5cf6f3240f8 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -499,6 +499,22 @@ 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_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, + }, { .fourcc =3D V4L2_PIX_FMT_H264_SLICE, .frmsize =3D { @@ -1461,6 +1477,78 @@ static irqreturn_t rkvdec_irq_handler(int irq, void = *priv) return variant->ops->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; @@ -1522,6 +1610,7 @@ static int rkvdec_disable_multicore(struct rkvdec_dev= *rkvdec) static const struct rkvdec_variant_ops rk3399_variant_ops =3D { .irq_handler =3D rk3399_irq_handler, .colmv_size =3D rkvdec_colmv_size, + .flatten_matrices =3D transpose_and_flatten_matrices, }; =20 static const struct rkvdec_variant rk3288_rkvdec_variant =3D { @@ -1565,6 +1654,7 @@ static const struct rcb_size_info vdpu381_rcb_sizes[]= =3D { static const struct rkvdec_variant_ops vdpu381_variant_ops =3D { .irq_handler =3D vdpu381_irq_handler, .colmv_size =3D rkvdec_colmv_size, + .flatten_matrices =3D transpose_and_flatten_matrices, }; =20 static const struct rkvdec_variant vdpu381_variant =3D { @@ -1591,6 +1681,7 @@ static const struct rcb_size_info vdpu383_rcb_sizes[]= =3D { static const struct rkvdec_variant_ops vdpu383_variant_ops =3D { .irq_handler =3D vdpu383_irq_handler, .colmv_size =3D vdpu383_colmv_size, + .flatten_matrices =3D vdpu383_flatten_matrices, }; =20 static const struct rkvdec_variant vdpu383_variant =3D { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.h index c723eaaef982..a24be6638b6b 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -74,6 +74,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) struct rkvdec_variant_ops { 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); }; =20 struct rkvdec_variant { @@ -193,5 +194,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.52.0