From nobody Sat Feb 7 13:05:44 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 5C19B27CB0A; Thu, 18 Dec 2025 23:28:38 +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=1766100522; cv=none; b=deajQIdtEWpkgN4k1PWfHw+xZPHju4kndiG0kvjmxzZfDzLQS2xkzpHMRkEPWSarR/vxsbYFFOdcc7xiYM+mIVflRlBJp9c5+UEGfLqkWxzn4mcTjy7TzesIl1+Mf1DB8Svwxe6ORPEIRjrs6bj4advbm1vAUMSra4YTlcIBmUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100522; c=relaxed/simple; bh=ZFtwY3pGQNpQabHwTVr1jPHoPNjRjHnnXc9mZgyYGwg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PTGDfYvxFxbS8ywNtrXPAmyPtFT3s9wHIHz35EuGdBKde/8CktudiT2Y/1wjt3BNSG9PXlHzCc3kVqnB9SCmFHu2WhC2EaTcktDyp8YAGLPXO6eWpNQn8CSwkRGQCu49XFbnH0++NRqUvA0sQVmJyCs2Gn39owh0s+DDcl2kGvE= 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=QbnPNwZY; 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="QbnPNwZY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100516; bh=ZFtwY3pGQNpQabHwTVr1jPHoPNjRjHnnXc9mZgyYGwg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QbnPNwZYps/wx8xmvasy4NsRdaSNDaJlZmSEDPB4qV6fq+53pm39rJAAxz+ZHBfcZ liyAaZPCh1+XbAxikPdxnxX1p2CorSzn5IPgD2MKKmp2XyjP+QiAcqU/rg1KOcLvcS gr4qhuNXGt34cTnCW6GX37iQYLA9jLUiGBWoWFMACfxQS530j2lhaHdPW3eaZrQM0F +uYluSQIDXut+v/Pk4sidugl6m0lKFkd0hf5zIjkUGteySWzfUVBi09hg46LNDWVto WWL5NpHqo3AvSgqtJMoJYStAb0WUO58Z45hjfGrNb+LSz/2fQVRC+w9ChH1rFJm5re GQVm9rQFjrbsA== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 62C4D17E1122; Fri, 19 Dec 2025 00:28:34 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 01/17] media: uapi: HEVC: Add v4l2_ctrl_hevc_ext_sps_[ls]t_rps controls Date: Thu, 18 Dec 2025 18:28:11 -0500 Message-ID: <20251218232829.337811-2-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 --- .../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 497ae74379f6c..3b1e05c6eb139 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 c41693115db64..6182b4e2d2ee0 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 c8baa9430c14d..82c8b52e771ce 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 Sat Feb 7 13:05:44 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 DC9D8299923; Thu, 18 Dec 2025 23:28:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100522; cv=none; b=V2PFzpDNjApshatsoGKREcqZyBZ6B4Fa2lv/ccE6NBt7QxZWieLprDxLGU0C4GNUqjqHnePVeIKvgGsecpfzFnkxQo6STp66zger0n27XjpngQvVy++RfqztaI4k+74Oz1D8B8yvXlgBrVIiasKlKlR4Nlsdv3QwFcevVReKNfY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100522; c=relaxed/simple; bh=F5qZAL3164R+JVuB6FU6TEMRwfXL4JAhA3VAndIF6KI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=un6VffcSKJ98f7v5iQReM8Ft4OGJGtM53K/pQFOYJ/buxF4VcfJl5PsYuZxNTJpLSr0JKLNdTMb822KagHQjSfSidpQFpN2iK9K3tLCdORkxZA/1xFqF7trMdlvFI3pBswRP7keECXSkW1w70vXigJx6VeRelLKuLKRZNMdbdSo= 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=ERYfxJtm; 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="ERYfxJtm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100519; bh=F5qZAL3164R+JVuB6FU6TEMRwfXL4JAhA3VAndIF6KI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ERYfxJtmKxoRyL4oYUzUoZzCeBmjOzblcm8ILY78vNSlqdnmCi0BPscaUwduDugsJ UwrrTUdmR/3xTjO37FZsxKExmAr36lzzUTNfh32CDcT4UKenOIpphJpxGe6RnNQ2yE OFVgy1TQ8Vqh+RSjjNl7jQ9cgA6kmb8MkzIctU72aLfssFIQAcqabBMfgmkn73pjpM Tu9eyllDxsO+OA1gxTMc2M8QZmRFaL/6RmoLJVFmZaH+ZdiQZ9XTM+Jc0guHW/zifP U3qx5nw4eFYoNWU46r+nlbgJHvjF4zIdF4E0vYDyhvdvzRMmoZIlRe07iwMs2rvGcz lMKb2N74A4ucg== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 F28EC17E12D6; Fri, 19 Dec 2025 00:28:36 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 02/17] media: v4l2-ctrls: Add hevc_ext_sps_[ls]t_rps controls Date: Thu, 18 Dec 2025 18:28:12 -0500 Message-ID: <20251218232829.337811-3-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The vdpu381 decoder found on newer Rockchip SoC need the information from the long term and short term ref pic sets from the SPS. So far, it wasn't included in the v4l2 API, so add it with new dynamic sized controls. Each element of the hevc_ext_sps_lt_rps array contains the long term ref pic set at that index. Each element of the hevc_ext_sps_st_rps contains the short term ref pic set at that index, as the raw data. It is the role of the drivers to calculate the reference sets values. Signed-off-by: Detlev Casanova --- drivers/media/v4l2-core/v4l2-ctrls-core.c | 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 209bc05883bb1..f11255255c74f 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 ad41f65374e23..167286c9e4243 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 f84ed133a6c9b..e9f1fcc4f8409 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 add08188f0689..5efaeb74ef92d 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 Sat Feb 7 13:05:44 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 F00A12E9733; Thu, 18 Dec 2025 23:28:43 +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=1766100526; cv=none; b=NNy+D0iya2Kij8hK4B8U/x23BQLlhuMM8mdWiRJhj4N+Xme18FZ1HB8QMYSAr+vyqW3qX2ts+6I7UpuKhCnMLtEjVtrBWyjlDF6Eg4tZAi/NkTRBPcxrre+JuYibbIQIIK7OoBdRayYVtLt2flsXBiWnXee6uK5QjEQsPvyNFkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100526; c=relaxed/simple; bh=UrByMHK8ShbXkuBF6BQYPAnZlDu/LbP3faYfzE1pIaE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k1wfyOgodCqqiUSo48yxrSQWScKdjDBnwxijj+J+4PAzoHB5jP1a0Q2BE9YRH3df6Fty9W3lL2u0KrpM0tp7hJPa9VXdxcxxTjHr1OLnBNY0pqpvCDYHvdH5qfy9NXq9EafHEyNw5XSdVYfVnbD0n7bPHjaq2awFOwlS2YjD4Qs= 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=Diva4TaP; 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="Diva4TaP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100521; bh=UrByMHK8ShbXkuBF6BQYPAnZlDu/LbP3faYfzE1pIaE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Diva4TaPMtTZrpkKEOeTd5ksH8dWic4wpchbONUPRmL1Aak4vv+L1vCXlnRe6WsRe WkPGVZ87zJ9fChNXSuF65yEr6+nEnpZ89bTw2PJlFKbZj/9ZmSi8PNYMo2JhiYE0BB XneZoj4ycrzN+ymrZKm/s6kFJgjzMHUXNuOqi4BN6NtC9dRYzlUEcTBJTiTEsvox5y 4I2gSe1mYevU2oPu5iN8cJHY4VnJEppkWYkd7m5aDMzN2zpvHyWOXpewtB4IrzMfWU jTj8S2aGKjaOnbvyaKTtHqkA7ps7mQ4qmKP8HZm58HyXzWaWtrXrr9m2Xue0Insl0Y 1PEK9w+8FvWRQ== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 8CCFD17E110D; Fri, 19 Dec 2025 00:28:39 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 03/17] media: visl: Add HEVC short and long term RPS sets Date: Thu, 18 Dec 2025 18:28:13 -0500 Message-ID: <20251218232829.337811-4-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 --- 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 d90b79de8384a..6bbf937570478 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 c2c2ef3a8798c..6e7562e555bb9 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 837b8ec12e975..963914c463dbc 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 Sat Feb 7 13:05:44 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 7DA45298CBC; Thu, 18 Dec 2025 23:28:46 +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=1766100532; cv=none; b=mgsWKgeWTovR/EH4MmpE6Gqe+/beoNh/X72mI+bDATbMdCHfg+pW5qRYNM0wXhmMTJsYbr3KQOBsIWFXbMSgylSREBDUBpbD5XGsIwnS2h1GLrkT4XveKgVqhSoo3bZ7w7Go2s0wg2ZEPfjxKqzN8mrSANkEUZfDn19BhZuyxmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100532; c=relaxed/simple; bh=JituC5dB4st/2LEUphdnXa7V3YSY62tUNO0WD/LO27s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EaHgzrMRt5Qw3oPRsZgnDvwqj8ccnT6nh77nMltavK9Iy3beOGJpTIIYSSmctl8p5Zmd0taiKeorFvpzmwNsKih93DFqoYs2HShNimXDOzFwSHzCAcAW9HZRDFVnYajCTiJRgHOWzkuKL1uKH+T9F7RiuMnatTjfV34kS6KTb5E= 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=S3B04ONx; 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="S3B04ONx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100524; bh=JituC5dB4st/2LEUphdnXa7V3YSY62tUNO0WD/LO27s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S3B04ONx4bXvPdnZOZeNxslmWTetPI9YRzpjtr7JqOCo8x860e4NesiFVyXMsRPlp 5axERYAopV0Jf24sp3cgEe8IYM9O4A7Pnkz2io1bv2ZlU1NVTRuG3kdY58O+RivljN KEm4lpCAqCQ3KwpAN3Sv3bEfptptjdf1fkdHM9GNvAqTRR5VjpPEt7lQfDfZTkVVkY k43vWIUi/O0/6qNQOqG9yjPzlss0aRqCa2XeBQEra7ZFvG6o3Vrn6V1Rj0b8lOe16L xJ8XIhj3+EdROiw0zeKL1+2pVWDGyPnFkIVXtg3E4++Gr82WKfwct7Ip8ffNc1vd8Q +Y/yzmtpj5DtA== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 2845B17E13D0; Fri, 19 Dec 2025 00:28:42 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 04/17] media: rkvdec: Switch to using structs instead of writel Date: Thu, 18 Dec 2025 18:28:14 -0500 Message-ID: <20251218232829.337811-5-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 d14b4d173448d..68e20cb81a885 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 fc7e6a260b0a7..2d9e0e947a6dc 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 c627b6b6f53a1..1af66c5f1c9b6 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 b4bf01e839eff..ba51a7c2fe555 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 5af9aa5ab353b..776149f871b09 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 566e06fa2b1ed..f35f6e80ea2e3 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 Sat Feb 7 13:05:44 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 ED4C828CF7C; Thu, 18 Dec 2025 23:28:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100534; cv=none; b=IuqTpGoPgw/0xjmxof21AfsT6kwSUh09T7trptc2V+6rHB1R4UJShV5iZFj3SLOWGKe9dfB0T1lUMN8kaGXsyLQGu0SdRG0bWeOZVvW+Oqe0VqdPrCP4gRbMYujxAcsusj97VvcFv1mJ3EZW8I4suGA5Bh0BRRG9Uhr8PT0psSE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100534; c=relaxed/simple; bh=5A9AMgqNNaDWqNk0M31a8F5/qHEGXvSzCMkcaKqJxsI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lBQq+f2HyWMdsYksnSxM5pizlVzKG/JdYrjVs+CD2Cnpaek44FqgQ8IQ1Ktg5aLd8kfrMCSP97UmSKIGlAKRx4LPQVCj25qsxaeA/dInu18lqmUxjom+YWovJjiMaidqlzR/lFkWhlQ3QbWyALsv+17462nI8UMAANaATwnYh2M= 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=mmo//D3d; 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="mmo//D3d" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100527; bh=5A9AMgqNNaDWqNk0M31a8F5/qHEGXvSzCMkcaKqJxsI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mmo//D3dC0e2PZ4eeY9eycyFycwDpruAC230Ye8ong3UIiiZs0eJlUUZbD3+QGq4e ft2MMucnqA0REeasR0LQul1Q20YSliBRFporCVaidGd14y5ViZ1JEj/VpeOJ++65nj Dw4MOpYnE0UDP+L5PuHhZMH7KjltwwNR7jC+ZgBhcr+2rk0Il8961ijcnrpRjnM5iC tg9/ExM7r8ZMWMUtMd8KleZOBwsLi82Q8uY1He4oDvRmOWFQqUmn+iYp/+zEnA71p0 5tqOMHQxFaCUTDkBnvD0cNZr2XaBfEGCh2bj+yLahVQF5maonMccfh55sXFtf/uY1/ hFHKODN4bJh+g== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 D192117E1122; Fri, 19 Dec 2025 00:28:44 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 05/17] media: rkvdec: Move cabac tables to their own source file Date: Thu, 18 Dec 2025 18:28:15 -0500 Message-ID: <20251218232829.337811-6-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 a77122641d141..a8ff5e3d7bec3 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 eac4ea604949f..bc87f59636ea1 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 68e20cb81a885..088840248a76b 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 2d9e0e947a6dc..dfadb9a13c9a8 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 Sat Feb 7 13:05:44 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 1CEA82BE029; Thu, 18 Dec 2025 23:28:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100534; cv=none; b=Clv9Hv0zKZHbMkCHYZLwGs4xt5JiJuXiD2eYfZpb1ieyXMh9hp0WyK64lzBcgc8KHbjnwmvtCkM8eqFGrwy6SdRLC9D1MV3PDgFqkde9Oc9Z2w2wnTLq82MtpXU8q4Q9dsHQQVWIUUhrfEjpYzDLXJyTv4aSX0BoxY1DbFByMEA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100534; c=relaxed/simple; bh=ysnLg7XcbLUG+pEfPcs8iI3XF5Q2cZW8GRIDia1EWfE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VTAeqRmtrrj99CrxoO2Q9J4MmH9rkfwpdCKEStW8yOrmS8nTzOdXaCkB4ZESzsrGu5yuEUxdhPR0sK5m0B1zERvS8oFitUqaoBch+XQgSCSg+MFodvonVzVfX65Gx+kzTQ43ZrcFuNgm5El+SDE7yG20mDiSUEym4m5Xwc4DQKs= 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=qrzbh8PV; 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="qrzbh8PV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100530; bh=ysnLg7XcbLUG+pEfPcs8iI3XF5Q2cZW8GRIDia1EWfE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qrzbh8PVhX4zpYLpsb5xk4vBmxInjDJdAUvH0GrYxKdHWhTayiT3dySKRz7L9G19J VoU9ILnjj1gkpnuRCotorfVmtA1/fQJtjnMiIXRa7ZRYorVX3zitMUqgZxlWMtOU2W ke7c04C1y42mQi3NqzQZk8jCwgqWGgvWr3OMIWHq3P1epSDB5DdMSK48qy91RW1mQU 1YBD6BIk9GgUANmuPwDYxbOVluearmVPaw9kAhZf5bIVQUQIZQ2UgVfYSZmt1H6HVG AwbYsi01kFfMTz37HhQLOTeg4608xsrK5BAS/q7hVIw5i58iLg84+o3FLW6O5IC65Q +CPGd0h+aZDtw== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 9C52217E110D; Fri, 19 Dec 2025 00:28:47 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 06/17] media: rkvdec: Use structs to represent the HW RPS Date: Thu, 18 Dec 2025 18:28:16 -0500 Message-ID: <20251218232829.337811-7-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 088840248a76b..fd941e9262796 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 Sat Feb 7 13:05:44 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 892B6299A90; Thu, 18 Dec 2025 23:28:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100538; cv=none; b=p78mZ0i6bIqbg+CyOZiOu+U96ppcmfLoAIot6PcsNsAlwNziyHRMb46sCRhDsmxZOxhDW2+1zLgP3sR/puUbeYB+JGP21E8BVbXdhSle5U45261/ivZlM/li0uVe1jCZ35z6vyaGKElYX6HShNKTdSSovMWeLAvAemjKNdXhrx4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100538; c=relaxed/simple; bh=5Q+wqiRn/AlnjwK0Ia9EZOs6BfJzHW45SrcKHzwtE+E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CeVtDCGX6ctYLOtCpPxfwrTwA7/wo6mBcoIkPSJawQwD8eHBMrtm+ulSYU1aRp4GXy9ceoZk3uiBXbZwHnpAVxCqtakDKpo7/OvZJtJVL8RVfCzLed0DEYv1Xrmto7JhaEa4IQLYn3CYaJGJoPoecQpur8lZJbrEVRsmPOoE+08= 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=qXA3tmkT; 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="qXA3tmkT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100532; bh=5Q+wqiRn/AlnjwK0Ia9EZOs6BfJzHW45SrcKHzwtE+E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qXA3tmkTKkbdKGPCjA3OA5ddZghimO8JiU8vhnd92u87/lRPb0ETQp4FbzgZTNsFd hkqIxduKH8vDYChMthiUy28DKc7Ib6ouIHJuqgRKzDOdt+uLq4BVeJ6qVN7F+PmeUe N36/6THI/6EqviPjd5Mo9W+kz+gW4pjjOTAL3O9UUJV6ZHcw92H1YuTKdvuIgx3fyD tmvFUVVeHpEVjEv0z+XAWWpdYPvHjHBFo/Yh05MzzSTwD4V6qs2oX+Wz3EL0P+xIwF WwD6d/UzYexwoPBxux7guYb2olu1bg4V3ty0+De851GrdwXhBILFkGnddoSSJe5dw5 FQdasp/Ge1mgQ== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 4DED917E12D6; Fri, 19 Dec 2025 00:28:50 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 07/17] media: rkvdec: Move h264 functions to common file Date: Thu, 18 Dec 2025 18:28:17 -0500 Message-ID: <20251218232829.337811-8-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 a8ff5e3d7bec3..d2ba7a7c15e59 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 0000000000000..e28f063944705 --- /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 0000000000000..bd0c0081365b1 --- /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 fd941e9262796..d93c7953692d6 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 Sat Feb 7 13:05:44 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 27E8E2D5419; Thu, 18 Dec 2025 23:28:57 +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=1766100542; cv=none; b=lpdrf8APnvAheaA85Pbisu/St9Y81bwc7QuXNwQczfrC7XWyTCfnn9lfhUV8oy3fqN8SGWFlKbVnEqodbTMUkvKk6+qakVIBCKvRCRwuMvy8jFDrod+hy9vv8iGpXG+pY9ePGHOssoFZZh+LApvNii3kuXK1+lGrhZ1RnDGwQtE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100542; c=relaxed/simple; bh=CBWACUaja3Rmfd7Ucv0xM+IAeSe4majq/0lp56NIRZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VEGKNdkQRm4kHkljOXg3O822aR4Al+aixtvs5qjynIjnos9ro7uROwXurrjGGhRCjlCoWt8TXKay5cMPkWAEW/Lp59tVi6XEpl0FE2XBNWYxUOIaKXNofh7dvosbvoglN1M97zA9KDJ7hkTfQxnijNk+rI8eMbahEq7l8YjUVZU= 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=G1WTFJq0; 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="G1WTFJq0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100535; bh=CBWACUaja3Rmfd7Ucv0xM+IAeSe4majq/0lp56NIRZQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G1WTFJq0yosyKbk3AAtwNzRm2Jew3o9CUvi4T42YI2CMN6Ty3oldLQvZ11QjTzoQR J8mFASvtXknM+UPf8vG5oj+A458Xcei91LetPotaOQKG0vrsVQoZcHqRbv7Y4uR0/7 2/1RkcSvUKCZigQJp668QTO66w/nymIC60UIqxr7GDak2mDOU8kEqLzVee07rg+zV2 HQppA4GuJVubj37QmOiYd6w2oxwc1Zm11jQ872Rt8TG2m4FmHTOijMFtinTq1TbOC3 aNBK7FCP/eb6K2z59gl+ql2mvMojnmnZgNUr0XJ7RR1ewD2lzI10Zbo2bbYWXk6fRK +9Pnjg0wrZlPw== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 02E4A17E13F9; Fri, 19 Dec 2025 00:28:52 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 08/17] media: rkvdec: Move hevc functions to common file Date: Thu, 18 Dec 2025 18:28:18 -0500 Message-ID: <20251218232829.337811-9-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 d2ba7a7c15e59..1b4bc44be23ee 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 0000000000000..cb56a9a243927 --- /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 0000000000000..e3099fdd784b1 --- /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 dfadb9a13c9a8..156ce381f0680 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 Sat Feb 7 13:05:44 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 EA2092BDC03; Thu, 18 Dec 2025 23:28:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100543; cv=none; b=MDrY8ZO2no984lJgMf9dKM/Gn0sIsTMMtARP/po4iLDBuqeEBOBUvnqCu0RapFErVRPdPnudfEKu751DkYwvhkv6Zi6qKaGzMEkQixTLcHWOwreLL49M9RQkHwPXQqI0TSHgGZPx1GQQj1V0QG/s5H+7G9Ui9SAytsAMlQwMB58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100543; c=relaxed/simple; bh=xp6xDIEHykUYdMxJOPXwKgmoay07/AFj8558RYs8On4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dHYNo6bFD1nav5fGCYnGLLDyJvJTJIH1WNtDq8wZZe0bvZEMNJTo5u+VAh9LfVJbhSgkfUgcpnsbv5FC1xtkMZgMk4in+ipvfHXrcWGtlwOYb/c4QW4qe3mdopMxzn5f6RLQOufmJh44i8BW8Y1zajyXKxj+MR4kJ0NUXPWsyM4= 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=CkIsIezF; 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="CkIsIezF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100538; bh=xp6xDIEHykUYdMxJOPXwKgmoay07/AFj8558RYs8On4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CkIsIezFUaUlL/h95g4/1/tb35KR7dj61rOtEKf9Ywfft3I5zl7MYvBnF5MfudJCy GdQXT/VGYZWmaKb/xefR4LLFMR1UGFtB+1I4VmGB3gsCZODyYlDnBBJkXELyfZg1XG Vch2yDKED+fUAYN2D/vkdTwgQ+x3IYZEkoFgp/2q6lD/X1rWf+toD9vw4lRRxFmcKC h4Ws/M7RvekzK0+eOJayrKyszzxypTCZrlDcVeBHE1/cNoXxCn0HeVFQRQkHSVdkls aVDTM02IRQai0fpwUSEOWuJta/7W4CA9eCbwk2IdrtzfXBDsNG4JUoKjhTHuaPmIvR MCJWtN5gEBlyg== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 AB9B417E150B; Fri, 19 Dec 2025 00:28:55 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 09/17] media: rkvdec: Add variant specific coded formats list Date: Thu, 18 Dec 2025 18:28:19 -0500 Message-ID: <20251218232829.337811-10-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 --- .../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 776149f871b09..92b1c7b62bd20 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 f35f6e80ea2e3..8c4f96ba5cdea 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 Sat Feb 7 13:05:44 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 74CD930E0F8; Thu, 18 Dec 2025 23:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100546; cv=none; b=IaXUjzQ0CkUbBH+Z5inbXQ0QV2RgOy3uNZR3b1xkPWE9oiFBXe0gH/8UuiLeq195QWGkxqU2KYdQKgG96BjcTZ07iq+Cvhbdh53ljaWQgrrO7F1qFV2tjXFVztYr9byFPBWzVuExHiBZlmbv/N2qJJxSEqLWx8PAVY6lSIbFb2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100546; c=relaxed/simple; bh=iQdVu9Nc7nnbdGNEWXH4PPnHahuT4xV7sxLeoDje+L8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ie2cY4f8mEywuC3N++6jn5YsvFjwBvqiIBtAPQTlHGrrfyHzc6d5jKEsvUxyWwH/dWKqDpGmp4FdI0Ui+6VJVimFql0MRgBDaZ8DsSlFPm5qnkJrnvy+BeMTaMm7SHzGehdps/bHfEWLaPn/rK/BBqfQqixyS1thsmWV+f/pmsQ= 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=fcURz2ku; 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="fcURz2ku" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100540; bh=iQdVu9Nc7nnbdGNEWXH4PPnHahuT4xV7sxLeoDje+L8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fcURz2kuN2JXKRNhPgjCFb7+8M7agxjjphysKI/54WkfXvpGC5yYs9Q6WdfxeaQhb CLyXwWFQ7zPd0nVyvm6SiWt7bsoxTbSl60Rj/b2w4NUF1GMEEwVbB9AP3RpcjtYd5P 8rRDq/58mrcB+vxjAn55TwfiD4E8IbsA3Xaadi1zXpeLJngTT+Wpgco21mTXCPI9Xe 61sVpz+MaXE3MAGqbt+Jct3XJz5l8x2R+GECgLUFB9WXxaoJSgXI7WBLC3Q7nDYQck JOpXj2ZYGX88xxFdqqgwXUw7aHmmaX+LSYepOi/W+kwR1/eETQu2vyRMkurKKj6Z/7 /a26r6OKvYJlw== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 601A317E150D; Fri, 19 Dec 2025 00:28:58 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 10/17] media: rkvdec: Add RCB and SRAM support Date: Thu, 18 Dec 2025 18:28:20 -0500 Message-ID: <20251218232829.337811-11-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The RCB (Rows and Cols Buffers) are a set of buffers used by other variations of the decoder to store temporary data. Those variation come with a dedicated SRAM area used to store those buffers for better performances. The buffer sizes are either the width or height of the frame being decoded multiplied by a documented factor and can be stored either in SRAM or RAM. A fallback to RAM is provided if the SRAM is full (e.g.: multiple streams are being decoded at the same time). To manage the different kind of allocation, an enum is added to the rkvdec_aux_buf struct to specify how the buffer was allocated, and so, how to free it. This commit is in preparation of other variants support. Tested-by: Diederik de Haas # Rock 5B Signed-off-by: Detlev Casanova --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../platform/rockchip/rkvdec/rkvdec-rcb.c | 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 1b4bc44be23ee..3d75103e536d2 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 0000000000000..fdcf1f1773797 --- /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 0000000000000..30e8002555c8a --- /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 92b1c7b62bd20..ff6a09e45462e 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 8c4f96ba5cdea..751f39afe7e2d 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 Sat Feb 7 13:05:44 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 48C5930DD13; Thu, 18 Dec 2025 23:29:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100548; cv=none; b=AD1BRo4Os7HBrUPSYj52gU2vDqL7j4Ao3Bhb/tQIe0y/0DjOAdR98jAd/JTHedJ+uEG3D2s9+RuLHrddDAW9JamV+ARqGjkv7WcsLY7Uc+FydpbPJSoMtMTLE02C7WSXgokn7+DfYh0Qe5TdgVNnHVuxDNOhiT/MnHORFVjZ8cA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100548; c=relaxed/simple; bh=ZEGBz1FCVl0fR3pfegZGsHwXpHzV3xPQaH5hpaCSvk8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=twdEyyhUmyX0mRIzF7QLGpBIS62pV6J3AvxVL9KUsXK3dOc3C5BcDQ7RJRb5pC6Pvmyc2kzJqYGpMxMdPb7LedT+d5oU49smAIuwK27CfyEvhVOFOM1JqFdVSivJY9J+haJGVMogyw3SZchmC12JvrgJ1vvGsFS8tiVQHBn23Yw= 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=PeDoACR9; 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="PeDoACR9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100543; bh=ZEGBz1FCVl0fR3pfegZGsHwXpHzV3xPQaH5hpaCSvk8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PeDoACR9kbfy2ApM1GuJcbGKyz1ogn8hesnEovlHT+POFJW7JoEDB54SFtX0xGl7N pc3OOyM52Go0sZMiCFTWf8KINVMJKHqx9d0FgnICs8AYAlfnnuHs7Te4qIJL+bvw/Q gLI8Lc0wCKHlldbfx9LLCUfSKrmydMfsb7+fZ2Rw7quI4x/Ud2nO2ls2hHs5ovh5Jh rJr3U9xg5mrVFbxAX1NJoND05b14o3ZORVcnLiS9gMHLg5rDN7j6GolwXXbQF8JcUo JFgjsxX5OPFUexqfk1oRmmlSd7fjB2SWzc/cCWr8tg6FUNWhgIem30adfYztCV6ZBZ 93k2XWGmZ7knQ== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 11CA117E1520; Fri, 19 Dec 2025 00:29:00 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 11/17] media: rkvdec: Support per-variant interrupt handler Date: Thu, 18 Dec 2025 18:28:21 -0500 Message-ID: <20251218232829.337811-12-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 --- .../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 ff6a09e45462e..174536ebdcc7c 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 751f39afe7e2d..faabedd2b9d88 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 Sat Feb 7 13:05:44 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 F188232F74F; Thu, 18 Dec 2025 23:29:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100550; cv=none; b=gZ0qCTYiKA1RK0oT8U0X25iagyzvM3ygmRSNh9SneGo8XOmiXdnog/o+OyJekSuUTF/jdtMipkIyXLBrqyD0f8vTRMUJCjV7ZBl0gMLe8Tpx7gu7BDkqcBU0UiG6pPMzfO6W/uvGImDkvZJsPHSlVHgZrP7Mg8WAS7awJtgUSIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100550; c=relaxed/simple; bh=DI87bIxkXahIW/0Dwt8uA9SVyJRKiXbphnxwImkvZMQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MymdwO7iXPzgREIDgZzSMPyUXG73qLv+0DmhnzC6cVCFgDLsa8GOYqZKJZ/IW1hF+tLWKqmNHqzgZgEJTJs1WRCUsmKacDorF3QFcL2O73y5p01zf9dg+3HbATBSRif9tmPppwNu/Uzbnf6TW7OIpEk3YjasWs4SNMQvWEnW5Zg= 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=h12XFL5f; 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="h12XFL5f" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100546; bh=DI87bIxkXahIW/0Dwt8uA9SVyJRKiXbphnxwImkvZMQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h12XFL5fgMJsVq4UXFNraWXNrWq07vx0PVFlPsy+MTNCnJEarMFRrRPTXJD/lycWC O4ypFUiLhhTFMldFAUKnlftrRLLVHNQcQmOWsbP8drAXG2UuArAM32WN7QJ2rMG9bN HK8tyuXcCHsSQXgjbyplOwBd6rt8puDAezfmucYOf7s1swS7moJBYDv4kBo7maZ06z kAUWFXJoQGdJuJ1GlWILOdGTd6QYZJ8qoguxwasB/0kMWCV8nzCN6VB6hlZ23tlsat RslsEDahc9dXpJMsahbanxkHMVENBkjRjOp/waos98zVaMIHheTPOEWoRwnyxhs6nM /PUDfz3xic7/A== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 BF0AB17E1543; Fri, 19 Dec 2025 00:29:03 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 12/17] media: rkvdec: Enable all clocks without naming them Date: Thu, 18 Dec 2025 18:28:22 -0500 Message-ID: <20251218232829.337811-13-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 174536ebdcc7c..ce96a0470d4d9 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 faabedd2b9d88..7766a79caf68b 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 Sat Feb 7 13:05:44 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 CF71233120F; Thu, 18 Dec 2025 23:29:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100554; cv=none; b=j9a/yVKRg/hj2EVuYzjW8nIB+t1K3z9IbUrNqH5SX+tARy7dP0s4Q6d+sjJ91p37ng4/ubH2rMdU9uEmFsEMg35aJouxJiCD/W52wMesUXLqt1jo9i9HPf9xwbY4e9yu+6o0UhmNp+KOu7KTm+iD368OVfsNitiFOtUuqJoFOC8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100554; c=relaxed/simple; bh=xi16N8WVlbn1t4okpwwS5XkaC5CK7jACWFwAtCe61Pk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UivkwXwj5jKlRBUdgxwF33Clu5IdDnNvtrUy9oZ2opGzGsZE7t768Qs1RPKk2xeSKJm7qJV6C1qUtPlvzZlgLc8DjbY2XSqyw9EjeKFwJfqQgxCrIDNW7WB0cyzpnq6kCQfCejMvii/pq5Sb6Xw17ikeHskjiicJwzMfm8IL5Xw= 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=gjFku5dO; 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="gjFku5dO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100548; bh=xi16N8WVlbn1t4okpwwS5XkaC5CK7jACWFwAtCe61Pk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gjFku5dOb7AYDq68zr5faMaSvGdivlS44lZHDaCQjzEE1aX9clZMjvzbhavuRpRZK TQlBnKawuwIMU0+iAXYRTzs9RyRbXLaf5EIPo3oYUUmKMki5obV6fGCEA9QEL0ZnZv VvfqceGPsAAAJYfgTCW4BvdWVOaB4eDt7T/Szie4dxwTXHns+XE7+1K47iYeC6LoJL W1t0SWKQlOuPCI0wtegxyfZQx4jtBgZLjrTMTIN6lcNmcHVvCnr3pqH5Qcttlvs8I6 31pXLFL08mv00YrV4BLBfR9HPseXO+89oOL++t00OXtq3WHu+aACx1JiVgnY1zpgkT pomQIipOGGbpQ== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 722CF17E1546; Fri, 19 Dec 2025 00:29:06 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 13/17] media: rkvdec: Disable multicore support Date: Thu, 18 Dec 2025 18:28:23 -0500 Message-ID: <20251218232829.337811-14-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 --- .../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 ce96a0470d4d9..af2eced900269 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 Sat Feb 7 13:05:44 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 8468131283B; Thu, 18 Dec 2025 23:29:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100557; cv=none; b=Qx8+OaHhOLR+Yc14wfywcqgZfCy2GaleJ+Po8XZ74Q3y+6zuomen6Qqv31P479kFz6HHNe4EGvEnXskuo5x+l4OVQOtVfg/AAg4rVlxGP7HOzSn9ngW62oAxfAVXvVzlDVjCBWhM/MZ1UhZP8Rwlnrm1B371Ekx6V+6cSREXA8Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100557; c=relaxed/simple; bh=X5SViVIvZP2UJv62Vorxvp6BKpWIOgWpdxcHf3CFN0Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BbmfGcuGA4rqMz+zrPh/DIw+M+w8j7KNaxqpj2uoDopNwn6rjxWyofBeFzuUt90Wnve0Ol2VNyqSdN6TxkHggANbhYCulFWvi7gVbNgwhbGMPIwQV7yajELpqdVZbmdxIQs0xma3AXu7/j+0BqIt+19hG9zZnebBe+w1dzxK/VM= 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=WszmDPHS; 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="WszmDPHS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100551; bh=X5SViVIvZP2UJv62Vorxvp6BKpWIOgWpdxcHf3CFN0Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WszmDPHSrvZ1epQ/Ma0gRk8pQ41/4UeiJwJHev9OOI/hpYYhc/0e/W6UAuXWPFW6P aYe9AQgWwMH9wJBPI62sCNE0qEROkAw3URQYrCYAB2dBlqT1RNd14w65cE6rEcqKAf ogVnuoIXkKO8M3SnfqVnMKs9XtQI7FYSwTSSHnh1jhuzKKU4Y1xCzdxYeWTOLgTPZc PjbU92W5BinCkpl4XbuFn+Hfh+fGuH0B+ItpPaS123o3PzkRjrIpw0FCd8y8cPb2Yi TQx9lH9kxD/0v5JswDUdWP7UXlnADmdUx/AKqRrSqg3jso5mMy9abgDfm7VYLzCbIX WEDEqd/fzL94A== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 0F2B817E13F9; Fri, 19 Dec 2025 00:29:08 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 14/17] media: rkvdec: Add H264 support for the VDPU381 variant Date: Thu, 18 Dec 2025 18:28:24 -0500 Message-ID: <20251218232829.337811-15-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-1-detlev.casanova@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This decoder variant is found in Rockchip RK3588 SoC family. Like for rkvdec on rk3399, it supports the NV12, NV15, NV16 and NV20 output formats and level up to 5.1. The maximum width and height have been significantly increased supporting up to 65520 pixels for both. 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 --- .../media/platform/rockchip/rkvdec/Makefile | 1 + .../rockchip/rkvdec/rkvdec-h264-common.h | 2 + .../rockchip/rkvdec/rkvdec-vdpu381-h264.c | 465 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu381-regs.h | 424 ++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 97 +++- .../media/platform/rockchip/rkvdec/rkvdec.h | 11 + 6 files changed, 997 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 3d75103e536d2..7bfd95151e404 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 bd0c0081365b1..3be6cea3a7585 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 0000000000000..eaa0f7aac08e3 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-h264.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip VDPU381 Video Decoder H264 backend + * + * Copyright (C) 2024 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include + +#include "rkvdec.h" +#include "rkvdec-rcb.h" +#include "rkvdec-h264-common.h" +#include "rkvdec-vdpu381-regs.h" + +struct rkvdec_sps { + u16 seq_parameter_set_id: 4; + u16 profile_idc: 8; + u16 constraint_set3_flag: 1; + u16 chroma_format_idc: 2; + u16 bit_depth_luma: 3; + u16 bit_depth_chroma: 3; + u16 qpprime_y_zero_transform_bypass_flag: 1; + u16 log2_max_frame_num_minus4: 4; + u16 max_num_ref_frames: 5; + u16 pic_order_cnt_type: 2; + u16 log2_max_pic_order_cnt_lsb_minus4: 4; + u16 delta_pic_order_always_zero_flag: 1; + u16 pic_width_in_mbs: 12; + u16 pic_height_in_mbs: 12; + u16 frame_mbs_only_flag: 1; + u16 mb_adaptive_frame_field_flag: 1; + u16 direct_8x8_inference_flag: 1; + u16 mvc_extension_enable: 1; + u16 num_views: 2; + + u16 reserved_bits: 12; + u16 reserved[11]; +} __packed; + +struct rkvdec_pps { + u16 pic_parameter_set_id: 8; + u16 pps_seq_parameter_set_id: 5; + u16 entropy_coding_mode_flag: 1; + u16 bottom_field_pic_order_in_frame_present_flag: 1; + u16 num_ref_idx_l0_default_active_minus1: 5; + u16 num_ref_idx_l1_default_active_minus1: 5; + u16 weighted_pred_flag: 1; + u16 weighted_bipred_idc: 2; + u16 pic_init_qp_minus26: 7; + u16 pic_init_qs_minus26: 6; + u16 chroma_qp_index_offset: 5; + u16 deblocking_filter_control_present_flag: 1; + u16 constrained_intra_pred_flag: 1; + u16 redundant_pic_cnt_present: 1; + u16 transform_8x8_mode_flag: 1; + u16 second_chroma_qp_index_offset: 5; + u16 scaling_list_enable_flag: 1; + u32 scaling_list_address; + u16 is_longterm; + + u8 reserved[3]; +} __packed; + +struct rkvdec_sps_pps { + struct rkvdec_sps sps; + struct rkvdec_pps pps; +} __packed; + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec_h264_priv_tbl { + s8 cabac_table[4][464][2]; + struct rkvdec_h264_scaling_list scaling_list; + struct rkvdec_sps_pps param_set[256]; + struct rkvdec_rps rps; +}; + +struct rkvdec_h264_ctx { + struct rkvdec_aux_buf priv_tbl; + struct rkvdec_h264_reflists reflists; + struct rkvdec_vdpu381_regs_h264 regs; +}; + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_h264_sps *sps =3D run->sps; + const struct v4l2_ctrl_h264_pps *pps =3D run->pps; + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_sps_pps *hw_ps; + dma_addr_t scaling_list_address; + u32 scaling_distance; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set[pps->pic_parameter_set_id]; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->sps.seq_parameter_set_id =3D sps->seq_parameter_set_id; + hw_ps->sps.profile_idc =3D sps->profile_idc; + hw_ps->sps.constraint_set3_flag =3D !!(sps->constraint_set_flags & (1 << = 3)); + hw_ps->sps.chroma_format_idc =3D sps->chroma_format_idc; + hw_ps->sps.bit_depth_luma =3D sps->bit_depth_luma_minus8; + hw_ps->sps.bit_depth_chroma =3D sps->bit_depth_chroma_minus8; + hw_ps->sps.qpprime_y_zero_transform_bypass_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS); + hw_ps->sps.log2_max_frame_num_minus4 =3D sps->log2_max_frame_num_minus4; + hw_ps->sps.max_num_ref_frames =3D sps->max_num_ref_frames; + hw_ps->sps.pic_order_cnt_type =3D sps->pic_order_cnt_type; + hw_ps->sps.log2_max_pic_order_cnt_lsb_minus4 =3D + sps->log2_max_pic_order_cnt_lsb_minus4; + hw_ps->sps.delta_pic_order_always_zero_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO); + hw_ps->sps.mvc_extension_enable =3D 1; + hw_ps->sps.num_views =3D 1; + + /* + * Use the SPS values since they are already in macroblocks + * dimensions, height can be field height (halved) if + * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows + * decoding smaller images into larger allocation which can be used + * to implementing SVC spatial layer support. + */ + hw_ps->sps.pic_width_in_mbs =3D sps->pic_width_in_mbs_minus1 + 1; + hw_ps->sps.pic_height_in_mbs =3D sps->pic_height_in_map_units_minus1 + 1; + hw_ps->sps.frame_mbs_only_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY); + hw_ps->sps.mb_adaptive_frame_field_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + hw_ps->sps.direct_8x8_inference_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); + + /* write pps */ + hw_ps->pps.pic_parameter_set_id =3D pps->pic_parameter_set_id; + hw_ps->pps.pps_seq_parameter_set_id =3D pps->seq_parameter_set_id; + hw_ps->pps.entropy_coding_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESE= NT); + hw_ps->pps.num_ref_idx_l0_default_active_minus1 =3D + pps->num_ref_idx_l0_default_active_minus1; + hw_ps->pps.num_ref_idx_l1_default_active_minus1 =3D + pps->num_ref_idx_l1_default_active_minus1; + hw_ps->pps.weighted_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED); + hw_ps->pps.weighted_bipred_idc =3D pps->weighted_bipred_idc; + hw_ps->pps.pic_init_qp_minus26 =3D pps->pic_init_qp_minus26; + hw_ps->pps.pic_init_qs_minus26 =3D pps->pic_init_qs_minus26; + hw_ps->pps.chroma_qp_index_offset =3D pps->chroma_qp_index_offset; + hw_ps->pps.deblocking_filter_control_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + hw_ps->pps.constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->pps.redundant_pic_cnt_present =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT); + hw_ps->pps.transform_8x8_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE); + hw_ps->pps.second_chroma_qp_index_offset =3D pps->second_chroma_qp_index_= offset; + hw_ps->pps.scaling_list_enable_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT); + + /* + * To be on the safe side, program the scaling matrix address + */ + scaling_distance =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + scaling_list_address =3D h264_ctx->priv_tbl.dma + scaling_distance; + hw_ps->pps.scaling_list_address =3D scaling_list_address; + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + hw_ps->pps.is_longterm |=3D (1 << i); + } +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS, + &h264_ctx->regs.common, + sizeof(h264_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS, + &h264_ctx->regs.h264_param, + sizeof(h264_ctx->regs.h264_param)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS, + &h264_ctx->regs.common_addr, + sizeof(h264_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS, + &h264_ctx->regs.h264_addr, + sizeof(h264_ctx->regs.h264_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_POC_HIGHBIT_REGS, + &h264_ctx->regs.h264_highpoc, + sizeof(h264_ctx->regs.h264_highpoc)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + dma_addr_t priv_start_addr =3D h264_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + struct rkvdec_vdpu381_regs_h264 *regs =3D &h264_ctx->regs; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + dma_addr_t dst_addr; + u32 hor_virstride; + u32 ver_virstride; + u32 y_virstride; + u32 offset; + u32 pixels; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set H264 mode */ + regs->common.reg009.dec_mode =3D VDPU381_MODE_H264; + + /* Set config */ + regs->common.reg011.buf_empty_en =3D 1; + regs->common.reg011.dec_clkgate_e =3D 1; + regs->common.reg011.dec_timeout_e =3D 1; + regs->common.reg011.pix_range_detection_e =3D 1; + + /* + * Even though the scan list address can be set in RPS, + * with some frames, it will try to use the address set in the register. + */ + regs->common.reg012.scanlist_addr_valid_en =3D 1; + + /* Set IDR flag */ + regs->common.reg013.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.stream_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); + + /* Set max slice number */ + regs->common.reg017.slice_num =3D MAX_SLICE_NUMBER; + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->common.reg018.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026.swreg_block_gating_e =3D 0xfffef; + regs->common.reg026.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_8K; + else + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_MAX; + + /* Set TOP and BOTTOM POCs */ + regs->h264_param.cur_top_poc =3D dec_params->top_field_order_cnt; + regs->h264_param.cur_bot_poc =3D dec_params->bottom_field_order_cnt; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf =3D run->ref_buf[i]; + dma_addr_t buf_dma; + + /* + * If a DPB entry is unused or invalid, address of current destination + * buffer is returned. + */ + if (!vb_buf) + vb_buf =3D &dst_buf->vb2_buf; + + buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + + /* Set reference addresses */ + regs->h264_addr.ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->h264_addr.colmv_base[i] =3D buf_dma + ctx->colmv_offset; + + struct rkvdec_vdpu381_h264_ref_info *ref_info =3D + ®s->h264_param.ref_info_regs[i / 4].ref_info[i % 4]; + + ref_info->ref_field =3D + !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD); + ref_info->ref_colmv_use_flag =3D + !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); + ref_info->ref_topfield_used =3D + !!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF); + ref_info->ref_botfield_used =3D + !!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF); + + regs->h264_param.ref_pocs[i * 2] =3D + dpb[i].top_field_order_cnt; + regs->h264_param.ref_pocs[i * 2 + 1] =3D + dpb[i].bottom_field_order_cnt; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.rlc_base =3D rlc_addr; + regs->common_addr.rlcwrite_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->common_addr.decout_base =3D dst_addr; + regs->common_addr.error_ref_base =3D dst_addr; + + /* Set colmv address */ + regs->common_addr.colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) + regs->common_addr.rcb_base[i] =3D rkvdec_rcb_buf_dma_addr(ctx, i); + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, param_set); + regs->h264_addr.pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, rps); + regs->h264_addr.rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_h264_priv_tbl, cabac_table); + regs->h264_addr.cabactbl_base =3D priv_start_addr + offset; + + offset =3D offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + regs->h264_addr.scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_h264_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_priv_tbl *priv_tbl; + struct rkvdec_h264_ctx *h264_ctx; + struct v4l2_ctrl *ctrl; + int ret; + + ctrl =3D v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_H264_SPS); + if (!ctrl) + return -EINVAL; + + h264_ctx =3D kzalloc(sizeof(*h264_ctx), GFP_KERNEL); + if (!h264_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &h264_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + h264_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + h264_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_h264_cabac_table, + sizeof(rkvdec_h264_cabac_table)); + + ctx->priv =3D h264_ctx; + return 0; + +err_free_ctx: + kfree(h264_ctx); + return ret; +} + +static void rkvdec_h264_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, h264_ctx->priv_tbl.size, + h264_ctx->priv_tbl.cpu, h264_ctx->priv_tbl.dma); + kfree(h264_ctx); +} + +static int rkvdec_h264_run(struct rkvdec_ctx *ctx) +{ + struct v4l2_h264_reflist_builder reflist_builder; + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_h264_priv_tbl *tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_h264_run run; + u32 watchdog_time; + + rkvdec_h264_run_preamble(ctx, &run); + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, + run.sps, run.decode_params->dpb); + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, + h264_ctx->reflists.b1); + + assemble_hw_scaling_list(&run, &tbl->scaling_list); + assemble_hw_pps(ctx, &run); + lookup_ref_buf_idx(ctx, &run); + assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + u64 timeout_threshold =3D h264_ctx->regs.common.timeout_threshold; + unsigned long axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); + + return 0; +} + +static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *= ctrl) +{ + if (ctrl->id =3D=3D V4L2_CID_STATELESS_H264_SPS) + return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops =3D { + .adjust_fmt =3D rkvdec_h264_adjust_fmt, + .get_image_fmt =3D rkvdec_h264_get_image_fmt, + .start =3D rkvdec_h264_start, + .stop =3D rkvdec_h264_stop, + .run =3D rkvdec_h264_run, + .try_ctrl =3D rkvdec_h264_try_ctrl, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h new file mode 100644 index 0000000000000..a9a2daa24048b --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h @@ -0,0 +1,424 @@ +/* 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 rkvdec_vdpu381_in_out { + u32 in_endian : 1; + u32 in_swap32_e : 1; + u32 in_swap64_e : 1; + u32 str_endian : 1; + u32 str_swap32_e : 1; + u32 str_swap64_e : 1; + u32 out_endian : 1; + u32 out_swap32_e : 1; + u32 out_cbcr_swap : 1; + u32 out_swap64_e : 1; + u32 reserved : 22; + } reg008; + + struct rkvdec_vdpu381_dec_mode { + u32 dec_mode : 10; + u32 reserved : 22; + } reg009; + + struct rkvdec_vdpu381_dec_e { + u32 dec_e : 1; + u32 reserved : 31; + } reg010; + + struct rkvdec_vdpu381_important_en { + u32 reserved : 1; + u32 dec_clkgate_e : 1; + u32 dec_e_strmd_clkgate_dis : 1; + u32 reserved0 : 1; + + u32 dec_irq_dis : 1; + u32 dec_timeout_e : 1; + u32 buf_empty_en : 1; + u32 reserved1 : 3; + + u32 dec_e_rewrite_valid : 1; + u32 reserved2 : 9; + u32 softrst_en_p : 1; + u32 force_softreset_valid : 1; + u32 reserved3 : 2; + u32 pix_range_detection_e : 1; + u32 reserved4 : 7; + } reg011; + + struct rkvdec_vdpu381_secondary_en { + u32 wr_ddr_align_en : 1; + u32 colmv_compress_en : 1; + u32 fbc_e : 1; + u32 reserved0 : 1; + + u32 buspr_slot_disable : 1; + u32 error_info_en : 1; + u32 info_collect_en : 1; + u32 wait_reset_en : 1; + + u32 scanlist_addr_valid_en : 1; + u32 scale_down_en : 1; + u32 error_cfg_wr_disable : 1; + u32 reserved1 : 21; + } reg012; + + struct rkvdec_vdpu381_en_mode_set { + u32 timeout_mode : 1; + u32 req_timeout_rst_sel : 1; + u32 reserved0 : 1; + u32 dec_commonirq_mode : 1; + u32 reserved1 : 2; + u32 stmerror_waitdecfifo_empty : 1; + u32 reserved2 : 2; + u32 h26x_streamd_error_mode : 1; + u32 reserved3 : 2; + u32 allow_not_wr_unref_bframe : 1; + u32 fbc_output_wr_disable : 1; + u32 reserved4 : 1; + u32 colmv_error_mode : 1; + + u32 reserved5 : 2; + u32 h26x_error_mode : 1; + u32 reserved6 : 2; + u32 ycacherd_prior : 1; + u32 reserved7 : 2; + u32 cur_pic_is_idr : 1; + u32 reserved8 : 1; + u32 right_auto_rst_disable : 1; + u32 frame_end_err_rst_flag : 1; + u32 rd_prior_mode : 1; + u32 rd_ctrl_prior_mode : 1; + u32 reserved9 : 1; + u32 filter_outbuf_mode : 1; + } reg013; + + struct rkvdec_vdpu381_fbc_param_set { + u32 fbc_force_uncompress : 1; + + u32 reserved0 : 2; + u32 allow_16x8_cp_flag : 1; + u32 reserved1 : 2; + + u32 fbc_h264_exten_4or8_flag : 1; + u32 reserved2 : 25; + } reg014; + + struct rkvdec_vdpu381_stream_param_set { + u32 rlc_mode_direct_write : 1; + u32 rlc_mode : 1; + u32 reserved0 : 3; + + u32 strm_start_bit : 7; + u32 reserved1 : 20; + } reg015; + + u32 stream_len; + + struct rkvdec_vdpu381_slice_number { + u32 slice_num : 25; + u32 reserved : 7; + } reg017; + + struct rkvdec_vdpu381_y_hor_stride { + u32 y_hor_virstride : 16; + u32 reserved : 16; + } reg018; + + struct rkvdec_vdpu381_uv_hor_stride { + u32 uv_hor_virstride : 16; + u32 reserved : 16; + } reg019; + + struct rkvdec_vdpu381_y_stride { + u32 y_virstride : 28; + u32 reserved : 4; + } reg020; + + struct rkvdec_vdpu381_error_ctrl_set { + u32 inter_error_prc_mode : 1; + u32 error_intra_mode : 1; + u32 error_deb_en : 1; + u32 picidx_replace : 5; + u32 error_spread_e : 1; + u32 reserved0 : 3; + u32 error_inter_pred_cross_slice : 1; + u32 reserved1 : 11; + u32 roi_error_ctu_cal_en : 1; + u32 reserved2 : 7; + } reg021; + + struct rkvdec_vdpu381_err_roi_ctu_offset_start { + u32 roi_x_ctu_offset_st : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserved1 : 4; + } reg022; + + struct rkvdec_vdpu381_err_roi_ctu_offset_end { + u32 roi_x_ctu_offset_end : 12; + u32 reserved0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserved1 : 4; + } reg023; + + struct rkvdec_vdpu381_cabac_error_en_lowbits { + u32 cabac_err_en_lowbits : 32; + } reg024; + + struct rkvdec_vdpu381_cabac_error_en_highbits { + u32 cabac_err_en_highbits : 30; + u32 reserved : 2; + } reg025; + + struct rkvdec_vdpu381_block_gating_en { + u32 swreg_block_gating_e : 20; + u32 reserved : 11; + u32 reg_cfg_gating_en : 1; + } reg026; + + struct SW027_CORE_SAFE_PIXELS { + u32 core_safe_x_pixels : 16; + u32 core_safe_y_pixels : 16; + } reg027; + + struct rkvdec_vdpu381_multiply_core_ctrl { + u32 swreg_vp9_wr_prob_idx : 3; + u32 reserved0 : 1; + u32 swreg_vp9_rd_prob_idx : 3; + u32 reserved1 : 1; + + u32 swreg_ref_req_advance_flag : 1; + u32 sw_colmv_req_advance_flag : 1; + u32 sw_poc_only_highbit_flag : 1; + u32 sw_poc_arb_flag : 1; + + u32 reserved2 : 4; + u32 sw_film_idx : 10; + u32 reserved3 : 2; + u32 sw_pu_req_mismatch_dis : 1; + u32 sw_colmv_req_mismatch_dis : 1; + u32 reserved4 : 2; + } reg028; + + struct SW029_SCALE_DOWN_CTRL { + u32 scale_down_hor_ratio : 2; + u32 reserved0 : 6; + u32 scale_down_vrz_ratio : 2; + u32 reserved1 : 22; + } reg029; + + struct SW032_Y_SCALE_DOWN_TILE8x8_HOR_STRIDE { + u32 y_scale_down_hor_stride : 20; + u32 reserved0 : 12; + } reg030; + + struct SW031_UV_SCALE_DOWN_TILE8x8_HOR_STRIDE { + u32 uv_scale_down_hor_stride : 20; + u32 reserved0 : 12; + } reg031; + + u32 timeout_threshold; +} __packed; + +/* base: OFFSET_COMMON_ADDR_REGS */ +struct rkvdec_vdpu381_regs_common_addr { + u32 rlc_base; + u32 rlcwrite_base; + u32 decout_base; + u32 colmv_cur_base; + u32 error_ref_base; + u32 rcb_base[10]; +} __packed; + +struct rkvdec_vdpu381_h26x_set { + u32 h26x_frame_orslice : 1; + u32 h26x_rps_mode : 1; + u32 h26x_stream_mode : 1; + u32 h26x_stream_lastpacket : 1; + u32 h264_firstslice_flag : 1; + u32 reserved : 27; +} __packed; + +/* base: OFFSET_CODEC_PARAMS_REGS */ +struct rkvdec_vdpu381_regs_h264_params { + struct rkvdec_vdpu381_h26x_set reg064; + + u32 cur_top_poc; + u32 cur_bot_poc; + u32 ref_pocs[32]; + + struct rkvdec_vdpu381_h264_info { + struct rkvdec_vdpu381_h264_ref_info { + u32 ref_field : 1; + u32 ref_topfield_used : 1; + u32 ref_botfield_used : 1; + u32 ref_colmv_use_flag : 1; + u32 ref_reserved : 4; + } __packed ref_info[4]; + } __packed ref_info_regs[4]; + + u32 reserved_103_111[9]; + + struct rkvdec_vdpu381_error_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserved : 28; + } reg112; +} __packed; + +struct rkvdec_vdpu381_regs_hevc_params { + struct rkvdec_vdpu381_h26x_set reg064; + + u32 cur_top_poc; + u32 cur_bot_poc; + + u32 reg067_082_ref_poc[16]; + + u32 reserved_083_098[16]; + + struct rkvdec_vdpu381_hevc_ref_valid { + u32 hevc_ref_valid_0 : 1; + u32 hevc_ref_valid_1 : 1; + u32 hevc_ref_valid_2 : 1; + u32 hevc_ref_valid_3 : 1; + u32 reserve0 : 4; + u32 hevc_ref_valid_4 : 1; + u32 hevc_ref_valid_5 : 1; + u32 hevc_ref_valid_6 : 1; + u32 hevc_ref_valid_7 : 1; + u32 reserve1 : 4; + u32 hevc_ref_valid_8 : 1; + u32 hevc_ref_valid_9 : 1; + u32 hevc_ref_valid_10 : 1; + u32 hevc_ref_valid_11 : 1; + u32 reserve2 : 4; + u32 hevc_ref_valid_12 : 1; + u32 hevc_ref_valid_13 : 1; + u32 hevc_ref_valid_14 : 1; + u32 reserve3 : 5; + } reg099; + + u32 reserved_100_102[3]; + + struct rkvdec_vdpu381_hevc_mvc0 { + u32 ref_pic_layer_same_with_cur : 16; + u32 reserve : 16; + } reg103; + + struct rkvdec_vdpu381_hevc_mvc1 { + u32 poc_lsb_not_present_flag : 1; + u32 num_direct_ref_layers : 6; + u32 reserve0 : 1; + + u32 num_reflayer_pics : 6; + u32 default_ref_layers_active_flag : 1; + u32 max_one_active_ref_layer_flag : 1; + + u32 poc_reset_info_present_flag : 1; + u32 vps_poc_lsb_aligned_flag : 1; + u32 mvc_poc15_valid_flag : 1; + u32 reserve1 : 13; + } reg104; + + u32 reserved_105_111[7]; + + struct rkvdec_vdpu381_hevc_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserve : 28; + } reg112; + +} __packed; + +/* base: OFFSET_CODEC_ADDR_REGS */ +struct rkvdec_vdpu381_regs_h26x_addr { + u32 reserved_160; + u32 pps_base; + u32 reserved_162; + u32 rps_base; + u32 ref_base[16]; + u32 scanlist_addr; + u32 colmv_base[16]; + u32 cabactbl_base; +} __packed; + +struct rkvdec_vdpu381_regs_h26x_highpoc { + struct rkvdec_vdpu381_ref_poc_highbit { + u32 ref0_poc_highbit : 4; + u32 ref1_poc_highbit : 4; + u32 ref2_poc_highbit : 4; + u32 ref3_poc_highbit : 4; + u32 ref4_poc_highbit : 4; + u32 ref5_poc_highbit : 4; + u32 ref6_poc_highbit : 4; + u32 ref7_poc_highbit : 4; + } reg200[4]; + struct rkvdec_vdpu381_cur_poc_highbit { + u32 cur_poc_highbit : 4; + u32 reserved : 28; + } reg204; +} __packed; + +struct rkvdec_vdpu381_regs_h264 { + struct rkvdec_vdpu381_regs_common common; + struct rkvdec_vdpu381_regs_h264_params h264_param; + struct rkvdec_vdpu381_regs_common_addr common_addr; + struct rkvdec_vdpu381_regs_h26x_addr h264_addr; + struct rkvdec_vdpu381_regs_h26x_highpoc h264_highpoc; +} __packed; + +struct rkvdec_vdpu381_regs_hevc { + struct rkvdec_vdpu381_regs_common common; + struct rkvdec_vdpu381_regs_hevc_params hevc_param; + struct rkvdec_vdpu381_regs_common_addr common_addr; + struct rkvdec_vdpu381_regs_h26x_addr hevc_addr; + struct rkvdec_vdpu381_regs_h26x_highpoc hevc_highpoc; +} __packed; + +#endif /* __RKVDEC_REGS_H__ */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index af2eced900269..3d243b6e11445 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) { @@ -1245,6 +1268,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 +1373,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 +1381,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 +1390,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 +1431,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 +1468,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 7766a79caf68b..401221061e081 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 @@ -170,8 +177,12 @@ void rkvdec_memcpy_toio(void __iomem *dst, void *src, = size_t len); =20 void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx); =20 +/* RKVDEC ops */ extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; =20 +/* VDPU381 ops */ +extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops; + #endif /* RKVDEC_H_ */ --=20 2.52.0 From nobody Sat Feb 7 13:05:44 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 ACCA2334C06; Thu, 18 Dec 2025 23:29: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=1766100559; cv=none; b=KfSrDuhLembfKHABxwhy9jhSC/t4zx4tDscL4q0UYQIPMKnLnwZDsd/CarL516WU9WVkDjdM/9JGSL9DlO/gzVVw7qAhcRfhyTM4L+SbwMDRc9SobDrh/usGTI8u0lvyPMyd80uTsyOR5jXWtamPoxg8v6Z3Nc+xgEZjBLicBUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100559; c=relaxed/simple; bh=TV9fOCpk+O4G+Kh7GBxdWWCvP/zzvm1pft22WOpgM1E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WIDo0nEZgV9tyP3DtH4iFaxuiq5vcM2Q9aV435Ctp5oQ85TjM//321PfZAy+J47f/6KLDqK3lROr2+bP9Te1hxj43sGrVxINTl2h75g1L5acsC7/ncAKofIfa0VF3gwc+hr3gV7CIzW2r+qjbP9yQPAmzuy293I+qP5CDoRFEV4= 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=nkSFeVOb; 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="nkSFeVOb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100554; bh=TV9fOCpk+O4G+Kh7GBxdWWCvP/zzvm1pft22WOpgM1E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nkSFeVObxYmEN10ag393JYcjs7ux6h9Ekq9n28TGjzXEuUa3SLvg4SYXIbOwJIf9L id/h+E3T+YoeeZdC75CQsHyKBKIqyfBxWm1JZRXn2WxMref7Uzje7xuKeEAtLZRoyp utzZANF0Xsy06nQyiwX3W/DXDAovkr8EmK5g9/H2EjeRjtEaL3ljZb76eSldY3hUWT MJ3GfvjPx/hLFjtamnuSQUEEmPV5362rehts3gZxUQdTVSIQq1bAO2y7wW0p/mw4ZN +objMW27pNRUK+KZL2iQ9NzsQ46g+bIX6fWdECwrk84rxyNLU+/+YTVsfMO9hMGoFJ QfJUrleLc+opg== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 B722F17E154C; Fri, 19 Dec 2025 00:29:11 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 15/17] media: rkvdec: Add H264 support for the VDPU383 variant Date: Thu, 18 Dec 2025 18:28:25 -0500 Message-ID: <20251218232829.337811-16-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 | 578 ++++++++++++++++++ .../rockchip/rkvdec/rkvdec-vdpu383-regs.h | 281 +++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 105 +++- .../media/platform/rockchip/rkvdec/rkvdec.h | 5 + 5 files changed, 965 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 7bfd95151e404..a58d4aede2fea 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 0000000000000..cc5a41bba81cc --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-h264.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip Video Decoder VDPU383 H264 backend + * + * Copyright (C) 2024 Collabora, Ltd. + * Detlev Casanova + */ + +#include +#include + +#include + +#include "rkvdec-rcb.h" +#include "rkvdec-vdpu383-regs.h" +#include "rkvdec-h264-common.h" + +struct rkvdec_sps { + u16 seq_parameter_set_id: 4; + u16 profile_idc: 8; + u16 constraint_set3_flag: 1; + u16 chroma_format_idc: 2; + u16 bit_depth_luma: 3; + u16 bit_depth_chroma: 3; + u16 qpprime_y_zero_transform_bypass_flag: 1; + u16 log2_max_frame_num_minus4: 4; + u16 max_num_ref_frames: 5; + u16 pic_order_cnt_type: 2; + u16 log2_max_pic_order_cnt_lsb_minus4: 4; + u16 delta_pic_order_always_zero_flag: 1; + + u16 pic_width_in_mbs: 16; + u16 pic_height_in_mbs: 16; + + u16 frame_mbs_only_flag: 1; + u16 mb_adaptive_frame_field_flag: 1; + u16 direct_8x8_inference_flag: 1; + u16 mvc_extension_enable: 1; + u16 num_views: 2; + u16 view_id0: 10; + u16 view_id1: 10; +} __packed; + +struct rkvdec_pps { + u32 pic_parameter_set_id: 8; + u32 pps_seq_parameter_set_id: 5; + u32 entropy_coding_mode_flag: 1; + u32 bottom_field_pic_order_in_frame_present_flag: 1; + u32 num_ref_idx_l0_default_active_minus1: 5; + u32 num_ref_idx_l1_default_active_minus1: 5; + u32 weighted_pred_flag: 1; + u32 weighted_bipred_idc: 2; + u32 pic_init_qp_minus26: 7; + u32 pic_init_qs_minus26: 6; + u32 chroma_qp_index_offset: 5; + u32 deblocking_filter_control_present_flag: 1; + u32 constrained_intra_pred_flag: 1; + u32 redundant_pic_cnt_present: 1; + u32 transform_8x8_mode_flag: 1; + u32 second_chroma_qp_index_offset: 5; + u32 scaling_list_enable_flag: 1; + u32 is_longterm: 16; + u32 voidx: 16; + + // dpb + u32 pic_field_flag: 1; + u32 pic_associated_flag: 1; + u32 cur_top_field: 32; + u32 cur_bot_field: 32; + + u32 top_field_order_cnt0: 32; + u32 bot_field_order_cnt0: 32; + u32 top_field_order_cnt1: 32; + u32 bot_field_order_cnt1: 32; + u32 top_field_order_cnt2: 32; + u32 bot_field_order_cnt2: 32; + u32 top_field_order_cnt3: 32; + u32 bot_field_order_cnt3: 32; + u32 top_field_order_cnt4: 32; + u32 bot_field_order_cnt4: 32; + u32 top_field_order_cnt5: 32; + u32 bot_field_order_cnt5: 32; + u32 top_field_order_cnt6: 32; + u32 bot_field_order_cnt6: 32; + u32 top_field_order_cnt7: 32; + u32 bot_field_order_cnt7: 32; + u32 top_field_order_cnt8: 32; + u32 bot_field_order_cnt8: 32; + u32 top_field_order_cnt9: 32; + u32 bot_field_order_cnt9: 32; + u32 top_field_order_cnt10: 32; + u32 bot_field_order_cnt10: 32; + u32 top_field_order_cnt11: 32; + u32 bot_field_order_cnt11: 32; + u32 top_field_order_cnt12: 32; + u32 bot_field_order_cnt12: 32; + u32 top_field_order_cnt13: 32; + u32 bot_field_order_cnt13: 32; + u32 top_field_order_cnt14: 32; + u32 bot_field_order_cnt14: 32; + u32 top_field_order_cnt15: 32; + u32 bot_field_order_cnt15: 32; + + u32 ref_field_flags: 16; + u32 ref_topfield_used: 16; + u32 ref_botfield_used: 16; + u32 ref_colmv_use_flag: 16; + + u32 reserved0: 30; + u32 reserved[3]; +} __packed; + +struct rkvdec_sps_pps { + struct rkvdec_sps sps; + struct rkvdec_pps pps; +} __packed; + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec_h264_priv_tbl { + s8 cabac_table[4][464][2]; + struct rkvdec_h264_scaling_list scaling_list; + struct rkvdec_sps_pps param_set[256]; + struct rkvdec_rps rps; +} __packed; + +struct rkvdec_h264_ctx { + struct rkvdec_aux_buf priv_tbl; + struct rkvdec_h264_reflists reflists; + struct vdpu383_regs_h26x regs; +}; + +static void set_field_order_cnt(struct rkvdec_sps_pps *hw_ps, int id, u32 = top, u32 bottom) +{ + switch (id) { + case 0: + hw_ps->pps.top_field_order_cnt0 =3D top; + hw_ps->pps.bot_field_order_cnt0 =3D bottom; + break; + case 1: + hw_ps->pps.top_field_order_cnt1 =3D top; + hw_ps->pps.bot_field_order_cnt1 =3D bottom; + break; + case 2: + hw_ps->pps.top_field_order_cnt2 =3D top; + hw_ps->pps.bot_field_order_cnt2 =3D bottom; + break; + case 3: + hw_ps->pps.top_field_order_cnt3 =3D top; + hw_ps->pps.bot_field_order_cnt3 =3D bottom; + break; + case 4: + hw_ps->pps.top_field_order_cnt4 =3D top; + hw_ps->pps.bot_field_order_cnt4 =3D bottom; + break; + case 5: + hw_ps->pps.top_field_order_cnt5 =3D top; + hw_ps->pps.bot_field_order_cnt5 =3D bottom; + break; + case 6: + hw_ps->pps.top_field_order_cnt6 =3D top; + hw_ps->pps.bot_field_order_cnt6 =3D bottom; + break; + case 7: + hw_ps->pps.top_field_order_cnt7 =3D top; + hw_ps->pps.bot_field_order_cnt7 =3D bottom; + break; + case 8: + hw_ps->pps.top_field_order_cnt8 =3D top; + hw_ps->pps.bot_field_order_cnt8 =3D bottom; + break; + case 9: + hw_ps->pps.top_field_order_cnt9 =3D top; + hw_ps->pps.bot_field_order_cnt9 =3D bottom; + break; + case 10: + hw_ps->pps.top_field_order_cnt10 =3D top; + hw_ps->pps.bot_field_order_cnt10 =3D bottom; + break; + case 11: + hw_ps->pps.top_field_order_cnt11 =3D top; + hw_ps->pps.bot_field_order_cnt11 =3D bottom; + break; + case 12: + hw_ps->pps.top_field_order_cnt12 =3D top; + hw_ps->pps.bot_field_order_cnt12 =3D bottom; + break; + case 13: + hw_ps->pps.top_field_order_cnt13 =3D top; + hw_ps->pps.bot_field_order_cnt13 =3D bottom; + break; + case 14: + hw_ps->pps.top_field_order_cnt14 =3D top; + hw_ps->pps.bot_field_order_cnt14 =3D bottom; + break; + case 15: + hw_ps->pps.top_field_order_cnt15 =3D top; + hw_ps->pps.bot_field_order_cnt15 =3D bottom; + break; + } +} + +static void assemble_hw_pps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + const struct v4l2_ctrl_h264_sps *sps =3D run->sps; + const struct v4l2_ctrl_h264_pps *pps =3D run->pps; + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_h264_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_h264_priv_tbl *priv_tbl =3D h264_ctx->priv_tbl.cpu; + struct rkvdec_sps_pps *hw_ps; + u32 pic_width, pic_height; + u32 i; + + /* + * HW read the SPS/PPS information from PPS packet index by PPS id. + * offset from the base can be calculated by PPS_id * 32 (size per PPS + * packet unit). so the driver copy SPS/PPS information to the exact PPS + * packet unit for HW accessing. + */ + hw_ps =3D &priv_tbl->param_set[pps->pic_parameter_set_id]; + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ + hw_ps->sps.seq_parameter_set_id =3D sps->seq_parameter_set_id; + hw_ps->sps.profile_idc =3D sps->profile_idc; + hw_ps->sps.constraint_set3_flag =3D !!(sps->constraint_set_flags & (1 << = 3)); + hw_ps->sps.chroma_format_idc =3D sps->chroma_format_idc; + hw_ps->sps.bit_depth_luma =3D sps->bit_depth_luma_minus8; + hw_ps->sps.bit_depth_chroma =3D sps->bit_depth_chroma_minus8; + hw_ps->sps.qpprime_y_zero_transform_bypass_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS); + hw_ps->sps.log2_max_frame_num_minus4 =3D sps->log2_max_frame_num_minus4; + hw_ps->sps.max_num_ref_frames =3D sps->max_num_ref_frames; + hw_ps->sps.pic_order_cnt_type =3D sps->pic_order_cnt_type; + hw_ps->sps.log2_max_pic_order_cnt_lsb_minus4 =3D + sps->log2_max_pic_order_cnt_lsb_minus4; + hw_ps->sps.delta_pic_order_always_zero_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO); + hw_ps->sps.mvc_extension_enable =3D 0; + hw_ps->sps.num_views =3D 0; + + /* + * Use the SPS values since they are already in macroblocks + * dimensions, height can be field height (halved) if + * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows + * decoding smaller images into larger allocation which can be used + * to implementing SVC spatial layer support. + */ + pic_width =3D 16 * (sps->pic_width_in_mbs_minus1 + 1); + pic_height =3D 16 * (sps->pic_height_in_map_units_minus1 + 1); + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) + pic_height *=3D 2; + if (!!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + pic_height /=3D 2; + + hw_ps->sps.pic_width_in_mbs =3D pic_width; + hw_ps->sps.pic_height_in_mbs =3D pic_height; + + hw_ps->sps.frame_mbs_only_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY); + hw_ps->sps.mb_adaptive_frame_field_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + hw_ps->sps.direct_8x8_inference_flag =3D + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); + + /* write pps */ + hw_ps->pps.pic_parameter_set_id =3D pps->pic_parameter_set_id; + hw_ps->pps.pps_seq_parameter_set_id =3D pps->seq_parameter_set_id; + hw_ps->pps.entropy_coding_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESE= NT); + hw_ps->pps.num_ref_idx_l0_default_active_minus1 =3D + pps->num_ref_idx_l0_default_active_minus1; + hw_ps->pps.num_ref_idx_l1_default_active_minus1 =3D + pps->num_ref_idx_l1_default_active_minus1; + hw_ps->pps.weighted_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED); + hw_ps->pps.weighted_bipred_idc =3D pps->weighted_bipred_idc; + hw_ps->pps.pic_init_qp_minus26 =3D pps->pic_init_qp_minus26; + hw_ps->pps.pic_init_qs_minus26 =3D pps->pic_init_qs_minus26; + hw_ps->pps.chroma_qp_index_offset =3D pps->chroma_qp_index_offset; + hw_ps->pps.deblocking_filter_control_present_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + hw_ps->pps.constrained_intra_pred_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED); + hw_ps->pps.redundant_pic_cnt_present =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT); + hw_ps->pps.transform_8x8_mode_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE); + hw_ps->pps.second_chroma_qp_index_offset =3D pps->second_chroma_qp_index_= offset; + hw_ps->pps.scaling_list_enable_flag =3D + !!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT); + + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + hw_ps->pps.is_longterm |=3D (1 << i); + + set_field_order_cnt(hw_ps, i, dpb[i].top_field_order_cnt, + dpb[i].bottom_field_order_cnt); + + hw_ps->pps.ref_field_flags |=3D + (!!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) << i; + hw_ps->pps.ref_colmv_use_flag |=3D + (!!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) << i; + hw_ps->pps.ref_topfield_used |=3D + (!!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF)) << i; + hw_ps->pps.ref_botfield_used |=3D + (!!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)) << i; + } + + hw_ps->pps.pic_field_flag =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC); + hw_ps->pps.pic_associated_flag =3D + !!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD); + + hw_ps->pps.cur_top_field =3D dec_params->top_field_order_cnt; + hw_ps->pps.cur_bot_field =3D dec_params->bottom_field_order_cnt; +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_REGS, + &h264_ctx->regs.common, + sizeof(h264_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_COMMON_ADDR_REGS, + &h264_ctx->regs.common_addr, + sizeof(h264_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_PARAMS_REGS, + &h264_ctx->regs.h26x_params, + sizeof(h264_ctx->regs.h26x_params)); + rkvdec_memcpy_toio(rkvdec->regs + VDPU383_OFFSET_CODEC_ADDR_REGS, + &h264_ctx->regs.h26x_addr, + sizeof(h264_ctx->regs.h26x_addr)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) +{ + const struct v4l2_ctrl_h264_decode_params *dec_params =3D run->decode_par= ams; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + dma_addr_t priv_start_addr =3D h264_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + struct vdpu383_regs_h26x *regs =3D &h264_ctx->regs; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + dma_addr_t dst_addr; + u32 hor_virstride; + u32 ver_virstride; + u32 y_virstride; + u32 offset; + u32 pixels; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set H264 mode */ + regs->common.reg008_dec_mode =3D VDPU383_MODE_H264; + + /* Set input stream length */ + regs->h26x_params.reg066_stream_len =3D vb2_get_plane_payload(&src_buf->v= b2_buf, 0); + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->h26x_params.reg068_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg069_raster_uv_hor_virstride =3D hor_virstride / 16; + regs->h26x_params.reg070_y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg010.strmd_auto_gating_e =3D 1; + regs->common.reg010.inter_auto_gating_e =3D 1; + regs->common.reg010.intra_auto_gating_e =3D 1; + regs->common.reg010.transd_auto_gating_e =3D 1; + regs->common.reg010.recon_auto_gating_e =3D 1; + regs->common.reg010.filterd_auto_gating_e =3D 1; + regs->common.reg010.bus_auto_gating_e =3D 1; + regs->common.reg010.ctrl_auto_gating_e =3D 1; + regs->common.reg010.rcb_auto_gating_e =3D 1; + regs->common.reg010.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < 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_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; + + h264_ctx =3D kzalloc(sizeof(*h264_ctx), GFP_KERNEL); + if (!h264_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &h264_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + h264_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + h264_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_h264_cabac_table, + sizeof(rkvdec_h264_cabac_table)); + + ctx->priv =3D h264_ctx; + + return 0; + +err_free_ctx: + kfree(h264_ctx); + return ret; +} + +static void rkvdec_h264_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, h264_ctx->priv_tbl.size, + h264_ctx->priv_tbl.cpu, h264_ctx->priv_tbl.dma); + kfree(h264_ctx); +} + +static int rkvdec_h264_run(struct rkvdec_ctx *ctx) +{ + struct v4l2_h264_reflist_builder reflist_builder; + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_h264_ctx *h264_ctx =3D ctx->priv; + struct rkvdec_h264_run run; + struct rkvdec_h264_priv_tbl *tbl =3D h264_ctx->priv_tbl.cpu; + u32 watchdog_time; + u64 timeout_threshold; + unsigned long axi_rate; + + rkvdec_h264_run_preamble(ctx, &run); + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, + run.sps, run.decode_params->dpb); + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, + h264_ctx->reflists.b1); + + assemble_hw_scaling_list(&run, &tbl->scaling_list); + assemble_hw_pps(ctx, &run); + lookup_ref_buf_idx(ctx, &run); + assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + timeout_threshold =3D h264_ctx->regs.common.reg013_core_timeout_threshold; + axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(timeout_threshold, rkvdec->link + VDPU383_LINK_TIMEOUT_THRESHOLD); + writel(0, rkvdec->link + VDPU383_LINK_IP_ENABLE); + writel(VDPU383_DEC_E_BIT, rkvdec->link + VDPU383_LINK_DEC_ENABLE); + + return 0; +} + +static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *= ctrl) +{ + if (ctrl->id =3D=3D V4L2_CID_STATELESS_H264_SPS) + return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps); + + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops =3D { + .adjust_fmt =3D rkvdec_h264_adjust_fmt, + .get_image_fmt =3D rkvdec_h264_get_image_fmt, + .start =3D rkvdec_h264_start, + .stop =3D rkvdec_h264_stop, + .run =3D rkvdec_h264_run, + .try_ctrl =3D rkvdec_h264_try_ctrl, +}; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-regs.h new file mode 100644 index 0000000000000..bc1c2b4272b0c --- /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 swreg9_important_en { + u32 fbc_e : 1; + u32 tile_e : 1; + u32 reserve0 : 2; + u32 buf_empty_en : 1; + u32 scale_down_en : 1; + u32 reserve1 : 1; + u32 pix_range_det_e : 1; + u32 av1_fgs_en : 1; + u32 reserve2 : 7; + u32 line_irq_en : 1; + u32 out_cbcr_swap : 1; + u32 fbc_force_uncompress : 1; + u32 fbc_sparse_mode : 1; + u32 reserve3 : 12; + } reg009; + + struct swreg010_block_gating_en { + u32 strmd_auto_gating_e : 1; + u32 inter_auto_gating_e : 1; + u32 intra_auto_gating_e : 1; + u32 transd_auto_gating_e : 1; + u32 recon_auto_gating_e : 1; + u32 filterd_auto_gating_e : 1; + u32 bus_auto_gating_e : 1; + u32 ctrl_auto_gating_e : 1; + u32 rcb_auto_gating_e : 1; + u32 err_prc_auto_gating_e : 1; + u32 reserve0 : 22; + } reg010; + + struct swreg011_cfg_para { + u32 reserve0 : 9; + u32 dec_timeout_dis : 1; + u32 reserve1 : 22; + } reg011; + + struct swreg012_cache_hash_mask { + u32 reserve0 : 7; + u32 cache_hash_mask : 25; + } reg012; + + u32 reg013_core_timeout_threshold; + + struct swreg014_line_irq_ctrl { + u32 dec_line_irq_step : 16; + u32 dec_line_offset_y_st : 16; + } reg014; + + struct swreg015_irq_sta { + u32 rkvdec_frame_rdy_sta : 1; + u32 rkvdec_strm_error_sta : 1; + u32 rkvdec_core_timeout_sta : 1; + u32 rkvdec_ip_timeout_sta : 1; + u32 rkvdec_bus_error_sta : 1; + u32 rkvdec_buffer_empty_sta : 1; + u32 rkvdec_colmv_ref_error_sta : 1; + u32 rkvdec_error_spread_sta : 1; + u32 create_core_timeout_sta : 1; + u32 wlast_miss_match_sta : 1; + u32 rkvdec_core_rst_rdy_sta : 1; + u32 rkvdec_ip_rst_rdy_sta : 1; + u32 force_busidle_rdy_sta : 1; + u32 ltb_pause_rdy_sta : 1; + u32 ltb_end_flag : 1; + u32 unsupport_decmode_error_sta : 1; + u32 wmask_bits : 15; + u32 reserve0 : 1; + } reg015; + + struct swreg016_error_ctrl_set { + u32 error_proc_disable : 1; + u32 reserve0 : 7; + u32 error_spread_disable : 1; + u32 reserve1 : 15; + u32 roi_error_ctu_cal_en : 1; + u32 reserve2 : 7; + } reg016; + + struct swreg017_err_roi_ctu_offset_start { + u32 roi_x_ctu_offset_st : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_st : 12; + u32 reserve1 : 4; + } reg017; + + struct swreg018_err_roi_ctu_offset_end { + u32 roi_x_ctu_offset_end : 12; + u32 reserve0 : 4; + u32 roi_y_ctu_offset_end : 12; + u32 reserve1 : 4; + } reg018; + + struct swreg019_error_ref_info { + u32 avs2_ref_error_field : 1; + u32 avs2_ref_error_topfield : 1; + u32 ref_error_topfield_used : 1; + u32 ref_error_botfield_used : 1; + u32 reserve0 : 28; + } reg019; + + u32 reg020_cabac_error_en_lowbits; + u32 reg021_cabac_error_en_highbits; + + u32 reg022_reserved; + + struct swreg023_invalid_pixel_fill { + u32 fill_y : 10; + u32 fill_u : 10; + u32 fill_v : 10; + u32 reserve0 : 2; + } reg023; + + u32 reg024_026_reserved[3]; + + struct swreg027_align_en { + u32 reserve0 : 4; + u32 ctu_align_wr_en : 1; + u32 reserve1 : 27; + } reg027; + + struct swreg028_debug_perf_latency_ctrl0 { + u32 axi_perf_work_e : 1; + u32 reserve0 : 2; + u32 axi_cnt_type : 1; + u32 rd_latency_id : 8; + u32 reserve1 : 4; + u32 rd_latency_thr : 12; + u32 reserve2 : 4; + } reg028; + + struct swreg029_debug_perf_latency_ctrl1 { + u32 addr_align_type : 2; + u32 ar_cnt_id_type : 1; + u32 aw_cnt_id_type : 1; + u32 ar_count_id : 8; + u32 reserve0 : 4; + u32 aw_count_id : 8; + u32 rd_band_width_mode : 1; + u32 reserve1 : 7; + } reg029; + + struct swreg030_qos_ctrl { + u32 axi_wr_qos_level : 4; + u32 reserve0 : 4; + u32 axi_wr_qos : 4; + u32 reserve1 : 4; + u32 axi_rd_qos_level : 4; + u32 reserve2 : 4; + u32 axi_rd_qos : 4; + u32 reserve3 : 4; + } reg030; +}; + +struct vdpu383_regs_common_addr { + u32 reg128_strm_base; + u32 reg129_rps_base; + u32 reg130_cabactbl_base; + u32 reg131_gbl_base; + u32 reg132_scanlist_addr; + u32 reg133_scale_down_base; + u32 reg134_fgs_base; + u32 reg135_139_reserved[5]; + + struct rcb_info { + u32 offset; + u32 size; + } reg140_162_rcb_info[11]; +}; + +struct vdpu383_regs_h26x_addr { + u32 reg168_decout_base; + u32 reg169_error_ref_base; + u32 reg170_185_ref_base[16]; + u32 reg186_191_reserved[6]; + u32 reg192_payload_st_cur_base; + u32 reg193_fbc_payload_offset; + u32 reg194_payload_st_error_ref_base; + u32 reg195_210_payload_st_ref_base[16]; + u32 reg211_215_reserved[5]; + u32 reg216_colmv_cur_base; + u32 reg217_232_colmv_ref_base[16]; +}; + +struct vdpu383_regs_h26x_params { + u32 reg064_start_decoder; + u32 reg065_strm_start_bit; + u32 reg066_stream_len; + u32 reg067_global_len; + u32 reg068_hor_virstride; + u32 reg069_raster_uv_hor_virstride; + u32 reg070_y_virstride; + u32 reg071_scl_ref_hor_virstride; + u32 reg072_scl_ref_raster_uv_hor_virstride; + u32 reg073_scl_ref_virstride; + u32 reg074_fgs_ref_hor_virstride; + u32 reg075_079_reserved[5]; + u32 reg080_error_ref_hor_virstride; + u32 reg081_error_ref_raster_uv_hor_virstride; + u32 reg082_error_ref_virstride; + u32 reg083_ref0_hor_virstride; + u32 reg084_ref0_raster_uv_hor_virstride; + u32 reg085_ref0_virstride; + u32 reg086_ref1_hor_virstride; + u32 reg087_ref1_raster_uv_hor_virstride; + u32 reg088_ref1_virstride; + u32 reg089_ref2_hor_virstride; + u32 reg090_ref2_raster_uv_hor_virstride; + u32 reg091_ref2_virstride; + u32 reg092_ref3_hor_virstride; + u32 reg093_ref3_raster_uv_hor_virstride; + u32 reg094_ref3_virstride; + u32 reg095_ref4_hor_virstride; + u32 reg096_ref4_raster_uv_hor_virstride; + u32 reg097_ref4_virstride; + u32 reg098_ref5_hor_virstride; + u32 reg099_ref5_raster_uv_hor_virstride; + u32 reg100_ref5_virstride; + u32 reg101_ref6_hor_virstride; + u32 reg102_ref6_raster_uv_hor_virstride; + u32 reg103_ref6_virstride; + u32 reg104_ref7_hor_virstride; + u32 reg105_ref7_raster_uv_hor_virstride; + u32 reg106_ref7_virstride; +}; + +struct vdpu383_regs_h26x { + struct vdpu383_regs_common common; /* 8-30 */ + struct vdpu383_regs_h26x_params h26x_params; /* 64-74, 80-106 */ + struct vdpu383_regs_common_addr common_addr; /* 128-134, 140-161 */ + struct vdpu383_regs_h26x_addr h26x_addr; /* 168-185, 192-210, 216-232 */ +} __packed; + +#endif /* __RKVDEC_VDPU838_REGS_H__ */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/medi= a/platform/rockchip/rkvdec/rkvdec.c index 3d243b6e11445..fe33e69710bfa 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) { @@ -1297,6 +1327,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; @@ -1366,6 +1425,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 { @@ -1408,6 +1468,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 { @@ -1418,6 +1479,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", @@ -1435,6 +1522,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); @@ -1478,6 +1569,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 401221061e081..a76bc270d0062 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; @@ -185,4 +187,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 Sat Feb 7 13:05:44 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 31D3530ACE5; Thu, 18 Dec 2025 23:29: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=1766100561; cv=none; b=aNJDvpOfL+R2KWodBeTEc3wEqB9MH3ZZIM5bIe7AKsQ2gHQiqollQpowX45OmJAGwMVrCD4zx5DWpHmKRcTo6BJ43j5eZcZV76lzmwdEiR7l9jP4f9523gyykhifOGanrl/N+m03CK4/xrGKliwrR1VBwosoY0c/pi0U6pdoKPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100561; c=relaxed/simple; bh=f7JeguCu7LcGcihC4GN2MtrEztjBQniuRrz8u+fcUBU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WZcdJRrDd72wEr5GBPYvbMAVrSUeDg5G5+co1jX8o6cZT4mXHn/bV8o6Si+0GfHJPix9Cjfhtb4CFhOonRGm3CzdSH646LLuTHWqh0B+YtNds9FlWCBHH1hJNLxNn84gZ6V7bLNWL7fuYM5uMpzfug8yDJoXLsi/KEtPL/5RUIg= 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=GNKfBC41; 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="GNKfBC41" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100556; bh=f7JeguCu7LcGcihC4GN2MtrEztjBQniuRrz8u+fcUBU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GNKfBC41ApXDQcvRvWt25SmDhvhrGwdHZZJli7Y3rK88dN6yj06o8Yu/taOK8tmNH nQnqb8i6EBnIdxgPvXrkKjExVHa4BlraacDBF5R46+pTFFZWcdjq0+hEIw1dNNPNiX QsHEB0waivPVZPCZCmhLQ2+4ALCtpeHa/Qkdc+NwfTrkuIG0Pz0GaBRgy3rPvq2wTb ujFtuVlPXNIKAoTOiIqSVeZ8wn3h9TM/XygBatqYwtxwDdEdsTy2LCNJrBnS7PkBNu Xc8Ak+pLx7j1vx5MkSwLPMMUulQ76Zl+i+f2lGiJVLhUwKXi5wlLDZblWFA5Smn/AC OTQ2yC3j1J52Q== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 55BF217E13D0; Fri, 19 Dec 2025 00:29:14 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman , Diederik de Haas Subject: [PATCH v7 16/17] media: rkvdec: Add HEVC support for the VDPU381 variant Date: Thu, 18 Dec 2025 18:28:26 -0500 Message-ID: <20251218232829.337811-17-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 | 622 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 82 +++ .../media/platform/rockchip/rkvdec/rkvdec.h | 3 + 6 files changed, 1102 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 a58d4aede2fea..e30fdd7d51c3c 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 cb56a9a243927..52926c67d0189 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 e3099fdd784b1..0d7498e6a112a 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 0000000000000..6a73f587bdd1d --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -0,0 +1,622 @@ +// 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_0 =3D valid; + break; + case 1: + regs->hevc_param.reg099.hevc_ref_valid_1 =3D valid; + break; + case 2: + regs->hevc_param.reg099.hevc_ref_valid_2 =3D valid; + break; + case 3: + regs->hevc_param.reg099.hevc_ref_valid_3 =3D valid; + break; + case 4: + regs->hevc_param.reg099.hevc_ref_valid_4 =3D valid; + break; + case 5: + regs->hevc_param.reg099.hevc_ref_valid_5 =3D valid; + break; + case 6: + regs->hevc_param.reg099.hevc_ref_valid_6 =3D valid; + break; + case 7: + regs->hevc_param.reg099.hevc_ref_valid_7 =3D valid; + break; + case 8: + regs->hevc_param.reg099.hevc_ref_valid_8 =3D valid; + break; + case 9: + regs->hevc_param.reg099.hevc_ref_valid_9 =3D valid; + break; + case 10: + regs->hevc_param.reg099.hevc_ref_valid_10 =3D valid; + break; + case 11: + regs->hevc_param.reg099.hevc_ref_valid_11 =3D valid; + break; + case 12: + regs->hevc_param.reg099.hevc_ref_valid_12 =3D valid; + break; + case 13: + regs->hevc_param.reg099.hevc_ref_valid_13 =3D valid; + break; + case 14: + regs->hevc_param.reg099.hevc_ref_valid_14 =3D valid; + break; + } +} + +static void rkvdec_write_regs(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS, + &hevc_ctx->regs.common, + sizeof(hevc_ctx->regs.common)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS, + &hevc_ctx->regs.hevc_param, + sizeof(hevc_ctx->regs.hevc_param)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS, + &hevc_ctx->regs.common_addr, + sizeof(hevc_ctx->regs.common_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS, + &hevc_ctx->regs.hevc_addr, + sizeof(hevc_ctx->regs.hevc_addr)); + rkvdec_memcpy_toio(rkvdec->regs + OFFSET_POC_HIGHBIT_REGS, + &hevc_ctx->regs.hevc_highpoc, + sizeof(hevc_ctx->regs.hevc_highpoc)); +} + +static void config_registers(struct rkvdec_ctx *ctx, + struct rkvdec_hevc_run *run) +{ + const struct v4l2_ctrl_hevc_decode_params *dec_params =3D run->decode_par= ams; + const struct v4l2_hevc_dpb_entry *dpb =3D dec_params->dpb; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_vdpu381_regs_hevc *regs =3D &hevc_ctx->regs; + dma_addr_t priv_start_addr =3D hevc_ctx->priv_tbl.dma; + const struct v4l2_pix_format_mplane *dst_fmt; + struct vb2_v4l2_buffer *src_buf =3D run->base.bufs.src; + struct vb2_v4l2_buffer *dst_buf =3D run->base.bufs.dst; + const struct v4l2_format *f; + dma_addr_t rlc_addr; + u32 hor_virstride =3D 0; + u32 ver_virstride =3D 0; + u32 y_virstride =3D 0; + u32 offset; + u32 pixels; + dma_addr_t dst_addr; + u32 i; + + memset(regs, 0, sizeof(*regs)); + + /* Set HEVC mode */ + regs->common.reg009.dec_mode =3D VDPU381_MODE_HEVC; + + /* Set config */ + regs->common.reg011.buf_empty_en =3D 1; + regs->common.reg011.dec_clkgate_e =3D 1; + regs->common.reg011.dec_timeout_e =3D 1; + regs->common.reg011.pix_range_detection_e =3D 1; + + /* Set IDR flag */ + regs->common.reg013.cur_pic_is_idr =3D + !!(dec_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC); + + /* Set input stream length */ + regs->common.stream_len =3D vb2_get_plane_payload(&src_buf->vb2_buf, 0); + + /* Set max slice number */ + regs->common.reg017.slice_num =3D 1; + + /* Set strides */ + f =3D &ctx->decoded_fmt; + dst_fmt =3D &f->fmt.pix_mp; + hor_virstride =3D dst_fmt->plane_fmt[0].bytesperline; + ver_virstride =3D dst_fmt->height; + y_virstride =3D hor_virstride * ver_virstride; + pixels =3D dst_fmt->height * dst_fmt->width; + + regs->common.reg018.y_hor_virstride =3D hor_virstride / 16; + regs->common.reg019.uv_hor_virstride =3D hor_virstride / 16; + regs->common.reg020.y_virstride =3D y_virstride / 16; + + /* Activate block gating */ + regs->common.reg026.swreg_block_gating_e =3D 0xfffef; + regs->common.reg026.reg_cfg_gating_en =3D 1; + + /* Set timeout threshold */ + if (pixels < RKVDEC_1080P_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_1080p; + else if (pixels < RKVDEC_4K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_4K; + else if (pixels < RKVDEC_8K_PIXELS) + regs->common.timeout_threshold =3D RKVDEC_TIMEOUT_8K; + + /* Set POC val */ + regs->hevc_param.cur_top_poc =3D dec_params->pic_order_cnt_val; + + /* Set ref pic address & poc */ + for (i =3D 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf =3D get_ref_buf(ctx, run, i); + dma_addr_t buf_dma =3D vb2_dma_contig_plane_dma_addr(vb_buf, 0); + u32 valid =3D !!(dec_params->num_active_dpb_entries > i); + + /* Set reference addresses */ + regs->hevc_addr.ref_base[i] =3D buf_dma; + + /* Set COLMV addresses */ + regs->hevc_addr.colmv_base[i] =3D buf_dma + ctx->colmv_offset; + + regs->hevc_param.reg067_082_ref_poc[i] =3D + dpb[i].pic_order_cnt_val; + + set_ref_valid(regs, i, valid); + regs->hevc_param.reg103.ref_pic_layer_same_with_cur |=3D 1 << i; + } + + /* Set rlc base address (input stream) */ + rlc_addr =3D vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + regs->common_addr.rlc_base =3D rlc_addr; + regs->common_addr.rlcwrite_base =3D rlc_addr; + + /* Set output base address */ + dst_addr =3D vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + regs->common_addr.decout_base =3D dst_addr; + regs->common_addr.error_ref_base =3D dst_addr; + + /* Set colmv address */ + regs->common_addr.colmv_cur_base =3D dst_addr + ctx->colmv_offset; + + /* Set RCB addresses */ + for (i =3D 0; i < rkvdec_rcb_buf_count(ctx); i++) + regs->common_addr.rcb_base[i] =3D rkvdec_rcb_buf_dma_addr(ctx, i); + + /* Set hw pps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, param_set); + regs->hevc_addr.pps_base =3D priv_start_addr + offset; + + /* Set hw rps address */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, rps); + regs->hevc_addr.rps_base =3D priv_start_addr + offset; + + /* Set cabac table */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); + regs->hevc_addr.cabactbl_base =3D priv_start_addr + offset; + + /* Set scaling matrix */ + offset =3D offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); + regs->hevc_addr.scanlist_addr =3D priv_start_addr + offset; + + rkvdec_write_regs(ctx); +} + +static int rkvdec_hevc_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; + + hevc_ctx =3D kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); + if (!hevc_ctx) + return -ENOMEM; + + priv_tbl =3D dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &hevc_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret =3D -ENOMEM; + goto err_free_ctx; + } + + hevc_ctx->priv_tbl.size =3D sizeof(*priv_tbl); + hevc_ctx->priv_tbl.cpu =3D priv_tbl; + memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, + sizeof(rkvdec_hevc_cabac_table)); + + ctx->priv =3D hevc_ctx; + return 0; + +err_free_ctx: + kfree(hevc_ctx); + return ret; +} + +static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_dev *rkvdec =3D ctx->dev; + + dma_free_coherent(rkvdec->dev, hevc_ctx->priv_tbl.size, + hevc_ctx->priv_tbl.cpu, hevc_ctx->priv_tbl.dma); + kfree(hevc_ctx); +} + +static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec =3D ctx->dev; + struct rkvdec_hevc_run run; + struct rkvdec_hevc_ctx *hevc_ctx =3D ctx->priv; + struct rkvdec_hevc_priv_tbl *tbl =3D hevc_ctx->priv_tbl.cpu; + + rkvdec_hevc_run_preamble(ctx, &run); + + /* + * On vdpu381, not setting the long and short term ref sets will just out= put wrong frames. + * Let's just warn about it and let the decoder run anyway. + */ + if ((!ctx->has_sps_lt_rps && run.sps->num_long_term_ref_pics_sps) || + (!ctx->has_sps_st_rps && run.sps->num_short_term_ref_pic_sets)) { + dev_warn_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); + } + + rkvdec_hevc_assemble_hw_scaling_list(&run, + &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); + assemble_hw_pps(ctx, &run); + rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); + + /* Start decoding! */ + writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); + + return 0; +} + +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 fe33e69710bfa..8405ddb5962b8 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 a76bc270d0062..ad19f6ae562d3 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) @@ -186,6 +188,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 Sat Feb 7 13:05:44 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 15D0033A6F7; Thu, 18 Dec 2025 23:29:20 +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=1766100564; cv=none; b=SZS6xUPbPfjM+uW76R1cFV0VxRlu9BrBZCMo+qMZMc+2QilO5nNPymqYVVlfE+fimUdfuE1C41JdhsOrlFiWE3/ZN8udfLPlopwnhXbRxR+Tg6D/oZKDrvHPY1aDfwExVdyzJ/Hc5ZpiasS3rP8hauUgHrbqGfVpGClGBhHsWYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766100564; c=relaxed/simple; bh=Zz+pGGBzU+QHlNotnwq2/PnfEriPocXoQ7Pt5as2zys=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CQetVE3wqpFdN+2B7Usa45sl651Kf2+iV0thbvTuObr5O2XwKxkko9Iu8PtAAan3+CCicn0VEyzfGKKYAz4UXoNxFYSCnbprQg8VrCJ2umSuXaWZvTUqpwe1yvWYN5NihSrsFvsyXWRV/YiT0+4IAhjxJfHB3dijYQoWpUYCNmQ= 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=COtMt8z0; 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="COtMt8z0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1766100559; bh=Zz+pGGBzU+QHlNotnwq2/PnfEriPocXoQ7Pt5as2zys=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=COtMt8z013ojZnBffr2xRXbOa5Ovi69zr1OW5v6rKr26mie113nqmTa1y2P+5+jcm KQ5I0I/B6wg11k+Hsz1NT5WWRuxlskJG1Gi8q7+ppkTC/HQsiLr+Q9V+lbETHWwvK9 YsyXa58DfdfrLIcNHY+zVsDDaYowbieFKC1w7pSV2+jfRiWiGwAtTEKRRq9gdExEBa TlcmJj1D7XAt/q1A77JcumOqL+Iaa4d0JYdmK7mIt4OYOE3NVBFY7H182S2SZ1zRFD Wdo9SV9HXpSiSqyUgtEiQwFan02nLzJT4LWS7hjSU3C2c1aEVPAuCnoJ8Zk6csSl3n +h1A7w4H/0ZQg== Received: from earth.mtl.collabora.ca (mtl.collabora.ca [66.171.169.34]) (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 0A5C217E156E; Fri, 19 Dec 2025 00:29:16 +0100 (CET) From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Mauro Carvalho Chehab , Detlev Casanova , Ezequiel Garcia , Heiko Stuebner , Daniel Almeida , Jonathan Corbet , Ricardo Ribalda , Hans Verkuil , Yunke Cao , Hans de Goede , Laurent Pinchart , Nicolas Dufresne , Pavan Bobba , Sakari Ailus , James Cowgill , linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, Jonas Karlman Subject: [PATCH v7 17/17] media: rkvdec: Add HEVC support for the VDPU383 variant Date: Thu, 18 Dec 2025 18:28:27 -0500 Message-ID: <20251218232829.337811-18-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251218232829.337811-1-detlev.casanova@collabora.com> References: <20251218232829.337811-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 | 720 ++++++++++++++++++ .../media/platform/rockchip/rkvdec/rkvdec.c | 91 +++ .../media/platform/rockchip/rkvdec/rkvdec.h | 2 + 8 files changed, 833 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 e30fdd7d51c3c..e629d571e4d89 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 52926c67d0189..81f41bf661d35 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 0d7498e6a112a..96521d7234776 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 156ce381f0680..89b70ca27127f 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 6a73f587bdd1d..c342c7838040f 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -586,8 +586,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) dev_warn_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); } =20 - rkvdec_hevc_assemble_hw_scaling_list(&run, - &tbl->scaling_list, + rkvdec_hevc_assemble_hw_scaling_list(ctx, &run, &tbl->scaling_list, &hevc_ctx->scaling_matrix_cache); assemble_hw_pps(ctx, &run); rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c b= /drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c new file mode 100644 index 0000000000000..26c49f79f07f5 --- /dev/null +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c @@ -0,0 +1,720 @@ +// 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.strmd_auto_gating_e =3D 1; + regs->common.reg010.inter_auto_gating_e =3D 1; + regs->common.reg010.intra_auto_gating_e =3D 1; + regs->common.reg010.transd_auto_gating_e =3D 1; + regs->common.reg010.recon_auto_gating_e =3D 1; + regs->common.reg010.filterd_auto_gating_e =3D 1; + regs->common.reg010.bus_auto_gating_e =3D 1; + regs->common.reg010.ctrl_auto_gating_e =3D 1; + regs->common.reg010.rcb_auto_gating_e =3D 1; + regs->common.reg010.err_prc_auto_gating_e =3D 1; + + /* Set timeout threshold */ + if (pixels < 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_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 watchdog_time; + u64 timeout_threshold; + unsigned long axi_rate; + + rkvdec_hevc_run_preamble(ctx, &run); + + /* + * On vdpu383, not setting the long and short term ref sets leads to IOMM= U page faults. + * To be on the safe side for this new v4l2 control, write an error in th= e log and mark + * the buffer as failed by returning an error here. + */ + if ((!ctx->has_sps_lt_rps && run.sps->num_long_term_ref_pics_sps) || + (!ctx->has_sps_st_rps && run.sps->num_short_term_ref_pic_sets)) { + dev_err_ratelimited(rkvdec->dev, "Long and short term RPS not set\n"); + return -EINVAL; + } + + rkvdec_hevc_assemble_hw_scaling_list(ctx, &run, &tbl->scaling_list, + &hevc_ctx->scaling_matrix_cache); + assemble_hw_pps(ctx, &run); + rkvdec_hevc_assemble_hw_rps(&run, &tbl->rps, &hevc_ctx->st_cache); + + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + /* Set watchdog at 2 times the hardware timeout threshold */ + timeout_threshold =3D hevc_ctx->regs.common.reg013_core_timeout_threshold; + axi_rate =3D clk_get_rate(rkvdec->axi_clk); + + if (axi_rate) + watchdog_time =3D 2 * (1000 * timeout_threshold) / axi_rate; + else + watchdog_time =3D 2000; + schedule_delayed_work(&rkvdec->watchdog_work, + msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(timeout_threshold, rkvdec->link + VDPU383_LINK_TIMEOUT_THRESHOLD); + writel(VDPU383_IP_CRU_MODE, rkvdec->link + VDPU383_LINK_IP_ENABLE); + writel(VDPU383_DEC_E_BIT, rkvdec->link + VDPU383_LINK_DEC_ENABLE); + + return 0; +} + +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 8405ddb5962b8..e547057dc75f9 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 { @@ -1447,6 +1463,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; @@ -1508,6 +1596,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 { @@ -1551,6 +1640,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 { @@ -1577,6 +1667,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 ad19f6ae562d3..c87d637770d36 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 { @@ -192,5 +193,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