diff --git a/config/kernel/linux-rk322x-current.config b/config/kernel/linux-rk322x-current.config index 7a30d7d00..061a46519 100644 --- a/config/kernel/linux-rk322x-current.config +++ b/config/kernel/linux-rk322x-current.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.10.27 Kernel Configuration +# Linux/arm 5.10.50 Kernel Configuration # CONFIG_CC_VERSION_TEXT="arm-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0" CONFIG_CC_IS_GCC=y @@ -1847,7 +1847,12 @@ CONFIG_VIRTIO_BLK=m # # NVME Support # +CONFIG_NVME_CORE=m +# CONFIG_NVME_MULTIPATH is not set +# CONFIG_NVME_HWMON is not set +CONFIG_NVME_FABRICS=m # CONFIG_NVME_FC is not set +CONFIG_NVME_TCP=m # CONFIG_NVME_TARGET is not set # end of NVME Support @@ -2381,6 +2386,7 @@ CONFIG_WLAN_VENDOR_TI=y # CONFIG_WL12XX is not set # CONFIG_WL18XX is not set # CONFIG_WLCORE is not set +# CONFIG_RTL8822BS is not set CONFIG_RTL8723DU=m CONFIG_RTL8723DS=m CONFIG_RTL8822BU=m @@ -5737,7 +5743,6 @@ CONFIG_AD7768_1=m # CONFIG_AD7923 is not set # CONFIG_AD7949 is not set # CONFIG_AD799X is not set -# CONFIG_AD9467 is not set # CONFIG_ADI_AXI_ADC is not set # CONFIG_CC10001_ADC is not set # CONFIG_CPCAP_ADC is not set @@ -6442,7 +6447,6 @@ CONFIG_PSTORE_CONSOLE=y # CONFIG_PSTORE_PMSG is not set # CONFIG_PSTORE_FTRACE is not set CONFIG_PSTORE_RAM=y -# CONFIG_PSTORE_BLK is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_EROFS_FS is not set diff --git a/config/kernel/linux-rk322x-edge.config b/config/kernel/linux-rk322x-edge.config index b547c3935..97078d51d 100644 --- a/config/kernel/linux-rk322x-edge.config +++ b/config/kernel/linux-rk322x-edge.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.12.5 Kernel Configuration +# Linux/arm 5.12.17 Kernel Configuration # CONFIG_CC_VERSION_TEXT="arm-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0" CONFIG_CC_IS_GCC=y @@ -1971,7 +1971,12 @@ CONFIG_VIRTIO_BLK=m # # NVME Support # +CONFIG_NVME_CORE=m +# CONFIG_NVME_MULTIPATH is not set +# CONFIG_NVME_HWMON is not set +CONFIG_NVME_FABRICS=m # CONFIG_NVME_FC is not set +CONFIG_NVME_TCP=m # CONFIG_NVME_TARGET is not set # end of NVME Support @@ -2507,8 +2512,8 @@ CONFIG_WLAN_VENDOR_TI=y # CONFIG_WL12XX is not set # CONFIG_WL18XX is not set # CONFIG_WLCORE is not set +# CONFIG_RTL8822BS is not set CONFIG_RTL8723DU=m -CONFIG_RTL8723DS=m CONFIG_RTL8822BU=m CONFIG_RTL8188EU=m CONFIG_RTL8821CU=m @@ -6622,7 +6627,6 @@ CONFIG_PSTORE_CONSOLE=y # CONFIG_PSTORE_PMSG is not set # CONFIG_PSTORE_FTRACE is not set CONFIG_PSTORE_RAM=y -# CONFIG_PSTORE_BLK is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_EROFS_FS is not set diff --git a/patch/kernel/archive/rk322x-5.10/01-linux-0010-v4l-from-list.patch b/patch/kernel/archive/rk322x-5.10/01-linux-0010-v4l-from-list.patch deleted file mode 100644 index cbdca440a..000000000 --- a/patch/kernel/archive/rk322x-5.10/01-linux-0010-v4l-from-list.patch +++ /dev/null @@ -1,4216 +0,0 @@ -From df70311e9ceb74ced1d16f58d26b1b0939878cd3 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:33 +0000 -Subject: [PATCH] media: rkvdec: h264: Fix reference frame_num wrap for second - field - -When decoding the second field in a complementary field pair the second -field is sharing the same frame_num with the first field. - -Currently the frame_num for the first field is wrapped when it matches the -field being decoded, this cause issues to decode the second field in a -complementary field pair. - -Fix this by using inclusive comparison, less than or equal. - -Signed-off-by: Jonas Karlman -Reviewed-by: Ezequiel Garcia ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 7cc3b478a5f4..054d2e3eed67 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -752,7 +752,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - continue; - - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM || -- dpb[i].frame_num < dec_params->frame_num) { -+ dpb[i].frame_num <= dec_params->frame_num) { - p[i] = dpb[i].frame_num; - continue; - } - -From 226b2391c4fac1651979a069e31c3356df6b9042 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:34 +0000 -Subject: [PATCH] media: rkvdec: Ensure decoded resolution fit coded resolution - -Ensure decoded CAPTURE buffer resolution is larger or equal to the coded -OPTUPT buffer resolution. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index d25c4a37e2af..b3e067031c83 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -223,6 +223,8 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, - pix_mp->pixelformat = coded_desc->decoded_fmts[0]; - - /* Always apply the frmsize constraint of the coded end. */ -+ pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); -+ pix_mp->height = max(pix_mp->height, ctx->coded_fmt.fmt.pix_mp.height); - v4l2_apply_frmsize_constraints(&pix_mp->width, - &pix_mp->height, - &coded_desc->frmsize); - -From eb75d2223e1a64e2e623b50d6fbb8dd3e92d9869 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:34 +0000 -Subject: [PATCH] media: rkvdec: h264: Validate and use pic width and height in - mbs - -The width and height in mbs is currently configured based on OUTPUT buffer -resolution, this works for frame pictures but can cause issues for field -pictures. - -When frame_mbs_only_flag is 0 the height in mbs should be height of -the field instead of height of frame. - -Validate pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1 -against OUTPUT buffer resolution and use these values to configure HW. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- - drivers/staging/media/rkvdec/rkvdec.c | 10 ++++++++++ - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 054d2e3eed67..d46424ba88e8 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -671,8 +671,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, - LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4); - WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO), - DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG); -- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS); -- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS); -+ WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS); -+ WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS); - WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY), - FRAME_MBS_ONLY_FLAG); - WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD), -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index b3e067031c83..06fc58440cd3 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -29,8 +29,11 @@ - - static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - { -+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); -+ - if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { - const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; -+ unsigned int width, height; - /* - * TODO: The hardware supports 10-bit and 4:2:2 profiles, - * but it's currently broken in the driver. -@@ -45,6 +48,13 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - if (sps->bit_depth_luma_minus8 != 0) - /* Only 8-bit is supported */ - return -EINVAL; -+ -+ width = (sps->pic_width_in_mbs_minus1 + 1) * 16; -+ height = (sps->pic_height_in_map_units_minus1 + 1) * 16; -+ -+ if (width > ctx->coded_fmt.fmt.pix_mp.width || -+ height > ctx->coded_fmt.fmt.pix_mp.height) -+ return -EINVAL; - } - return 0; - } - -From e97a5b83858e9e23d9c507c23fd79bbb139a33a1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:35 +0000 -Subject: [PATCH] media: rkvdec: h264: Fix bit depth wrap in pps packet - -The luma and chroma bit depth fields in the pps packet is 3 bits wide. -8 is wrongly added to the bit depth value written to these 3-bit fields. -Because only the 3 LSB is written the hardware is configured correctly. - -Correct this by not adding 8 to the luma and chroma bit depth value. - -Signed-off-by: Jonas Karlman -Reviewed-by: Ezequiel Garcia ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index d46424ba88e8..6536cf0d6054 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -661,8 +661,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, - WRITE_PPS(0xff, PROFILE_IDC); - WRITE_PPS(1, CONSTRAINT_SET3_FLAG); - WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC); -- WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); -- WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); -+ WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA); -+ WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA); - WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG); - WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4); - WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES); - -From c875840c995082de33ca342b4ff2e620abf54abf Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:35 +0000 -Subject: [PATCH] media: rkvdec: h264: Do not override output buffer sizeimage - -The output buffer sizeimage is currently forced to 2 bytes per pixel, this -can lead to high memory usage for 4K content when multiple output buffers -is created by userspace. - -Do not override output buffer sizeimage and let userspace have control of -output buffer sizeimage by only setting sizeimage if none is provided. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 6536cf0d6054..bf632d45282b 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, - struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; - - fmt->num_planes = 1; -- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * -- RKVDEC_H264_MAX_DEPTH_IN_BYTES; -+ if (!fmt->plane_fmt[0].sizeimage) -+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * -+ RKVDEC_H264_MAX_DEPTH_IN_BYTES; - return 0; - } - - -From 0b8704eecf6b6a77daa4a5aa5b78f2359895f065 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:35 +0000 -Subject: [PATCH] media: v4l2-common: Add helpers to calculate bytesperline and - sizeimage - -Add helper functions to calculate plane bytesperline and sizeimage, these -new helpers consider block width and height when calculating plane -bytesperline and sizeimage. - -This prepare support for new pixel formats added in next patch that make -use of block width and height. - -Signed-off-by: Jonas Karlman ---- - drivers/media/v4l2-core/v4l2-common.c | 77 +++++++++++++-------------- - 1 file changed, 38 insertions(+), 39 deletions(-) - -diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c -index 3dc17ebe14fa..4102c373b48a 100644 ---- a/drivers/media/v4l2-core/v4l2-common.c -+++ b/drivers/media/v4l2-core/v4l2-common.c -@@ -333,6 +333,33 @@ static inline unsigned int v4l2_format_block_height(const struct v4l2_format_inf - return info->block_h[plane]; - } - -+static inline unsigned int v4l2_format_plane_width(const struct v4l2_format_info *info, int plane, -+ unsigned int width) -+{ -+ unsigned int hdiv = plane ? info->hdiv : 1; -+ unsigned int bytes = DIV_ROUND_UP(width * info->bpp[plane], -+ v4l2_format_block_width(info, plane) * -+ v4l2_format_block_height(info, plane)); -+ -+ return DIV_ROUND_UP(bytes, hdiv); -+} -+ -+static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane, -+ unsigned int height) -+{ -+ unsigned int vdiv = plane ? info->vdiv : 1; -+ unsigned int lines = ALIGN(height, v4l2_format_block_height(info, plane)); -+ -+ return DIV_ROUND_UP(lines, vdiv); -+} -+ -+static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane, -+ unsigned int width, unsigned int height) -+{ -+ return v4l2_format_plane_width(info, plane, width) * -+ v4l2_format_plane_height(info, plane, height); -+} -+ - void v4l2_apply_frmsize_constraints(u32 *width, u32 *height, - const struct v4l2_frmsize_stepwise *frmsize) - { -@@ -368,37 +395,19 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, - - if (info->mem_planes == 1) { - plane = &pixfmt->plane_fmt[0]; -- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; -+ plane->bytesperline = v4l2_format_plane_width(info, 0, width); - plane->sizeimage = 0; - -- for (i = 0; i < info->comp_planes; i++) { -- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; -- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; -- unsigned int aligned_width; -- unsigned int aligned_height; -- -- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); -- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); -- -- plane->sizeimage += info->bpp[i] * -- DIV_ROUND_UP(aligned_width, hdiv) * -- DIV_ROUND_UP(aligned_height, vdiv); -- } -+ for (i = 0; i < info->comp_planes; i++) -+ plane->sizeimage += -+ v4l2_format_plane_size(info, i, width, height); - } else { - for (i = 0; i < info->comp_planes; i++) { -- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; -- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; -- unsigned int aligned_width; -- unsigned int aligned_height; -- -- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); -- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); -- - plane = &pixfmt->plane_fmt[i]; - plane->bytesperline = -- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); -- plane->sizeimage = -- plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); -+ v4l2_format_plane_width(info, i, width); -+ plane->sizeimage = plane->bytesperline * -+ v4l2_format_plane_height(info, i, height); - } - } - return 0; -@@ -422,22 +431,12 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, - pixfmt->width = width; - pixfmt->height = height; - pixfmt->pixelformat = pixelformat; -- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; -+ pixfmt->bytesperline = v4l2_format_plane_width(info, 0, width); - pixfmt->sizeimage = 0; - -- for (i = 0; i < info->comp_planes; i++) { -- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; -- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; -- unsigned int aligned_width; -- unsigned int aligned_height; -- -- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); -- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); -- -- pixfmt->sizeimage += info->bpp[i] * -- DIV_ROUND_UP(aligned_width, hdiv) * -- DIV_ROUND_UP(aligned_height, vdiv); -- } -+ for (i = 0; i < info->comp_planes; i++) -+ pixfmt->sizeimage += -+ v4l2_format_plane_size(info, i, width, height); - return 0; - } - EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); - -From 28d45e94fc74ebdad92e561c0f99f604f2a4adc3 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:36 +0000 -Subject: [PATCH] media: v4l2: Add NV15 and NV20 pixel formats - -Add NV15 and NV20 pixel formats used by the Rockchip Video Decoder for -10-bit buffers. - -NV15 and NV20 is a packed 10-bit 4:2:0/4:2:2 semi-planar Y/CbCr format -similar to P010 and P210 but has no padding between components. Instead, -luminance and chrominance samples are grouped into 4s so that each group is -packed into an integer number of bytes: - -YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes - -The '15' and '20' suffix refers to the optimum effective bits per pixel -which is achieved when the total number of luminance samples is a multiple -of 8 for NV15 and 4 for NV20. - -Signed-off-by: Jonas Karlman ---- - .../userspace-api/media/v4l/pixfmt-nv15.rst | 101 ++++++++++++++++++ - .../userspace-api/media/v4l/pixfmt-nv20.rst | 99 +++++++++++++++++ - .../userspace-api/media/v4l/yuv-formats.rst | 2 + - drivers/media/v4l2-core/v4l2-common.c | 3 + - drivers/media/v4l2-core/v4l2-ioctl.c | 2 + - include/uapi/linux/videodev2.h | 3 + - 6 files changed, 210 insertions(+) - create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv15.rst - create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv20.rst - -diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst -new file mode 100644 -index 000000000000..d059db58c6e0 ---- /dev/null -+++ b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst -@@ -0,0 +1,101 @@ -+.. Permission is granted to copy, distribute and/or modify this -+.. document under the terms of the GNU Free Documentation License, -+.. Version 1.1 or any later version published by the Free Software -+.. Foundation, with no Invariant Sections, no Front-Cover Texts -+.. and no Back-Cover Texts. A copy of the license is included at -+.. Documentation/userspace-api/media/fdl-appendix.rst. -+.. -+.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections -+ -+.. _V4L2-PIX-FMT-NV15: -+ -+************************** -+V4L2_PIX_FMT_NV15 ('NV15') -+************************** -+ -+Format with ½ horizontal and vertical chroma resolution, also known as -+YUV 4:2:0. One luminance and one chrominance plane with alternating -+chroma samples similar to ``V4L2_PIX_FMT_NV12`` but with 10-bit samples -+that are grouped into four and packed into five bytes. -+ -+The '15' suffix refers to the optimum effective bits per pixel which is -+achieved when the total number of luminance samples is a multiple of 8. -+ -+ -+Description -+=========== -+ -+This is a packed 10-bit two-plane version of the YUV 4:2:0 format. The -+three components are separated into two sub-images or planes. The Y plane -+is first. The Y plane has five bytes per each group of four pixels. A -+combined CbCr plane immediately follows the Y plane in memory. The CbCr -+plane is the same width, in bytes, as the Y plane (and of the image), but -+is half as tall in pixels. Each CbCr pair belongs to four pixels. For -+example, Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, -+Y'\ :sub:`01`, Y'\ :sub:`10`, Y'\ :sub:`11`. -+ -+If the Y plane has pad bytes after each row, then the CbCr plane has as -+many pad bytes after its rows. -+ -+**Byte Order.** -+Little endian. Each cell is one byte. Pixels cross the byte boundary. -+ -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ -+ * - start + 0: -+ - Y'\ :sub:`00[7:0]` -+ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` -+ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` -+ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` -+ - Y'\ :sub:`03[9:2]` -+ * - start + 5: -+ - Y'\ :sub:`10[7:0]` -+ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` -+ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` -+ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` -+ - Y'\ :sub:`13[9:2]` -+ * - start + 10: -+ - Cb'\ :sub:`00[7:0]` -+ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` -+ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` -+ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` -+ - Cr'\ :sub:`01[9:2]` -+ -+ -+**Color Sample Location:** -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ -+ * - -+ - 0 -+ - -+ - 1 -+ - 2 -+ - -+ - 3 -+ * - 0 -+ - Y -+ - -+ - Y -+ - Y -+ - -+ - Y -+ * - -+ - -+ - C -+ - -+ - -+ - C -+ - -+ * - 1 -+ - Y -+ - -+ - Y -+ - Y -+ - -+ - Y -diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst -new file mode 100644 -index 000000000000..a8123be0baa3 ---- /dev/null -+++ b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst -@@ -0,0 +1,99 @@ -+.. Permission is granted to copy, distribute and/or modify this -+.. document under the terms of the GNU Free Documentation License, -+.. Version 1.1 or any later version published by the Free Software -+.. Foundation, with no Invariant Sections, no Front-Cover Texts -+.. and no Back-Cover Texts. A copy of the license is included at -+.. Documentation/userspace-api/media/fdl-appendix.rst. -+.. -+.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections -+ -+.. _V4L2-PIX-FMT-NV20: -+ -+************************** -+V4L2_PIX_FMT_NV20 ('NV20') -+************************** -+ -+Format with ½ horizontal chroma resolution, also known as YUV 4:2:2. -+One luminance and one chrominance plane with alternating chroma samples -+similar to ``V4L2_PIX_FMT_NV16`` but with 10-bit samples -+that are grouped into four and packed into five bytes. -+ -+The '20' suffix refers to the optimum effective bits per pixel which is -+achieved when the total number of luminance samples is a multiple of 4. -+ -+ -+Description -+=========== -+ -+This is a packed 10-bit two-plane version of the YUV 4:2:2 format. The -+three components are separated into two sub-images or planes. The Y plane -+is first. The Y plane has five bytes per each group of four pixels. A -+combined CbCr plane immediately follows the Y plane in memory. The CbCr -+plane is the same width and height, in bytes, as the Y plane (and of the -+image). Each CbCr pair belongs to two pixels. For example, -+Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, Y'\ :sub:`01`. -+ -+If the Y plane has pad bytes after each row, then the CbCr plane has as -+many pad bytes after its rows. -+ -+**Byte Order.** -+Little endian. Each cell is one byte. Pixels cross the byte boundary. -+ -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ -+ * - start + 0: -+ - Y'\ :sub:`00[7:0]` -+ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` -+ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` -+ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` -+ - Y'\ :sub:`03[9:2]` -+ * - start + 5: -+ - Y'\ :sub:`10[7:0]` -+ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` -+ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` -+ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` -+ - Y'\ :sub:`13[9:2]` -+ * - start + 10: -+ - Cb'\ :sub:`00[7:0]` -+ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` -+ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` -+ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` -+ - Cr'\ :sub:`01[9:2]` -+ * - start + 15: -+ - Cb'\ :sub:`10[7:0]` -+ - Cr'\ :sub:`10[5:0]`\ Cb'\ :sub:`10[9:8]` -+ - Cb'\ :sub:`11[3:0]`\ Cr'\ :sub:`10[9:6]` -+ - Cr'\ :sub:`11[1:0]`\ Cb'\ :sub:`11[9:4]` -+ - Cr'\ :sub:`11[9:2]` -+ -+ -+**Color Sample Location:** -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ -+ * - -+ - 0 -+ - -+ - 1 -+ - 2 -+ - -+ - 3 -+ * - 0 -+ - Y -+ - C -+ - Y -+ - Y -+ - C -+ - Y -+ * - 1 -+ - Y -+ - C -+ - Y -+ - Y -+ - C -+ - Y -diff --git a/Documentation/userspace-api/media/v4l/yuv-formats.rst b/Documentation/userspace-api/media/v4l/yuv-formats.rst -index 4a05a105a9e6..e08e5dbdacea 100644 ---- a/Documentation/userspace-api/media/v4l/yuv-formats.rst -+++ b/Documentation/userspace-api/media/v4l/yuv-formats.rst -@@ -54,4 +54,6 @@ to brightness information. - pixfmt-nv16 - pixfmt-nv16m - pixfmt-nv24 -+ pixfmt-nv15 -+ pixfmt-nv20 - pixfmt-m420 -diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c -index 4102c373b48a..0caac755d303 100644 ---- a/drivers/media/v4l2-core/v4l2-common.c -+++ b/drivers/media/v4l2-core/v4l2-common.c -@@ -267,6 +267,9 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) - { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - -+ { .format = V4L2_PIX_FMT_NV15, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 2, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, -+ { .format = V4L2_PIX_FMT_NV20, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 1, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, -+ - { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index eeff398fbdcc..80cb42450a1b 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1319,6 +1319,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) - case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break; - case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break; - case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break; -+ case V4L2_PIX_FMT_NV15: descr = "10-bit Y/CbCr 4:2:0 (Packed)"; break; -+ case V4L2_PIX_FMT_NV20: descr = "10-bit Y/CbCr 4:2:2 (Packed)"; break; - case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break; - case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break; - case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break; -diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h -index 534eaa4d39bc..f21eba15ceae 100644 ---- a/include/uapi/linux/videodev2.h -+++ b/include/uapi/linux/videodev2.h -@@ -609,6 +609,9 @@ struct v4l2_pix_format { - #define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */ - #define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */ - -+#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit packed */ -+#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/CbCr 4:2:2 10-bit packed */ -+ - /* two non contiguous planes - one Y, one Cr + Cb interleaved */ - #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ - #define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ - -From 1e18a042326b9e3b659b259b36c0d006ce0f48ad Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:36 +0000 -Subject: [PATCH] media: rkvdec: h264: Use bytesperline and buffer height to - calculate stride - -Use bytesperline and buffer height to calculate the strides configured. - -This does not really change anything other than ensuring the bytesperline -that is signaled to userspace matches what is configured in HW. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index bf632d45282b..6f2d41b2e076 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -893,9 +893,9 @@ static void config_registers(struct rkvdec_ctx *ctx, - dma_addr_t rlc_addr; - dma_addr_t refer_addr; - u32 rlc_len; -- u32 hor_virstride = 0; -- u32 ver_virstride = 0; -- u32 y_virstride = 0; -+ u32 hor_virstride; -+ u32 ver_virstride; -+ u32 y_virstride; - u32 yuv_virstride = 0; - u32 offset; - dma_addr_t dst_addr; -@@ -906,8 +906,8 @@ static void config_registers(struct rkvdec_ctx *ctx, - - f = &ctx->decoded_fmt; - dst_fmt = &f->fmt.pix_mp; -- hor_virstride = (sps->bit_depth_luma_minus8 + 8) * dst_fmt->width / 8; -- ver_virstride = round_up(dst_fmt->height, 16); -+ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; -+ ver_virstride = dst_fmt->height; - y_virstride = hor_virstride * ver_virstride; - - if (sps->chroma_format_idc == 0) - -From f4eb3cf298b45fd835483bcc92e299031c45b8f7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:37 +0000 -Subject: [PATCH] media: rkvdec: Extract rkvdec_fill_decoded_pixfmt helper - method - -This extract setting decoded pixfmt into a helper method, current code is -replaced with a call to the new helper method. - -The helper method is also called from a new function in next patch. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec.c | 29 ++++++++++++++------------- - 1 file changed, 15 insertions(+), 14 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 06fc58440cd3..dc16bf8d57a9 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -27,6 +27,17 @@ - #include "rkvdec.h" - #include "rkvdec-regs.h" - -+static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp) -+{ -+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, -+ pix_mp->width, pix_mp->height); -+ pix_mp->plane_fmt[0].sizeimage += 128 * -+ DIV_ROUND_UP(pix_mp->width, 16) * -+ DIV_ROUND_UP(pix_mp->height, 16); -+ pix_mp->field = V4L2_FIELD_NONE; -+} -+ - static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - { - struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); -@@ -167,13 +178,9 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) - - rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -- v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, -- ctx->coded_fmt_desc->decoded_fmts[0], -- ctx->coded_fmt.fmt.pix_mp.width, -- ctx->coded_fmt.fmt.pix_mp.height); -- f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 * -- DIV_ROUND_UP(f->fmt.pix_mp.width, 16) * -- DIV_ROUND_UP(f->fmt.pix_mp.height, 16); -+ f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; -+ f->fmt.pix_mp.height = ctx->coded_fmt.fmt.pix_mp.height; -+ rkvdec_fill_decoded_pixfmt(ctx, &f->fmt.pix_mp); - } - - static int rkvdec_enum_framesizes(struct file *file, void *priv, -@@ -239,13 +246,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, - &pix_mp->height, - &coded_desc->frmsize); - -- v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, -- pix_mp->width, pix_mp->height); -- pix_mp->plane_fmt[0].sizeimage += -- 128 * -- DIV_ROUND_UP(pix_mp->width, 16) * -- DIV_ROUND_UP(pix_mp->height, 16); -- pix_mp->field = V4L2_FIELD_NONE; -+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); - - return 0; - } - -From a63d03a5130710d6ff90846c26534a819617ee3a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:37 +0000 -Subject: [PATCH] media: rkvdec: Lock capture pixel format in s_ctrl and s_fmt - -Add an optional valid_fmt operation that should return the valid -pixelformat of CAPTURE buffers. - -This is used in next patch to ensure correct pixelformat is used for 10-bit -and 4:2:2 content. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec.c | 59 ++++++++++++++++++++++++--- - drivers/staging/media/rkvdec/rkvdec.h | 2 + - 2 files changed, 55 insertions(+), 6 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index dc16bf8d57a9..6b2a2f4164b2 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -38,6 +38,16 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, - pix_mp->field = V4L2_FIELD_NONE; - } - -+static u32 rkvdec_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) -+{ -+ const struct rkvdec_coded_fmt_desc *coded_desc = ctx->coded_fmt_desc; -+ -+ if (coded_desc->ops->valid_fmt) -+ return coded_desc->ops->valid_fmt(ctx, ctrl); -+ -+ return ctx->valid_fmt; -+} -+ - static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - { - struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); -@@ -60,6 +70,10 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - /* Only 8-bit is supported */ - return -EINVAL; - -+ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) -+ /* Only current valid format */ -+ return -EINVAL; -+ - width = (sps->pic_width_in_mbs_minus1 + 1) * 16; - height = (sps->pic_height_in_map_units_minus1 + 1) * 16; - -@@ -70,8 +84,27 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - return 0; - } - -+static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); -+ -+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { -+ ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); -+ if (ctx->valid_fmt) { -+ struct v4l2_pix_format_mplane *pix_mp; -+ -+ pix_mp = &ctx->decoded_fmt.fmt.pix_mp; -+ pix_mp->pixelformat = ctx->valid_fmt; -+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); -+ } -+ } -+ -+ return 0; -+} -+ - static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { - .try_ctrl = rkvdec_try_ctrl, -+ .s_ctrl = rkvdec_s_ctrl, - }; - - static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { -@@ -176,6 +209,7 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) - { - struct v4l2_format *f = &ctx->decoded_fmt; - -+ ctx->valid_fmt = 0; - rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; -@@ -231,13 +265,17 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, - if (WARN_ON(!coded_desc)) - return -EINVAL; - -- for (i = 0; i < coded_desc->num_decoded_fmts; i++) { -- if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) -- break; -- } -+ if (ctx->valid_fmt) { -+ pix_mp->pixelformat = ctx->valid_fmt; -+ } else { -+ for (i = 0; i < coded_desc->num_decoded_fmts; i++) { -+ if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) -+ break; -+ } - -- if (i == coded_desc->num_decoded_fmts) -- pix_mp->pixelformat = coded_desc->decoded_fmts[0]; -+ if (i == coded_desc->num_decoded_fmts) -+ pix_mp->pixelformat = coded_desc->decoded_fmts[0]; -+ } - - /* Always apply the frmsize constraint of the coded end. */ - pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); -@@ -312,6 +350,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv, - return ret; - - ctx->decoded_fmt = *f; -+ ctx->valid_fmt = f->fmt.pix_mp.pixelformat; - return 0; - } - -@@ -401,6 +440,14 @@ static int rkvdec_enum_capture_fmt(struct file *file, void *priv, - if (WARN_ON(!ctx->coded_fmt_desc)) - return -EINVAL; - -+ if (ctx->valid_fmt) { -+ if (f->index) -+ return -EINVAL; -+ -+ f->pixelformat = ctx->valid_fmt; -+ return 0; -+ } -+ - if (f->index >= ctx->coded_fmt_desc->num_decoded_fmts) - return -EINVAL; - -diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h -index 77a137cca88e..e95c52e3168a 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.h -+++ b/drivers/staging/media/rkvdec/rkvdec.h -@@ -63,6 +63,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) - struct rkvdec_coded_fmt_ops { - int (*adjust_fmt)(struct rkvdec_ctx *ctx, - struct v4l2_format *f); -+ u32 (*valid_fmt)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); - int (*start)(struct rkvdec_ctx *ctx); - void (*stop)(struct rkvdec_ctx *ctx); - int (*run)(struct rkvdec_ctx *ctx); -@@ -96,6 +97,7 @@ struct rkvdec_ctx { - struct v4l2_fh fh; - struct v4l2_format coded_fmt; - struct v4l2_format decoded_fmt; -+ u32 valid_fmt; - const struct rkvdec_coded_fmt_desc *coded_fmt_desc; - struct v4l2_ctrl_handler ctrl_hdl; - struct rkvdec_dev *dev; - -From e146c2ad5f79b68d1f84aebfdcee7afa1b0da450 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:37 +0000 -Subject: [PATCH] media: rkvdec: h264: Support High 10 and 4:2:2 profiles - -Add support and enable decoding of H264 High 10 and 4:2:2 profiles. - -Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW -requirement on 10-bit format buffers. - -The new valid_fmt operation is implemented and return a valid pixelformat -for the provided SPS control. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 20 ++++++++++++++++++++ - drivers/staging/media/rkvdec/rkvdec.c | 19 +++++++++---------- - 2 files changed, 29 insertions(+), 10 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 6f2d41b2e076..c115cd362a7f 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -1021,6 +1021,25 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, - return 0; - } - -+static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) -+{ -+ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; -+ -+ if (sps->bit_depth_luma_minus8 == 0) { -+ if (sps->chroma_format_idc == 2) -+ return V4L2_PIX_FMT_NV16; -+ else -+ return V4L2_PIX_FMT_NV12; -+ } else if (sps->bit_depth_luma_minus8 == 2) { -+ if (sps->chroma_format_idc == 2) -+ return V4L2_PIX_FMT_NV20; -+ else -+ return V4L2_PIX_FMT_NV15; -+ } -+ -+ return 0; -+} -+ - static int rkvdec_h264_start(struct rkvdec_ctx *ctx) - { - struct rkvdec_dev *rkvdec = ctx->dev; -@@ -1124,6 +1143,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) - - const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = { - .adjust_fmt = rkvdec_h264_adjust_fmt, -+ .valid_fmt = rkvdec_h264_valid_fmt, - .start = rkvdec_h264_start, - .stop = rkvdec_h264_stop, - .run = rkvdec_h264_run, -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 6b2a2f4164b2..bd8ec2915fe9 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -31,7 +31,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, - struct v4l2_pix_format_mplane *pix_mp) - { - v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, -- pix_mp->width, pix_mp->height); -+ ALIGN(pix_mp->width, 64), pix_mp->height); - pix_mp->plane_fmt[0].sizeimage += 128 * - DIV_ROUND_UP(pix_mp->width, 16) * - DIV_ROUND_UP(pix_mp->height, 16); -@@ -55,19 +55,15 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { - const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; - unsigned int width, height; -- /* -- * TODO: The hardware supports 10-bit and 4:2:2 profiles, -- * but it's currently broken in the driver. -- * Reject them for now, until it's fixed. -- */ -- if (sps->chroma_format_idc > 1) -- /* Only 4:0:0 and 4:2:0 are supported */ -+ -+ if (sps->chroma_format_idc > 2) -+ /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */ - return -EINVAL; - if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) - /* Luma and chroma bit depth mismatch */ - return -EINVAL; -- if (sps->bit_depth_luma_minus8 != 0) -- /* Only 8-bit is supported */ -+ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) -+ /* Only 8-bit and 10-bit is supported */ - return -EINVAL; - - if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) -@@ -145,6 +141,9 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = { - - static const u32 rkvdec_h264_decoded_fmts[] = { - V4L2_PIX_FMT_NV12, -+ V4L2_PIX_FMT_NV15, -+ V4L2_PIX_FMT_NV16, -+ V4L2_PIX_FMT_NV20, - }; - - static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { - -From bc3510d94b7f2ccaa8152e8d08522fb166583806 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 6 Jul 2020 21:54:38 +0000 -Subject: [PATCH] media: rkvdec: h264: Support profile and level controls - -The Rockchip Video Decoder used in RK3399 supports H.264 profiles from -Baseline to High 4:2:2 up to Level 5.1, except for the Extended profile. - -Expose the V4L2_CID_MPEG_VIDEO_H264_PROFILE and the -V4L2_CID_MPEG_VIDEO_H264_LEVEL control, so that userspace can query the -driver for the list of supported profiles and level. - -Signed-off-by: Jonas Karlman -Reviewed-by: Ezequiel Garcia ---- - drivers/staging/media/rkvdec/rkvdec.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index bd8ec2915fe9..87987a782d75 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -132,6 +132,19 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { - .cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, - .cfg.max = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, - }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, -+ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, -+ .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422, -+ .cfg.menu_skip_mask = -+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), -+ .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, -+ .cfg.min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, -+ .cfg.max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1, -+ }, - }; - - static const struct rkvdec_ctrls rkvdec_h264_ctrls = { - -From 22900938ef269ca5c54d6c5e5fc83d4ba24f6d37 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Mon, 2 Nov 2020 21:05:49 +0200 -Subject: [PATCH] media: rkvdec: Fix .buf_prepare - -The driver should only set the payload on .buf_prepare if the -buffer is CAPTURE type. If an OUTPUT buffer has a zero bytesused -set by userspace then v4l2-core will set it to buffer length. - -Fixes: cd33c830448ba ("media: rkvdec: Add the rkvdec driver") -Signed-off-by: Ezequiel Garcia -Signed-off-by: Adrian Ratiu ---- - drivers/staging/media/rkvdec/rkvdec.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 87987a782d75..2e1d272a3af7 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -543,7 +543,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) - if (vb2_plane_size(vb, i) < sizeimage) - return -EINVAL; - } -- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); -+ -+ /* -+ * Buffer bytesused is written by driver for CAPTURE buffers. -+ * (if userspace passes 0 bytesused for OUTPUT buffers, v4l2-core sets -+ * it to buffer length). -+ */ -+ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) -+ vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); -+ - return 0; - } - - -From 7541cecc1d80a0072c9286411052dd24f0bcc14c Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Mon, 2 Nov 2020 21:05:50 +0200 -Subject: [PATCH] media: uapi: Add VP9 stateless decoder controls - -Add the VP9 stateless decoder controls plus the documentation that goes -with it. - -Signed-off-by: Boris Brezillon -Signed-off-by: Ezequiel Garcia -Signed-off-by: Adrian Ratiu ---- - .../userspace-api/media/v4l/biblio.rst | 10 + - .../media/v4l/ext-ctrls-codec.rst | 550 ++++++++++++++++++ - drivers/media/v4l2-core/v4l2-ctrls.c | 239 ++++++++ - drivers/media/v4l2-core/v4l2-ioctl.c | 1 + - include/media/v4l2-ctrls.h | 5 + - include/media/vp9-ctrls.h | 486 ++++++++++++++++ - 6 files changed, 1291 insertions(+) - create mode 100644 include/media/vp9-ctrls.h - -diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst -index 7869b6f6ff72..6b4a83b053f5 100644 ---- a/Documentation/userspace-api/media/v4l/biblio.rst -+++ b/Documentation/userspace-api/media/v4l/biblio.rst -@@ -407,3 +407,13 @@ VP8 - :title: RFC 6386: "VP8 Data Format and Decoding Guide" - - :author: J. Bankoski et al. -+ -+.. _vp9: -+ -+VP9 -+=== -+ -+ -+:title: VP9 Bitstream & Decoding Process Specification -+ -+:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) -diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -index ce728c757eaf..456488f2b5ca 100644 ---- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -@@ -2730,6 +2730,556 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - - - ``padding[3]`` - - Applications and drivers must set this to zero. - -+.. _v4l2-mpeg-vp9: -+ -+``V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0..3) (struct)`` -+ Stores VP9 probabilities attached to a specific frame context. The VP9 -+ specification allows using a maximum of 4 contexts. Each frame being -+ decoded refers to one of those context. See section '7.1.2 Refresh -+ probs semantics' section of :ref:`vp9` for more details about these -+ contexts. -+ -+ This control is bi-directional: -+ -+ * all 4 contexts must be initialized by userspace just after the -+ stream is started and before the first decoding request is submitted. -+ * the referenced context might be read by the kernel when a decoding -+ request is submitted, and will be updated after the decoder is done -+ decoding the frame if the `V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX` flag -+ is set. -+ * contexts will be read back by user space before each decoding request -+ to retrieve the updated probabilities. -+ * userspace will re-initialize the context to their default values when -+ a reset context is required. -+ -+ .. note:: -+ -+ This compound control is not yet part of the public kernel API and -+ it is expected to change. -+ -+.. c:type:: v4l2_ctrl_vp9_frame_ctx -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| -+ -+.. flat-table:: struct v4l2_ctrl_vp9_frame_ctx -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - struct :c:type:`v4l2_vp9_probabilities` -+ - ``probs`` -+ - Structure with VP9 probabilities attached to the context. -+ -+.. c:type:: v4l2_vp9_probabilities -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: struct v4l2_vp9_probabilities -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``tx8[2][1]`` -+ - TX 8x8 probabilities. -+ * - __u8 -+ - ``tx16[2][2]`` -+ - TX 16x16 probabilities. -+ * - __u8 -+ - ``tx32[2][3]`` -+ - TX 32x32 probabilities. -+ * - __u8 -+ - ``coef[4][2][2][6][6][3]`` -+ - Coefficient probabilities. -+ * - __u8 -+ - ``skip[3]`` -+ - Skip probabilities. -+ * - __u8 -+ - ``inter_mode[7][3]`` -+ - Inter prediction mode probabilities. -+ * - __u8 -+ - ``interp_filter[4][2]`` -+ - Interpolation filter probabilities. -+ * - __u8 -+ - ``is_inter[4]`` -+ - Is inter-block probabilities. -+ * - __u8 -+ - ``comp_mode[5]`` -+ - Compound prediction mode probabilities. -+ * - __u8 -+ - ``single_ref[5][2]`` -+ - Single reference probabilities. -+ * - __u8 -+ - ``comp_mode[5]`` -+ - Compound reference probabilities. -+ * - __u8 -+ - ``y_mode[4][9]`` -+ - Y prediction mode probabilities. -+ * - __u8 -+ - ``uv_mode[10][9]`` -+ - UV prediction mode probabilities. -+ * - __u8 -+ - ``partition[16][3]`` -+ - Partition probabilities. -+ * - __u8 -+ - ``mv.joint[3]`` -+ - Motion vector joint probabilities. -+ * - __u8 -+ - ``mv.sign[2]`` -+ - Motion vector sign probabilities. -+ * - __u8 -+ - ``mv.class[2][10]`` -+ - Motion vector class probabilities. -+ * - __u8 -+ - ``mv.class0_bit[2]`` -+ - Motion vector class0 bit probabilities. -+ * - __u8 -+ - ``mv.bits[2][10]`` -+ - Motion vector bits probabilities. -+ * - __u8 -+ - ``mv.class0_fr[2][2][3]`` -+ - Motion vector class0 fractional bit probabilities. -+ * - __u8 -+ - ``mv.fr[2][3]`` -+ - Motion vector fractional bit probabilities. -+ * - __u8 -+ - ``mv.class0_hp[2]`` -+ - Motion vector class0 high precision fractional bit probabilities. -+ * - __u8 -+ - ``mv.hp[2]`` -+ - Motion vector high precision fractional bit probabilities. -+ -+``V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (struct)`` -+ Specifies the frame parameters for the associated VP9 frame decode request. -+ This includes the necessary parameters for configuring a stateless hardware -+ decoding pipeline for VP9. The bitstream parameters are defined according -+ to :ref:`vp9`. -+ -+ .. note:: -+ -+ This compound control is not yet part of the public kernel API and -+ it is expected to change. -+ -+.. c:type:: v4l2_ctrl_vp9_frame_decode_params -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: struct v4l2_ctrl_vp9_frame_decode_params -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u32 -+ - ``flags`` -+ - Combination of V4L2_VP9_FRAME_FLAG_* flags. See -+ :c:type:`v4l2_vp9_frame_flags`. -+ * - __u16 -+ - ``compressed_header_size`` -+ - Compressed header size in bytes. -+ * - __u16 -+ - ``uncompressed_header_size`` -+ - Uncompressed header size in bytes. -+ * - __u8 -+ - ``profile`` -+ - VP9 profile. Can be 0, 1, 2 or 3. -+ * - __u8 -+ - ``reset_frame_context`` -+ - Frame context that should be used/updated when decoding the frame. -+ * - __u8 -+ - ``bit_depth`` -+ - Component depth in bits. Must be 8 for profile 0 and 1. Must 10 or 12 -+ for profile 2 and 3. -+ * - __u8 -+ - ``interpolation_filter`` -+ - Specifies the filter selection used for performing inter prediction. See -+ :c:type:`v4l2_vp9_interpolation_filter`. -+ * - __u8 -+ - ``tile_cols_log2`` -+ - Specifies the base 2 logarithm of the width of each tile (where the -+ width is measured in units of 8x8 blocks). Shall be less than or equal -+ to 6. -+ * - __u8 -+ - ``tile_rows_log2`` -+ - Specifies the base 2 logarithm of the height of each tile (where the -+ height is measured in units of 8x8 blocks) -+ * - __u8 -+ - ``tx_mode`` -+ - Specifies the TX mode. See :c:type:`v4l2_vp9_tx_mode`. -+ * - __u8 -+ - ``reference_mode`` -+ - Specifies the type of inter prediction to be used. See -+ :c:type:`v4l2_vp9_reference_mode`. -+ * - __u8 -+ - ``padding[7]`` -+ - Needed to make this struct 64 bit aligned. Shall be filled with zeroes. -+ * - __u16 -+ - ``frame_width_minus_1`` -+ - Add 1 to get the frame width expressed in pixels. -+ * - __u16 -+ - ``frame_height_minus_1`` -+ - Add 1 to get the frame height expressed in pixels. -+ * - __u16 -+ - ``frame_width_minus_1`` -+ - Add 1 to get the expected render width expressed in pixels. This is -+ not used during the decoding process but might be used by HW scalers to -+ prepare a frame that's ready for scanout. -+ * - __u16 -+ - frame_height_minus_1 -+ - Add 1 to get the expected render height expressed in pixels. This is -+ not used during the decoding process but might be used by HW scalers to -+ prepare a frame that's ready for scanout. -+ * - __u64 -+ - ``refs[3]`` -+ - Array of reference frame timestamps. -+ * - struct :c:type:`v4l2_vp9_loop_filter` -+ - ``lf`` -+ - Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter`. -+ * - struct :c:type:`v4l2_vp9_quantization` -+ - ``quant`` -+ - Quantization parameters. See :c:type:`v4l2_vp9_quantization`. -+ * - struct :c:type:`v4l2_vp9_segmentation` -+ - ``seg`` -+ - Segmentation parameters. See :c:type:`v4l2_vp9_segmentation`. -+ * - struct :c:type:`v4l2_vp9_probabilities` -+ - ``probs`` -+ - Probabilities. See :c:type:`v4l2_vp9_probabilities`. -+ -+.. c:type:: v4l2_vp9_frame_flags -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_frame_flags -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME`` -+ - The frame is a key frame. -+ * - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME`` -+ - The frame should be displayed. -+ * - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT`` -+ - The decoding should be error resilient. -+ * - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY`` -+ - The frame does not reference other frames. -+ * - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV`` -+ - the frame might can high precision motion vectors. -+ * - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX`` -+ - Frame context should be updated after decoding. -+ * - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE`` -+ - Parallel decoding is used. -+ * - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING`` -+ - Vertical subsampling is enabled. -+ * - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING`` -+ - Horizontal subsampling is enabled. -+ * - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING`` -+ - The full UV range is used. -+ -+.. c:type:: v4l2_vp9_ref_id -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_ref_id -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_REF_ID_LAST`` -+ - Last reference frame. -+ * - ``V4L2_REF_ID_GOLDEN`` -+ - Golden reference frame. -+ * - ``V4L2_REF_ID_ALTREF`` -+ - Alternative reference frame. -+ * - ``V4L2_REF_ID_CNT`` -+ - Number of reference frames. -+ -+.. c:type:: v4l2_vp9_tx_mode -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_tx_mode -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_TX_MODE_ONLY_4X4`` -+ - Transform size is 4x4. -+ * - ``V4L2_VP9_TX_MODE_ALLOW_8X8`` -+ - Transform size can be up to 8x8. -+ * - ``V4L2_VP9_TX_MODE_ALLOW_16X16`` -+ - Transform size can be up to 16x16. -+ * - ``V4L2_VP9_TX_MODE_ALLOW_32X32`` -+ - transform size can be up to 32x32. -+ * - ``V4L2_VP9_TX_MODE_SELECT`` -+ - Bitstream contains transform size for each block. -+ -+.. c:type:: v4l2_vp9_reference_mode -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_reference_mode -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_REF_MODE_SINGLE`` -+ - Indicates that all the inter blocks use only a single reference frame -+ to generate motion compensated prediction. -+ * - ``V4L2_VP9_REF_MODE_COMPOUND`` -+ - Requires all the inter blocks to use compound mode. Single reference -+ frame prediction is not allowed. -+ * - ``V4L2_VP9_REF_MODE_SELECT`` -+ - Allows each individual inter block to select between single and -+ compound prediction modes. -+ -+.. c:type:: v4l2_vp9_interpolation_filter -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_interpolation_filter -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_INTERP_FILTER_8TAP`` -+ - Height tap filter. -+ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH`` -+ - Height tap smooth filter. -+ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SHARP`` -+ - Height tap sharp filter. -+ * - ``V4L2_VP9_INTERP_FILTER_BILINEAR`` -+ - Bilinear filter. -+ * - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE`` -+ - Filter selection is signaled at the block level. -+ -+.. c:type:: v4l2_vp9_reset_frame_context -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_reset_frame_context -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_RESET_FRAME_CTX_NONE`` -+ - Do not reset any frame context. -+ * - ``V4L2_VP9_RESET_FRAME_CTX_SPEC`` -+ - Reset the frame context pointed by -+ :c:type:`v4l2_ctrl_vp9_frame_decode_params`.frame_context_idx. -+ * - ``V4L2_VP9_RESET_FRAME_CTX_ALL`` -+ - Reset all frame contexts. -+ -+.. c:type:: v4l2_vp9_intra_prediction_mode -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_intra_prediction_mode -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_INTRA_PRED_DC`` -+ - DC intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_V`` -+ - Vertical intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_H`` -+ - Horizontal intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D45`` -+ - D45 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D135`` -+ - D135 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D117`` -+ - D117 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D153`` -+ - D153 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D207`` -+ - D207 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_D63`` -+ - D63 intra prediction. -+ * - ``V4L2_VP9_INTRA_PRED_MODE_TM`` -+ - True motion intra prediction. -+ -+.. c:type:: v4l2_vp9_segmentation -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: struct v4l2_vp9_segmentation -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``flags`` -+ - Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See -+ :c:type:`v4l2_vp9_segmentation_flags`. -+ * - __u8 -+ - ``tree_probs[7]`` -+ - Specifies the probability values to be used when decoding a Segment-ID. -+ See '5.15. Segmentation map' section of :ref:`vp9` for more details. -+ * - __u8 -+ - ``pred_prob[3]`` -+ - Specifies the probability values to be used when decoding a -+ Predicted-Segment-ID. See '6.4.14. Get segment id syntax' -+ section of :ref:`vp9` for more details. -+ * - __u8 -+ - ``padding[5]`` -+ - Used to align this struct on 64 bit. Shall be filled with zeroes. -+ * - __u8 -+ - ``feature_enabled[8]`` -+ - Bitmask defining which features are enabled in each segment. -+ * - __u8 -+ - ``feature_data[8][4]`` -+ - Data attached to each feature. Data entry is only valid if the feature -+ is enabled. -+ -+.. c:type:: v4l2_vp9_segment_feature -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_segment_feature -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_SEGMENT_FEATURE_QP_DELTA`` -+ - QP delta segment feature. -+ * - ``V4L2_VP9_SEGMENT_FEATURE_LF`` -+ - Loop filter segment feature. -+ * - ``V4L2_VP9_SEGMENT_FEATURE_REF_FRAME`` -+ - Reference frame segment feature. -+ * - ``V4L2_VP9_SEGMENT_FEATURE_SKIP`` -+ - Skip segment feature. -+ * - ``V4L2_VP9_SEGMENT_FEATURE_CNT`` -+ - Number of segment features. -+ -+.. c:type:: v4l2_vp9_segmentation_flags -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_segmentation_flags -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED`` -+ - Indicates that this frame makes use of the segmentation tool. -+ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP`` -+ - Indicates that the segmentation map should be updated during the -+ decoding of this frame. -+ * - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` -+ - Indicates that the updates to the segmentation map are coded -+ relative to the existing segmentation map. -+ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA`` -+ - Indicates that new parameters are about to be specified for each -+ segment. -+ * - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE`` -+ - Indicates that the segmentation parameters represent the actual values -+ to be used. -+ -+.. c:type:: v4l2_vp9_quantization -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: struct v4l2_vp9_quantization -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``base_q_idx`` -+ - Indicates the base frame qindex. -+ * - __s8 -+ - ``delta_q_y_dc`` -+ - Indicates the Y DC quantizer relative to base_q_idx. -+ * - __s8 -+ - ``delta_q_uv_dc`` -+ - Indicates the UV DC quantizer relative to base_q_idx. -+ * - __s8 -+ - ``delta_q_uv_ac`` -+ - Indicates the UV AC quantizer relative to base_q_idx. -+ * - __u8 -+ - ``padding[4]`` -+ - Padding bytes used to align this struct on 64 bit. Must be set to 0. -+ -+.. c:type:: v4l2_vp9_loop_filter -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: struct v4l2_vp9_loop_filter -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``flags`` -+ - Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags. -+ See :c:type:`v4l2_vp9_loop_filter_flags`. -+ * - __u8 -+ - ``level`` -+ - Indicates the loop filter strength. -+ * - __u8 -+ - ``sharpness`` -+ - Indicates the sharpness level. -+ * - __s8 -+ - ``ref_deltas[4]`` -+ - Contains the adjustment needed for the filter level based on the chosen -+ reference frame. -+ * - __s8 -+ - ``mode_deltas[2]`` -+ - Contains the adjustment needed for the filter level based on the chosen -+ mode -+ * - __u8 -+ - ``level_lookup[8][4][2]`` -+ - Level lookup table. -+ -+ -+.. c:type:: v4l2_vp9_loop_filter_flags -+ -+.. cssclass:: longtable -+ -+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| -+ -+.. flat-table:: enum v4l2_vp9_loop_filter_flags -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 2 -+ -+ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED`` -+ - When set, the filter level depends on the mode and reference frame used -+ to predict a block. -+ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE`` -+ - When set, the bitstream contains additional syntax elements that -+ specify which mode and reference frame deltas are to be updated. -+ - .. raw:: latex - - \normalsize -diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index bd7f330c941c..a88e962ac8a1 100644 ---- a/drivers/media/v4l2-core/v4l2-ctrls.c -+++ b/drivers/media/v4l2-core/v4l2-ctrls.c -@@ -971,6 +971,11 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; - case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: return "VP9 Level"; - case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: return "VP9 Frame Decode Parameters"; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): return "VP9 Frame Context 0"; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): return "VP9 Frame Context 1"; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): return "VP9 Frame Context 2"; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): return "VP9 Frame Context 3"; - - /* HEVC controls */ - case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; -@@ -1452,6 +1457,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: - *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; - break; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: -+ *type = V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS; -+ break; -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): -+ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): -+ *type = V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT; -+ break; - case V4L2_CID_MPEG_VIDEO_HEVC_SPS: - *type = V4L2_CTRL_TYPE_HEVC_SPS; - break; -@@ -1754,6 +1768,219 @@ static void std_log(const struct v4l2_ctrl *ctrl) - 0; \ - }) - -+static int -+validate_vp9_lf_params(struct v4l2_vp9_loop_filter *lf) -+{ -+ unsigned int i, j, k; -+ -+ if (lf->flags & -+ ~(V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED | -+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE)) -+ return -EINVAL; -+ -+ /* -+ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED implies -+ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE. -+ */ -+ if (lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE && -+ !(lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED)) -+ return -EINVAL; -+ -+ /* That all values are in the accepted range. */ -+ if (lf->level > GENMASK(5, 0)) -+ return -EINVAL; -+ -+ if (lf->sharpness > GENMASK(2, 0)) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { -+ if (lf->ref_deltas[i] < -63 || lf->ref_deltas[i] > 63) -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { -+ if (lf->mode_deltas[i] < -63 || lf->mode_deltas[i] > 63) -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(lf->level_lookup); i++) { -+ for (j = 0; j < ARRAY_SIZE(lf->level_lookup[0]); j++) { -+ for (k = 0; k < ARRAY_SIZE(lf->level_lookup[0][0]); k++) { -+ if (lf->level_lookup[i][j][k] > 63) -+ return -EINVAL; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int -+validate_vp9_quant_params(struct v4l2_vp9_quantization *quant) -+{ -+ if (quant->delta_q_y_dc < -15 || quant->delta_q_y_dc > 15 || -+ quant->delta_q_uv_dc < -15 || quant->delta_q_uv_dc > 15 || -+ quant->delta_q_uv_ac < -15 || quant->delta_q_uv_ac > 15) -+ return -EINVAL; -+ -+ memset(quant->padding, 0, sizeof(quant->padding)); -+ return 0; -+} -+ -+static int -+validate_vp9_seg_params(struct v4l2_vp9_segmentation *seg) -+{ -+ unsigned int i, j; -+ -+ if (seg->flags & -+ ~(V4L2_VP9_SEGMENTATION_FLAG_ENABLED | -+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | -+ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE | -+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA | -+ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) -+ return -EINVAL; -+ -+ /* -+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP and -+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA imply -+ * V4L2_VP9_SEGMENTATION_FLAG_ENABLED. -+ */ -+ if ((seg->flags & -+ (V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | -+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) && -+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)) -+ return -EINVAL; -+ -+ /* -+ * V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE implies -+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP. -+ */ -+ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE && -+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)) -+ return -EINVAL; -+ -+ /* -+ * V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE implies -+ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA. -+ */ -+ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE && -+ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(seg->feature_enabled); i++) { -+ if (seg->feature_enabled[i] & -+ ~(V4L2_VP9_SEGMENT_FEATURE_QP_DELTA | -+ V4L2_VP9_SEGMENT_FEATURE_LF | -+ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME | -+ V4L2_VP9_SEGMENT_FEATURE_SKIP)) -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(seg->feature_data); i++) { -+ const int range[] = {255, 63, 3, 0}; -+ -+ for (j = 0; j < ARRAY_SIZE(seg->feature_data[j]); j++) { -+ if (seg->feature_data[i][j] < -range[j] || -+ seg->feature_data[i][j] > range[j]) -+ return -EINVAL; -+ } -+ } -+ -+ memset(seg->padding, 0, sizeof(seg->padding)); -+ return 0; -+} -+ -+static int -+validate_vp9_frame_decode_params(struct v4l2_ctrl_vp9_frame_decode_params *dec_params) -+{ -+ int ret; -+ -+ /* Make sure we're not passed invalid flags. */ -+ if (dec_params->flags & -+ ~(V4L2_VP9_FRAME_FLAG_KEY_FRAME | -+ V4L2_VP9_FRAME_FLAG_SHOW_FRAME | -+ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | -+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY | -+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV | -+ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | -+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE | -+ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | -+ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING | -+ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING)) -+ return -EINVAL; -+ -+ /* -+ * The refresh context and error resilient flags are mutually exclusive. -+ * Same goes for parallel decoding and error resilient modes. -+ */ -+ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT && -+ dec_params->flags & -+ (V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | -+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) -+ return -EINVAL; -+ -+ if (dec_params->profile > V4L2_VP9_PROFILE_MAX) -+ return -EINVAL; -+ -+ if (dec_params->reset_frame_context > V4L2_VP9_RESET_FRAME_CTX_ALL) -+ return -EINVAL; -+ -+ if (dec_params->frame_context_idx >= V4L2_VP9_NUM_FRAME_CTX) -+ return -EINVAL; -+ -+ /* -+ * Profiles 0 and 1 only support 8-bit depth, profiles 2 and 3 only 10 -+ * and 12 bit depths. -+ */ -+ if ((dec_params->profile < 2 && dec_params->bit_depth != 8) || -+ (dec_params->profile >= 2 && -+ (dec_params->bit_depth != 10 && dec_params->bit_depth != 12))) -+ return -EINVAL; -+ -+ /* Profile 0 and 2 only accept YUV 4:2:0. */ -+ if ((dec_params->profile == 0 || dec_params->profile == 2) && -+ (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || -+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) -+ return -EINVAL; -+ -+ /* Profile 1 and 3 only accept YUV 4:2:2, 4:4:0 and 4:4:4. */ -+ if ((dec_params->profile == 1 || dec_params->profile == 3) && -+ ((dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) && -+ (dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) -+ return -EINVAL; -+ -+ if (dec_params->interpolation_filter > V4L2_VP9_INTERP_FILTER_SWITCHABLE) -+ return -EINVAL; -+ -+ /* -+ * According to the spec, tile_cols_log2 shall be less than or equal -+ * to 6. -+ */ -+ if (dec_params->tile_cols_log2 > 6) -+ return -EINVAL; -+ -+ if (dec_params->tx_mode > V4L2_VP9_TX_MODE_SELECT) -+ return -EINVAL; -+ -+ if (dec_params->reference_mode > V4L2_VP9_REF_MODE_SELECT) -+ return -EINVAL; -+ -+ ret = validate_vp9_lf_params(&dec_params->lf); -+ if (ret) -+ return ret; -+ -+ ret = validate_vp9_quant_params(&dec_params->quant); -+ if (ret) -+ return ret; -+ -+ ret = validate_vp9_seg_params(&dec_params->seg); -+ if (ret) -+ return ret; -+ -+ memset(dec_params->padding, 0, sizeof(dec_params->padding)); -+ return 0; -+} -+ - /* Validate a new control */ - - #define zero_padding(s) \ -@@ -1871,6 +2098,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, - zero_padding(p_vp8_frame_header->coder_state); - break; - -+ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: -+ return validate_vp9_frame_decode_params(p); -+ -+ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: -+ break; -+ - case V4L2_CTRL_TYPE_HEVC_SPS: - p_hevc_sps = p; - -@@ -2617,6 +2850,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, - case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: - elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); - break; -+ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: -+ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_ctx); -+ break; -+ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: -+ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_decode_params); -+ break; - case V4L2_CTRL_TYPE_HEVC_SPS: - elem_size = sizeof(struct v4l2_ctrl_hevc_sps); - break; -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index 80cb42450a1b..9351c2635646 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1429,6 +1429,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) - case V4L2_PIX_FMT_VP8: descr = "VP8"; break; - case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; - case V4L2_PIX_FMT_VP9: descr = "VP9"; break; -+ case V4L2_PIX_FMT_VP9_FRAME: descr = "VP9 Frame"; break; - case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ - case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; - case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ -diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h -index cb25f345e9ad..fb299d83df6b 100644 ---- a/include/media/v4l2-ctrls.h -+++ b/include/media/v4l2-ctrls.h -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - - /* forward references */ -@@ -53,6 +54,8 @@ struct video_device; - * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. - * @p_h264_pred_weights: Pointer to a struct v4l2_ctrl_h264_pred_weights. - * @p_vp8_frame_header: Pointer to a VP8 frame header structure. -+ * @p_vp9_frame_ctx: Pointer to a VP9 frame context structure. -+ * @p_vp9_frame_decode_params: Pointer to a VP9 frame params structure. - * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. - * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. - * @p_hevc_slice_params: Pointer to an HEVC slice parameters structure. -@@ -80,6 +83,8 @@ union v4l2_ctrl_ptr { - struct v4l2_ctrl_hevc_sps *p_hevc_sps; - struct v4l2_ctrl_hevc_pps *p_hevc_pps; - struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; -+ struct v4l2_ctrl_vp9_frame_ctx *p_vp9_frame_ctx; -+ struct v4l2_ctrl_vp9_frame_decode_params *p_vp9_frame_decode_params; - struct v4l2_area *p_area; - void *p; - const void *p_const; -diff --git a/include/media/vp9-ctrls.h b/include/media/vp9-ctrls.h -new file mode 100644 -index 000000000000..a14fffb3ad61 ---- /dev/null -+++ b/include/media/vp9-ctrls.h -@@ -0,0 +1,486 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * These are the VP9 state controls for use with stateless VP9 -+ * codec drivers. -+ * -+ * It turns out that these structs are not stable yet and will undergo -+ * more changes. So keep them private until they are stable and ready to -+ * become part of the official public API. -+ */ -+ -+#ifndef _VP9_CTRLS_H_ -+#define _VP9_CTRLS_H_ -+ -+#include -+ -+#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') -+ -+#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i)) -+#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004) -+#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400 -+#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404 -+ -+/** -+ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags -+ * -+ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on -+ * the mode and reference frame used -+ * to predict a block -+ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional -+ * syntax elements that specify which -+ * mode and reference frame deltas -+ * are to be updated -+ * -+ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See -+ * section '7.2.8 Loop filter semantics' of the VP9 specification for more -+ * details. -+ */ -+enum v4l2_vp9_loop_filter_flags { -+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0, -+ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1, -+}; -+ -+/** -+ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters -+ * -+ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags -+ * @level: indicates the loop filter strength -+ * @sharpness: indicates the sharpness level -+ * @ref_deltas: contains the adjustment needed for the filter level based on -+ * the chosen reference frame -+ * @mode_deltas: contains the adjustment needed for the filter level based on -+ * the chosen mode -+ * @level_lookup: level lookup table -+ * -+ * This structure contains all loop filter related parameters. See sections -+ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process' -+ * of the VP9 specification for more details. -+ */ -+struct v4l2_vp9_loop_filter { -+ __u8 flags; -+ __u8 level; -+ __u8 sharpness; -+ __s8 ref_deltas[4]; -+ __s8 mode_deltas[2]; -+ __u8 level_lookup[8][4][2]; -+ __u8 padding; -+}; -+ -+/** -+ * struct v4l2_vp9_quantization - VP9 quantization parameters -+ * -+ * @base_q_idx: indicates the base frame qindex -+ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx -+ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx -+ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx -+ * @padding: padding bytes to align things on 64 bits. Must be set to 0 -+ * -+ * Encodes the quantization parameters. See section '7.2.9 Quantization params -+ * syntax' of the VP9 specification for more details. -+ */ -+struct v4l2_vp9_quantization { -+ __u8 base_q_idx; -+ __s8 delta_q_y_dc; -+ __s8 delta_q_uv_dc; -+ __s8 delta_q_uv_ac; -+ __u8 padding[4]; -+}; -+ -+/** -+ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags -+ * -+ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of -+ * the segmentation tool -+ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map -+ * should be updated during the -+ * decoding of this frame -+ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to -+ * the segmentation map are coded -+ * relative to the existing -+ * segmentation map -+ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are -+ * about to be specified for each -+ * segment -+ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the -+ * segmentation parameters -+ * represent the actual values -+ * to be used -+ * -+ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See -+ * section '7.2.10 Segmentation params syntax' of the VP9 specification for -+ * more details. -+ */ -+enum v4l2_vp9_segmentation_flags { -+ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0, -+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1, -+ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2, -+ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3, -+ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4, -+}; -+ -+#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) -+#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf -+ -+/** -+ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs -+ * -+ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature -+ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature -+ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature -+ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature -+ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features -+ * -+ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the -+ * VP9 specification for more details. -+ */ -+enum v4l2_vp9_segment_feature { -+ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA, -+ V4L2_VP9_SEGMENT_FEATURE_LF, -+ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME, -+ V4L2_VP9_SEGMENT_FEATURE_SKIP, -+ V4L2_VP9_SEGMENT_FEATURE_CNT, -+}; -+ -+/** -+ * struct v4l2_vp9_segmentation - VP9 segmentation parameters -+ * -+ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags -+ * @tree_probs: specifies the probability values to be used when -+ * decoding a Segment-ID. See '5.15. Segmentation map' -+ * section of the VP9 specification for more details. -+ * @pred_prob: specifies the probability values to be used when decoding a -+ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' -+ * section of :ref:`vp9` for more details.. -+ * @padding: padding used to make things aligned on 64 bits. Shall be zero -+ * filled -+ * @feature_enabled: bitmask defining which features are enabled in each -+ * segment -+ * @feature_data: data attached to each feature. Data entry is only valid if -+ * the feature is enabled -+ * -+ * Encodes the quantization parameters. See section '7.2.10 Segmentation -+ * params syntax' of the VP9 specification for more details. -+ */ -+struct v4l2_vp9_segmentation { -+ __u8 flags; -+ __u8 tree_probs[7]; -+ __u8 pred_probs[3]; -+ __u8 padding[5]; -+ __u8 feature_enabled[8]; -+ __s16 feature_data[8][4]; -+}; -+ -+/** -+ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes -+ * -+ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction -+ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction -+ * -+ * See section '7.4.5 Intra frame mode info semantics' for more details. -+ */ -+enum v4l2_vp9_intra_prediction_mode { -+ V4L2_VP9_INTRA_PRED_MODE_DC, -+ V4L2_VP9_INTRA_PRED_MODE_V, -+ V4L2_VP9_INTRA_PRED_MODE_H, -+ V4L2_VP9_INTRA_PRED_MODE_D45, -+ V4L2_VP9_INTRA_PRED_MODE_D135, -+ V4L2_VP9_INTRA_PRED_MODE_D117, -+ V4L2_VP9_INTRA_PRED_MODE_D153, -+ V4L2_VP9_INTRA_PRED_MODE_D207, -+ V4L2_VP9_INTRA_PRED_MODE_D63, -+ V4L2_VP9_INTRA_PRED_MODE_TM, -+}; -+ -+/** -+ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities -+ * @joint: motion vector joint probabilities -+ * @sign: motion vector sign probabilities -+ * @class: motion vector class probabilities -+ * @class0_bit: motion vector class0 bit probabilities -+ * @bits: motion vector bits probabilities -+ * @class0_fr: motion vector class0 fractional bit probabilities -+ * @fr: motion vector fractional bit probabilities -+ * @class0_hp: motion vector class0 high precision fractional bit probabilities -+ * @hp: motion vector high precision fractional bit probabilities -+ */ -+struct v4l2_vp9_mv_probabilities { -+ __u8 joint[3]; -+ __u8 sign[2]; -+ __u8 class[2][10]; -+ __u8 class0_bit[2]; -+ __u8 bits[2][10]; -+ __u8 class0_fr[2][2][3]; -+ __u8 fr[2][3]; -+ __u8 class0_hp[2]; -+ __u8 hp[2]; -+}; -+ -+/** -+ * struct v4l2_vp9_probabilities - VP9 Probabilities -+ * -+ * @tx8: TX 8x8 probabilities -+ * @tx16: TX 16x16 probabilities -+ * @tx32: TX 32x32 probabilities -+ * @coef: coefficient probabilities -+ * @skip: skip probabilities -+ * @inter_mode: inter mode probabilities -+ * @interp_filter: interpolation filter probabilities -+ * @is_inter: is inter-block probabilities -+ * @comp_mode: compound prediction mode probabilities -+ * @single_ref: single ref probabilities -+ * @comp_ref: compound ref probabilities -+ * @y_mode: Y prediction mode probabilities -+ * @uv_mode: UV prediction mode probabilities -+ * @partition: partition probabilities -+ * @mv: motion vector probabilities -+ * -+ * Structure containing most VP9 probabilities. See the VP9 specification -+ * for more details. -+ */ -+struct v4l2_vp9_probabilities { -+ __u8 tx8[2][1]; -+ __u8 tx16[2][2]; -+ __u8 tx32[2][3]; -+ __u8 coef[4][2][2][6][6][3]; -+ __u8 skip[3]; -+ __u8 inter_mode[7][3]; -+ __u8 interp_filter[4][2]; -+ __u8 is_inter[4]; -+ __u8 comp_mode[5]; -+ __u8 single_ref[5][2]; -+ __u8 comp_ref[5]; -+ __u8 y_mode[4][9]; -+ __u8 uv_mode[10][9]; -+ __u8 partition[16][3]; -+ -+ struct v4l2_vp9_mv_probabilities mv; -+}; -+ -+/** -+ * enum v4l2_vp9_reset_frame_context - Valid values for -+ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context -+ * -+ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context -+ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by -+ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx -+ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts -+ * -+ * See section '7.2 Uncompressed header semantics' of the VP9 specification -+ * for more details. -+ */ -+enum v4l2_vp9_reset_frame_context { -+ V4L2_VP9_RESET_FRAME_CTX_NONE, -+ V4L2_VP9_RESET_FRAME_CTX_SPEC, -+ V4L2_VP9_RESET_FRAME_CTX_ALL, -+}; -+ -+/** -+ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types -+ * -+ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter -+ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter -+ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter -+ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter -+ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the -+ * block level -+ * -+ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification -+ * for more details. -+ */ -+enum v4l2_vp9_interpolation_filter { -+ V4L2_VP9_INTERP_FILTER_8TAP, -+ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH, -+ V4L2_VP9_INTERP_FILTER_8TAP_SHARP, -+ V4L2_VP9_INTERP_FILTER_BILINEAR, -+ V4L2_VP9_INTERP_FILTER_SWITCHABLE, -+}; -+ -+/** -+ * enum v4l2_vp9_reference_mode - VP9 reference modes -+ * -+ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a -+ * single reference frame to generate motion -+ * compensated prediction -+ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound -+ * mode. Single reference frame prediction is not -+ * allowed -+ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select -+ * between single and compound prediction modes -+ * -+ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification -+ * for more details. -+ */ -+enum v4l2_vp9_reference_mode { -+ V4L2_VP9_REF_MODE_SINGLE, -+ V4L2_VP9_REF_MODE_COMPOUND, -+ V4L2_VP9_REF_MODE_SELECT, -+}; -+ -+/** -+ * enum v4l2_vp9_tx_mode - VP9 TX modes -+ * -+ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4 -+ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8 -+ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16 -+ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32 -+ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block -+ * -+ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more -+ * details. -+ */ -+enum v4l2_vp9_tx_mode { -+ V4L2_VP9_TX_MODE_ONLY_4X4, -+ V4L2_VP9_TX_MODE_ALLOW_8X8, -+ V4L2_VP9_TX_MODE_ALLOW_16X16, -+ V4L2_VP9_TX_MODE_ALLOW_32X32, -+ V4L2_VP9_TX_MODE_SELECT, -+}; -+ -+/** -+ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs -+ * -+ * @V4L2_REF_ID_LAST: last reference frame -+ * @V4L2_REF_ID_GOLDEN: golden reference frame -+ * @V4L2_REF_ID_ALTREF: alternative reference frame -+ * @V4L2_REF_ID_CNT: number of reference frames -+ * -+ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more -+ * details. -+ */ -+enum v4l2_vp9_ref_id { -+ V4L2_REF_ID_LAST, -+ V4L2_REF_ID_GOLDEN, -+ V4L2_REF_ID_ALTREF, -+ V4L2_REF_ID_CNT, -+}; -+ -+/** -+ * enum v4l2_vp9_frame_flags - VP9 frame flags -+ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame -+ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed -+ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient -+ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames -+ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision -+ * motion vectors -+ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated -+ * after decoding -+ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used -+ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled -+ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled -+ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used -+ * -+ * Check the VP9 specification for more details. -+ */ -+enum v4l2_vp9_frame_flags { -+ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0, -+ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1, -+ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2, -+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3, -+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4, -+ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5, -+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6, -+ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7, -+ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8, -+ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9, -+}; -+ -+#define V4L2_VP9_PROFILE_MAX 3 -+ -+/** -+ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control -+ * -+ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags -+ * @compressed_header_size: compressed header size in bytes -+ * @uncompressed_header_size: uncompressed header size in bytes -+ * @profile: VP9 profile. Can be 0, 1, 2 or 3 -+ * @reset_frame_context: specifies whether the frame context should be reset -+ * to default values. See &v4l2_vp9_reset_frame_context -+ * for more details -+ * @frame_context_idx: frame context that should be used/updated -+ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all -+ * profiles support 10 and/or 12 bits depths -+ * @interpolation_filter: specifies the filter selection used for performing -+ * inter prediction. See &v4l2_vp9_interpolation_filter -+ * for more details -+ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile -+ * (where the width is measured in units of 8x8 blocks). -+ * Shall be less than or equal to 6 -+ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile -+ * (where the height is measured in units of 8x8 blocks) -+ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details -+ * @reference_mode: specifies the type of inter prediction to be used. See -+ * &v4l2_vp9_reference_mode for more details -+ * @padding: needed to make this struct 64 bit aligned. Shall be filled with -+ * zeros -+ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed -+ * in pixels -+ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed -+ * in pixels -+ * @frame_width_minus_1: add 1 to it and you'll get the expected render width -+ * expressed in pixels. This is not used during the -+ * decoding process but might be used by HW scalers to -+ * prepare a frame that's ready for scanout -+ * @frame_height_minus_1: add 1 to it and you'll get the expected render height -+ * expressed in pixels. This is not used during the -+ * decoding process but might be used by HW scalers to -+ * prepare a frame that's ready for scanout -+ * @refs: array of ref frames timestamps. See &v4l2_vp9_ref_id for more details -+ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details -+ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details -+ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details -+ * @probs: probabilities. See &v4l2_vp9_probabilities for more details -+ */ -+struct v4l2_ctrl_vp9_frame_decode_params { -+ __u32 flags; -+ __u16 compressed_header_size; -+ __u16 uncompressed_header_size; -+ __u8 profile; -+ __u8 reset_frame_context; -+ __u8 frame_context_idx; -+ __u8 bit_depth; -+ __u8 interpolation_filter; -+ __u8 tile_cols_log2; -+ __u8 tile_rows_log2; -+ __u8 tx_mode; -+ __u8 reference_mode; -+ __u8 padding[7]; -+ __u16 frame_width_minus_1; -+ __u16 frame_height_minus_1; -+ __u16 render_width_minus_1; -+ __u16 render_height_minus_1; -+ __u64 refs[V4L2_REF_ID_CNT]; -+ struct v4l2_vp9_loop_filter lf; -+ struct v4l2_vp9_quantization quant; -+ struct v4l2_vp9_segmentation seg; -+ struct v4l2_vp9_probabilities probs; -+}; -+ -+#define V4L2_VP9_NUM_FRAME_CTX 4 -+ -+/** -+ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control -+ * -+ * @probs: VP9 probabilities -+ * -+ * This control is accessed in both direction. The user should initialize the -+ * 4 contexts with default values just after starting the stream. Then before -+ * decoding a frame it should query the current frame context (the one passed -+ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize -+ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based -+ * on the bitstream info and passed to the kernel. The codec should update -+ * the frame context after the frame has been decoded, so that next time -+ * userspace query this context it contains the updated probabilities. -+ */ -+struct v4l2_ctrl_vp9_frame_ctx { -+ struct v4l2_vp9_probabilities probs; -+}; -+ -+#endif /* _VP9_CTRLS_H_ */ - -From 4e75ff472abd06d88758d73146697a0f4817d4f2 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Mon, 2 Nov 2020 21:05:51 +0200 -Subject: [PATCH] media: rkvdec: Add the VP9 backend - -The Rockchip VDEC supports VP9 profile 0 up to 4096x2304@30fps. Add -a backend for this new format. - -Signed-off-by: Boris Brezillon -Signed-off-by: Ezequiel Garcia -Signed-off-by: Adrian Ratiu ---- - drivers/staging/media/rkvdec/Makefile | 2 +- - drivers/staging/media/rkvdec/rkvdec-vp9.c | 1577 +++++++++++++++++++++ - drivers/staging/media/rkvdec/rkvdec.c | 60 +- - drivers/staging/media/rkvdec/rkvdec.h | 6 + - 4 files changed, 1643 insertions(+), 2 deletions(-) - create mode 100644 drivers/staging/media/rkvdec/rkvdec-vp9.c - -diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile -index c08fed0a39f9..cb86b429cfaa 100644 ---- a/drivers/staging/media/rkvdec/Makefile -+++ b/drivers/staging/media/rkvdec/Makefile -@@ -1,3 +1,3 @@ - obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o - --rockchip-vdec-y += rkvdec.o rkvdec-h264.o -+rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o -diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c -new file mode 100644 -index 000000000000..8b443ed511c9 ---- /dev/null -+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c -@@ -0,0 +1,1577 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Rockchip Video Decoder VP9 backend -+ * -+ * Copyright (C) 2019 Collabora, Ltd. -+ * Boris Brezillon -+ * -+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. -+ * Alpha Lin -+ */ -+ -+#include -+#include -+#include -+ -+#include "rkvdec.h" -+#include "rkvdec-regs.h" -+ -+#define RKVDEC_VP9_PROBE_SIZE 4864 -+#define RKVDEC_VP9_COUNT_SIZE 13232 -+#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728 -+ -+struct rkvdec_vp9_intra_mode_probs { -+ u8 y_mode[105]; -+ u8 uv_mode[23]; -+}; -+ -+struct rkvdec_vp9_intra_only_frame_probs { -+ u8 coef_intra[4][2][128]; -+ struct rkvdec_vp9_intra_mode_probs intra_mode[10]; -+}; -+ -+struct rkvdec_vp9_inter_frame_probs { -+ u8 y_mode[4][9]; -+ u8 comp_mode[5]; -+ u8 comp_ref[5]; -+ u8 single_ref[5][2]; -+ u8 inter_mode[7][3]; -+ u8 interp_filter[4][2]; -+ u8 padding0[11]; -+ u8 coef[2][4][2][128]; -+ u8 uv_mode_0_2[3][9]; -+ u8 padding1[5]; -+ u8 uv_mode_3_5[3][9]; -+ u8 padding2[5]; -+ u8 uv_mode_6_8[3][9]; -+ u8 padding3[5]; -+ u8 uv_mode_9[9]; -+ u8 padding4[7]; -+ u8 padding5[16]; -+ struct { -+ u8 joint[3]; -+ u8 sign[2]; -+ u8 class[2][10]; -+ u8 class0_bit[2]; -+ u8 bits[2][10]; -+ u8 class0_fr[2][2][3]; -+ u8 fr[2][3]; -+ u8 class0_hp[2]; -+ u8 hp[2]; -+ } mv; -+}; -+ -+struct rkvdec_vp9_probs { -+ u8 partition[16][3]; -+ u8 pred[3]; -+ u8 tree[7]; -+ u8 skip[3]; -+ u8 tx32[2][3]; -+ u8 tx16[2][2]; -+ u8 tx8[2][1]; -+ u8 is_inter[4]; -+ /* 128 bit alignment */ -+ u8 padding0[3]; -+ union { -+ struct rkvdec_vp9_inter_frame_probs inter; -+ struct rkvdec_vp9_intra_only_frame_probs intra_only; -+ }; -+}; -+ -+/* Data structure describing auxiliary buffer format. */ -+struct rkvdec_vp9_priv_tbl { -+ struct rkvdec_vp9_probs probs; -+ u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE]; -+}; -+ -+struct rkvdec_vp9_refs_counts { -+ u32 eob[2]; -+ u32 coeff[3]; -+}; -+ -+struct rkvdec_vp9_inter_frame_symbol_counts { -+ u32 partition[16][4]; -+ u32 skip[3][2]; -+ u32 inter[4][2]; -+ u32 tx32p[2][4]; -+ u32 tx16p[2][4]; -+ u32 tx8p[2][2]; -+ u32 y_mode[4][10]; -+ u32 uv_mode[10][10]; -+ u32 comp[5][2]; -+ u32 comp_ref[5][2]; -+ u32 single_ref[5][2][2]; -+ u32 mv_mode[7][4]; -+ u32 filter[4][3]; -+ u32 mv_joint[4]; -+ u32 sign[2][2]; -+ /* add 1 element for align */ -+ u32 classes[2][11 + 1]; -+ u32 class0[2][2]; -+ u32 bits[2][10][2]; -+ u32 class0_fp[2][2][4]; -+ u32 fp[2][4]; -+ u32 class0_hp[2][2]; -+ u32 hp[2][2]; -+ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; -+}; -+ -+struct rkvdec_vp9_intra_frame_symbol_counts { -+ u32 partition[4][4][4]; -+ u32 skip[3][2]; -+ u32 intra[4][2]; -+ u32 tx32p[2][4]; -+ u32 tx16p[2][4]; -+ u32 tx8p[2][2]; -+ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; -+}; -+ -+struct rkvdec_vp9_run { -+ struct rkvdec_run base; -+ const struct v4l2_ctrl_vp9_frame_decode_params *decode_params; -+}; -+ -+struct rkvdec_vp9_frame_info { -+ u32 valid : 1; -+ u32 segmapid : 1; -+ u32 frame_context_idx : 2; -+ u32 reference_mode : 2; -+ u32 tx_mode : 3; -+ u32 interpolation_filter : 3; -+ u32 flags; -+ u64 timestamp; -+ struct v4l2_vp9_segmentation seg; -+ struct v4l2_vp9_loop_filter lf; -+}; -+ -+struct rkvdec_vp9_ctx { -+ struct rkvdec_aux_buf priv_tbl; -+ struct rkvdec_aux_buf count_tbl; -+ struct v4l2_ctrl_vp9_frame_ctx frame_context; -+ struct rkvdec_vp9_frame_info cur; -+ struct rkvdec_vp9_frame_info last; -+}; -+ -+static u32 rkvdec_fastdiv(u32 dividend, u16 divisor) -+{ -+#define DIV_INV(d) ((u32)(((1ULL << 32) + ((d) - 1)) / (d))) -+#define DIVS_INV(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) \ -+ DIV_INV(d0), DIV_INV(d1), DIV_INV(d2), DIV_INV(d3), \ -+ DIV_INV(d4), DIV_INV(d5), DIV_INV(d6), DIV_INV(d7), \ -+ DIV_INV(d8), DIV_INV(d9) -+ -+ static const u32 inv[] = { -+ DIV_INV(2), DIV_INV(3), DIV_INV(4), DIV_INV(5), -+ DIV_INV(6), DIV_INV(7), DIV_INV(8), DIV_INV(9), -+ DIVS_INV(10, 11, 12, 13, 14, 15, 16, 17, 18, 19), -+ DIVS_INV(20, 21, 22, 23, 24, 25, 26, 27, 28, 29), -+ DIVS_INV(30, 31, 32, 33, 34, 35, 36, 37, 38, 39), -+ DIVS_INV(40, 41, 42, 43, 44, 45, 46, 47, 48, 49), -+ DIVS_INV(50, 51, 52, 53, 54, 55, 56, 57, 58, 59), -+ DIVS_INV(60, 61, 62, 63, 64, 65, 66, 67, 68, 69), -+ DIVS_INV(70, 71, 72, 73, 74, 75, 76, 77, 78, 79), -+ DIVS_INV(80, 81, 82, 83, 84, 85, 86, 87, 88, 89), -+ DIVS_INV(90, 91, 92, 93, 94, 95, 96, 97, 98, 99), -+ DIVS_INV(100, 101, 102, 103, 104, 105, 106, 107, 108, 109), -+ DIVS_INV(110, 111, 112, 113, 114, 115, 116, 117, 118, 119), -+ DIVS_INV(120, 121, 122, 123, 124, 125, 126, 127, 128, 129), -+ DIVS_INV(130, 131, 132, 133, 134, 135, 136, 137, 138, 139), -+ DIVS_INV(140, 141, 142, 143, 144, 145, 146, 147, 148, 149), -+ DIVS_INV(150, 151, 152, 153, 154, 155, 156, 157, 158, 159), -+ DIVS_INV(160, 161, 162, 163, 164, 165, 166, 167, 168, 169), -+ DIVS_INV(170, 171, 172, 173, 174, 175, 176, 177, 178, 179), -+ DIVS_INV(180, 181, 182, 183, 184, 185, 186, 187, 188, 189), -+ DIVS_INV(190, 191, 192, 193, 194, 195, 196, 197, 198, 199), -+ DIVS_INV(200, 201, 202, 203, 204, 205, 206, 207, 208, 209), -+ DIVS_INV(210, 211, 212, 213, 214, 215, 216, 217, 218, 219), -+ DIVS_INV(220, 221, 222, 223, 224, 225, 226, 227, 228, 229), -+ DIVS_INV(230, 231, 232, 233, 234, 235, 236, 237, 238, 239), -+ DIVS_INV(240, 241, 242, 243, 244, 245, 246, 247, 248, 249), -+ DIV_INV(250), DIV_INV(251), DIV_INV(252), DIV_INV(253), -+ DIV_INV(254), DIV_INV(255), DIV_INV(256), -+ }; -+ -+ if (divisor == 0) -+ return 0; -+ else if (divisor == 1) -+ return dividend; -+ -+ if (WARN_ON(divisor - 2 >= ARRAY_SIZE(inv))) -+ return dividend; -+ -+ return ((u64)dividend * inv[divisor - 2]) >> 32; -+} -+ -+static const u8 vp9_kf_y_mode_prob[10][10][9] = { -+ { -+ /* above = dc */ -+ { 137, 30, 42, 148, 151, 207, 70, 52, 91 },/*left = dc */ -+ { 92, 45, 102, 136, 116, 180, 74, 90, 100 },/*left = v */ -+ { 73, 32, 19, 187, 222, 215, 46, 34, 100 },/*left = h */ -+ { 91, 30, 32, 116, 121, 186, 93, 86, 94 },/*left = d45 */ -+ { 72, 35, 36, 149, 68, 206, 68, 63, 105 },/*left = d135*/ -+ { 73, 31, 28, 138, 57, 124, 55, 122, 151 },/*left = d117*/ -+ { 67, 23, 21, 140, 126, 197, 40, 37, 171 },/*left = d153*/ -+ { 86, 27, 28, 128, 154, 212, 45, 43, 53 },/*left = d207*/ -+ { 74, 32, 27, 107, 86, 160, 63, 134, 102 },/*left = d63 */ -+ { 59, 67, 44, 140, 161, 202, 78, 67, 119 } /*left = tm */ -+ }, { /* above = v */ -+ { 63, 36, 126, 146, 123, 158, 60, 90, 96 },/*left = dc */ -+ { 43, 46, 168, 134, 107, 128, 69, 142, 92 },/*left = v */ -+ { 44, 29, 68, 159, 201, 177, 50, 57, 77 },/*left = h */ -+ { 58, 38, 76, 114, 97, 172, 78, 133, 92 },/*left = d45 */ -+ { 46, 41, 76, 140, 63, 184, 69, 112, 57 },/*left = d135*/ -+ { 38, 32, 85, 140, 46, 112, 54, 151, 133 },/*left = d117*/ -+ { 39, 27, 61, 131, 110, 175, 44, 75, 136 },/*left = d153*/ -+ { 52, 30, 74, 113, 130, 175, 51, 64, 58 },/*left = d207*/ -+ { 47, 35, 80, 100, 74, 143, 64, 163, 74 },/*left = d63 */ -+ { 36, 61, 116, 114, 128, 162, 80, 125, 82 } /*left = tm */ -+ }, { /* above = h */ -+ { 82, 26, 26, 171, 208, 204, 44, 32, 105 },/*left = dc */ -+ { 55, 44, 68, 166, 179, 192, 57, 57, 108 },/*left = v */ -+ { 42, 26, 11, 199, 241, 228, 23, 15, 85 },/*left = h */ -+ { 68, 42, 19, 131, 160, 199, 55, 52, 83 },/*left = d45 */ -+ { 58, 50, 25, 139, 115, 232, 39, 52, 118 },/*left = d135*/ -+ { 50, 35, 33, 153, 104, 162, 64, 59, 131 },/*left = d117*/ -+ { 44, 24, 16, 150, 177, 202, 33, 19, 156 },/*left = d153*/ -+ { 55, 27, 12, 153, 203, 218, 26, 27, 49 },/*left = d207*/ -+ { 53, 49, 21, 110, 116, 168, 59, 80, 76 },/*left = d63 */ -+ { 38, 72, 19, 168, 203, 212, 50, 50, 107 } /*left = tm */ -+ }, { /* above = d45 */ -+ { 103, 26, 36, 129, 132, 201, 83, 80, 93 },/*left = dc */ -+ { 59, 38, 83, 112, 103, 162, 98, 136, 90 },/*left = v */ -+ { 62, 30, 23, 158, 200, 207, 59, 57, 50 },/*left = h */ -+ { 67, 30, 29, 84, 86, 191, 102, 91, 59 },/*left = d45 */ -+ { 60, 32, 33, 112, 71, 220, 64, 89, 104 },/*left = d135*/ -+ { 53, 26, 34, 130, 56, 149, 84, 120, 103 },/*left = d117*/ -+ { 53, 21, 23, 133, 109, 210, 56, 77, 172 },/*left = d153*/ -+ { 77, 19, 29, 112, 142, 228, 55, 66, 36 },/*left = d207*/ -+ { 61, 29, 29, 93, 97, 165, 83, 175, 162 },/*left = d63 */ -+ { 47, 47, 43, 114, 137, 181, 100, 99, 95 } /*left = tm */ -+ }, { /* above = d135 */ -+ { 69, 23, 29, 128, 83, 199, 46, 44, 101 },/*left = dc */ -+ { 53, 40, 55, 139, 69, 183, 61, 80, 110 },/*left = v */ -+ { 40, 29, 19, 161, 180, 207, 43, 24, 91 },/*left = h */ -+ { 60, 34, 19, 105, 61, 198, 53, 64, 89 },/*left = d45 */ -+ { 52, 31, 22, 158, 40, 209, 58, 62, 89 },/*left = d135*/ -+ { 44, 31, 29, 147, 46, 158, 56, 102, 198 },/*left = d117*/ -+ { 35, 19, 12, 135, 87, 209, 41, 45, 167 },/*left = d153*/ -+ { 55, 25, 21, 118, 95, 215, 38, 39, 66 },/*left = d207*/ -+ { 51, 38, 25, 113, 58, 164, 70, 93, 97 },/*left = d63 */ -+ { 47, 54, 34, 146, 108, 203, 72, 103, 151 } /*left = tm */ -+ }, { /* above = d117 */ -+ { 64, 19, 37, 156, 66, 138, 49, 95, 133 },/*left = dc */ -+ { 46, 27, 80, 150, 55, 124, 55, 121, 135 },/*left = v */ -+ { 36, 23, 27, 165, 149, 166, 54, 64, 118 },/*left = h */ -+ { 53, 21, 36, 131, 63, 163, 60, 109, 81 },/*left = d45 */ -+ { 40, 26, 35, 154, 40, 185, 51, 97, 123 },/*left = d135*/ -+ { 35, 19, 34, 179, 19, 97, 48, 129, 124 },/*left = d117*/ -+ { 36, 20, 26, 136, 62, 164, 33, 77, 154 },/*left = d153*/ -+ { 45, 18, 32, 130, 90, 157, 40, 79, 91 },/*left = d207*/ -+ { 45, 26, 28, 129, 45, 129, 49, 147, 123 },/*left = d63 */ -+ { 38, 44, 51, 136, 74, 162, 57, 97, 121 } /*left = tm */ -+ }, { /* above = d153 */ -+ { 75, 17, 22, 136, 138, 185, 32, 34, 166 },/*left = dc */ -+ { 56, 39, 58, 133, 117, 173, 48, 53, 187 },/*left = v */ -+ { 35, 21, 12, 161, 212, 207, 20, 23, 145 },/*left = h */ -+ { 56, 29, 19, 117, 109, 181, 55, 68, 112 },/*left = d45 */ -+ { 47, 29, 17, 153, 64, 220, 59, 51, 114 },/*left = d135*/ -+ { 46, 16, 24, 136, 76, 147, 41, 64, 172 },/*left = d117*/ -+ { 34, 17, 11, 108, 152, 187, 13, 15, 209 },/*left = d153*/ -+ { 51, 24, 14, 115, 133, 209, 32, 26, 104 },/*left = d207*/ -+ { 55, 30, 18, 122, 79, 179, 44, 88, 116 },/*left = d63 */ -+ { 37, 49, 25, 129, 168, 164, 41, 54, 148 } /*left = tm */ -+ }, { /* above = d207 */ -+ { 82, 22, 32, 127, 143, 213, 39, 41, 70 },/*left = dc */ -+ { 62, 44, 61, 123, 105, 189, 48, 57, 64 },/*left = v */ -+ { 47, 25, 17, 175, 222, 220, 24, 30, 86 },/*left = h */ -+ { 68, 36, 17, 106, 102, 206, 59, 74, 74 },/*left = d45 */ -+ { 57, 39, 23, 151, 68, 216, 55, 63, 58 },/*left = d135*/ -+ { 49, 30, 35, 141, 70, 168, 82, 40, 115 },/*left = d117*/ -+ { 51, 25, 15, 136, 129, 202, 38, 35, 139 },/*left = d153*/ -+ { 68, 26, 16, 111, 141, 215, 29, 28, 28 },/*left = d207*/ -+ { 59, 39, 19, 114, 75, 180, 77, 104, 42 },/*left = d63 */ -+ { 40, 61, 26, 126, 152, 206, 61, 59, 93 } /*left = tm */ -+ }, { /* above = d63 */ -+ { 78, 23, 39, 111, 117, 170, 74, 124, 94 },/*left = dc */ -+ { 48, 34, 86, 101, 92, 146, 78, 179, 134 },/*left = v */ -+ { 47, 22, 24, 138, 187, 178, 68, 69, 59 },/*left = h */ -+ { 56, 25, 33, 105, 112, 187, 95, 177, 129 },/*left = d45 */ -+ { 48, 31, 27, 114, 63, 183, 82, 116, 56 },/*left = d135*/ -+ { 43, 28, 37, 121, 63, 123, 61, 192, 169 },/*left = d117*/ -+ { 42, 17, 24, 109, 97, 177, 56, 76, 122 },/*left = d153*/ -+ { 58, 18, 28, 105, 139, 182, 70, 92, 63 },/*left = d207*/ -+ { 46, 23, 32, 74, 86, 150, 67, 183, 88 },/*left = d63 */ -+ { 36, 38, 48, 92, 122, 165, 88, 137, 91 } /*left = tm */ -+ }, { /* above = tm */ -+ { 65, 70, 60, 155, 159, 199, 61, 60, 81 },/*left = dc */ -+ { 44, 78, 115, 132, 119, 173, 71, 112, 93 },/*left = v */ -+ { 39, 38, 21, 184, 227, 206, 42, 32, 64 },/*left = h */ -+ { 58, 47, 36, 124, 137, 193, 80, 82, 78 },/*left = d45 */ -+ { 49, 50, 35, 144, 95, 205, 63, 78, 59 },/*left = d135*/ -+ { 41, 53, 52, 148, 71, 142, 65, 128, 51 },/*left = d117*/ -+ { 40, 36, 28, 143, 143, 202, 40, 55, 137 },/*left = d153*/ -+ { 52, 34, 29, 129, 183, 227, 42, 35, 43 },/*left = d207*/ -+ { 42, 44, 44, 104, 105, 164, 64, 130, 80 },/*left = d63 */ -+ { 43, 81, 53, 140, 169, 204, 68, 84, 72 } /*left = tm */ -+ } -+}; -+ -+static const u8 kf_partition_probs[16][3] = { -+ /* 8x8 -> 4x4 */ -+ { 158, 97, 94 }, /* a/l both not split */ -+ { 93, 24, 99 }, /* a split, l not split */ -+ { 85, 119, 44 }, /* l split, a not split */ -+ { 62, 59, 67 }, /* a/l both split */ -+ /* 16x16 -> 8x8 */ -+ { 149, 53, 53 }, /* a/l both not split */ -+ { 94, 20, 48 }, /* a split, l not split */ -+ { 83, 53, 24 }, /* l split, a not split */ -+ { 52, 18, 18 }, /* a/l both split */ -+ /* 32x32 -> 16x16 */ -+ { 150, 40, 39 }, /* a/l both not split */ -+ { 78, 12, 26 }, /* a split, l not split */ -+ { 67, 33, 11 }, /* l split, a not split */ -+ { 24, 7, 5 }, /* a/l both split */ -+ /* 64x64 -> 32x32 */ -+ { 174, 35, 49 }, /* a/l both not split */ -+ { 68, 11, 27 }, /* a split, l not split */ -+ { 57, 15, 9 }, /* l split, a not split */ -+ { 12, 3, 3 }, /* a/l both split */ -+}; -+ -+static const u8 kf_uv_mode_prob[10][9] = { -+ { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, /* y = dc */ -+ { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, /* y = v */ -+ { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, /* y = h */ -+ { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, /* y = d45 */ -+ { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, /* y = d135 */ -+ { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, /* y = d117 */ -+ { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, /* y = d153 */ -+ { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, /* y = d207 */ -+ { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, /* y = d63 */ -+ { 102, 19, 66, 162, 182, 122, 35, 59, 128 } /* y = tm */ -+}; -+ -+static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) -+{ -+ unsigned int idx = 0; -+ u8 byte_count = 0, p; -+ s32 k, m, n; -+ -+ for (k = 0; k < 6; k++) { -+ for (m = 0; m < 6; m++) { -+ for (n = 0; n < 3; n++) { -+ p = coef[k][m][n]; -+ coeff_plane[idx++] = p; -+ byte_count++; -+ if (byte_count == 27) { -+ idx += 5; -+ byte_count = 0; -+ } -+ } -+ } -+ } -+} -+ -+static void init_intra_only_probs(struct rkvdec_ctx *ctx, -+ const struct rkvdec_vp9_run *run) -+{ -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; -+ struct rkvdec_vp9_intra_only_frame_probs *rkprobs; -+ const struct v4l2_vp9_probabilities *probs; -+ unsigned int i, j, k, m; -+ -+ rkprobs = &tbl->probs.intra_only; -+ dec_params = run->decode_params; -+ probs = &dec_params->probs; -+ -+ /* -+ * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related -+ * prob 64 x 128 bits -+ */ -+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { -+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) -+ write_coeff_plane(probs->coef[i][j][0], -+ rkprobs->coef_intra[i][j]); -+ } -+ -+ /* intra mode prob 80 x 128 bits */ -+ for (i = 0; i < ARRAY_SIZE(vp9_kf_y_mode_prob); i++) { -+ u32 byte_count = 0; -+ int idx = 0; -+ -+ /* vp9_kf_y_mode_prob */ -+ for (j = 0; j < ARRAY_SIZE(vp9_kf_y_mode_prob[0]); j++) { -+ for (k = 0; k < ARRAY_SIZE(vp9_kf_y_mode_prob[0][0]); -+ k++) { -+ u8 val = vp9_kf_y_mode_prob[i][j][k]; -+ -+ rkprobs->intra_mode[i].y_mode[idx++] = val; -+ byte_count++; -+ if (byte_count == 27) { -+ byte_count = 0; -+ idx += 5; -+ } -+ } -+ } -+ -+ idx = 0; -+ if (i < 4) { -+ for (m = 0; m < (i < 3 ? 23 : 21); m++) { -+ const u8 *ptr = (const u8 *)kf_uv_mode_prob; -+ -+ rkprobs->intra_mode[i].uv_mode[idx++] = ptr[i * 23 + m]; -+ } -+ } -+ } -+} -+ -+static void init_inter_probs(struct rkvdec_ctx *ctx, -+ const struct rkvdec_vp9_run *run) -+{ -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; -+ struct rkvdec_vp9_inter_frame_probs *rkprobs; -+ const struct v4l2_vp9_probabilities *probs; -+ unsigned int i, j, k; -+ -+ rkprobs = &tbl->probs.inter; -+ dec_params = run->decode_params; -+ probs = &dec_params->probs; -+ -+ /* -+ * inter probs -+ * 151 x 128 bits, aligned to 152 x 128 bits -+ * inter only -+ * intra_y_mode & inter_block info 6 x 128 bits -+ */ -+ -+ memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode)); -+ memcpy(rkprobs->comp_mode, probs->comp_mode, -+ sizeof(rkprobs->comp_mode)); -+ memcpy(rkprobs->comp_ref, probs->comp_ref, -+ sizeof(rkprobs->comp_ref)); -+ memcpy(rkprobs->single_ref, probs->single_ref, -+ sizeof(rkprobs->single_ref)); -+ memcpy(rkprobs->inter_mode, probs->inter_mode, -+ sizeof(rkprobs->inter_mode)); -+ memcpy(rkprobs->interp_filter, probs->interp_filter, -+ sizeof(rkprobs->interp_filter)); -+ -+ /* 128 x 128 bits coeff related */ -+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { -+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { -+ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) -+ write_coeff_plane(probs->coef[i][j][k], -+ rkprobs->coef[k][i][j]); -+ } -+ } -+ -+ /* intra uv mode 6 x 128 */ -+ memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0], -+ sizeof(rkprobs->uv_mode_0_2)); -+ memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3], -+ sizeof(rkprobs->uv_mode_3_5)); -+ memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6], -+ sizeof(rkprobs->uv_mode_6_8)); -+ memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9], -+ sizeof(rkprobs->uv_mode_9)); -+ -+ /* mv related 6 x 128 */ -+ memcpy(rkprobs->mv.joint, probs->mv.joint, -+ sizeof(rkprobs->mv.joint)); -+ memcpy(rkprobs->mv.sign, probs->mv.sign, -+ sizeof(rkprobs->mv.sign)); -+ memcpy(rkprobs->mv.class, probs->mv.class, -+ sizeof(rkprobs->mv.class)); -+ memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit, -+ sizeof(rkprobs->mv.class0_bit)); -+ memcpy(rkprobs->mv.bits, probs->mv.bits, -+ sizeof(rkprobs->mv.bits)); -+ memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr, -+ sizeof(rkprobs->mv.class0_fr)); -+ memcpy(rkprobs->mv.fr, probs->mv.fr, -+ sizeof(rkprobs->mv.fr)); -+ memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp, -+ sizeof(rkprobs->mv.class0_hp)); -+ memcpy(rkprobs->mv.hp, probs->mv.hp, -+ sizeof(rkprobs->mv.hp)); -+} -+ -+static void init_probs(struct rkvdec_ctx *ctx, -+ const struct rkvdec_vp9_run *run) -+{ -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; -+ struct rkvdec_vp9_probs *rkprobs = &tbl->probs; -+ const struct v4l2_vp9_segmentation *seg; -+ const struct v4l2_vp9_probabilities *probs; -+ bool intra_only; -+ -+ dec_params = run->decode_params; -+ probs = &dec_params->probs; -+ seg = &dec_params->seg; -+ -+ memset(rkprobs, 0, sizeof(*rkprobs)); -+ -+ intra_only = !!(dec_params->flags & -+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | -+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); -+ -+ /* sb info 5 x 128 bit */ -+ memcpy(rkprobs->partition, -+ intra_only ? kf_partition_probs : probs->partition, -+ sizeof(rkprobs->partition)); -+ -+ memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); -+ memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree)); -+ memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip)); -+ memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32)); -+ memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16)); -+ memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8)); -+ memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter)); -+ -+ if (intra_only) -+ init_intra_only_probs(ctx, run); -+ else -+ init_inter_probs(ctx, run); -+} -+ -+struct vp9d_ref_config { -+ u32 reg_frm_size; -+ u32 reg_hor_stride; -+ u32 reg_y_stride; -+ u32 reg_yuv_stride; -+ u32 reg_ref_base; -+}; -+ -+static struct vp9d_ref_config ref_config[3] = { -+ { -+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0), -+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0), -+ .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE, -+ .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, -+ .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE, -+ }, -+ { -+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1), -+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1), -+ .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, -+ .reg_yuv_stride = 0, -+ .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, -+ }, -+ { -+ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2), -+ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2), -+ .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, -+ .reg_yuv_stride = 0, -+ .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE, -+ } -+}; -+ -+static struct rkvdec_decoded_buffer * -+get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) -+{ -+ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; -+ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; -+ int buf_idx; -+ -+ /* -+ * If a ref is unused or invalid, address of current destination -+ * buffer is returned. -+ */ -+ buf_idx = vb2_find_timestamp(cap_q, timestamp, 0); -+ if (buf_idx < 0) -+ return vb2_to_rkvdec_decoded_buf(&dst->vb2_buf); -+ -+ return vb2_to_rkvdec_decoded_buf(vb2_get_buffer(cap_q, buf_idx)); -+} -+ -+static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf) -+{ -+ u32 aligned_pitch, aligned_height, yuv_len; -+ -+ aligned_height = round_up(buf->vp9.height, 64); -+ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; -+ yuv_len = (aligned_height * aligned_pitch * 3) / 2; -+ -+ return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) + -+ yuv_len; -+} -+ -+static void -+config_ref_registers(struct rkvdec_ctx *ctx, -+ const struct rkvdec_vp9_run *run, -+ struct rkvdec_decoded_buffer **ref_bufs, -+ enum v4l2_vp9_ref_id id) -+{ -+ u32 aligned_pitch, aligned_height, y_len, yuv_len; -+ struct rkvdec_decoded_buffer *buf = ref_bufs[id]; -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ -+ aligned_height = round_up(buf->vp9.height, 64); -+ writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(buf->vp9.width) | -+ RKVDEC_VP9_FRAMEHEIGHT(buf->vp9.height), -+ rkvdec->regs + ref_config[id].reg_frm_size); -+ -+ writel_relaxed(vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0), -+ rkvdec->regs + ref_config[id].reg_ref_base); -+ -+ if (&buf->base.vb == run->base.bufs.dst) -+ return; -+ -+ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; -+ y_len = aligned_height * aligned_pitch; -+ yuv_len = (y_len * 3) / 2; -+ -+ writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | -+ RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), -+ rkvdec->regs + ref_config[id].reg_hor_stride); -+ writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), -+ rkvdec->regs + ref_config[id].reg_y_stride); -+ -+ if (!ref_config[id].reg_yuv_stride) -+ return; -+ -+ writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), -+ rkvdec->regs + ref_config[id].reg_yuv_stride); -+} -+ -+static bool seg_featured_enabled(const struct v4l2_vp9_segmentation *seg, -+ enum v4l2_vp9_segment_feature feature, -+ unsigned int segid) -+{ -+ u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature); -+ -+ return !!(seg->feature_enabled[segid] & mask); -+} -+ -+static void -+config_seg_registers(struct rkvdec_ctx *ctx, -+ unsigned int segid) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ const struct v4l2_vp9_segmentation *seg; -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ s16 feature_val; -+ u8 feature_id; -+ u32 val = 0; -+ -+ seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; -+ feature_id = V4L2_VP9_SEGMENT_FEATURE_QP_DELTA; -+ if (seg_featured_enabled(seg, feature_id, segid)) { -+ feature_val = seg->feature_data[segid][feature_id]; -+ val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | -+ RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); -+ } -+ -+ feature_id = V4L2_VP9_SEGMENT_FEATURE_LF; -+ if (seg_featured_enabled(seg, feature_id, segid)) { -+ feature_val = seg->feature_data[segid][feature_id]; -+ val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | -+ RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); -+ } -+ -+ feature_id = V4L2_VP9_SEGMENT_FEATURE_REF_FRAME; -+ if (seg_featured_enabled(seg, feature_id, segid)) { -+ feature_val = seg->feature_data[segid][feature_id]; -+ val |= RKVDEC_SEGID_REFERINFO_EN(1) | -+ RKVDEC_SEGID_REFERINFO(feature_val); -+ } -+ -+ feature_id = V4L2_VP9_SEGMENT_FEATURE_SKIP; -+ if (seg_featured_enabled(seg, feature_id, segid)) -+ val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); -+ -+ if (!segid && -+ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) -+ val |= RKVDEC_SEGID_ABS_DELTA(1); -+ -+ writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); -+} -+ -+static void -+update_dec_buf_info(struct rkvdec_decoded_buffer *buf, -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) -+{ -+ buf->vp9.width = dec_params->frame_width_minus_1 + 1; -+ buf->vp9.height = dec_params->frame_height_minus_1 + 1; -+ buf->vp9.bit_depth = dec_params->bit_depth; -+} -+ -+static void -+update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx, -+ struct rkvdec_decoded_buffer *buf, -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) -+{ -+ vp9_ctx->cur.valid = true; -+ vp9_ctx->cur.frame_context_idx = dec_params->frame_context_idx; -+ vp9_ctx->cur.reference_mode = dec_params->reference_mode; -+ vp9_ctx->cur.tx_mode = dec_params->tx_mode; -+ vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter; -+ vp9_ctx->cur.flags = dec_params->flags; -+ vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp; -+ vp9_ctx->cur.seg = dec_params->seg; -+ vp9_ctx->cur.lf = dec_params->lf; -+} -+ -+static void -+update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx) -+{ -+ vp9_ctx->last = vp9_ctx->cur; -+} -+ -+static void config_registers(struct rkvdec_ctx *ctx, -+ const struct rkvdec_vp9_run *run) -+{ -+ u32 y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch; -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; -+ struct rkvdec_decoded_buffer *ref_bufs[V4L2_REF_ID_CNT]; -+ struct rkvdec_decoded_buffer *dst, *last, *mv_ref; -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ u32 val, stream_len, last_frame_info = 0; -+ const struct v4l2_vp9_segmentation *seg; -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ dma_addr_t addr; -+ bool intra_only; -+ unsigned int i; -+ -+ dec_params = run->decode_params; -+ dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf); -+ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) -+ ref_bufs[i] = get_ref_buf(ctx, &dst->base.vb, -+ dec_params->refs[i]); -+ -+ if (vp9_ctx->last.valid) -+ last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp); -+ else -+ last = dst; -+ -+ update_dec_buf_info(dst, dec_params); -+ update_ctx_cur_info(vp9_ctx, dst, dec_params); -+ seg = &dec_params->seg; -+ -+ intra_only = !!(dec_params->flags & -+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | -+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); -+ -+ writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), -+ rkvdec->regs + RKVDEC_REG_SYSCTRL); -+ -+ bit_depth = dec_params->bit_depth; -+ aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); -+ -+ aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width * -+ bit_depth, -+ 512) / 8; -+ y_len = aligned_height * aligned_pitch; -+ uv_len = y_len / 2; -+ yuv_len = y_len + uv_len; -+ -+ writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) | -+ RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16), -+ rkvdec->regs + RKVDEC_REG_PICPAR); -+ writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16), -+ rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); -+ writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16), -+ rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); -+ -+ stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); -+ writel_relaxed(RKVDEC_STRM_LEN(stream_len), -+ rkvdec->regs + RKVDEC_REG_STRM_LEN); -+ -+ /* -+ * Reset count buffer, because decoder only output intra related syntax -+ * counts when decoding intra frame, but update entropy need to update -+ * all the probabilities. -+ */ -+ if (intra_only) -+ memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size); -+ -+ vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid; -+ if (!intra_only && -+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && -+ (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || -+ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) -+ vp9_ctx->cur.segmapid++; -+ -+ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) -+ config_ref_registers(ctx, run, ref_bufs, i); -+ -+ for (i = 0; i < 8; i++) -+ config_seg_registers(ctx, i); -+ -+ writel_relaxed(RKVDEC_VP9_TX_MODE(dec_params->tx_mode) | -+ RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), -+ rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); -+ -+ if (!intra_only) { -+ const struct v4l2_vp9_loop_filter *lf; -+ s8 delta; -+ -+ if (vp9_ctx->last.valid) -+ lf = &vp9_ctx->last.lf; -+ else -+ lf = &vp9_ctx->cur.lf; -+ -+ val = 0; -+ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { -+ delta = lf->ref_deltas[i]; -+ val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta); -+ } -+ -+ writel_relaxed(val, -+ rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); -+ -+ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { -+ delta = lf->mode_deltas[i]; -+ last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i, -+ delta); -+ } -+ } -+ -+ if (vp9_ctx->last.valid && !intra_only && -+ vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) -+ last_frame_info |= RKVDEC_SEG_EN_LASTFRAME; -+ -+ if (vp9_ctx->last.valid && -+ vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) -+ last_frame_info |= RKVDEC_LAST_SHOW_FRAME; -+ -+ if (vp9_ctx->last.valid && -+ vp9_ctx->last.flags & -+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) -+ last_frame_info |= RKVDEC_LAST_INTRA_ONLY; -+ -+ if (vp9_ctx->last.valid && -+ last->vp9.width == dst->vp9.width && -+ last->vp9.height == dst->vp9.height) -+ last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR; -+ -+ writel_relaxed(last_frame_info, -+ rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME); -+ -+ writel_relaxed(stream_len - dec_params->compressed_header_size - -+ dec_params->uncompressed_header_size, -+ rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE); -+ -+ for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { -+ u32 refw = ref_bufs[i]->vp9.width; -+ u32 refh = ref_bufs[i]->vp9.height; -+ u32 hscale, vscale; -+ -+ hscale = (refw << 14) / dst->vp9.width; -+ vscale = (refh << 14) / dst->vp9.height; -+ writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) | -+ RKVDEC_VP9_REF_VER_SCALE(vscale), -+ rkvdec->regs + RKVDEC_VP9_REF_SCALE(i)); -+ } -+ -+ addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); -+ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); -+ addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0); -+ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); -+ writel_relaxed(vp9_ctx->priv_tbl.dma + -+ offsetof(struct rkvdec_vp9_priv_tbl, probs), -+ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); -+ writel_relaxed(vp9_ctx->count_tbl.dma, -+ rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE); -+ -+ writel_relaxed(vp9_ctx->priv_tbl.dma + -+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + -+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid), -+ rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE); -+ writel_relaxed(vp9_ctx->priv_tbl.dma + -+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + -+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)), -+ rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE); -+ -+ if (!intra_only && -+ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && -+ vp9_ctx->last.valid) -+ mv_ref = last; -+ else -+ mv_ref = dst; -+ -+ writel_relaxed(get_mv_base_addr(mv_ref), -+ rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); -+ -+ writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | -+ (ctx->decoded_fmt.fmt.pix_mp.height << 16), -+ rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); -+} -+ -+static int -+validate_dec_params(struct rkvdec_ctx *ctx, -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) -+{ -+ unsigned int aligned_width, aligned_height; -+ -+ /* We only support profile 0. */ -+ if (dec_params->profile != 0) { -+ dev_err(ctx->dev->dev, "unsupported profile %d\n", -+ dec_params->profile); -+ return -EINVAL; -+ } -+ -+ aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64); -+ aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64); -+ -+ /* -+ * Userspace should update the capture/decoded format when the -+ * resolution changes. -+ */ -+ if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width || -+ aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) { -+ dev_err(ctx->dev->dev, -+ "unexpected bitstream resolution %dx%d\n", -+ dec_params->frame_width_minus_1 + 1, -+ dec_params->frame_height_minus_1 +1); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, -+ struct rkvdec_vp9_run *run) -+{ -+ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; -+ const struct v4l2_ctrl_vp9_frame_ctx *fctx = NULL; -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct v4l2_ctrl *ctrl; -+ u8 frm_ctx; -+ int ret; -+ -+ rkvdec_run_preamble(ctx, &run->base); -+ -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS); -+ WARN_ON(!ctrl); -+ -+ dec_params = ctrl ? ctrl->p_cur.p : NULL; -+ if (WARN_ON(!dec_params)) -+ return -EINVAL; -+ -+ ret = validate_dec_params(ctx, dec_params); -+ if (ret) -+ return ret; -+ -+ run->decode_params = dec_params; -+ -+ /* No need to load the frame context if we don't need to update it. */ -+ if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) -+ return 0; -+ -+ /* -+ * When a refresh context is requested in parallel mode, we should just -+ * update the context with the probs passed in the decode parameters. -+ */ -+ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE) { -+ vp9_ctx->frame_context.probs = dec_params->probs; -+ return 0; -+ } -+ -+ frm_ctx = run->decode_params->frame_context_idx; -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(frm_ctx)); -+ if (WARN_ON(!ctrl)) -+ return 0; -+ -+ fctx = ctrl->p_cur.p; -+ vp9_ctx->frame_context = *fctx; -+ -+ /* -+ * For intra-only frames, we must update the context TX and skip probs -+ * with the value passed in the decode params. -+ */ -+ if (dec_params->flags & -+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) { -+ struct v4l2_vp9_probabilities *probs; -+ -+ probs = &vp9_ctx->frame_context.probs; -+ memcpy(probs->skip, dec_params->probs.skip, -+ sizeof(probs->skip)); -+ memcpy(probs->tx8, dec_params->probs.tx8, -+ sizeof(probs->tx8)); -+ memcpy(probs->tx16, dec_params->probs.tx16, -+ sizeof(probs->tx16)); -+ memcpy(probs->tx32, dec_params->probs.tx32, -+ sizeof(probs->tx32)); -+ } -+ -+ return 0; -+} -+ -+static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ struct rkvdec_vp9_run run = { }; -+ int ret; -+ -+ ret = rkvdec_vp9_run_preamble(ctx, &run); -+ if (ret) { -+ rkvdec_run_postamble(ctx, &run.base); -+ return ret; -+ } -+ -+ /* Prepare probs. */ -+ init_probs(ctx, &run); -+ -+ /* Configure hardware registers. */ -+ config_registers(ctx, &run); -+ -+ rkvdec_run_postamble(ctx, &run.base); -+ -+ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); -+ -+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); -+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); -+ -+ writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); -+ /* Start decoding! */ -+ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | -+ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, -+ rkvdec->regs + RKVDEC_REG_INTERRUPT); -+ -+ return 0; -+} -+ -+static u8 adapt_prob(u8 p1, u32 ct0, u32 ct1, u16 max_count, u32 update_factor) -+{ -+ u32 ct = ct0 + ct1, p2; -+ u32 lo = 1; -+ u32 hi = 255; -+ -+ if (!ct) -+ return p1; -+ -+ p2 = ((ct0 << 8) + (ct >> 1)) / ct; -+ p2 = clamp(p2, lo, hi); -+ ct = min_t(u32, ct, max_count); -+ -+ if (WARN_ON(max_count >= 257)) -+ return p1; -+ -+ update_factor = rkvdec_fastdiv(update_factor * ct, max_count); -+ -+ return p1 + (((p2 - p1) * update_factor + 128) >> 8); -+} -+ -+#define BAND_6(band) ((band) == 0 ? 3 : 6) -+ -+static void adapt_coeff(u8 coef[6][6][3], -+ const struct rkvdec_vp9_refs_counts ref_cnt[6][6], -+ u32 uf) -+{ -+ s32 l, m, n; -+ -+ for (l = 0; l < 6; l++) { -+ for (m = 0; m < BAND_6(l); m++) { -+ u8 *p = coef[l][m]; -+ const u32 n0 = ref_cnt[l][m].coeff[0]; -+ const u32 n1 = ref_cnt[l][m].coeff[1]; -+ const u32 n2 = ref_cnt[l][m].coeff[2]; -+ const u32 neob = ref_cnt[l][m].eob[1]; -+ const u32 eob_count = ref_cnt[l][m].eob[0]; -+ const u32 branch_ct[3][2] = { -+ { neob, eob_count - neob }, -+ { n0, n1 + n2 }, -+ { n1, n2 } -+ }; -+ -+ for (n = 0; n < 3; n++) -+ p[n] = adapt_prob(p[n], branch_ct[n][0], -+ branch_ct[n][1], 24, uf); -+ } -+ } -+} -+ -+static void -+adapt_coef_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6], -+ unsigned int uf) -+{ -+ unsigned int i, j, k; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { -+ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { -+ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); -+ k++) { -+ adapt_coeff(probs->coef[i][j][k], -+ ref_cnt[k][i][j], -+ uf); -+ } -+ } -+ } -+} -+ -+static void adapt_intra_frame_probs(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; -+ const struct rkvdec_vp9_intra_frame_symbol_counts *sym_cnts; -+ -+ sym_cnts = vp9_ctx->count_tbl.cpu; -+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); -+} -+ -+static void -+adapt_skip_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->skip); i++) -+ probs->skip[i] = adapt_prob(probs->skip[i], -+ sym_cnts->skip[i][0], -+ sym_cnts->skip[i][1], -+ 20, 128); -+} -+ -+static void -+adapt_is_inter_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++) -+ probs->is_inter[i] = adapt_prob(probs->is_inter[i], -+ sym_cnts->inter[i][0], -+ sym_cnts->inter[i][1], -+ 20, 128); -+} -+ -+static void -+adapt_comp_mode_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++) -+ probs->comp_mode[i] = adapt_prob(probs->comp_mode[i], -+ sym_cnts->comp[i][0], -+ sym_cnts->comp[i][1], -+ 20, 128); -+} -+ -+static void -+adapt_comp_ref_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++) -+ probs->comp_ref[i] = adapt_prob(probs->comp_ref[i], -+ sym_cnts->comp_ref[i][0], -+ sym_cnts->comp_ref[i][1], -+ 20, 128); -+} -+ -+static void -+adapt_single_ref_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) { -+ u8 *p = probs->single_ref[i]; -+ -+ p[0] = adapt_prob(p[0], sym_cnts->single_ref[i][0][0], -+ sym_cnts->single_ref[i][0][1], 20, 128); -+ p[1] = adapt_prob(p[1], sym_cnts->single_ref[i][1][0], -+ sym_cnts->single_ref[i][1][1], 20, 128); -+ } -+} -+ -+static void -+adapt_partition_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->partition); i++) { -+ const u32 *c = sym_cnts->partition[i]; -+ u8 *p = probs->partition[i]; -+ -+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); -+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); -+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); -+ } -+} -+ -+static void -+adapt_tx_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) { -+ u8 *p16x16 = probs->tx16[i]; -+ u8 *p32x32 = probs->tx32[i]; -+ const u32 *c16 = sym_cnts->tx16p[i]; -+ const u32 *c32 = sym_cnts->tx32p[i]; -+ const u32 *c8 = sym_cnts->tx8p[i]; -+ u8 *p8x8 = probs->tx8[i]; -+ -+ p8x8[0] = adapt_prob(p8x8[0], c8[0], c8[1], 20, 128); -+ p16x16[0] = adapt_prob(p16x16[0], c16[0], c16[1] + c16[2], -+ 20, 128); -+ p16x16[1] = adapt_prob(p16x16[1], c16[1], c16[2], 20, 128); -+ p32x32[0] = adapt_prob(p32x32[0], c32[0], -+ c32[1] + c32[2] + c32[3], 20, 128); -+ p32x32[1] = adapt_prob(p32x32[1], c32[1], c32[2] + c32[3], -+ 20, 128); -+ p32x32[2] = adapt_prob(p32x32[2], c32[2], c32[3], 20, 128); -+ } -+} -+ -+static void -+adapt_interp_filter_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) { -+ u8 *p = probs->interp_filter[i]; -+ const u32 *c = sym_cnts->filter[i]; -+ -+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2], 20, 128); -+ p[1] = adapt_prob(p[1], c[1], c[2], 20, 128); -+ } -+} -+ -+static void -+adapt_inter_mode_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) { -+ const u32 *c = sym_cnts->mv_mode[i]; -+ u8 *p = probs->inter_mode[i]; -+ -+ p[0] = adapt_prob(p[0], c[2], c[1] + c[0] + c[3], 20, 128); -+ p[1] = adapt_prob(p[1], c[0], c[1] + c[3], 20, 128); -+ p[2] = adapt_prob(p[2], c[1], c[3], 20, 128); -+ } -+} -+ -+static void -+adapt_mv_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts, -+ bool high_prec_mv) -+{ -+ const u32 *c = sym_cnts->mv_joint; -+ u8 *p = probs->mv.joint; -+ unsigned int i, j; -+ u32 sum; -+ -+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); -+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); -+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); -+ -+ for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) { -+ p = probs->mv.sign; -+ -+ p[i] = adapt_prob(p[i], sym_cnts->sign[i][0], -+ sym_cnts->sign[i][1], 20, 128); -+ -+ p = probs->mv.class[i]; -+ c = sym_cnts->classes[i]; -+ sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + -+ c[9] + c[10]; -+ p[0] = adapt_prob(p[0], c[0], sum, 20, 128); -+ sum -= c[1]; -+ p[1] = adapt_prob(p[1], c[1], sum, 20, 128); -+ sum -= c[2] + c[3]; -+ p[2] = adapt_prob(p[2], c[2] + c[3], sum, 20, 128); -+ p[3] = adapt_prob(p[3], c[2], c[3], 20, 128); -+ sum -= c[4] + c[5]; -+ p[4] = adapt_prob(p[4], c[4] + c[5], sum, 20, 128); -+ p[5] = adapt_prob(p[5], c[4], c[5], 20, 128); -+ sum -= c[6]; -+ p[6] = adapt_prob(p[6], c[6], sum, 20, 128); -+ p[7] = adapt_prob(p[7], c[7] + c[8], c[9] + c[10], 20, 128); -+ p[8] = adapt_prob(p[8], c[7], c[8], 20, 128); -+ p[9] = adapt_prob(p[9], c[9], c[10], 20, 128); -+ -+ p = probs->mv.class0_bit; -+ p[i] = adapt_prob(p[i], -+ sym_cnts->class0[i][0], -+ sym_cnts->class0[i][1], 20, 128); -+ -+ p = probs->mv.bits[i]; -+ for (j = 0; j < 10; j++) -+ p[j] = adapt_prob(p[j], sym_cnts->bits[i][j][0], -+ sym_cnts->bits[i][j][1], 20, 128); -+ -+ for (j = 0; j < 2; j++) { -+ p = probs->mv.class0_fr[i][j]; -+ c = sym_cnts->class0_fp[i][j]; -+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], -+ 20, 128); -+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); -+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); -+ } -+ -+ p = probs->mv.fr[i]; -+ c = sym_cnts->fp[i]; -+ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); -+ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); -+ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); -+ -+ if (!high_prec_mv) -+ continue; -+ -+ p = probs->mv.class0_hp; -+ p[i] = adapt_prob(p[i], sym_cnts->class0_hp[i][0], -+ sym_cnts->class0_hp[i][1], 20, 128); -+ -+ p = probs->mv.hp; -+ p[i] = adapt_prob(p[i], sym_cnts->hp[i][0], -+ sym_cnts->hp[i][1], 20, 128); -+ } -+} -+ -+static void -+adapt_intra_mode_probs(u8 *p, const u32 *c) -+{ -+ u32 sum = 0, s2; -+ unsigned int i; -+ -+ for (i = V4L2_VP9_INTRA_PRED_MODE_V; i <= V4L2_VP9_INTRA_PRED_MODE_TM; -+ i++) -+ sum += c[i]; -+ -+ p[0] = adapt_prob(p[0], c[V4L2_VP9_INTRA_PRED_MODE_DC], sum, 20, 128); -+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_TM]; -+ p[1] = adapt_prob(p[1], c[V4L2_VP9_INTRA_PRED_MODE_TM], sum, 20, 128); -+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_V]; -+ p[2] = adapt_prob(p[2], c[V4L2_VP9_INTRA_PRED_MODE_V], sum, 20, 128); -+ s2 = c[V4L2_VP9_INTRA_PRED_MODE_H] + c[V4L2_VP9_INTRA_PRED_MODE_D135] + -+ c[V4L2_VP9_INTRA_PRED_MODE_D117]; -+ sum -= s2; -+ p[3] = adapt_prob(p[3], s2, sum, 20, 128); -+ s2 -= c[V4L2_VP9_INTRA_PRED_MODE_H]; -+ p[4] = adapt_prob(p[4], c[V4L2_VP9_INTRA_PRED_MODE_H], s2, 20, 128); -+ p[5] = adapt_prob(p[5], c[V4L2_VP9_INTRA_PRED_MODE_D135], -+ c[V4L2_VP9_INTRA_PRED_MODE_D117], 20, 128); -+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D45]; -+ p[6] = adapt_prob(p[6], c[V4L2_VP9_INTRA_PRED_MODE_D45], -+ sum, 20, 128); -+ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D63]; -+ p[7] = adapt_prob(p[7], c[V4L2_VP9_INTRA_PRED_MODE_D63], sum, -+ 20, 128); -+ p[8] = adapt_prob(p[8], c[V4L2_VP9_INTRA_PRED_MODE_D153], -+ c[V4L2_VP9_INTRA_PRED_MODE_D207], 20, 128); -+} -+ -+static void -+adapt_y_intra_mode_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++) -+ adapt_intra_mode_probs(probs->y_mode[i], sym_cnts->y_mode[i]); -+} -+ -+static void -+adapt_uv_intra_mode_probs(struct v4l2_vp9_probabilities *probs, -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(probs->uv_mode); i++) -+ adapt_intra_mode_probs(probs->uv_mode[i], -+ sym_cnts->uv_mode[i]); -+} -+ -+static void -+adapt_inter_frame_probs(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; -+ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts; -+ -+ sym_cnts = vp9_ctx->count_tbl.cpu; -+ /* coefficients */ -+ if (vp9_ctx->last.valid && -+ !(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME)) -+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); -+ else -+ adapt_coef_probs(probs, sym_cnts->ref_cnt, 128); -+ -+ /* skip flag */ -+ adapt_skip_probs(probs, sym_cnts); -+ -+ /* intra/inter flag */ -+ adapt_is_inter_probs(probs, sym_cnts); -+ -+ /* comppred flag */ -+ adapt_comp_mode_probs(probs, sym_cnts); -+ -+ /* reference frames */ -+ adapt_comp_ref_probs(probs, sym_cnts); -+ -+ if (vp9_ctx->cur.reference_mode != V4L2_VP9_REF_MODE_COMPOUND) -+ adapt_single_ref_probs(probs, sym_cnts); -+ -+ /* block partitioning */ -+ adapt_partition_probs(probs, sym_cnts); -+ -+ /* tx size */ -+ if (vp9_ctx->cur.tx_mode == V4L2_VP9_TX_MODE_SELECT) -+ adapt_tx_probs(probs, sym_cnts); -+ -+ /* interpolation filter */ -+ if (vp9_ctx->cur.interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE) -+ adapt_interp_filter_probs(probs, sym_cnts); -+ -+ /* inter modes */ -+ adapt_inter_mode_probs(probs, sym_cnts); -+ -+ /* mv probs */ -+ adapt_mv_probs(probs, sym_cnts, -+ !!(vp9_ctx->cur.flags & -+ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV)); -+ -+ /* y intra modes */ -+ adapt_y_intra_mode_probs(probs, sym_cnts); -+ -+ /* uv intra modes */ -+ adapt_uv_intra_mode_probs(probs, sym_cnts); -+} -+ -+static void adapt_probs(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ bool intra_only; -+ -+ intra_only = !!(vp9_ctx->cur.flags & -+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | -+ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); -+ -+ if (intra_only) -+ adapt_intra_frame_probs(ctx); -+ else -+ adapt_inter_frame_probs(ctx); -+} -+ -+static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, -+ struct vb2_v4l2_buffer *src_buf, -+ struct vb2_v4l2_buffer *dst_buf, -+ enum vb2_buffer_state result) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct v4l2_ctrl *ctrl; -+ unsigned int fctx_idx; -+ -+ if (result == VB2_BUF_STATE_ERROR) -+ goto out_update_last; -+ -+ if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) -+ goto out_update_last; -+ -+ fctx_idx = vp9_ctx->cur.frame_context_idx; -+ -+ if (!(vp9_ctx->cur.flags & -+ (V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | -+ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE))) -+ adapt_probs(ctx); -+ -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(fctx_idx)); -+ if (WARN_ON(!ctrl)) -+ goto out_update_last; -+ -+ v4l2_ctrl_s_ctrl_compound(ctrl, V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT, -+ &vp9_ctx->frame_context); -+ -+out_update_last: -+ update_ctx_last_info(vp9_ctx); -+} -+ -+static int rkvdec_vp9_start(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ struct rkvdec_vp9_priv_tbl *priv_tbl; -+ struct rkvdec_vp9_ctx *vp9_ctx; -+ u8 *count_tbl; -+ int ret; -+ -+ vp9_ctx = kzalloc(sizeof(*vp9_ctx), GFP_KERNEL); -+ if (!vp9_ctx) -+ return -ENOMEM; -+ -+ ctx->priv = vp9_ctx; -+ -+ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), -+ &vp9_ctx->priv_tbl.dma, GFP_KERNEL); -+ if (!priv_tbl) { -+ ret = -ENOMEM; -+ goto err_free_ctx; -+ } -+ -+ vp9_ctx->priv_tbl.size = sizeof(*priv_tbl); -+ vp9_ctx->priv_tbl.cpu = priv_tbl; -+ memset(priv_tbl, 0, sizeof(*priv_tbl)); -+ -+ count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE, -+ &vp9_ctx->count_tbl.dma, GFP_KERNEL); -+ if (!count_tbl) { -+ ret = -ENOMEM; -+ goto err_free_priv_tbl; -+ } -+ -+ vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE; -+ vp9_ctx->count_tbl.cpu = count_tbl; -+ memset(count_tbl, 0, sizeof(*count_tbl)); -+ -+ return 0; -+ -+err_free_priv_tbl: -+ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, -+ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); -+ -+err_free_ctx: -+ kfree(vp9_ctx); -+ return ret; -+} -+ -+static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ -+ dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size, -+ vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma); -+ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, -+ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); -+ kfree(vp9_ctx); -+} -+ -+static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx, -+ struct v4l2_format *f) -+{ -+ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; -+ -+ fmt->num_planes = 1; -+ if (!fmt->plane_fmt[0].sizeimage) -+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2; -+ return 0; -+} -+ -+const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops = { -+ .adjust_fmt = rkvdec_vp9_adjust_fmt, -+ .start = rkvdec_vp9_start, -+ .stop = rkvdec_vp9_stop, -+ .run = rkvdec_vp9_run, -+ .done = rkvdec_vp9_done, -+}; -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 2e1d272a3af7..1013d1aba59a 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -159,6 +159,40 @@ static const u32 rkvdec_h264_decoded_fmts[] = { - V4L2_PIX_FMT_NV20, - }; - -+static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { -+ { -+ .mandatory = true, -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0), -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1), -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2), -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3), -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE, -+ .cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, -+ .cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, -+ .cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0, -+ }, -+}; -+ -+static const struct rkvdec_ctrls rkvdec_vp9_ctrls = { -+ .ctrls = rkvdec_vp9_ctrl_descs, -+ .num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs), -+}; -+ -+static const u32 rkvdec_vp9_decoded_fmts[] = { -+ V4L2_PIX_FMT_NV12, -+}; -+ - static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { - { - .fourcc = V4L2_PIX_FMT_H264_SLICE, -@@ -174,6 +208,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { - .ops = &rkvdec_h264_fmt_ops, - .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), - .decoded_fmts = rkvdec_h264_decoded_fmts, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_VP9_FRAME, -+ .frmsize = { -+ .min_width = 64, -+ .max_width = 4096, -+ .step_width = 64, -+ .min_height = 64, -+ .max_height = 2304, -+ .step_height = 64, -+ }, -+ .ctrls = &rkvdec_vp9_ctrls, -+ .ops = &rkvdec_vp9_fmt_ops, -+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts), -+ .decoded_fmts = rkvdec_vp9_decoded_fmts, - } - }; - -@@ -373,7 +422,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, - struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; - const struct rkvdec_coded_fmt_desc *desc; - struct v4l2_format *cap_fmt; -- struct vb2_queue *peer_vq; -+ struct vb2_queue *peer_vq, *vq; - int ret; - - /* -@@ -385,6 +434,15 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, - if (vb2_is_busy(peer_vq)) - return -EBUSY; - -+ /* -+ * Some codecs like VP9 can contain dynamic resolution changes which -+ * are currently not supported by the V4L2 API or driver, so return -+ * an error if userspace tries to reconfigure the output format. -+ */ -+ vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ if (vb2_is_busy(vq)) -+ return -EINVAL; -+ - ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_output_fmt); - if (ret) - return ret; -diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h -index e95c52e3168a..5f66f07acac5 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.h -+++ b/drivers/staging/media/rkvdec/rkvdec.h -@@ -51,6 +51,10 @@ struct rkvdec_vp9_decoded_buffer_info { - struct rkvdec_decoded_buffer { - /* Must be the first field in this struct. */ - struct v4l2_m2m_buffer base; -+ -+ union { -+ struct rkvdec_vp9_decoded_buffer_info vp9; -+ }; - }; - - static inline struct rkvdec_decoded_buffer * -@@ -119,4 +123,6 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); - void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); - - extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; -+extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; -+ - #endif /* RKVDEC_H_ */ diff --git a/patch/kernel/archive/rk322x-5.10/01-linux-1001-drm-wip.patch b/patch/kernel/archive/rk322x-5.10/01-linux-1001-drm-wip.patch deleted file mode 100644 index 957f36ad6..000000000 --- a/patch/kernel/archive/rk322x-5.10/01-linux-1001-drm-wip.patch +++ /dev/null @@ -1,4704 +0,0 @@ -From 0af28d066edbb4297d5140ff4c93db7b0bc0b182 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 3 May 2020 16:51:31 +0000 -Subject: [PATCH] drm/rockchip: vop: filter modes outside 0.5% pixel clock - tolerance - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +++++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index c80f7d9fd13f..6cbdb4672a4b 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1142,6 +1142,38 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) - spin_unlock_irqrestore(&vop->irq_lock, flags); - } - -+/* -+ * The VESA DMT standard specifies a 0.5% pixel clock frequency tolerance. -+ * The CVT spec reuses that tolerance in its examples. -+ */ -+#define CLOCK_TOLERANCE_PER_MILLE 5 -+ -+static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode) -+{ -+ struct vop *vop = to_vop(crtc); -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); -+ long rounded_rate; -+ long lowest, highest; -+ -+ if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) -+ return MODE_OK; -+ -+ rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); -+ if (rounded_rate < 0) -+ return MODE_NOCLOCK; -+ -+ lowest = mode->clock * (1000 - CLOCK_TOLERANCE_PER_MILLE); -+ if (rounded_rate < lowest) -+ return MODE_CLOCK_LOW; -+ -+ highest = mode->clock * (1000 + CLOCK_TOLERANCE_PER_MILLE); -+ if (rounded_rate > highest) -+ return MODE_CLOCK_HIGH; -+ -+ return MODE_OK; -+} -+ - static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -@@ -1512,6 +1544,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, - } - - static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { -+ .mode_valid = vop_crtc_mode_valid, - .mode_fixup = vop_crtc_mode_fixup, - .atomic_check = vop_crtc_atomic_check, - .atomic_begin = vop_crtc_atomic_begin, - -From 35e601dd9730b541bde93ec5cd5320b2c14a84fa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 11:46:16 +0000 -Subject: [PATCH] WIP: drm/rockchip: vop: max_output - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 ++++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 +++++++ - 3 files changed, 18 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 6cbdb4672a4b..106b38ea12df 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1152,6 +1152,7 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) - { - struct vop *vop = to_vop(crtc); -+ const struct vop_rect *max_output = &vop->data->max_output; - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); - long rounded_rate; - long lowest, highest; -@@ -1171,6 +1172,10 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - if (rounded_rate > highest) - return MODE_CLOCK_HIGH; - -+ if (max_output->width && max_output->height) -+ return drm_mode_validate_size(mode, max_output->width, -+ max_output->height); -+ - return MODE_OK; - } - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 4a2099cb582e..1516231bbf93 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -185,6 +185,11 @@ struct vop_win_data { - enum drm_plane_type type; - }; - -+struct vop_rect { -+ int width; -+ int height; -+}; -+ - struct vop_data { - uint32_t version; - const struct vop_intr *intr; -@@ -197,6 +202,7 @@ struct vop_data { - const struct vop_win_data *win; - unsigned int win_size; - unsigned int lut_size; -+ struct vop_rect max_output; - - #define VOP_FEATURE_OUTPUT_RGB10 BIT(0) - #define VOP_FEATURE_INTERNAL_RGB BIT(1) -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 80053d91a301..57c36e9207c1 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -682,6 +682,7 @@ static const struct vop_intr rk3288_vop_intr = { - static const struct vop_data rk3288_vop = { - .version = VOP_VERSION(3, 1), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 3840, 2160 }, - .intr = &rk3288_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -782,6 +783,7 @@ static const struct vop_misc rk3368_misc = { - - static const struct vop_data rk3368_vop = { - .version = VOP_VERSION(3, 2), -+ .max_output = { 4096, 2160 }, - .intr = &rk3368_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -803,6 +805,7 @@ static const struct vop_intr rk3366_vop_intr = { - - static const struct vop_data rk3366_vop = { - .version = VOP_VERSION(3, 4), -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -909,6 +912,7 @@ static const struct vop_afbc rk3399_vop_afbc = { - static const struct vop_data rk3399_vop_big = { - .version = VOP_VERSION(3, 5), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -935,6 +939,7 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { - - static const struct vop_data rk3399_vop_lit = { - .version = VOP_VERSION(3, 6), -+ .max_output = { 2560, 1600 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -955,6 +960,7 @@ static const struct vop_win_data rk3228_vop_win_data[] = { - static const struct vop_data rk3228_vop = { - .version = VOP_VERSION(3, 7), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -1026,6 +1032,7 @@ static const struct vop_win_data rk3328_vop_win_data[] = { - static const struct vop_data rk3328_vop = { - .version = VOP_VERSION(3, 8), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3328_vop_intr, - .common = &rk3328_common, - .modeset = &rk3328_modeset, - -From 61b85ebc7d075446c5f8a57607eb1fc87b16e2a8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:49 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: allow high tmds bit rates - -Prepare support for High TMDS Bit Rates used by HDMI2.0 display modes. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 23de359a1dec..cdf953850873 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -317,6 +317,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, - { - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - -+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); -+ - return phy_power_on(hdmi->phy); - } - - -From a1675f5032286c3f2e939a7392361fc15099c0b7 Mon Sep 17 00:00:00 2001 -From: Yakir Yang -Date: Mon, 11 Jul 2016 19:05:39 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI - -Dut to the high HDMI signal voltage driver, Mickey have meet -a serious RF/EMI problem, so we decided to reduce HDMI signal -voltage to a proper value. - -The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed) - ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43 - tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35 - -1. We decided to reduce voltage value to lower, but VSwing still -keep high, RF/EMI have been improved but still failed. - ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 - tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 - -2. We try to keep voltage value and vswing both lower, then RF/EMI -test all passed ;) - ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 - tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 -When we back to run HDMI different test and single-end test, we see -different test passed, but signle-end test failed. The oscilloscope -show that simgle-end clock's VL value is 1.78v (which remind LowLimit -should not lower then 2.6v). - -3. That's to say there are some different between PHY document and -measure value. And according to experiment 2 results, we need to -higher clock voltage and lower data voltage, then we can keep RF/EMI -satisfied and single-end & differen test passed. - ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47 - tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39 - -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cdf953850873..4652c0e0dcd6 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -181,7 +181,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { - static const struct dw_hdmi_phy_config rockchip_phy_config[] = { - /*pixelclk symbol term vlev*/ - { 74250000, 0x8009, 0x0004, 0x0272}, -- { 148500000, 0x802b, 0x0004, 0x028d}, -+ { 165000000, 0x802b, 0x0004, 0x0209}, - { 297000000, 0x8039, 0x0005, 0x028d}, - { ~0UL, 0x0000, 0x0000, 0x0000} - }; - -From 15a5f1ae8e0f570e81affb35b9b4aa4c0f485614 Mon Sep 17 00:00:00 2001 -From: Nickey Yang -Date: Mon, 13 Feb 2017 15:40:29 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: add phy_config for 594Mhz pixel clock - -Add phy_config for 594Mhz pixel clock used for 4K@60hz - -Signed-off-by: Nickey Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 4652c0e0dcd6..10c3dc521cbd 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -183,6 +183,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { - { 74250000, 0x8009, 0x0004, 0x0272}, - { 165000000, 0x802b, 0x0004, 0x0209}, - { 297000000, 0x8039, 0x0005, 0x028d}, -+ { 594000000, 0x8039, 0x0000, 0x019d}, - { ~0UL, 0x0000, 0x0000, 0x0000} - }; - - -From 43ac4790ecf27cf8db51e68298c541224af046a6 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Mon, 11 Jul 2016 19:05:36 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always - -Jitter was improved by lowering the MPLL bandwidth to account for high -frequency noise in the rk3288 PLL. In each case MPLL bandwidth was -lowered only enough to get us a comfortable margin. We believe that -lowering the bandwidth like this is safe given sufficient testing. - -Signed-off-by: Douglas Anderson -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++-------------- - 1 file changed, 2 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 10c3dc521cbd..cc7675638e4f 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -160,20 +160,8 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { - /* pixelclk bpp8 bpp10 bpp12 */ - { -- 40000000, { 0x0018, 0x0018, 0x0018 }, -- }, { -- 65000000, { 0x0028, 0x0028, 0x0028 }, -- }, { -- 66000000, { 0x0038, 0x0038, 0x0038 }, -- }, { -- 74250000, { 0x0028, 0x0038, 0x0038 }, -- }, { -- 83500000, { 0x0028, 0x0038, 0x0038 }, -- }, { -- 146250000, { 0x0038, 0x0038, 0x0038 }, -- }, { -- 148500000, { 0x0000, 0x0038, 0x0038 }, -- }, { -+ 600000000, { 0x0000, 0x0000, 0x0000 }, -+ }, { - ~0UL, { 0x0000, 0x0000, 0x0000}, - } - }; - -From 7604ef86c3d010fbfa61cf030b055b3860a53682 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Mon, 11 Jul 2016 19:05:42 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: Use auto-generated tables - -The previous tables for mpll_cfg and curr_ctrl were created using the -20-pages of example settings provided by the PHY vendor. Those -example settings weren't particularly dense, so there were places -where we were guessing what the settings would be for 10-bit and -12-bit (not that we use those anyway). It was also always a lot of -extra work every time we wanted to add a new clock rate since we had -to cross-reference several tables. - -In I've gone through the work to figure -out how to generate this table automatically. Let's now use the -automatically generated table and then we'll never need to look at it -again. - -We only support 8-bit mode right now and only support a small number -of clock rates and and I've verified that the only 8-bit rate that was -affected was 148.5. That mode appears to have been wrong in the old -table. - -Signed-off-by: Douglas Anderson -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++++++++++--------- - 1 file changed, 69 insertions(+), 61 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cc7675638e4f..c4c158106ca4 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -79,80 +79,88 @@ struct rockchip_hdmi { - - static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - { -- 27000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ 30666000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2153, 0x0000 }, -+ { 0x40f3, 0x0000 }, - }, -- }, { -- 36000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ }, { -+ 36800000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2153, 0x0000 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 40000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ }, { -+ 46000000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2142, 0x0001 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 54000000, { -- { 0x0072, 0x0001}, -- { 0x2142, 0x0001}, -- { 0x40a2, 0x0001}, -+ }, { -+ 61333000, { -+ { 0x0072, 0x0001 }, -+ { 0x2142, 0x0001 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 65000000, { -- { 0x0072, 0x0001}, -- { 0x2142, 0x0001}, -- { 0x40a2, 0x0001}, -+ }, { -+ 73600000, { -+ { 0x0072, 0x0001 }, -+ { 0x2142, 0x0001 }, -+ { 0x4061, 0x0002 }, - }, -- }, { -- 66000000, { -- { 0x013e, 0x0003}, -- { 0x217e, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 92000000, { -+ { 0x0072, 0x0001 }, -+ { 0x2145, 0x0002 }, -+ { 0x4061, 0x0002 }, -+ }, -+ }, { -+ 122666000, { -+ { 0x0051, 0x0002 }, -+ { 0x2145, 0x0002 }, -+ { 0x4061, 0x0002 }, - }, -- }, { -- 74250000, { -- { 0x0072, 0x0001}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 147200000, { -+ { 0x0051, 0x0002 }, -+ { 0x2145, 0x0002 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 83500000, { -- { 0x0072, 0x0001}, -+ }, { -+ 184000000, { -+ { 0x0051, 0x0002 }, -+ { 0x214c, 0x0003 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 108000000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 226666000, { -+ { 0x0040, 0x0003 }, -+ { 0x214c, 0x0003 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 106500000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 272000000, { -+ { 0x0040, 0x0003 }, -+ { 0x214c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -- 146250000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 340000000, { -+ { 0x0040, 0x0003 }, -+ { 0x3b4c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -- 148500000, { -- { 0x0051, 0x0003}, -- { 0x214c, 0x0003}, -- { 0x4064, 0x0003} -+ }, { -+ 600000000, { -+ { 0x1a40, 0x0003 }, -+ { 0x3b4c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -+ }, { - ~0UL, { -- { 0x00a0, 0x000a }, -- { 0x2001, 0x000f }, -- { 0x4002, 0x000f }, -+ { 0x0000, 0x0000 }, -+ { 0x0000, 0x0000 }, -+ { 0x0000, 0x0000 }, - }, - } - }; - -From 119aca9dc20be1639fe8146237d2821695a2bc6b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:52 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: limit tmds to 340mhz - -RK3228/RK3328 does not provide a stable hdmi signal at TMDS rates -above 371.25MHz (340MHz pixel clock). - -Limit the pixel clock rate to 340MHz to provide a stable signal. -Also limit the pixel clock to the display reported max tmds clock. - -This also enables use of pixel clocks up to 340MHz on RK3288/RK3399. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++------------ - 1 file changed, 4 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index c4c158106ca4..b62d8f4fc9a8 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -221,19 +221,11 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *info, - const struct drm_display_mode *mode) - { -- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; -- int pclk = mode->clock * 1000; -- bool valid = false; -- int i; -- -- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { -- if (pclk == mpll_cfg[i].mpixelclock) { -- valid = true; -- break; -- } -- } -+ if (mode->clock > 340000 || -+ (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) -+ return MODE_CLOCK_HIGH; - -- return (valid) ? MODE_OK : MODE_BAD; -+ return MODE_OK; - } - - static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - -From 9f31d6e1e2951eeaa979e1f9eb4b04cb64a4daf8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 3 May 2020 22:36:23 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: limit resolution to 3840x2160 - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index b62d8f4fc9a8..6f7641fbe6cc 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -225,7 +225,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) - return MODE_CLOCK_HIGH; - -- return MODE_OK; -+ return drm_mode_validate_size(mode, 3840, 2160); - } - - static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - -From bea1222407f1eb9d6af776d98eae5bd0f3544134 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:52 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: remove unused plat_data on - rk3228/rk3328 - -mpll_cfg/cur_ctr/phy_config is not used when phy_force_vendor is true, -lets remove them. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 6f7641fbe6cc..cc20a83fa9b8 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -396,9 +396,6 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { - .mode_valid = dw_hdmi_rockchip_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3228_chip_data, - .phy_ops = &rk3228_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", -@@ -433,9 +430,6 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .mode_valid = dw_hdmi_rockchip_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3328_chip_data, - .phy_ops = &rk3328_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", - -From 0bd355e25df8c93481ea6995bec7f452da97d5bf Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:50 +0000 -Subject: [PATCH] clk: rockchip: set parent rate for DCLK_VOP clock on rk3228 - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3228.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 2ac006e99c03..1f9176a5cc07 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -393,7 +393,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), - DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, - RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), -- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, -+ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), - - FACTOR(0, "xin12m", "xin24m", 0, 1, 2), - -From 957c41ed6b5a182b12880b6f16f6e17d034bf483 Mon Sep 17 00:00:00 2001 -From: Nickey Yang -Date: Mon, 17 Jul 2017 16:35:34 +0800 -Subject: [PATCH] HACK: clk: rockchip: rk3288: dedicate npll for vopb and hdmi - use - -MINIARM: set npll be used for hdmi only - -Signed-off-by: Nickey Yang -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288.dtsi | 2 ++ - drivers/clk/rockchip/clk-rk3288.c | 4 ++-- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index 68d5a58cfe88..a376dea3bb1b 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -1046,6 +1046,8 @@ vopb: vop@ff930000 { - resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; - reset-names = "axi", "ahb", "dclk"; - iommus = <&vopb_mmu>; -+ assigned-clocks = <&cru DCLK_VOP0>; -+ assigned-clock-parents = <&cru PLL_NPLL>; - status = "disabled"; - - vopb_out: port { -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index 15c8f1dcba9a..460b19d65ef3 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -234,7 +234,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { - [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), - RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), - [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), -- RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), -+ RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), - }; - - static struct clk_div_table div_hclk_cpu_t[] = { -@@ -444,7 +444,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { - RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, - RK3288_CLKGATE_CON(3), 4, GFLAGS), - -- COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, -+ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, - RK3288_CLKGATE_CON(3), 1, GFLAGS), - COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, - -From 0f7295f13d592ba60dee79a0cc23302ed2febffa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 4 Aug 2018 14:51:14 +0200 -Subject: [PATCH] HACK: clk: rockchip: rk3288: use npll table to to improve - HDMI compatibility - -Based on https://github.com/TinkerBoard/debian_kernel/commit/3d90870530b8a2901681f7b7fa598ee7381e49f3 - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3288.c | 23 ++++++++++++++++++++++- - 1 file changed, 22 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index 460b19d65ef3..b973c6b0315b 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -124,6 +124,27 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { - { /* sentinel */ }, - }; - -+static struct rockchip_pll_rate_table rk3288_npll_rates[] = { -+ RK3066_PLL_RATE_NB(594000000, 1, 99, 4, 32), -+ RK3066_PLL_RATE_NB(585000000, 6, 585, 4, 32), -+ RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), -+ RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), -+ RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), -+ RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), -+ RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), -+ RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), -+ RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), -+ RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), -+ RK3066_PLL_RATE(148352000, 13, 1125, 14), -+ RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), -+ RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), -+ RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), -+ RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), -+ RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), -+ RK3066_PLL_RATE(74176000, 26, 1125, 14), -+ { /* sentinel */ }, -+}; -+ - #define RK3288_DIV_ACLK_CORE_M0_MASK 0xf - #define RK3288_DIV_ACLK_CORE_M0_SHIFT 0 - #define RK3288_DIV_ACLK_CORE_MP_MASK 0xf -@@ -234,7 +255,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { - [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), - RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), - [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), -- RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), -+ RK3288_MODE_CON, 14, 9, 0, rk3288_npll_rates), - }; - - static struct clk_div_table div_hclk_cpu_t[] = { - -From e9d9694635e5cd9a84779e045c670239fc255606 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 28 Oct 2018 21:43:01 +0100 -Subject: [PATCH] HACK: clk: rockchip: rk3288: add more npll clocks - -Fixes 2560x1440@60Hz, 1600x1200@60Hz, 1920x1200@60Hz, 1680x1050@60Hz and 1440x900@60Hz modes on my monitor - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3288.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index b973c6b0315b..9192b89c2550 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -130,18 +130,34 @@ static struct rockchip_pll_rate_table rk3288_npll_rates[] = { - RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), - RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), - RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), -+ RK3066_PLL_RATE(348500000, 8, 697, 6), - RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), - RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), - RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), - RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), -+ RK3066_PLL_RATE(241500000, 2, 161, 8), -+ RK3066_PLL_RATE(162000000, 1, 81, 12), -+ RK3066_PLL_RATE(154000000, 6, 539, 14), - RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), - RK3066_PLL_RATE(148352000, 13, 1125, 14), - RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), -+ RK3066_PLL_RATE(121750000, 6, 487, 16), -+ RK3066_PLL_RATE(119000000, 3, 238, 16), - RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), - RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), -+ RK3066_PLL_RATE(101000000, 3, 202, 16), -+ RK3066_PLL_RATE(88750000, 6, 355, 16), - RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), -+ RK3066_PLL_RATE(83500000, 3, 167, 16), -+ RK3066_PLL_RATE(79500000, 1, 53, 16), - RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), - RK3066_PLL_RATE(74176000, 26, 1125, 14), -+ RK3066_PLL_RATE(72000000, 1, 48, 16), -+ RK3066_PLL_RATE(71000000, 3, 142, 16), -+ RK3066_PLL_RATE(68250000, 2, 91, 16), -+ RK3066_PLL_RATE(65000000, 3, 130, 16), -+ RK3066_PLL_RATE(40000000, 3, 80, 16), -+ RK3066_PLL_RATE(33750000, 2, 45, 16), - { /* sentinel */ }, - }; - - -From 2e18be0e366e9afcfe7dcdb69c3c90cce472bfa0 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 25 May 2020 20:36:45 +0000 -Subject: [PATCH] HACK: clk: rockchip: rk3399: dedicate vpll for vopb and hdmi - use - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3399.c | 32 +++++++++++++++++++++++++------ - 1 file changed, 26 insertions(+), 6 deletions(-) - -diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c -index 3682d5675cf7..0934145c09ad 100644 ---- a/drivers/clk/rockchip/clk-rk3399.c -+++ b/drivers/clk/rockchip/clk-rk3399.c -@@ -111,6 +111,25 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { - { /* sentinel */ }, - }; - -+static struct rockchip_pll_rate_table rk3399_vpll_rates[] = { -+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ -+ RK3036_PLL_RATE( 594000000, 1, 123, 5, 1, 0, 12582912), /* vco = 2970000000 */ -+ RK3036_PLL_RATE( 593406592, 1, 123, 5, 1, 0, 10508804), /* vco = 2967032965 */ -+ RK3036_PLL_RATE( 297000000, 1, 123, 5, 2, 0, 12582912), /* vco = 2970000000 */ -+ RK3036_PLL_RATE( 296703296, 1, 123, 5, 2, 0, 10508807), /* vco = 2967032970 */ -+ RK3036_PLL_RATE( 148500000, 1, 129, 7, 3, 0, 15728640), /* vco = 3118500000 */ -+ RK3036_PLL_RATE( 148351648, 1, 123, 5, 4, 0, 10508800), /* vco = 2967032960 */ -+ RK3036_PLL_RATE( 106500000, 1, 124, 7, 4, 0, 4194304), /* vco = 2982000000 */ -+ RK3036_PLL_RATE( 74250000, 1, 129, 7, 6, 0, 15728640), /* vco = 3118500000 */ -+ RK3036_PLL_RATE( 74175824, 1, 129, 7, 6, 0, 13550823), /* vco = 3115384608 */ -+ RK3036_PLL_RATE( 65000000, 1, 113, 7, 6, 0, 12582912), /* vco = 2730000000 */ -+ RK3036_PLL_RATE( 59340659, 1, 121, 7, 7, 0, 2581098), /* vco = 2907692291 */ -+ RK3036_PLL_RATE( 54000000, 1, 110, 7, 7, 0, 4194304), /* vco = 2646000000 */ -+ RK3036_PLL_RATE( 27000000, 1, 55, 7, 7, 0, 2097152), /* vco = 1323000000 */ -+ RK3036_PLL_RATE( 26973026, 1, 55, 7, 7, 0, 1173232), /* vco = 1321678323 */ -+ { /* sentinel */ }, -+}; -+ - /* CRU parents */ - PNAME(mux_pll_p) = { "xin24m", "xin32k" }; - -@@ -129,7 +148,7 @@ PNAME(mux_ddrclk_p) = { "clk_ddrc_lpll_src", - PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", - "gpll_aclk_cci_src", - "npll_aclk_cci_src", -- "vpll_aclk_cci_src" }; -+ "prevent:vpll" }; - PNAME(mux_cci_trace_p) = { "cpll_cci_trace", - "gpll_cci_trace" }; - PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", -@@ -156,9 +175,10 @@ PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", - "ppll", "upll", "xin24m" }; - - PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; --PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", -+ -+PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "prevent:vpll", "cpll", "gpll", - "npll" }; --PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", -+PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "prevent:vpll", "cpll", "gpll", - "xin24m" }; - - PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", -@@ -235,7 +255,7 @@ static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { - [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), - RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), - [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), -- RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), -+ RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_vpll_rates), - }; - - static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { -@@ -285,7 +305,7 @@ static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = - RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); - - static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = -- MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, -+ MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); - - static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = -@@ -1166,7 +1186,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { - GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, - RK3399_CLKGATE_CON(28), 0, GFLAGS), - -- COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, -+ COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, - RK3399_CLKGATE_CON(10), 12, GFLAGS), - - -From b2d23eae37a78a425144a21eb8bfbedc03edc754 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 19 Jul 2020 16:35:11 +0000 -Subject: [PATCH] HACK: dts: rockchip: do not use vopl for hdmi - ---- - arch/arm/boot/dts/rk3288.dtsi | 9 --------- - arch/arm64/boot/dts/rockchip/rk3399.dtsi | 9 --------- - 2 files changed, 18 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index a376dea3bb1b..9757976d6e8a 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -1104,11 +1104,6 @@ vopl_out: port { - #address-cells = <1>; - #size-cells = <0>; - -- vopl_out_hdmi: endpoint@0 { -- reg = <0>; -- remote-endpoint = <&hdmi_in_vopl>; -- }; -- - vopl_out_edp: endpoint@1 { - reg = <1>; - remote-endpoint = <&edp_in_vopl>; -@@ -1249,10 +1244,6 @@ hdmi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_hdmi>; - }; -- hdmi_in_vopl: endpoint@1 { -- reg = <1>; -- remote-endpoint = <&vopl_out_hdmi>; -- }; - }; - }; - }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index f5dee5f447bb..3e44bf8eac5c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -1640,11 +1640,6 @@ vopl_out_edp: endpoint@1 { - remote-endpoint = <&edp_in_vopl>; - }; - -- vopl_out_hdmi: endpoint@2 { -- reg = <2>; -- remote-endpoint = <&hdmi_in_vopl>; -- }; -- - vopl_out_mipi1: endpoint@3 { - reg = <3>; - remote-endpoint = <&mipi1_in_vopl>; -@@ -1816,10 +1811,6 @@ hdmi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_hdmi>; - }; -- hdmi_in_vopl: endpoint@1 { -- reg = <1>; -- remote-endpoint = <&vopl_out_hdmi>; -- }; - }; - }; - }; - -From c94f4e569387f6874b2c96a3db684751529fb6b6 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 12:33:01 +0000 -Subject: [PATCH] Revert "fixup! WIP: drm/rockchip: vop: max_output" - -This reverts commit c69612ca6820500cd1a0a3e4f8eb8c6f7b971cda. ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 106b38ea12df..138f449924f8 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1184,8 +1184,19 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *adjusted_mode) - { - struct vop *vop = to_vop(crtc); -+ const struct vop_rect *max_output = &vop->data->max_output; - unsigned long rate; - -+ if (max_output->width && max_output->height) { -+ enum drm_mode_status status; -+ -+ status = drm_mode_validate_size(adjusted_mode, -+ max_output->width, -+ max_output->height); -+ if (status != MODE_OK) -+ return false; -+ } -+ - /* - * Clock craziness. - * - -From 8af324175e002a9ee48be8618dce51ffc348a409 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 15 Jul 2020 15:24:47 +0000 -Subject: [PATCH] drm/rockchip: vop: fix crtc duplicate state - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 138f449924f8..0a25de483515 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1578,7 +1578,11 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) - { - struct rockchip_crtc_state *rockchip_state; - -- rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); -+ if (WARN_ON(!crtc->state)) -+ return NULL; -+ -+ rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state), -+ sizeof(*rockchip_state), GFP_KERNEL); - if (!rockchip_state) - return NULL; - - -From cf2f0b3497dd7094b96d0f61d71e07927aae3e0c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 15:15:50 +0000 -Subject: [PATCH] WIP: drm/rockchip: vop: filter interlaced modes - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 0a25de483515..5ab1412173a7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1160,6 +1160,9 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) - return MODE_OK; - -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return MODE_NO_INTERLACE; -+ - rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); - if (rounded_rate < 0) - return MODE_NOCLOCK; - -From 1400714403b22c227d281c8fc5a3c07cc6312740 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: add bridge and switch to - drm_bridge_funcs - -Switch the dw-hdmi driver to drm_bridge_funcs by implementing -a new local bridge, connecting it to the dw-hdmi bridge. - -Also enable bridge format negotiation by implementing -atomic_get_input_bus_fmts and support for 8-bit RGB 4:4:4. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 138 ++++++++++++++------ - 1 file changed, 95 insertions(+), 43 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cc20a83fa9b8..745fd1c13cef 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -68,6 +68,7 @@ struct rockchip_hdmi { - struct device *dev; - struct regmap *regmap; - struct drm_encoder encoder; -+ struct drm_bridge bridge; - const struct rockchip_hdmi_chip_data *chip_data; - struct clk *vpll_clk; - struct clk *grf_clk; -@@ -228,30 +229,20 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - return drm_mode_validate_size(mode, 3840, 2160); - } - --static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) -+static void -+dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode, -+ const struct drm_display_mode *adjusted_mode) - { --} -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - --static bool --dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, -- const struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) --{ -- return true; -+ clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } - --static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, -- struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) -+static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - { -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -- -- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); --} -- --static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) --{ -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 val; - int ret; - -@@ -279,10 +270,21 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) - ret ? "LIT" : "BIG"); - } - -+static bool is_rgb(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int --dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) -+dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - -@@ -292,12 +294,38 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, - return 0; - } - --static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { -- .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, -- .mode_set = dw_hdmi_rockchip_encoder_mode_set, -- .enable = dw_hdmi_rockchip_encoder_enable, -- .disable = dw_hdmi_rockchip_encoder_disable, -- .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, -+static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmt; -+ -+ *num_input_fmts = 0; -+ -+ if (!is_rgb(output_fmt)) -+ return NULL; -+ -+ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -+ if (!input_fmt) -+ return NULL; -+ -+ *num_input_fmts = 1; -+ *input_fmt = output_fmt; -+ -+ return input_fmt; -+} -+ -+static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { -+ .mode_set = dw_hdmi_rockchip_bridge_mode_set, -+ .enable = dw_hdmi_rockchip_bridge_enable, -+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, -+ .atomic_get_input_bus_fmts = dw_hdmi_rockchip_get_input_bus_fmts, -+ .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, -+ .atomic_reset = drm_atomic_helper_bridge_reset, - }; - - static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, -@@ -476,6 +504,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - struct dw_hdmi_plat_data *plat_data; - const struct of_device_id *match; - struct drm_device *drm = data; -+ struct drm_bridge *next_bridge; - struct drm_encoder *encoder; - struct rockchip_hdmi *hdmi; - int ret; -@@ -516,8 +545,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { -- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", -- ret); -+ DRM_DEV_ERROR(hdmi->dev, "Failed to enable vpll: %d\n", ret); - return ret; - } - -@@ -525,27 +553,51 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->phy)) { - ret = PTR_ERR(hdmi->phy); - if (ret != -EPROBE_DEFER) -- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); -- return ret; -+ DRM_DEV_ERROR(hdmi->dev, "Failed to get phy: %d\n", ret); -+ goto err_disable_clk; - } - -- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); -- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, "Failed to init encoder: %d\n", ret); -+ goto err_disable_clk; -+ } - -- platform_set_drvdata(pdev, hdmi); -+ hdmi->bridge.funcs = &dw_hdmi_rockchip_bridge_funcs; -+ drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); - -- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); -+ platform_set_drvdata(pdev, hdmi); - -- /* -- * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), -- * which would have called the encoder cleanup. Do it manually. -- */ -+ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); - if (IS_ERR(hdmi->hdmi)) { - ret = PTR_ERR(hdmi->hdmi); -- drm_encoder_cleanup(encoder); -- clk_disable_unprepare(hdmi->vpll_clk); -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(hdmi->dev, "Failed to init dw-hdmi bridge: %d\n", ret); -+ goto err_encoder_cleanup; -+ } -+ -+ next_bridge = of_drm_find_bridge(pdev->dev.of_node); -+ if (!next_bridge) { -+ ret = -EPROBE_DEFER; -+ goto err_dw_hdmi_remove; -+ } -+ -+ ret = drm_bridge_attach(encoder, next_bridge, &hdmi->bridge, 0); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(hdmi->dev, "Failed to attach dw-hdmi bridge: %d\n", ret); -+ goto err_dw_hdmi_remove; - } - -+ return 0; -+ -+err_dw_hdmi_remove: -+ dw_hdmi_remove(hdmi->hdmi); -+err_encoder_cleanup: -+ drm_encoder_cleanup(encoder); -+err_disable_clk: -+ clk_disable_unprepare(hdmi->vpll_clk); -+ - return ret; - } - -@@ -554,7 +606,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, - { - struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - -- dw_hdmi_unbind(hdmi->hdmi); -+ dw_hdmi_remove(hdmi->hdmi); - clk_disable_unprepare(hdmi->vpll_clk); - } - - -From ea791312a81f11f719a019e30c7736e7ab314739 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 18:00:44 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: add mtmdsclock parameter to phy - configure ops - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 ++++++---- - drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- - include/drm/bridge/dw_hdmi.h | 3 ++- - 3 files changed, 10 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 0c79a9ba48bb..50199329ad6f 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -137,7 +137,8 @@ struct dw_hdmi_phy_data { - bool has_svsret; - int (*configure)(struct dw_hdmi *hdmi, - const struct dw_hdmi_plat_data *pdata, -- unsigned long mpixelclock); -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock); - }; - - struct dw_hdmi { -@@ -1441,7 +1442,8 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) - */ - static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_plat_data *pdata, -- unsigned long mpixelclock) -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock) - { - const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; - const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; -@@ -1516,9 +1518,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, - - /* Write to the PHY as configured by the platform */ - if (pdata->configure_phy) -- ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); -+ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock, mtmdsclock); - else -- ret = phy->configure(hdmi, pdata, mpixelclock); -+ ret = phy->configure(hdmi, pdata, mpixelclock, mtmdsclock); - if (ret) { - dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", - mpixelclock); -diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -index 7b8ec8310699..539d86131fd4 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -+++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -@@ -53,7 +53,8 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, - } - - static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, -- unsigned long mpixelclock) -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock) - { - const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; - -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index ea34ca146b82..4f61ede6486d 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -152,7 +152,8 @@ struct dw_hdmi_plat_data { - const struct dw_hdmi_curr_ctrl *cur_ctr; - const struct dw_hdmi_phy_config *phy_config; - int (*configure_phy)(struct dw_hdmi *hdmi, void *data, -- unsigned long mpixelclock); -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock); - }; - - struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, - -From 0ea5bddefeeecd75d9dbee409ad8a8fddff6d378 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 21:34:48 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: support configuring phy for deep color - -Q: Should we rename dw_hdmi_curr_ctrl and dw_hdmi_phy_config mpixelclock to mtmdsclock ? - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 50199329ad6f..2581789178c7 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1448,6 +1448,7 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; - const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; - const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; -+ int depth; - - /* TOFIX Will need 420 specific PHY configuration tables */ - -@@ -1457,11 +1458,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - break; - - for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) -- if (mpixelclock <= curr_ctrl->mpixelclock) -+ if (mtmdsclock <= curr_ctrl->mpixelclock) - break; - - for (; phy_config->mpixelclock != ~0UL; phy_config++) -- if (mpixelclock <= phy_config->mpixelclock) -+ if (mtmdsclock <= phy_config->mpixelclock) - break; - - if (mpll_config->mpixelclock == ~0UL || -@@ -1469,11 +1470,17 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - phy_config->mpixelclock == ~0UL) - return -EINVAL; - -- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, -+ depth = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); -+ if (depth > 8 && mpixelclock != mtmdsclock) -+ depth = fls(depth - 8) - 1; -+ else -+ depth = 0; -+ -+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, - HDMI_3D_TX_PHY_CPCE_CTRL); -- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, -+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, - HDMI_3D_TX_PHY_GMPCTRL); -- dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], -+ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], - HDMI_3D_TX_PHY_CURRCTRL); - - dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); - -From 153e20ab5fd968cb5aff1e0cd7191d1ca1a6744e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 22:25:15 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: add mpll_cfg_420 for ycbcr420 mode - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- - include/drm/bridge/dw_hdmi.h | 1 + - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 2581789178c7..6d319b95b992 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1450,7 +1450,9 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; - int depth; - -- /* TOFIX Will need 420 specific PHY configuration tables */ -+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) && -+ pdata->mpll_cfg_420) -+ mpll_config = pdata->mpll_cfg_420; - - /* PLL/MPLL Cfg - always match on final entry */ - for (; mpll_config->mpixelclock != ~0UL; mpll_config++) -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 4f61ede6486d..0ebe01835d2a 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -149,6 +149,7 @@ struct dw_hdmi_plat_data { - - /* Synopsys PHY support */ - const struct dw_hdmi_mpll_config *mpll_cfg; -+ const struct dw_hdmi_mpll_config *mpll_cfg_420; - const struct dw_hdmi_curr_ctrl *cur_ctr; - const struct dw_hdmi_phy_config *phy_config; - int (*configure_phy)(struct dw_hdmi *hdmi, void *data, - -From 21174838c2d39a88ea46dbf64ced1ac133f32e7c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 15 Jul 2020 09:49:21 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: mode_valid: allow 420 clock rate - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 745fd1c13cef..9784111ea746 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -222,8 +222,15 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *info, - const struct drm_display_mode *mode) - { -- if (mode->clock > 340000 || -- (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) -+ struct dw_hdmi_plat_data *pdata = (struct dw_hdmi_plat_data *)data; -+ int clock = mode->clock; -+ -+ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > 340000 || -+ (info->max_tmds_clock && clock > info->max_tmds_clock)) - return MODE_CLOCK_HIGH; - - return drm_mode_validate_size(mode, 3840, 2160); -@@ -524,6 +531,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - - hdmi->dev = &pdev->dev; - hdmi->chip_data = plat_data->phy_data; -+ plat_data->priv_data = plat_data; - plat_data->phy_data = hdmi; - encoder = &hdmi->encoder; - - -From fbf69694a8f832cfa942f16a4bd8a630aa8f0f3f Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: limit mode and bus format to - max_tmds_clock - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 120 ++++++++++++++-------- - 1 file changed, 76 insertions(+), 44 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 6d319b95b992..c2425d7fc465 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1859,6 +1859,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, - HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); - } - -+static unsigned int -+hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) -+{ -+ int color_depth = hdmi_bus_fmt_color_depth(bus_format); -+ unsigned int tmdsclock = pixelclock; -+ -+ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) -+ tmdsclock = (u64)pixelclock * color_depth / 8; -+ -+ if (hdmi_bus_fmt_is_yuv420(bus_format)) -+ tmdsclock /= 2; -+ -+ return tmdsclock; -+} -+ - static void hdmi_av_composer(struct dw_hdmi *hdmi, - const struct drm_display_info *display, - const struct drm_display_mode *mode) -@@ -1870,29 +1885,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - unsigned int vdisplay, hdisplay; - - vmode->mpixelclock = mode->clock * 1000; -+ vmode->mtmdsclock = -+ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, -+ vmode->mpixelclock); - - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); -- -- vmode->mtmdsclock = vmode->mpixelclock; -- -- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -- switch (hdmi_bus_fmt_color_depth( -- hdmi->hdmi_data.enc_out_bus_format)) { -- case 16: -- vmode->mtmdsclock = vmode->mpixelclock * 2; -- break; -- case 12: -- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; -- break; -- case 10: -- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; -- break; -- } -- } -- -- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -- vmode->mtmdsclock /= 2; -- - dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); - - /* Set up HDMI_FC_INVIDCONF */ -@@ -2544,8 +2541,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) - * - MEDIA_BUS_FMT_RGB888_1X24, - */ - --/* Can return a maximum of 11 possible output formats for a mode/connector */ --#define MAX_OUTPUT_SEL_FORMATS 11 -+/* Can return a maximum of 15 possible output formats for a mode/connector */ -+#define MAX_OUTPUT_SEL_FORMATS 15 -+ -+static bool is_tmds_allowed(struct drm_display_info *info, -+ struct drm_display_mode *mode, -+ u32 bus_format) -+{ -+ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ -+ if (max_tmds_clock >= tmdsclock) -+ return true; -+ -+ return false; -+} - - static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -2557,8 +2567,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_display_info *info = &conn->display_info; - struct drm_display_mode *mode = &crtc_state->mode; - u8 max_bpc = conn_state->max_requested_bpc; -- bool is_hdmi2_sink = info->hdmi.scdc.supported || -- (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); - u32 *output_fmts; - unsigned int i = 0; - -@@ -2581,29 +2589,33 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - * If the current mode enforces 4:2:0, force the output but format - * to 4:2:0 and do not add the YUV422/444/RGB formats - */ -- if (conn->ycbcr_420_allowed && -- (drm_mode_is_420_only(info, mode) || -- (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { -+ if (conn->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) { - - /* Order bus formats from 16bit to 8bit if supported */ - if (max_bpc >= 16 && info->bpc == 16 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; - - if (max_bpc >= 12 && info->bpc >= 12 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; - - if (max_bpc >= 10 && info->bpc >= 10 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; - - /* Default 8bit fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; - - *num_output_fmts = i; - -- return output_fmts; -+ if (drm_mode_is_420_only(info, mode)) -+ return output_fmts; - } - - /* -@@ -2612,40 +2624,51 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - */ - - if (max_bpc >= 16 && info->bpc == 16) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; - } - - if (max_bpc >= 12 && info->bpc >= 12) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; - } - - if (max_bpc >= 10 && info->bpc >= 10) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; - } - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; - - /* Default 8bit RGB fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB888_1X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; - - *num_output_fmts = i; - -@@ -2825,11 +2848,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - struct dw_hdmi *hdmi = bridge->driver_private; - const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; - enum drm_mode_status mode_status = MODE_OK; -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ int clock = mode->clock; - - /* We don't support double-clocked modes */ - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_BAD; - -+ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > max_tmds_clock) -+ return MODE_CLOCK_HIGH; -+ - if (pdata->mode_valid) - mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, - mode); - -From 6e9f31fe455b92a19f12c4bae9c9f4b00efde58e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] WIP: drm/rockchip: dw_hdmi: add 10-bit rgb bus format - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 + - 2 files changed, 43 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 9784111ea746..ddff1582b271 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -77,6 +77,7 @@ struct rockchip_hdmi { - }; - - #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) -+#define to_crtc_state(x) container_of(x, struct drm_crtc_state, x) - - static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - { -@@ -242,6 +243,11 @@ dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *adjusted_mode) - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_crtc_state *crtc_state = to_crtc_state(adjusted_mode); -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, s->bus_width); - - clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } -@@ -280,6 +286,7 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - static bool is_rgb(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_RGB888_1X24: - return true; - default: -@@ -287,6 +294,16 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_10bit(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int - dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -294,9 +311,24 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ struct drm_atomic_state *state = bridge_state->base.state; -+ struct drm_crtc_state *old_crtc_state; -+ struct rockchip_crtc_state *old_state; -+ u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ s->output_bpc = 10; -+ s->bus_format = format; -+ s->bus_width = is_10bit(format) ? 10 : 8; -+ -+ old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -+ if (old_crtc_state && !crtc_state->mode_changed) { -+ old_state = to_rockchip_crtc_state(old_crtc_state); -+ if (s->bus_format != old_state->bus_format || -+ s->bus_width != old_state->bus_width) -+ crtc_state->mode_changed = true; -+ } - - return 0; - } -@@ -308,10 +340,19 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - u32 output_fmt, - unsigned int *num_input_fmts) - { -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 *input_fmt; -+ bool has_10bit = true; - - *num_input_fmts = 0; - -+ if (drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder)) -+ has_10bit = false; -+ -+ if (!has_10bit && is_10bit(output_fmt)) -+ return NULL; -+ - if (!is_rgb(output_fmt)) - return NULL; - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -index e33c2dcd0d4b..03944e08b6c7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -@@ -31,6 +31,8 @@ struct rockchip_crtc_state { - int output_bpc; - int output_flags; - bool enable_afbc; -+ u32 bus_format; -+ int bus_width; - }; - #define to_rockchip_crtc_state(s) \ - container_of(s, struct rockchip_crtc_state, base) - -From 83871fb221f71065f78cff3c8019f8684481a155 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:42:44 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: add content type connector property - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index c2425d7fc465..f86b8fa40ab6 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1646,6 +1646,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, - const struct drm_connector *connector, - const struct drm_display_mode *mode) - { -+ const struct drm_connector_state *conn_state = connector->state; - struct hdmi_avi_infoframe frame; - u8 val; - -@@ -1703,6 +1704,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - } - -+ drm_hdmi_avi_infoframe_content_type(&frame, conn_state); -+ - /* - * The Designware IP uses a different byte format from standard - * AVI info frames, though generally the bits are in the correct -@@ -2431,7 +2434,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, - if (!crtc) - return 0; - -- if (!hdr_metadata_equal(old_state, new_state)) { -+ if (!hdr_metadata_equal(old_state, new_state) || -+ old_state->content_type != new_state->content_type) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); -@@ -2499,6 +2503,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) - - drm_connector_attach_max_bpc_property(connector, 8, 16); - -+ drm_connector_attach_content_type_property(connector); -+ - if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.hdr_output_metadata_property, 0); - -From 553cc49748b8f0d074735f18cd45f050fca567e7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv444 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 30 ++++++++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 ++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 14 ++++++++++ - 4 files changed, 78 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index ddff1582b271..eea8e1491204 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -62,6 +62,7 @@ struct rockchip_hdmi_chip_data { - int lcdsel_grf_reg; - u32 lcdsel_big; - u32 lcdsel_lit; -+ bool ycbcr_444_allowed; - }; - - struct rockchip_hdmi { -@@ -294,10 +295,22 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_yuv444(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { - case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_YUV10_1X30: - return true; - default: - return false; -@@ -314,12 +327,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_atomic_state *state = bridge_state->base.state; - struct drm_crtc_state *old_crtc_state; - struct rockchip_crtc_state *old_state; -+ struct drm_bridge *next_bridge; -+ struct drm_bridge_state *next_bridge_state; - u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; - s->output_bpc = 10; - s->bus_format = format; -+ -+ next_bridge = drm_bridge_get_next_bridge(bridge); -+ if (next_bridge) { -+ next_bridge_state = drm_atomic_get_new_bridge_state(state, -+ next_bridge); -+ format = next_bridge_state->output_bus_cfg.format; -+ } -+ - s->bus_width = is_10bit(format) ? 10 : 8; - - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -@@ -353,7 +376,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (!has_10bit && is_10bit(output_fmt)) - return NULL; - -- if (!is_rgb(output_fmt)) -+ if (is_yuv444(output_fmt)) { -+ if (!hdmi->chip_data->ycbcr_444_allowed) -+ return NULL; -+ } else if (!is_rgb(output_fmt)) - return NULL; - - input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -@@ -502,6 +528,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { - - static struct rockchip_hdmi_chip_data rk3328_chip_data = { - .lcdsel_grf_reg = -1, -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { -@@ -517,6 +544,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { - .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, - .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), - .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 5ab1412173a7..a17bd4e90ba7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -310,6 +310,17 @@ static int vop_convert_afbc_format(uint32_t format) - return -EINVAL; - } - -+static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, - uint32_t dst, bool is_horizontal, - int vsu_mode, int *vskiplines) -@@ -1329,6 +1340,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - u16 vact_end = vact_st + vdisplay; - uint32_t pin_pol, val; - int dither_bpc = s->output_bpc ? s->output_bpc : 10; -+ bool yuv_output = is_yuv_output(s->bus_format); - int ret; - - if (old_state && old_state->self_refresh_active) { -@@ -1402,6 +1414,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -+ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); - else -@@ -1417,6 +1431,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, overlay_mode, yuv_output); -+ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); -+ -+ /* -+ * Background color is 10bit depth if vop version >= 3.5 -+ */ -+ if (!yuv_output) -+ val = 0; -+ else if (VOP_MAJOR(vop_data->version) == 3 && -+ VOP_MINOR(vop_data->version) >= 5) -+ val = 0x20010200; -+ else -+ val = 0x801080; -+ VOP_REG_SET(vop, common, dsp_background, val); -+ - VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); - val = hact_st << 16; - val |= hact_end; -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 1516231bbf93..b820ad3fa091 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -92,10 +92,16 @@ struct vop_common { - struct vop_reg mmu_en; - struct vop_reg out_mode; - struct vop_reg standby; -+ -+ struct vop_reg overlay_mode; -+ struct vop_reg dsp_data_swap; -+ struct vop_reg dsp_out_yuv; -+ struct vop_reg dsp_background; - }; - - struct vop_misc { - struct vop_reg global_regdone_en; -+ struct vop_reg win_channel[4]; - }; - - struct vop_intr { -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 57c36e9207c1..800b9341dd42 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -644,6 +644,11 @@ static const struct vop_common rk3288_common = { - .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), - }; - - /* -@@ -996,6 +1001,10 @@ static const struct vop_output rk3328_output = { - - static const struct vop_misc rk3328_misc = { - .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), -+ -+ .win_channel[0] = VOP_REG(RK3328_WIN0_CTRL2, 0xff, 0), -+ .win_channel[1] = VOP_REG(RK3328_WIN1_CTRL2, 0xff, 0), -+ .win_channel[2] = VOP_REG(RK3328_WIN2_CTRL2, 0xff, 0), - }; - - static const struct vop_common rk3328_common = { -@@ -1008,6 +1017,11 @@ static const struct vop_common rk3328_common = { - .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), - }; - - static const struct vop_intr rk3328_vop_intr = { - -From 6127108151898a2c69fb50749d7e647ac35cf8aa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv420 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 +++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 10 +++++---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ - 4 files changed, 48 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index eea8e1491204..c25ebe31b98d 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -306,9 +306,21 @@ static bool is_yuv444(u32 format) - } - } - -+static bool is_yuv420(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: - case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_YUV10_1X30: - return true; -@@ -345,6 +357,11 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - - s->bus_width = is_10bit(format) ? 10 : 8; - -+ if (is_yuv420(format)) { -+ s->output_mode = ROCKCHIP_OUT_MODE_YUV420; -+ s->bus_width /= 2; -+ } -+ - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); - if (old_crtc_state && !crtc_state->mode_changed) { - old_state = to_rockchip_crtc_state(old_crtc_state); -@@ -365,6 +382,7 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = conn_state->connector; - u32 *input_fmt; - bool has_10bit = true; - -@@ -379,6 +397,9 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (is_yuv444(output_fmt)) { - if (!hdmi->chip_data->ycbcr_444_allowed) - return NULL; -+ } else if (is_yuv420(output_fmt)) { -+ if (!connector->ycbcr_420_allowed) -+ return NULL; - } else if (!is_rgb(output_fmt)) - return NULL; - -@@ -538,6 +559,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .phy_name = "inno_dw_hdmi_phy2", - .phy_force_vendor = true, - .use_drm_infoframe = true, -+ .ycbcr_420_allowed = true, - }; - - static struct rockchip_hdmi_chip_data rk3399_chip_data = { -@@ -554,6 +576,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { - .phy_config = rockchip_phy_config, - .phy_data = &rk3399_chip_data, - .use_drm_infoframe = true, -+ .ycbcr_420_allowed = true, - }; - - static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index a17bd4e90ba7..5ea8031eb0f7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -311,6 +311,19 @@ static int vop_convert_afbc_format(uint32_t format) - } - - static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool has_uv_swapped(uint32_t bus_format) - { - switch (bus_format) { - case MEDIA_BUS_FMT_YUV8_1X24: -@@ -1414,7 +1427,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -- VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ VOP_REG_SET(vop, common, dsp_data_swap, has_uv_swapped(s->bus_format) ? 2 : 0); - - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); -@@ -1431,6 +1444,9 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, dclk_ddr, -+ s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); -+ - VOP_REG_SET(vop, common, overlay_mode, yuv_output); - VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index b820ad3fa091..8e6e999e5163 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -94,6 +94,7 @@ struct vop_common { - struct vop_reg standby; - - struct vop_reg overlay_mode; -+ struct vop_reg dclk_ddr; - struct vop_reg dsp_data_swap; - struct vop_reg dsp_out_yuv; - struct vop_reg dsp_background; -@@ -257,11 +258,12 @@ struct vop_data { - /* - * display output interface supported by rockchip lcdc - */ --#define ROCKCHIP_OUT_MODE_P888 0 --#define ROCKCHIP_OUT_MODE_P666 1 --#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_P888 0 -+#define ROCKCHIP_OUT_MODE_P666 1 -+#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_YUV420 14 - /* for use special outface */ --#define ROCKCHIP_OUT_MODE_AAAA 15 -+#define ROCKCHIP_OUT_MODE_AAAA 15 - - /* output flags */ - #define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 800b9341dd42..dd4546f9f410 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -646,6 +646,7 @@ static const struct vop_common rk3288_common = { - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3288_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), -@@ -1019,6 +1020,7 @@ static const struct vop_common rk3328_common = { - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), - -From c70da56116a103e5f6bd154b7819217410a9c4f7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 7 Jun 2020 20:25:25 +0000 -Subject: [PATCH] drm: drm_fourcc: add NV20 and NV30 YUV formats - -DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled -variant of NV15, a 10-bit 2-plane YUV format that has no padding between -components. Instead, luminance and chrominance samples are grouped into 4s -so that each group is packed into an integer number of bytes: - -YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes - -The '20' and '30' suffix refers to the optimum effective bits per pixel -which is achieved when the total number of luminance samples is a multiple -of 4. - -V2: Added NV30 format - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/drm_fourcc.c | 8 ++++++++ - include/uapi/drm/drm_fourcc.h | 2 ++ - 2 files changed, 10 insertions(+) - -diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c -index 722c7ebe4e88..2daf8a304b53 100644 ---- a/drivers/gpu/drm/drm_fourcc.c -+++ b/drivers/gpu/drm/drm_fourcc.c -@@ -278,6 +278,14 @@ const struct drm_format_info *__drm_format_info(u32 format) - .num_planes = 2, .char_per_block = { 5, 5, 0 }, - .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, - .vsub = 2, .is_yuv = true }, -+ { .format = DRM_FORMAT_NV20, .depth = 0, -+ .num_planes = 2, .char_per_block = { 5, 5, 0 }, -+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, -+ .vsub = 1, .is_yuv = true }, -+ { .format = DRM_FORMAT_NV30, .depth = 0, -+ .num_planes = 2, .char_per_block = { 5, 5, 0 }, -+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1, -+ .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_Q410, .depth = 0, - .num_planes = 3, .char_per_block = { 2, 2, 2 }, - .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, -diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h -index 82f327801267..d8e6159213dc 100644 ---- a/include/uapi/drm/drm_fourcc.h -+++ b/include/uapi/drm/drm_fourcc.h -@@ -242,6 +242,8 @@ extern "C" { - * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian - */ - #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ -+#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ -+#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */ - - /* - * 2 plane YCbCr MSB aligned - -From b41c8312d8bcd440bc42a799dd09b4acd9d4eca2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 7 Jun 2020 20:25:26 +0000 -Subject: [PATCH] drm: rockchip: add NV15, NV20 and NV30 support - -Add support for displaying 10-bit 4:2:0 and 4:2:2 formats produced by the -Rockchip Video Decoder on RK322X, RK3288, RK3328, RK3368 and RK3399. -Also add support for 10-bit 4:4:4 format while at it. - -V2: Added NV30 support - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++-- - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 32 +++++++++++++++++---- - 3 files changed, 54 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 5ea8031eb0f7..413534cf1a93 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -261,6 +261,18 @@ static bool has_rb_swapped(uint32_t format) - } - } - -+static bool is_fmt_10(uint32_t format) -+{ -+ switch (format) { -+ case DRM_FORMAT_NV15: -+ case DRM_FORMAT_NV20: -+ case DRM_FORMAT_NV30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static enum vop_data_format vop_convert_format(uint32_t format) - { - switch (format) { -@@ -276,10 +288,13 @@ static enum vop_data_format vop_convert_format(uint32_t format) - case DRM_FORMAT_BGR565: - return VOP_FMT_RGB565; - case DRM_FORMAT_NV12: -+ case DRM_FORMAT_NV15: - return VOP_FMT_YUV420SP; - case DRM_FORMAT_NV16: -+ case DRM_FORMAT_NV20: - return VOP_FMT_YUV422SP; - case DRM_FORMAT_NV24: -+ case DRM_FORMAT_NV30: - return VOP_FMT_YUV444SP; - default: - DRM_ERROR("unsupported format[%08x]\n", format); -@@ -946,7 +961,12 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; - dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); - -- offset = (src->x1 >> 16) * fb->format->cpp[0]; -+ if (fb->format->block_w[0]) -+ offset = (src->x1 >> 16) * fb->format->char_per_block[0] / -+ fb->format->block_w[0]; -+ else -+ offset = (src->x1 >> 16) * fb->format->cpp[0]; -+ - offset += (src->y1 >> 16) * fb->pitches[0]; - dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; - -@@ -972,6 +992,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - } - - VOP_WIN_SET(vop, win, format, format); -+ VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); - VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); - VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); -@@ -988,7 +1009,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - uv_obj = fb->obj[1]; - rk_uv_obj = to_rockchip_obj(uv_obj); - -- offset = (src->x1 >> 16) * bpp / hsub; -+ if (fb->format->block_w[1]) -+ offset = (src->x1 >> 16) * bpp / -+ fb->format->block_w[1] / hsub; -+ else -+ offset = (src->x1 >> 16) * bpp / hsub; - offset += (src->y1 >> 16) * fb->pitches[1] / vsub; - - dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 8e6e999e5163..9f50e0e00127 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -161,6 +161,7 @@ struct vop_win_phy { - struct vop_reg enable; - struct vop_reg gate; - struct vop_reg format; -+ struct vop_reg fmt_10; - struct vop_reg rb_swap; - struct vop_reg act_info; - struct vop_reg dsp_info; -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index dd4546f9f410..7d5191421ddf 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -50,6 +50,23 @@ static const uint32_t formats_win_full[] = { - DRM_FORMAT_NV24, - }; - -+static const uint32_t formats_win_full_10[] = { -+ DRM_FORMAT_XRGB8888, -+ DRM_FORMAT_ARGB8888, -+ DRM_FORMAT_XBGR8888, -+ DRM_FORMAT_ABGR8888, -+ DRM_FORMAT_RGB888, -+ DRM_FORMAT_BGR888, -+ DRM_FORMAT_RGB565, -+ DRM_FORMAT_BGR565, -+ DRM_FORMAT_NV12, -+ DRM_FORMAT_NV16, -+ DRM_FORMAT_NV24, -+ DRM_FORMAT_NV15, -+ DRM_FORMAT_NV20, -+ DRM_FORMAT_NV30, -+}; -+ - static const uint64_t format_modifiers_win_full[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID, -@@ -579,11 +596,12 @@ static const struct vop_scl_regs rk3288_win_full_scl = { - - static const struct vop_win_phy rk3288_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), - .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -@@ -720,11 +738,12 @@ static const struct vop_intr rk3368_vop_intr = { - - static const struct vop_win_phy rk3368_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), - .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21), - .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22), -@@ -871,11 +890,12 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { - - static const struct vop_win_phy rk3399_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full_afbc, - .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), - .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), - .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), - -From 478dd53361097d99541d777ce0f7fec7a79b7fa8 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 21:11:08 +0200 -Subject: [PATCH] !fixup drm/rockchip: rk3368's vop does not support 10-bit - formats - ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 7d5191421ddf..20c3e6248ec7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -738,8 +738,8 @@ static const struct vop_intr rk3368_vop_intr = { - - static const struct vop_win_phy rk3368_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full_10, -- .nformats = ARRAY_SIZE(formats_win_full_10), -+ .data_formats = formats_win_full, -+ .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), - -From 1f05ca5dfe7bd1553d32be9f450614b545be0912 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 23:20:34 +0200 -Subject: [PATCH] drm/rockchip: enable ycbcr_420_allowed and ycbcr_444_allowed - for RK3228 - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index c25ebe31b98d..5562326e4bce 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -515,6 +515,7 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { - - static struct rockchip_hdmi_chip_data rk3228_chip_data = { - .lcdsel_grf_reg = -1, -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { -@@ -523,6 +524,7 @@ static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { - .phy_ops = &rk3228_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", - .phy_force_vendor = true, -+ .ycbcr_420_allowed = true, - }; - - static struct rockchip_hdmi_chip_data rk3288_chip_data = { - -From 4273e39fec795fe18f83414655d30b0b9c5420d9 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:28 +0200 -Subject: [PATCH] drm: rockchip: add scaling for RK3036 win1 - -Add the registers needed to make scaling work on RK3036's win1. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 20c3e6248ec7..93a00b6ac295 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -94,15 +94,20 @@ static const uint64_t format_modifiers_win_lite[] = { - DRM_FORMAT_MOD_INVALID, - }; - --static const struct vop_scl_regs rk3036_win_scl = { -+static const struct vop_scl_regs rk3036_win0_scl = { - .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), - .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), - .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), - .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), - }; - -+static const struct vop_scl_regs rk3036_win1_scl = { -+ .scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0), -+ .scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16), -+}; -+ - static const struct vop_win_phy rk3036_win0_data = { -- .scl = &rk3036_win_scl, -+ .scl = &rk3036_win0_scl, - .data_formats = formats_win_full, - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, -@@ -119,6 +124,7 @@ static const struct vop_win_phy rk3036_win0_data = { - }; - - static const struct vop_win_phy rk3036_win1_data = { -+ .scl = &rk3036_win1_scl, - .data_formats = formats_win_lite, - .nformats = ARRAY_SIZE(formats_win_lite), - .format_modifiers = format_modifiers_win_lite, - -From a05d484d84e54a59c7846d2b409dda1e7355e3de Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:29 +0200 -Subject: [PATCH] drm: rockchip: add missing registers for RK3188 - -Add dither_up, dsp_lut_en and data_blank registers to enable their -respective functionality for RK3188's VOP. -While at that also fix .dsp_blank register which is (only) set though -BIT24 (same as RK3066) - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 93a00b6ac295..f8a898c5bb62 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -528,7 +528,10 @@ static const struct vop_common rk3188_common = { - .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27), - .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), - .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), -- .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), -+ .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24), -+ .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), -+ .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), -+ .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), - }; - - static const struct vop_win_data rk3188_vop_win_data[] = { - -From 6dd7876510c6a23e6d6b1243c730d73e6acb1137 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:44:12 +0200 -Subject: [PATCH] drm: rockchip: add missing registers for RK3066 - -Add dither_up, dsp_lut_en and data_blank registers to enable their -respective functionality for RK3066's VOP. -While at that also fix .rb_swap and .format registers for all windows, -which have to be set though RK3066_SYS_CTRL1. Also remove .scl from -win1: Scaling is only supported on the primary plane. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index f8a898c5bb62..77f8b49a4d17 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -372,8 +372,8 @@ static const struct vop_win_phy rk3066_win0_data = { - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19), - .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), -@@ -384,13 +384,12 @@ static const struct vop_win_phy rk3066_win0_data = { - }; - - static const struct vop_win_phy rk3066_win1_data = { -- .scl = &rk3066_win_scl, - .data_formats = formats_win_full, - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23), - .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), -@@ -405,8 +404,8 @@ static const struct vop_win_phy rk3066_win2_data = { - .nformats = ARRAY_SIZE(formats_win_lite), - .format_modifiers = format_modifiers_win_lite, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27), - .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), -@@ -431,6 +430,9 @@ static const struct vop_common rk3066_common = { - .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11), - .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10), - .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), -+ .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), -+ .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), -+ .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), - }; - - static const struct vop_win_data rk3066_vop_win_data[] = { - -From 08b0db205ddef2853dd75c0691d7d6d6f94c611b Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:30 +0200 -Subject: [PATCH] drm: rockchip: add alpha support for RK3036, RK3066, RK3126 - and RK3188 - -With commit 2aae8ed1f390 -("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") alpha -support was introduced for PX30's VOP. -RK3036, RK3066, RK3126 and RK3188 VOPs support alpha blending in the -same manner. -With the exception of RK3066 all of them support pre-multiplied alpha. - -Lets add these registers to make this work for those VOPs as well. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 21 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 77f8b49a4d17..27a04c5bc2fd 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -121,6 +121,9 @@ static const struct vop_win_phy rk3036_win0_data = { - .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_phy rk3036_win1_data = { -@@ -136,6 +139,9 @@ static const struct vop_win_phy rk3036_win1_data = { - .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_data rk3036_vop_win_data[] = { -@@ -202,6 +208,9 @@ static const struct vop_win_phy rk3126_win1_data = { - .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_data rk3126_vop_win_data[] = { -@@ -381,6 +390,8 @@ static const struct vop_win_phy rk3066_win0_data = { - .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0), - }; - - static const struct vop_win_phy rk3066_win1_data = { -@@ -397,6 +408,8 @@ static const struct vop_win_phy rk3066_win1_data = { - .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1), - }; - - static const struct vop_win_phy rk3066_win2_data = { -@@ -410,6 +423,8 @@ static const struct vop_win_phy rk3066_win2_data = { - .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2), - }; - - static const struct vop_modeset rk3066_modeset = { -@@ -495,6 +510,9 @@ static const struct vop_win_phy rk3188_win0_data = { - .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), - .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), -+ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18), -+ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0), -+ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_phy rk3188_win1_data = { -@@ -509,6 +527,9 @@ static const struct vop_win_phy rk3188_win1_data = { - .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), - .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_modeset rk3188_modeset = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -index 6e9fa5815d4d..0b3cd65ba5c1 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -@@ -955,6 +955,7 @@ - #define RK3188_DSP_CTRL0 0x04 - #define RK3188_DSP_CTRL1 0x08 - #define RK3188_INT_STATUS 0x10 -+#define RK3188_ALPHA_CTRL 0x14 - #define RK3188_WIN0_YRGB_MST0 0x20 - #define RK3188_WIN0_CBR_MST0 0x24 - #define RK3188_WIN0_YRGB_MST1 0x28 - -From 9fb777928ddfedc0412fa79b320814c06b7195cf Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:31 +0200 -Subject: [PATCH] drm: rockchip: set alpha_en to 0 if it is not used - -alpha_en should be set to 0 if it is not used, i.e. to disable alpha -blending if it was enabled before and should be disabled now. - -Fixes: 2aae8ed1f390 ("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 413534cf1a93..9b1cc0f413fc 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1062,6 +1062,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - VOP_WIN_SET(vop, win, alpha_en, 1); - } else { - VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); -+ VOP_WIN_SET(vop, win, alpha_en, 0); - } - - VOP_WIN_SET(vop, win, enable, 1); - -From 9be348c6cade7e709be7347d336c7638bf603b46 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 23:38:05 +0200 -Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3188 - ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 27a04c5bc2fd..b47f036d4a2c 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -555,6 +555,7 @@ static const struct vop_common rk3188_common = { - .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), - .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), - .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), -+ .dsp_data_swap = VOP_REG(RK3188_DSP_CTRL1, 0x1f, 26), - }; - - static const struct vop_win_data rk3188_vop_win_data[] = { - -From 195b202dbc5abe9c65e029826a7f3e2a2d71067a Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:22:02 +0200 -Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3066 - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index b47f036d4a2c..ae4a27704ad6 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -448,6 +448,7 @@ static const struct vop_common rk3066_common = { - .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), - .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), - .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), -+ .dsp_data_swap = VOP_REG(RK3066_DSP_CTRL1, 0x1f, 26), - }; - - static const struct vop_win_data rk3066_vop_win_data[] = { - -From 526739e44d5b0936db93bb92d2a98835723502c3 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 16 Aug 2020 00:55:19 +0200 -Subject: [PATCH] drm/rockchip: inno hdmi - add audio support - add required - aclk - fix video timing - fix phy pre-emphasis - ---- - .../display/rockchip/inno_hdmi-rockchip.txt | 6 +- - arch/arm/boot/dts/rk3036.dtsi | 24 +- - drivers/gpu/drm/rockchip/inno_hdmi.c | 266 +++++++++++++++++- - drivers/gpu/drm/rockchip/inno_hdmi.h | 2 + - 4 files changed, 279 insertions(+), 19 deletions(-) - -diff --git a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -index cec21714f0e0..b022c931e186 100644 ---- a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -+++ b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -@@ -7,7 +7,7 @@ Required properties: - - reg: - Physical base address and length of the controller's registers. - - clocks, clock-names: -- Phandle to hdmi controller clock, name should be "pclk" -+ Phandle to hdmi controller clock, name should be "aclk" and "pclk". - - interrupts: - HDMI interrupt number - - ports: -@@ -21,8 +21,8 @@ hdmi: hdmi@20034000 { - compatible = "rockchip,rk3036-inno-hdmi"; - reg = <0x20034000 0x4000>; - interrupts = ; -- clocks = <&cru PCLK_HDMI>; -- clock-names = "pclk"; -+ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; -+ clock-names = "aclk", "pclk"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_ctl>; - -diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi -index d7668a437c70..a86e1dc7fb5b 100644 ---- a/arch/arm/boot/dts/rk3036.dtsi -+++ b/arch/arm/boot/dts/rk3036.dtsi -@@ -397,11 +397,14 @@ hdmi: hdmi@20034000 { - compatible = "rockchip,rk3036-inno-hdmi"; - reg = <0x20034000 0x4000>; - interrupts = ; -- clocks = <&cru PCLK_HDMI>; -- clock-names = "pclk"; -+ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; -+ clock-names = "aclk", "pclk"; - rockchip,grf = <&grf>; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_ctl>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - status = "disabled"; - - hdmi_in: port { -@@ -414,6 +417,23 @@ hdmi_in_vop: endpoint@0 { - }; - }; - -+ hdmi_sound: hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "HDMI"; -+ status = "disabled"; -+ -+ simple-audio-card,dai-link { -+ format = "i2s"; -+ mclk-fs = <256>; -+ cpu { -+ sound-dai = <&i2s>; -+ }; -+ codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ }; -+ - timer: timer@20044000 { - compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer"; - reg = <0x20044000 0x20>; -diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c -index 7afdc54eb3ec..7e93208609a0 100644 ---- a/drivers/gpu/drm/rockchip/inno_hdmi.c -+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -21,6 +22,8 @@ - #include - #include - -+#include -+ - #include "rockchip_drm_drv.h" - #include "rockchip_drm_vop.h" - -@@ -28,6 +31,12 @@ - - #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x) - -+struct audio_info { -+ int sample_rate; -+ int channels; -+ int sample_width; -+}; -+ - struct hdmi_data_info { - int vic; - bool sink_is_hdmi; -@@ -52,8 +61,10 @@ struct inno_hdmi { - struct drm_device *drm_dev; - - int irq; -+ struct clk *aclk; - struct clk *pclk; - void __iomem *regs; -+ struct regmap *regmap; - - struct drm_connector connector; - struct drm_encoder encoder; -@@ -63,6 +74,9 @@ struct inno_hdmi { - - unsigned int tmds_rate; - -+ struct platform_device *audio_pdev; -+ bool audio_enable; -+ - struct hdmi_data_info hdmi_data; - struct drm_display_mode previous_mode; - }; -@@ -189,11 +203,17 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) - - static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) - { -+ -+ u8 value; -+ - switch (mode) { - case NORMAL: - inno_hdmi_sys_power(hdmi, false); -- -- hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); -+ if (hdmi->tmds_rate > 140000000) -+ value = 0x6f; -+ else -+ value = 0x3f; -+ hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, value); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); - - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); -@@ -301,6 +321,21 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, - return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0); - } - -+static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi, -+ struct audio_info *audio) -+{ -+ struct hdmi_audio_infoframe *faudio; -+ union hdmi_infoframe frame; -+ int rc; -+ -+ rc = hdmi_audio_infoframe_init(&frame.audio); -+ faudio = (struct hdmi_audio_infoframe *)&frame; -+ -+ faudio->channels = audio->channels; -+ -+ return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AAI, 0, 0, 0); -+} -+ - static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) - { - struct hdmi_data_info *data = &hdmi->hdmi_data; -@@ -383,6 +418,11 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - { - int value; - -+ value = BIT(20) | BIT(21); -+ value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; -+ value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; -+ regmap_write(hdmi->regmap, 0x148, value); -+ - /* Set detail external video timing polarity and interlace mode */ - value = v_EXTERANL_VIDEO(1); - value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? -@@ -402,7 +442,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF); - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); - -- value = mode->hsync_start - mode->hdisplay; -+ value = mode->htotal - mode->hsync_start; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF); - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); - -@@ -417,7 +457,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - value = mode->vtotal - mode->vdisplay; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF); - -- value = mode->vsync_start - mode->vdisplay; -+ value = mode->vtotal - mode->vsync_start; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF); - - value = mode->vsync_end - mode->vsync_start; -@@ -473,8 +513,9 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, - inno_hdmi_i2c_init(hdmi); - - /* Unmute video and audio output */ -- hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, -- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0)); -+ if (hdmi->audio_enable) -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0)); - - return 0; - } -@@ -521,6 +562,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, - - s->output_mode = ROCKCHIP_OUT_MODE_P888; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ s->bus_format = MEDIA_BUS_FMT_RGB888_1X24; - - return 0; - } -@@ -597,6 +639,175 @@ static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { - .mode_valid = inno_hdmi_connector_mode_valid, - }; - -+int inno_hdmi_audio_config_set(struct inno_hdmi *hdmi, struct audio_info *audio) -+{ -+ int rate, N, channel; -+ -+ if (audio->channels < 3) -+ channel = I2S_CHANNEL_1_2; -+ else if (audio->channels < 5) -+ channel = I2S_CHANNEL_3_4; -+ else if (audio->channels < 7) -+ channel = I2S_CHANNEL_5_6; -+ else -+ channel = I2S_CHANNEL_7_8; -+ -+ switch (audio->sample_rate) { -+ case 32000: -+ rate = AUDIO_32K; -+ N = N_32K; -+ break; -+ case 44100: -+ rate = AUDIO_441K; -+ N = N_441K; -+ break; -+ case 48000: -+ rate = AUDIO_48K; -+ N = N_48K; -+ break; -+ case 88200: -+ rate = AUDIO_882K; -+ N = N_882K; -+ break; -+ case 96000: -+ rate = AUDIO_96K; -+ N = N_96K; -+ break; -+ case 176400: -+ rate = AUDIO_1764K; -+ N = N_1764K; -+ break; -+ case 192000: -+ rate = AUDIO_192K; -+ N = N_192K; -+ break; -+ default: -+ dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", -+ __func__, audio->sample_rate); -+ return -ENOENT; -+ } -+ -+ /* set_audio source I2S */ -+ hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); -+ hdmi_writeb(hdmi, AUDIO_SAMPLE_RATE, rate); -+ hdmi_writeb(hdmi, AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | -+ v_I2S_CHANNEL(channel)); -+ -+ hdmi_writeb(hdmi, AUDIO_I2S_MAP, 0x00); -+ hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, 0); -+ -+ /* Set N value */ -+ hdmi_writeb(hdmi, AUDIO_N_H, (N >> 16) & 0x0F); -+ hdmi_writeb(hdmi, AUDIO_N_M, (N >> 8) & 0xFF); -+ hdmi_writeb(hdmi, AUDIO_N_L, N & 0xFF); -+ -+ /*Set hdmi nlpcm mode to support hdmi bitstream*/ -+ hdmi_writeb(hdmi, HDMI_AUDIO_CHANNEL_STATUS, v_AUDIO_STATUS_NLPCM(0)); -+ -+ return inno_hdmi_config_audio_aai(hdmi, audio); -+} -+ -+static int inno_hdmi_audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ struct audio_info audio = { -+ .sample_width = params->sample_width, -+ .sample_rate = params->sample_rate, -+ .channels = params->channels, -+ }; -+ -+ if (!hdmi->hdmi_data.sink_has_audio) { -+ dev_err(hdmi->dev, "Sink do not support audio!\n"); -+ return -ENODEV; -+ } -+ -+ if (!hdmi->encoder.crtc) -+ return -ENODEV; -+ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ break; -+ default: -+ dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt); -+ return -EINVAL; -+ } -+ -+ return inno_hdmi_audio_config_set(hdmi, &audio); -+} -+ -+static void inno_hdmi_audio_shutdown(struct device *dev, void *data) -+{ -+ /* do nothing */ -+} -+ -+static int inno_hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ -+ if (!hdmi->hdmi_data.sink_has_audio) { -+ dev_err(hdmi->dev, "Sink do not support audio!\n"); -+ return -ENODEV; -+ } -+ -+ hdmi->audio_enable = !mute; -+ -+ if (mute) -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, -+ v_AUDIO_MUTE(1) | v_AUDIO_PD(1)); -+ else -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, -+ v_AUDIO_MUTE(0) | v_AUDIO_PD(0)); -+ -+ return 0; -+} -+ -+static int inno_hdmi_audio_get_eld(struct device *dev, void *data, -+ uint8_t *buf, size_t len) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ struct drm_mode_config *config = &hdmi->encoder.dev->mode_config; -+ struct drm_connector *connector; -+ int ret = -ENODEV; -+ -+ mutex_lock(&config->mutex); -+ list_for_each_entry(connector, &config->connector_list, head) { -+ if (&hdmi->encoder == connector->encoder) { -+ memcpy(buf, connector->eld, -+ min(sizeof(connector->eld), len)); -+ ret = 0; -+ } -+ } -+ mutex_unlock(&config->mutex); -+ -+ return ret; -+} -+ -+static const struct hdmi_codec_ops audio_codec_ops = { -+ .hw_params = inno_hdmi_audio_hw_params, -+ .audio_shutdown = inno_hdmi_audio_shutdown, -+ //.digital_mute = inno_hdmi_audio_digital_mute, -+ .get_eld = inno_hdmi_audio_get_eld, -+}; -+ -+static int inno_hdmi_audio_codec_init(struct inno_hdmi *hdmi, -+ struct device *dev) -+{ -+ struct hdmi_codec_pdata codec_data = { -+ .i2s = 1, -+ .ops = &audio_codec_ops, -+ .max_i2s_channels = 8, -+ }; -+ -+ hdmi->audio_enable = false; -+ hdmi->audio_pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE, -+ &codec_data, sizeof(codec_data)); -+ -+ return PTR_ERR_OR_ZERO(hdmi->audio_pdev); -+} -+ - static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) - { - struct drm_encoder *encoder = &hdmi->encoder; -@@ -627,6 +838,8 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) - - drm_connector_attach_encoder(&hdmi->connector, encoder); - -+ inno_hdmi_audio_codec_init(hdmi, dev); -+ - return 0; - } - -@@ -826,23 +1039,44 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->regs)) - return PTR_ERR(hdmi->regs); - -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ hdmi->aclk = devm_clk_get(hdmi->dev, "aclk"); -+ if (IS_ERR(hdmi->aclk)) { -+ dev_err(hdmi->dev, "Unable to get HDMI aclk clk\n"); -+ return PTR_ERR(hdmi->aclk); -+ } -+ - hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); - if (IS_ERR(hdmi->pclk)) { - DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); - return PTR_ERR(hdmi->pclk); - } - -+ ret = clk_prepare_enable(hdmi->aclk); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, -+ "Cannot enable HDMI aclk clock: %d\n", ret); -+ return ret; -+ } -+ -+ - ret = clk_prepare_enable(hdmi->pclk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Cannot enable HDMI pclk clock: %d\n", ret); -- return ret; -+ goto err_disable_aclk; - } - -- irq = platform_get_irq(pdev, 0); -- if (irq < 0) { -- ret = irq; -- goto err_disable_clk; -+ hdmi->regmap = -+ syscon_regmap_lookup_by_phandle(hdmi->dev->of_node, -+ "rockchip,grf"); -+ if (IS_ERR(hdmi->regmap)) { -+ dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); -+ ret = PTR_ERR(hdmi->regmap); -+ goto err_disable_aclk; - } - - inno_hdmi_reset(hdmi); -@@ -851,7 +1085,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->ddc)) { - ret = PTR_ERR(hdmi->ddc); - hdmi->ddc = NULL; -- goto err_disable_clk; -+ goto err_disable_pclk; - } - - /* -@@ -884,9 +1118,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - hdmi->encoder.funcs->destroy(&hdmi->encoder); - err_put_adapter: - i2c_put_adapter(hdmi->ddc); --err_disable_clk: -+err_disable_pclk: - clk_disable_unprepare(hdmi->pclk); -- return ret; -+err_disable_aclk: -+ clk_disable_unprepare(hdmi->aclk); -+ -+return ret; - } - - static void inno_hdmi_unbind(struct device *dev, struct device *master, -@@ -899,6 +1136,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, - - i2c_put_adapter(hdmi->ddc); - clk_disable_unprepare(hdmi->pclk); -+ clk_disable_unprepare(hdmi->aclk); - } - - static const struct component_ops inno_hdmi_ops = { -diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h -index 93245b55f967..b722afc4e41f 100644 ---- a/drivers/gpu/drm/rockchip/inno_hdmi.h -+++ b/drivers/gpu/drm/rockchip/inno_hdmi.h -@@ -96,11 +96,13 @@ enum { - #define HDMI_AV_MUTE 0x05 - #define m_AVMUTE_CLEAR (1 << 7) - #define m_AVMUTE_ENABLE (1 << 6) -+#define m_AUDIO_PD (1 << 2) - #define m_AUDIO_MUTE (1 << 1) - #define m_VIDEO_BLACK (1 << 0) - #define v_AVMUTE_CLEAR(n) (n << 7) - #define v_AVMUTE_ENABLE(n) (n << 6) - #define v_AUDIO_MUTE(n) (n << 1) -+#define v_AUDIO_PD(n) (n << 2) - #define v_VIDEO_MUTE(n) (n << 0) - - #define HDMI_VIDEO_TIMING_CTL 0x08 - -From a8d962000848a237f8e8f0de8395d4e7df2a7197 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 16 Aug 2020 23:40:24 +0200 -Subject: [PATCH] WIP: ARM: dts: rockchip add vpll clock to RK322Xs hdmi node - ---- - arch/arm/boot/dts/rk322x.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 4bc631881c05..f98a945c68d3 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -766,8 +766,8 @@ hdmi: hdmi@200a0000 { - interrupts = ; - assigned-clocks = <&cru SCLK_HDMI_PHY>; - assigned-clock-parents = <&hdmi_phy>; -- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>; -- clock-names = "isfr", "iahb", "cec"; -+ clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>; -+ clock-names = "isfr", "iahb", "vpll", "cec"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>; - resets = <&cru SRST_HDMI_P>; - -From 30c781872a7b883b18193fa5aed75c312b06f4ab Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 18 Nov 2017 11:09:39 +0100 -Subject: [PATCH] rockchip: vop: force skip lines if image too big - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 9b1cc0f413fc..a34ff7593e1f 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -932,6 +932,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - int format; - int is_yuv = fb->format->is_yuv; - int i; -+ int skiplines = 0; - - /* - * can't update plane when vop is disabled. -@@ -950,8 +951,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - obj = fb->obj[0]; - rk_obj = to_rockchip_obj(obj); - -+ /* -+ * Force skip lines when image is yuv and 3840 width, -+ * fixes a "jumping" green lines issue on RK3328. -+ */ - actual_w = drm_rect_width(src) >> 16; -- actual_h = drm_rect_height(src) >> 16; -+ if (actual_w == 3840 && is_yuv) -+ skiplines = 1; -+ actual_h = drm_rect_height(src) >> (16 + skiplines); - act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); - - dsp_info = (drm_rect_height(dest) - 1) << 16; -@@ -993,7 +1000,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - - VOP_WIN_SET(vop, win, format, format); - VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); -- VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); -+ VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4 >> skiplines)); - VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); - VOP_WIN_SET(vop, win, y_mir_en, -@@ -1017,7 +1024,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - offset += (src->y1 >> 16) * fb->pitches[1] / vsub; - - dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; -- VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); -+ VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4 >> skiplines)); - VOP_WIN_SET(vop, win, uv_mst, dma_addr); - - for (i = 0; i < NUM_YUV2YUV_COEFFICIENTS; i++) { - -From b26ffb40570c456d0f84a3fa7886e2120c0397c2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 13:48:12 +0200 -Subject: [PATCH] drm: bridge: it66121: add IT66121FN variant - ---- - drivers/gpu/drm/bridge/ite-it66121.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 7e1a90319a6a..68f7e50fdddd 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -242,6 +242,11 @@ static const struct it66121_conf it66121_conf_simple = { - .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, - }; - -+static const struct it66121_conf it66121fn_conf_simple = { -+ .input_mode_reg = IT66121_INPUT_MODE_RGB, -+ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, -+}; -+ - static void it66121_hw_reset(struct it66121_ctx *ctx) - { - gpiod_set_value(ctx->gpio_reset, 1); -@@ -970,6 +975,9 @@ static const struct of_device_id it66121_dt_match[] = { - { .compatible = "ite,it66121", - .data = &it66121_conf_simple, - }, -+ { .compatible = "ite,it66121fn", -+ .data = &it66121fn_conf_simple, -+ }, - { }, - }; - MODULE_DEVICE_TABLE(of, it66121_dt_match); - -From a52fbdfbb0bccb1202beb25b58bdc29517c178d2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 23:15:45 +0200 -Subject: [PATCH] HACK: drm/rockchip: return false in ... if no platform device - is found - -This check will perfectly fail for bridges which are connected via i2c -and are therefore no platform devices. -TODO: look for a smarter solution - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -index b7654f5e4225..44ec8003e2a4 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -@@ -274,7 +274,7 @@ int rockchip_drm_endpoint_is_subdriver(struct device_node *ep) - pdev = of_find_device_by_node(node); - of_node_put(node); - if (!pdev) -- return -ENODEV; -+ return false; - - /* - * All rockchip subdrivers have probed at this point, so - -From 1fca49c650ba0441613da75e43323afb5525c8de Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 14:22:32 +0200 -Subject: [PATCH] drm/bridge: it66121 fix regmap config - -registers 0x00~0x2f don't need/must not have a selector -also: fix regmap range ---- - drivers/gpu/drm/bridge/ite-it66121.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 68f7e50fdddd..90f0881818d6 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -218,21 +218,21 @@ struct it66121_ctx { - - static const struct regmap_range_cfg it66121_regmap_banks[] = { - { -- .name = "it66121", -- .range_min = 0x00, -- .range_max = 0x1FF, -+ .name = "it66121-banks", -+ .range_min = 0x30, -+ .range_max = 0x1bf, - .selector_reg = IT66121_CLK_BANK_REG, - .selector_mask = 0x1, - .selector_shift = 0, -- .window_start = 0x00, -- .window_len = 0x130, -+ .window_start = 0x30, -+ .window_len = 0xcf, - }, - }; - - static const struct regmap_config it66121_regmap_config = { - .val_bits = 8, - .reg_bits = 8, -- .max_register = 0x1FF, -+ .max_register = 0x1bf, - .ranges = it66121_regmap_banks, - .num_ranges = ARRAY_SIZE(it66121_regmap_banks), - }; - -From 525f46ff24e5db028d341d04d1aede0cfc672c39 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 17:29:54 +0200 -Subject: [PATCH] drm/bridge: it66121 add detection message - ---- - drivers/gpu/drm/bridge/ite-it66121.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 90f0881818d6..650dd2f063cc 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -936,8 +936,11 @@ static int it66121_probe(struct i2c_client *client, - ids[2] != IT66121_DEVICE_ID0 || - ((ids[3] & IT66121_DEVICE_MASK) != IT66121_DEVICE_ID1)) { - ite66121_power_off(ctx); -+ DRM_INFO("HDMITX it66121 could not be indentified.\n"); - return -ENODEV; -- } -+ } else -+ DRM_INFO("HDMITX it66121 rev %d succsessfully indentified.\n", -+ ids[3] >> 4); - - ctx->bridge.funcs = &it66121_bridge_funcs; - ctx->bridge.of_node = dev->of_node; - -From ff31ba7e3c18672f7fa3ac17f9399301cc55cacb Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:28:21 +0200 -Subject: [PATCH] drm/bridge it66121 add AFE_XP_PLL_CTRL settings - -Add IT66121_AFE_XP_PLL_CTRL settings, it's unknown what they actualy -mean, since there is no documentation about it. Values have been taken -from vendor driver and it helps stablize signal at 1080p modes. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 650dd2f063cc..bc6ca85e5ee1 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -72,6 +72,10 @@ - #define IT66121_AFE_XP_EC1_REG 0x68 - #define IT66121_AFE_XP_EC1_LOWCLK BIT(4) - -+#define IT66121_AFE_XP_PLL_CTRL 0x6a -+#define IT66121_AFE_XP_PLL_HIGH_CLK_MASK (BIT(4) | BIT(5) | \ -+ BIT(6)) -+ - #define IT66121_SW_RST_REG 0x04 - #define IT66121_SW_RST_REF BIT(5) - #define IT66121_SW_RST_AREF BIT(4) -@@ -325,6 +329,13 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_AFE_XP_EC1_LOWCLK, 0x80); - if (ret) - return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_PLL_CTRL, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK); -+ if (ret) -+ return ret; -+ - } else { - ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, - IT66121_AFE_XP_GAINBIT | -@@ -346,6 +357,13 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_AFE_XP_EC1_LOWCLK); - if (ret) - return ret; -+ -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_PLL_CTRL, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK, -+ ~(IT66121_AFE_XP_PLL_HIGH_CLK_MASK) & 0xff); -+ if (ret) -+ return ret; - } - - /* Clear reset flags */ - -From 2a962b60c92993e1a1c82e74a403b33641d1cfbd Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 19 Aug 2020 19:02:02 +0200 -Subject: [PATCH] drm/bridge it66121 fire_afe if IT66121_SYS_STATUS_VID_STABLE - -There is an interrupt if video is stable - we should fire afe after that -arrived. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 101 ++++++++++++++++++++++----- - 1 file changed, 83 insertions(+), 18 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index bc6ca85e5ee1..81d1f53d50f5 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -95,12 +95,30 @@ - #define IT66121_HDCP_EN1P1FEAT BIT(1) - - #define IT66121_INT_STATUS1_REG 0x06 --#define IT66121_INT_STATUS1_AUD_OVF BIT(7) --#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) --#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) --#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) --#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) --#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) -+#define IT66121_INT_STATUS1_AUD_OVF BIT(7) -+#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) -+#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) -+#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) -+#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) -+#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) -+ -+#define IT66121_INT_STATUS2_REG 0x07 -+#define IT66121_INT_STATUS2_PKT_3D BIT(7) -+#define IT66121_INT_STATUS2_VID_UNSTABLE BIT(6) -+#define IT66121_INT_STATUS2_PKT_ACP BIT(5) -+#define IT66121_INT_STATUS2_PKT_NULL BIT(4) -+#define IT66121_INT_STATUS2_PKT_GEN BIT(3) -+#define IT66121_INT_STATUS2_CHK_KSV_LIST BIT(2) -+#define IT66121_INT_STATUS2_AUTH_DONE BIT(1) -+#define IT66121_INT_STATUS2_AUTH_FAIL BIT(0) -+ -+#define IT66121_INT_STATUS3_REG 0x08 -+#define IT66121_INT_STATUS3_AUD_CTS BIT(6) -+#define IT66121_INT_STATUS3_VSYNC BIT(5) -+#define IT66121_INT_STATUS3_VID_STABLE BIT(4) -+#define IT66121_INT_STATUS2_PKT_MPEG BIT(3) -+#define IT66121_INT_STATUS3_PKT_AUD BIT(1) -+#define IT66121_INT_STATUS3_PKT_AVI BIT(0) - - #define IT66121_DDC_HEADER_REG 0x11 - #define IT66121_DDC_HEADER_HDCP 0x74 -@@ -132,16 +150,43 @@ - #define IT66121_INT_MASK1_RX_SENS BIT(1) - #define IT66121_INT_MASK1_HPD BIT(0) - -+#define IT66121_INT_MASK2_REG 0x0a -+#define IT66121_INT_MASK2_PKT_AVI BIT(7) -+#define IT66121_INT_MASK2_VID_UNSTABLE BIT(6) -+#define IT66121_INT_MASK2_PKT_ACP BIT(5) -+#define IT66121_INT_MASK2_PKT_NULL BIT(4) -+#define IT66121_INT_MASK2_PKT_GEN BIT(3) -+#define IT66121_INT_MASK2_CHK_KSV_LIST BIT(2) -+#define IT66121_INT_MASK2_AUTH_DONE BIT(1) -+#define IT66121_INT_MASK2_AUTH_FAIL BIT(0) -+ -+#define IT66121_INT_MASK3_REG 0x0b -+#define IT66121_INT_MASK3_PKT_3D BIT(6) -+#define IT66121_INT_MASK3_AUD_CTS BIT(5) -+#define IT66121_INT_MASK3_VSYNC BIT(4) -+#define IT66121_INT_MASK3_VID_STABLE BIT(3) -+#define IT66121_INT_MASK3_PKT_MPEG BIT(2) -+#define IT66121_INT_MASK3_PKT_AUD BIT(0) -+ - #define IT66121_INT_CLR1_REG 0x0C --#define IT66121_INT_CLR1_PKTACP BIT(7) --#define IT66121_INT_CLR1_PKTNULL BIT(6) --#define IT66121_INT_CLR1_PKTGEN BIT(5) --#define IT66121_INT_CLR1_KSVLISTCHK BIT(4) --#define IT66121_INT_CLR1_AUTHDONE BIT(3) --#define IT66121_INT_CLR1_AUTHFAIL BIT(2) -+#define IT66121_INT_CLR1_PKT_ACP BIT(7) -+#define IT66121_INT_CLR1_PKT_NULL BIT(6) -+#define IT66121_INT_CLR1_PKT_GEN BIT(5) -+#define IT66121_INT_CLR1_CHK_KSV_LIST BIT(4) -+#define IT66121_INT_CLR1_AUTH_DONE BIT(3) -+#define IT66121_INT_CLR1_AUTH_FAIL BIT(2) - #define IT66121_INT_CLR1_RX_SENS BIT(1) - #define IT66121_INT_CLR1_HPD BIT(0) - -+#define IT66121_INT_CLR2_REG 0x0d -+#define IT66121_INT_CLR2_VSYNC BIT(7) -+#define IT66121_INT_CLR2_VID_STABLE BIT(6) -+#define IT66121_INT_CLR2_PKT_MPEG BIT(5) -+#define IT66121_INT_CLR2_PKT_AUD BIT(3) -+#define IT66121_INT_CLR2_PKT_AVI BIT(2) -+#define IT66121_INT_CLR2_PKT_3D BIT(1) -+#define IT66121_INT_CLR2_VID_UNSTABLE BIT(0) -+ - #define IT66121_AV_MUTE_REG 0xC1 - #define IT66121_AV_MUTE_ON BIT(0) - #define IT66121_AV_MUTE_BLUESCR BIT(1) -@@ -371,10 +416,9 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_SW_RST_REF | IT66121_SW_RST_VID, - ~(IT66121_SW_RST_REF | IT66121_SW_RST_VID) & - 0xFF); -- if (ret) -- return ret; - -- return it66121_fire_afe(ctx); -+ return ret; -+ - } - - static inline int it66121_wait_ddc_ready(struct it66121_ctx *ctx) -@@ -711,6 +755,12 @@ static int it66121_bridge_attach(struct drm_bridge *bridge, - return ret; - - /* Start interrupts */ -+ ret = regmap_write_bits(ctx->regmap, IT66121_INT_MASK3_REG, -+ IT66121_INT_MASK3_VID_STABLE, -+ ~(IT66121_INT_MASK3_VID_STABLE) & 0xff); -+ if (ret) -+ return ret; -+ - return regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, - IT66121_INT_MASK1_DDC_NOACK | - IT66121_INT_MASK1_HPD | -@@ -847,18 +897,18 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = { - static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - { - int ret; -- unsigned int val; -+ unsigned int val, sys_status; - struct it66121_ctx *ctx = dev_id; - struct device *dev = ctx->dev; - bool event = false; - - mutex_lock(&ctx->lock); - -- ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val); -+ ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &sys_status); - if (ret) - goto unlock; - -- if (val & IT66121_SYS_STATUS_ACTIVE_IRQ) { -+ if (sys_status & IT66121_SYS_STATUS_ACTIVE_IRQ) { - ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); - if (ret) { - dev_err(dev, "Cannot read STATUS1_REG %d\n", ret); -@@ -882,6 +932,21 @@ static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - } - } - -+ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS3_REG, &val); -+ if (ret) { -+ dev_err(dev, "Cannot read STATUS3_REG %d\n", ret); -+ } else if (val) { -+ if (val & IT66121_INT_STATUS3_VID_STABLE) { -+ if (sys_status & IT66121_SYS_STATUS_VID_STABLE) -+ it66121_fire_afe(ctx); -+ -+ regmap_write_bits(ctx->regmap, -+ IT66121_INT_CLR2_REG, -+ IT66121_INT_CLR2_VID_STABLE, -+ IT66121_INT_CLR2_VID_STABLE); -+ } -+ } -+ - regmap_write_bits(ctx->regmap, IT66121_SYS_STATUS_REG, - IT66121_SYS_STATUS_CLEAR_IRQ, - IT66121_SYS_STATUS_CLEAR_IRQ); - -From 2ec0caed703ceb5aad46c162c1f3fde4789fd635 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:44:12 +0200 -Subject: [PATCH] drm/bridge it66121: add I2S sound support - -Add sound support for it66121 - todos: - - TODOs - - refactor some huge functions - - smarter error handling (whole driver) - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/Kconfig | 1 + - drivers/gpu/drm/bridge/ite-it66121.c | 685 +++++++++++++++++++++++++++ - 2 files changed, 686 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig -index 6fe281070602..fd026f7cb4ba 100644 ---- a/drivers/gpu/drm/bridge/Kconfig -+++ b/drivers/gpu/drm/bridge/Kconfig -@@ -64,6 +64,7 @@ config DRM_LONTIUM_LT9611 - config DRM_ITE_IT66121 - tristate "ITE IT66121 HDMI bridge" - depends on OF -+ select SND_SOC_HDMI_CODEC if SND_SOC - select DRM_KMS_HELPER - select REGMAP_I2C - help -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 81d1f53d50f5..98f3d68fe01f 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* -+ * Copyright (C) 2020 Alex Bee - * Copyright (C) 2020 BayLibre, SAS - * Author: Phong LE - * Copyright (C) 2018-2019, Artem Mygaiev -@@ -26,6 +27,9 @@ - #include - #include - -+#include -+#include -+ - #define IT66121_MASTER_SEL_REG 0x10 - #define IT66121_MASTER_SEL_HOST BIT(0) - -@@ -245,11 +249,149 @@ - #define IT66121_EDID_FIFO_SIZE 32 - #define IT66121_AFE_CLK_HIGH 80000 - -+#define IT66121_AUD_CLK_CTRL_REG 0x58 -+#define IT66121_AUD_AUT_IP_CLK BIT(0) -+#define IT66121_AUD_AUT_OVR_SMPL_CLK BIT(4) -+#define IT66121_AUD_EXT_MCLK_128FS (0 << 2) -+#define IT66121_AUD_EXT_MCLK_256FS BIT(2) -+#define IT66121_AUD_EXT_MCLK_512FS (2 << 2) -+#define IT66121_AUD_EXT_MCLK_1024FS (3 << 2) -+ -+#define IT66121_AUD_INFO_REG_SZ 5 -+#define IT66121_AUD_INFO_DB1_REG 0x168 -+#define IT66121_AUD_INFO_DB2_REG 0x169 -+#define IT66121_AUD_INFO_DB3_REG 0x16a -+#define IT66121_AUD_INFO_DB4_REG 0x16b -+#define IT66121_AUD_INFO_DB5_REG 0x16c -+#define IT66121_AUD_INFO_CSUM_REG 0x16d -+ -+#define IT66121_AUD_INFO_PKT_REG 0xce -+#define IT66121_AUD_INFO_PKT_ON BIT(0) -+#define IT66121_AUD_INFO_PKT_RPT BIT(1) -+ -+#define IT66121_AUD_PKT_N1_REG 0x133 -+#define IT66121_AUD_PKT_N2_REG 0x134 -+#define IT66121_AUD_PKT_N3_REG 0x135 -+ -+#define IT66121_AUD_PKT_CTS_MODE_REG 0xc5 -+#define IT66121_AUD_PKT_CTS_MODE_USER BIT(1) -+#define IT66121_AUD_PKT_CTS_MODE_AUTO_VAL 0 -+#define IT66121_AUD_PKT_CTS1_REG 0x130 -+#define IT66121_AUD_PKT_CTS2_REG 0x131 -+#define IT66121_AUD_PKT_CTS3_REG 0x132 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS1_REG 0x135 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS2_REG 0x136 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS3_REG 0x137 -+ -+#define IT66121_AUD_CHST_MODE_REG 0x191 -+#define IT66121_AUD_CHST_MODE_NLPCM BIT(1) -+#define IT66121_AUD_CHST_CAT_REG 0x192 -+#define IT66121_AUD_CHST_SRCNUM_REG 0x193 -+#define IT66121_AUD_CHST_CHTNUM_REG 0x194 -+#define IT66121_AUD_CHST_CA_FS_REG 0x198 -+#define IT66121_AUD_CHST_OFS_WL_REG 0x199 -+ -+#define IT66121_AUD_CTRL0_REG 0xe0 -+#define IT66121_AUD_SWL_16BIT (0 << 6) -+#define IT66121_AUD_SWL_18BIT BIT(6) -+#define IT66121_AUD_SWL_20BIT (2 << 6) -+#define IT66121_AUD_SWL_24BIT (3 << 6) -+#define IT66121_AUD_SWL_MASK IT66121_AUD_SWL_24BIT -+#define IT66121_AUD_SPDIFTC BIT(5) -+#define IT66121_AUD_SPDIF BIT(4) -+#define IT66121_AUD_I2S (0 << 4) -+#define IT66121_AUD_TYPE_MASK IT66121_AUD_SPDIF -+#define IT66121_AUD_EN_I2S3 BIT(3) -+#define IT66121_AUD_EN_I2S2 BIT(2) -+#define IT66121_AUD_EN_I2S1 BIT(1) -+#define IT66121_AUD_EN_I2S0 BIT(0) -+#define IT66121_AUD_EN_I2S_MASK 0x0f -+#define IT66121_AUD_EN_SPDIF 1 -+ -+#define IT66121_AUD_CTRL1_REG 0xe1 -+#define IT66121_AUD_FMT_STD_I2S (0 << 0) -+#define IT66121_AUD_FMT_32BIT_I2S BIT(0) -+#define IT66121_AUD_FMT_LEFT_JUSTIFY (0 << 1) -+#define IT66121_AUD_FMT_RIGHT_JUSTIFY BIT(1) -+#define IT66121_AUD_FMT_DELAY_1T_TO_WS (0 << 2) -+#define IT66121_AUD_FMT_NO_DELAY_TO_WS BIT(2) -+#define IT66121_AUD_FMT_WS0_LEFT (0 << 3) -+#define IT66121_AUD_FMT_WS0_RIGHT BIT(3) -+#define IT66121_AUD_FMT_MSB_SHIFT_FIRST (0 << 4) -+#define IT66121_AUD_FMT_LSB_SHIFT_FIRST BIT(4) -+#define IT66121_AUD_FMT_RISE_EDGE_SAMPLE_WS (0 << 5) -+#define IT66121_AUD_FMT_FALL_EDGE_SAMPLE_WS BIT(5) -+#define IT66121_AUD_FMT_FULLPKT BIT(6) -+ -+#define IT66121_AUD_FIFOMAP_REG 0xe2 -+#define IT66121_AUD_FIFO3_SEL 6 -+#define IT66121_AUD_FIFO2_SEL 4 -+#define IT66121_AUD_FIFO1_SEL 2 -+#define IT66121_AUD_FIFO0_SEL 0 -+#define IT66121_AUD_FIFO_SELSRC3 3 -+#define IT66121_AUD_FIFO_SELSRC2 2 -+#define IT66121_AUD_FIFO_SELSRC1 1 -+#define IT66121_AUD_FIFO_SELSRC0 0 -+#define IT66121_AUD_FIFOMAP_DEFAULT (IT66121_AUD_FIFO_SELSRC0 \ -+ << IT66121_AUD_FIFO0_SEL | \ -+ IT66121_AUD_FIFO_SELSRC1 \ -+ << IT66121_AUD_FIFO1_SEL | \ -+ IT66121_AUD_FIFO_SELSRC2 \ -+ << IT66121_AUD_FIFO2_SEL | \ -+ IT66121_AUD_FIFO_SELSRC3 \ -+ << IT66121_AUD_FIFO3_SEL) -+ -+#define IT66121_AUD_CTRL3_REG 0xe3 -+#define IT66121_AUD_MULCH BIT(7) -+#define IT66121_AUD_ZERO_CTS BIT(6) -+#define IT66121_AUD_CHSTSEL BIT(4) -+#define IT66121_AUD_S3RLCHG BIT(3) -+#define IT66121_AUD_S2RLCHG BIT(2) -+#define IT66121_AUD_S1RLCHG BIT(1) -+#define IT66121_AUD_S0RLCHG BIT(0) -+#define IT66121_AUD_SRLCHG_MASK 0x0f -+#define IT66121_AUD_SRLCHG_DEFAULT ((~IT66121_AUD_S0RLCHG & \ -+ ~IT66121_AUD_S1RLCHG & \ -+ ~IT66121_AUD_S2RLCHG & \ -+ ~IT66121_AUD_S3RLCHG) & \ -+ IT66121_AUD_SRLCHG_MASK) -+ -+#define IT66121_AUD_SRC_VALID_FLAT_REG 0xe4 -+#define IT66121_AUD_SPXFLAT_SRC3 BIT(7) -+#define IT66121_AUD_SPXFLAT_SRC2 BIT(6) -+#define IT66121_AUD_SPXFLAT_SRC1 BIT(5) -+#define IT66121_AUD_SPXFLAT_SRC0 BIT(4) -+#define IT66121_AUD_SPXFLAT_MASK 0xf0 -+#define IT66121_AUD_SPXFLAT_SRC_ALL (IT66121_AUD_SPXFLAT_SRC0 | \ -+ IT66121_AUD_SPXFLAT_SRC1 | \ -+ IT66121_AUD_SPXFLAT_SRC2 | \ -+ IT66121_AUD_SPXFLAT_SRC3) -+#define IT66121_AUD_ERR2FLAT BIT(3) -+#define IT66121_AUD_S3VALID BIT(2) -+#define IT66121_AUD_S2VALID BIT(1) -+#define IT66121_AUD_S1VALID BIT(0) -+ -+#define IT66121_AUD_HDAUDIO_REG 0xe5 -+#define IT66121_AUD_HBR BIT(3) -+#define IT66121_AUD_DSD BIT(1) -+ - struct it66121_conf { - unsigned int input_mode_reg; - unsigned int input_conversion_reg; - }; - -+struct it66121_audio { -+ struct platform_device *pdev; -+ unsigned int sources; -+ unsigned int n; -+ unsigned int cts; -+ unsigned int format; -+ unsigned int sample_wl; -+ bool is_hbr; -+ struct hdmi_audio_infoframe audio_infoframe; -+ struct snd_aes_iec958 aes_iec958; -+}; -+ - struct it66121_ctx { - struct regmap *regmap; - struct drm_bridge bridge; -@@ -260,6 +402,8 @@ struct it66121_ctx { - struct regulator_bulk_data supplies[3]; - bool dual_edge; - const struct it66121_conf *conf; -+ bool sink_has_audio; -+ struct it66121_audio audio; - struct mutex lock; /* Protects fields below and device registers */ - struct edid *edid; - struct hdmi_avi_infoframe hdmi_avi_infoframe; -@@ -610,6 +754,7 @@ static int it66121_connector_get_modes(struct drm_connector *connector) - } - - num_modes = drm_add_edid_modes(connector, ctx->edid); -+ ctx->sink_has_audio = drm_detect_monitor_audio(ctx->edid); - - unlock: - mutex_unlock(&ctx->lock); -@@ -894,6 +1039,536 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = { - .mode_set = it66121_bridge_mode_set, - }; - -+/* Audio related functions */ -+ -+static int it66121_audio_reset_fifo(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD, -+ IT66121_SW_RST_AUD); -+ if (ret) -+ return ret; -+ -+ usleep_range(2000, 4000); -+ -+ return regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD, -+ ~(IT66121_SW_RST_AUD) & 0xff); -+} -+ -+static int it66121_audio_set_infoframe(struct it66121_ctx *ctx) -+{ -+ int i, ret; -+ u8 infoframe_buf[HDMI_INFOFRAME_SIZE(AUDIO)]; -+ -+ const u16 audioinfo_reg[IT66121_AUD_INFO_REG_SZ] = { -+ IT66121_AUD_INFO_DB1_REG, -+ IT66121_AUD_INFO_DB2_REG, -+ IT66121_AUD_INFO_DB3_REG, -+ IT66121_AUD_INFO_DB4_REG, -+ IT66121_AUD_INFO_DB5_REG -+ }; -+ -+ ret = hdmi_audio_infoframe_pack(&ctx->audio.audio_infoframe, infoframe_buf, -+ sizeof(infoframe_buf)); -+ if (ret < 0) { -+ dev_err(ctx->dev, "%s: failed to pack audio infoframe: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ for (i = 0; i < IT66121_AUD_INFO_REG_SZ; i++) { -+ ret = regmap_write(ctx->regmap, audioinfo_reg[i], -+ infoframe_buf[i + HDMI_INFOFRAME_HEADER_SIZE]); -+ if (ret) -+ return ret; -+ } -+ -+ /* -+ * TODO: linux defines 10 bytes; currently only 5 are filled -+ * if that ever changes checksum will differ since -+ * it66121 takes max 5 bytes -> calc checksum here???? -+ */ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_INFO_CSUM_REG, infoframe_buf[3]); -+ -+ if (ret) -+ return ret; -+ -+ return regmap_write(ctx->regmap, IT66121_AUD_INFO_PKT_REG, -+ IT66121_AUD_INFO_PKT_ON | IT66121_AUD_INFO_PKT_RPT); -+} -+ -+static int it66121_audio_set_cts_n(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N1_REG, -+ ctx->audio.n & 0xff); -+ if (ret) -+ return ret; -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N2_REG, -+ (ctx->audio.n >> 8) & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N3_REG, -+ (ctx->audio.n >> 16) & 0xf); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS1_REG, -+ ctx->audio.cts & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS2_REG, -+ (ctx->audio.cts >> 8) & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS3_REG, -+ (ctx->audio.cts >> 16) & 0xf); -+ if (ret) -+ return ret; -+ -+ /* -+ * magic values ("password") have to be written to -+ * f8 register to enable writing to IT66121_AUD_PKT_CTS_MODE_REG -+ */ -+ -+ ret = regmap_write(ctx->regmap, 0xf8, 0xc3); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, 0xf8, 0xa5); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, -+ IT66121_AUD_PKT_CTS_MODE_REG, -+ IT66121_AUD_PKT_CTS_MODE_USER, -+ ctx->audio.cts == IT66121_AUD_PKT_CTS_MODE_AUTO_VAL -+ ? ~IT66121_AUD_PKT_CTS_MODE_USER & 0xff -+ : IT66121_AUD_PKT_CTS_MODE_USER); -+ if (ret) -+ return ret; -+ -+ /* -+ * disabling write to IT66121_AUD_PKT_CTS_MODE_REG -+ * again by overwriting perviously set "password" -+ */ -+ return regmap_write(ctx->regmap, 0xf8, 0xff); -+} -+ -+static int it66121_audio_set_channel_status(struct it66121_ctx *ctx) -+{ -+ int ret; -+ unsigned int val; -+ -+ /* TODO: check: always use NLPCM - would to cover LPCM also?*/ -+ val = IT66121_AUD_CHST_MODE_NLPCM; -+ val |= ctx->audio.aes_iec958.status[0] & IEC958_AES0_CON_NOT_COPYRIGHT -+ ? BIT(3) -+ : (0 << 3); -+ val |= (ctx->audio.aes_iec958.status[0] & IEC958_AES0_CON_EMPHASIS) << 4; -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_MODE_REG, -+ val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CAT_REG, -+ ctx->audio.aes_iec958.status[1]); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_SRCNUM_REG, -+ ctx->audio.aes_iec958.status[2] & -+ IEC958_AES2_CON_SOURCE); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CHTNUM_REG, -+ ((ctx->audio.aes_iec958.status[2] & -+ IEC958_AES2_CON_CHANNEL) >> 4)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CA_FS_REG, -+ (ctx->audio.aes_iec958.status[3] & -+ IEC958_AES3_CON_CLOCK) << 2 | -+ (ctx->audio.aes_iec958.status[3] & -+ IEC958_AES3_CON_FS)); -+ if (ret) -+ return ret; -+ -+ return regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_OFS_WL_REG, -+ ctx->audio.aes_iec958.status[4]); -+} -+ -+static int it66121_audio_mute(struct it66121_ctx *ctx, bool enable) -+{ -+ return regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, -+ IT66121_AUD_EN_I2S_MASK, -+ enable ? 0x0 : ctx->audio.sources); -+} -+ -+static int it66121_audio_set_controls(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, -+ IT66121_AUD_TYPE_MASK | IT66121_AUD_SWL_MASK, -+ IT66121_AUD_I2S | ctx->audio.sample_wl); -+ -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL1_REG, -+ ctx->audio.format); -+ if (ret) -+ return ret; -+ -+ /* default fifo mapping: fifo0 => source0, fifo1 => source1, ... */ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_FIFOMAP_REG, -+ IT66121_AUD_FIFOMAP_DEFAULT); -+ if (ret) -+ return ret; -+ -+ /* Do not swap R/L for any source */ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL3_REG, -+ IT66121_AUD_SRLCHG_MASK, -+ IT66121_AUD_SRLCHG_DEFAULT); -+ if (ret) -+ return ret; -+ -+ /* "unflat" all sources */ -+ ret = regmap_write_bits(ctx->regmap, -+ IT66121_AUD_SRC_VALID_FLAT_REG, -+ IT66121_AUD_SPXFLAT_MASK, -+ ~IT66121_AUD_SPXFLAT_SRC_ALL & 0xff); -+ if (ret) -+ return ret; -+ -+ /* TODO: check if we really support HBR audio yet */ -+ return regmap_write_bits(ctx->regmap, IT66121_AUD_HDAUDIO_REG, -+ IT66121_AUD_HBR, -+ ctx->audio.is_hbr -+ ? IT66121_AUD_HBR -+ : ~IT66121_AUD_HBR & 0xff); -+} -+ -+static int it66121_audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ int ret; -+ unsigned int sources = 0; -+ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ if (!ctx->sink_has_audio) { -+ dev_err(ctx->dev, "%s: sink has no audio", __func__); -+ return -EINVAL; -+ } -+ -+ /* for now i2s only */ -+ if (daifmt->bit_clk_master | daifmt->frame_clk_master) { -+ dev_err(ctx->dev, -+ "%s: only clk_master and frame_clk_master formats are supported\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ /* TODO: move all these switches in functions ? */ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ ctx->audio.format = IT66121_AUD_FMT_32BIT_I2S; -+ break; -+ case HDMI_RIGHT_J: -+ ctx->audio.format = IT66121_AUD_FMT_RIGHT_JUSTIFY; -+ break; -+ case HDMI_LEFT_J: -+ ctx->audio.format = IT66121_AUD_FMT_LEFT_JUSTIFY; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported daiformat: %u\n", -+ __func__, daifmt->fmt); -+ return -EINVAL; -+ } -+ -+ switch (params->channels) { -+ case 7 ... 8: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S3; -+ sources++; -+ fallthrough; -+ case 5 ... 6: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S2; -+ sources++; -+ fallthrough; -+ case 3 ... 4: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S1; -+ sources++; -+ fallthrough; -+ case 1 ... 2: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S0; -+ sources++; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported channel count: %d\n", -+ __func__, params->channels); -+ return -EINVAL; -+ } -+ -+ switch (params->sample_width) { -+ case 16: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_16BIT; -+ break; -+ case 18: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_18BIT; -+ break; -+ case 20: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_20BIT; -+ break; -+ case 24: -+ case 32: -+ /* assume 24 bit wordlength for 32 bit width */ -+ ctx->audio.sample_wl = IT66121_AUD_SWL_24BIT; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported sample width: %d\n", -+ __func__, params->channels); -+ return -EINVAL; -+ } -+ -+ switch (params->sample_rate) { -+ case 32000: -+ case 48000: -+ case 96000: -+ case 192000: -+ ctx->audio.n = 128 * params->sample_rate / 1000; -+ ctx->audio.is_hbr = false; -+ break; -+ case 44100: -+ case 88200: -+ case 176400: -+ ctx->audio.n = 128 * params->sample_rate / 900; -+ ctx->audio.is_hbr = false; -+ break; -+ case 768000: -+ ctx->audio.n = 24576; -+ ctx->audio.is_hbr = true; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported sample_rate: %d\n", -+ __func__, params->sample_rate); -+ return -EINVAL; -+ } -+ -+ /* not all bits are correctly filled in snd_aes_iec958 - fill them here */ -+ if ((params->iec.status[2] & IEC958_AES2_CON_SOURCE) == IEC958_AES2_CON_SOURCE_UNSPEC) -+ params->iec.status[2] |= sources; -+ -+ if ((params->iec.status[2] & IEC958_AES2_CON_CHANNEL) == IEC958_AES2_CON_CHANNEL_UNSPEC) -+ params->iec.status[2] |= params->channels << 4; -+ -+ /* OFs is 1-complement of Fs */ -+ if ((params->iec.status[4] & IEC958_AES4_CON_ORIGFS) == IEC958_AES4_CON_ORIGFS_NOTID && -+ (params->iec.status[3] & IEC958_AES3_CON_FS) != IEC958_AES3_CON_FS_NOTID) -+ params->iec.status[4] |= (~(params->iec.status[3] & IEC958_AES3_CON_FS) & 0xf) << 4; -+ -+ ctx->audio.format |= IT66121_AUD_FMT_FULLPKT; -+ ctx->audio.cts = IT66121_AUD_PKT_CTS_MODE_AUTO_VAL; -+ ctx->audio.audio_infoframe = params->cea; -+ ctx->audio.aes_iec958 = params->iec; -+ -+ ret = it66121_audio_reset_fifo(ctx); -+ if (ret) -+ return ret; -+ -+ ret = it66121_audio_set_infoframe(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to assemble/enable audio infoframe: %d\n", -+ __func__, ret); -+ /* TODO: Really fail here? */ -+ return ret; -+ } -+ -+ ret = it66121_audio_set_cts_n(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write cts/n values: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ ret = it66121_audio_set_channel_status(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write channel_status %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ ret = it66121_audio_set_controls(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write audio controls %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static void it66121_audio_shutdown(struct device *dev, void *data) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); -+ -+ regmap_write(ctx->regmap, IT66121_AUD_CLK_CTRL_REG, 0x0); -+ -+ regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, -+ IT66121_INT_MASK1_AUD_OVF, -+ IT66121_INT_MASK1_AUD_OVF); -+ -+ regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, -+ IT66121_CLK_BANK_PWROFF_ACLK, -+ IT66121_CLK_BANK_PWROFF_ACLK); -+ -+ regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ ~(IT66121_SW_RST_AUD | IT66121_SW_RST_AREF) & 0xff); -+} -+ -+static int it66121_audio_startup(struct device *dev, void *data) -+{ -+ int ret; -+ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); -+ if (ret) -+ return ret; -+ /* TODO: check how to determine Fs at runtime -> only for spdif???*/ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_CLK_CTRL_REG, -+ IT66121_AUD_AUT_OVR_SMPL_CLK | -+ IT66121_AUD_EXT_MCLK_256FS); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, -+ IT66121_CLK_BANK_PWROFF_ACLK, -+ ~IT66121_CLK_BANK_PWROFF_ACLK & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, -+ IT66121_INT_MASK1_AUD_OVF, -+ ~IT66121_INT_MASK1_AUD_OVF & 0xff); -+ if (ret) -+ return ret; -+ -+ return regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ ~(IT66121_SW_RST_AUD | IT66121_SW_RST_AREF) & 0xff); -+} -+ -+int it66121_audio_mute_stream(struct device *dev, void *data, bool enable, -+ int direction) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ return it66121_audio_mute(ctx, enable); -+} -+ -+static int it66121_audio_get_dai_id(struct snd_soc_component *component, -+ struct device_node *endpoint) -+{ -+ struct of_endpoint of_ep; -+ int ret; -+ -+ ret = of_graph_parse_endpoint(endpoint, &of_ep); -+ if (ret < 0) -+ return ret; -+ -+ /* -+ * HDMI sound should be located as reg = <2> -+ * Then, it is sound port 0 -+ */ -+ if (of_ep.port == 2) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int it66121_audio_get_eld(struct device *dev, void *data, -+ u8 *buf, size_t len) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ memcpy(buf, ctx->connector.eld, -+ min(sizeof(ctx->connector.eld), len)); -+ -+ return 0; -+} -+ -+static const struct hdmi_codec_ops it66121_audio_codec_ops = { -+ .audio_shutdown = it66121_audio_shutdown, -+ .audio_startup = it66121_audio_startup, -+ .mute_stream = it66121_audio_mute_stream, -+ .no_capture_mute = 1, -+ .hw_params = it66121_audio_hw_params, -+ .get_eld = it66121_audio_get_eld, -+ .get_dai_id = it66121_audio_get_dai_id, -+}; -+ -+static const struct hdmi_codec_pdata codec_data = { -+ .ops = &it66121_audio_codec_ops, -+ .i2s = 1, /* Only i2s support for now. */ -+ .spdif = 0, -+ .max_i2s_channels = 8, -+}; -+ -+static int it66121_audio_codec_init(struct it66121_ctx *it66121, -+ struct device *dev) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ ctx->audio.pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, -+ &codec_data, sizeof(codec_data)); -+ -+ if (IS_ERR(ctx->audio.pdev)) -+ return PTR_ERR(ctx->audio.pdev); -+ -+ DRM_INFO("%s has been bound to to HDMITX it66121\n", -+ HDMI_CODEC_DRV_NAME); -+ -+ return 0; -+} -+ -+static void it66121_audio_codec_exit(struct it66121_ctx *ctx) -+{ -+ if (ctx->audio.pdev) { -+ platform_device_unregister(ctx->audio.pdev); -+ ctx->audio.pdev = NULL; -+ } -+} -+ - static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - { - int ret; -@@ -930,6 +1605,8 @@ static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - } - event = true; - } -+ if (val & IT66121_INT_STATUS1_AUD_OVF) -+ it66121_audio_reset_fifo(ctx); - } - - ret = regmap_read(ctx->regmap, IT66121_INT_STATUS3_REG, &val); -@@ -1042,6 +1719,12 @@ static int it66121_probe(struct i2c_client *client, - - drm_bridge_add(&ctx->bridge); - -+ ret = it66121_audio_codec_init(ctx, dev); -+ if (ret) { -+ dev_err(dev, "Failed to initialize audio codec %d\n", ret); -+ return ret; -+ } -+ - return 0; - } - -@@ -1049,6 +1732,7 @@ static int it66121_remove(struct i2c_client *client) - { - struct it66121_ctx *ctx = i2c_get_clientdata(client); - -+ it66121_audio_codec_exit(ctx); - ite66121_power_off(ctx); - drm_bridge_remove(&ctx->bridge); - kfree(ctx->edid); -@@ -1086,6 +1770,7 @@ static struct i2c_driver it66121_driver = { - - module_i2c_driver(it66121_driver); - -+MODULE_AUTHOR("Alex Bee"); - MODULE_AUTHOR("Phong LE"); - MODULE_DESCRIPTION("IT66121 HDMI transmitter driver"); - MODULE_LICENSE("GPL v2"); - -From a6545c717b35bb1e53f8df75093e7582d1b75635 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:46:01 +0200 -Subject: [PATCH] drm/bridge: it66121: increase reset time - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 98f3d68fe01f..a01d2e46bb0c 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -443,7 +443,7 @@ static const struct it66121_conf it66121fn_conf_simple = { - static void it66121_hw_reset(struct it66121_ctx *ctx) - { - gpiod_set_value(ctx->gpio_reset, 1); -- msleep(20); -+ msleep(50); - gpiod_set_value(ctx->gpio_reset, 0); - } - diff --git a/patch/kernel/archive/rk322x-5.10/01-linux-1002-v4l-wip.patch b/patch/kernel/archive/rk322x-5.10/01-linux-1002-v4l-wip.patch deleted file mode 100644 index 9c3088c73..000000000 --- a/patch/kernel/archive/rk322x-5.10/01-linux-1002-v4l-wip.patch +++ /dev/null @@ -1,6606 +0,0 @@ -From 322d662f2a0a2b807da3978eedc234b93dbf53c2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 10:18:16 +0000 -Subject: [PATCH] WIP: media: rkvdec: continue to gate clock when decoding - finish - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 1013d1aba59a..f3d788f90fed 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -1090,7 +1090,8 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) - state = (status & RKVDEC_RDY_STA) ? - VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; - -- writel(0, rkvdec->regs + RKVDEC_REG_INTERRUPT); -+ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E, -+ rkvdec->regs + RKVDEC_REG_INTERRUPT); - if (cancel_delayed_work(&rkvdec->watchdog_work)) { - struct rkvdec_ctx *ctx; - -@@ -1111,7 +1112,8 @@ static void rkvdec_watchdog_func(struct work_struct *work) - ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); - if (ctx) { - dev_err(rkvdec->dev, "Frame processing timed out!\n"); -- writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT); -+ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, -+ rkvdec->regs + RKVDEC_REG_INTERRUPT); - writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); - rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); - } - -From 819ed8a7ae45790f45ee62a769d7f50092b7d2e4 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 10:16:01 +0000 -Subject: [PATCH] WIP: media: rkvdec: pm runtime dont use autosuspend before - disable and cleanup - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index f3d788f90fed..e1eec79fe9a2 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -1211,9 +1211,9 @@ static int rkvdec_remove(struct platform_device *pdev) - { - struct rkvdec_dev *rkvdec = platform_get_drvdata(pdev); - -- rkvdec_v4l2_cleanup(rkvdec); -- pm_runtime_disable(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ rkvdec_v4l2_cleanup(rkvdec); - return 0; - } - - -From f2a417e4106f6a07116d74a99194c89cfa8858f1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 11:23:04 +0000 -Subject: [PATCH] WIP: media: rkvdec: h264: return early when no reference - pictures - -NOTE: also change from a switch statement to access reflists from a pointer array, -should simplify once we add support for field reference list - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 18 +++++------------- - 1 file changed, 5 insertions(+), 13 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index c115cd362a7f..d9a2fd9386e2 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -734,6 +734,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - const struct v4l2_ctrl_h264_sps *sps = run->sps; - struct rkvdec_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu; - u32 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); -+ u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; - - u32 *hw_rps = priv_tbl->rps; - u32 i, j; -@@ -741,6 +742,9 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - - memset(hw_rps, 0, sizeof(priv_tbl->rps)); - -+ if (!h264_ctx->reflists.num_valid) -+ return; -+ - /* - * 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 -@@ -763,19 +767,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { - for (i = 0; i < h264_ctx->reflists.num_valid; i++) { - u8 dpb_valid = 0; -- u8 idx = 0; -- -- switch (j) { -- case 0: -- idx = h264_ctx->reflists.p[i]; -- break; -- case 1: -- idx = h264_ctx->reflists.b0[i]; -- break; -- case 2: -- idx = h264_ctx->reflists.b1[i]; -- break; -- } -+ u8 idx = reflists[j][i]; - - if (idx >= ARRAY_SIZE(dec_params->dpb)) - continue; - -From 918eabd2461d3394689c85d0b0df3711392eb699 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 14:42:27 +0000 -Subject: [PATCH] WIP: media: rkvdec: h264: add field decoding support - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 79 ++++++++++++++++++---- - 1 file changed, 64 insertions(+), 15 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index d9a2fd9386e2..d4f27ef7addd 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -737,7 +737,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; - - u32 *hw_rps = priv_tbl->rps; -- u32 i, j; -+ u32 i, j, k; - u16 *p = (u16 *)hw_rps; - - memset(hw_rps, 0, sizeof(priv_tbl->rps)); -@@ -764,18 +764,71 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - p[i] = dpb[i].frame_num - max_frame_num; - } - -- for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { -- for (i = 0; i < h264_ctx->reflists.num_valid; i++) { -- u8 dpb_valid = 0; -- u8 idx = reflists[j][i]; -+ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) { -+ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { -+ for (i = 0; i < h264_ctx->reflists.num_valid; i++) { -+ u8 dpb_valid = 0; -+ u8 idx = reflists[j][i]; - -- if (idx >= ARRAY_SIZE(dec_params->dpb)) -- continue; -- dpb_valid = !!(dpb[idx].flags & -- V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); -+ if (idx >= ARRAY_SIZE(dec_params->dpb)) -+ continue; -+ dpb_valid = !!(dpb[idx].flags & -+ V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); - -- set_ps_field(hw_rps, DPB_INFO(i, j), -- idx | dpb_valid << 4); -+ set_ps_field(hw_rps, DPB_INFO(i, j), -+ idx | dpb_valid << 4); -+ } -+ } -+ return; -+ } -+ -+ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { -+ enum v4l2_h264_field_reference a_parity = -+ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) -+ ? V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; -+ enum v4l2_h264_field_reference b_parity = -+ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) -+ ? V4L2_H264_TOP_FIELD_REF : V4L2_H264_BOTTOM_FIELD_REF; -+ u32 flags = V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; -+ i = 0; -+ -+ for (k = 0; k < 2; k++) { -+ u8 a = 0; -+ u8 b = 0; -+ u32 long_term = k ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0; -+ -+ while (a < h264_ctx->reflists.num_valid || b < h264_ctx->reflists.num_valid) { -+ for (; a < h264_ctx->reflists.num_valid; a++) { -+ u8 idx = reflists[j][a]; -+ if (idx >= ARRAY_SIZE(dec_params->dpb)) -+ continue; -+ if ((dpb[idx].reference & a_parity) == a_parity && -+ (dpb[idx].flags & flags) == long_term) { -+ set_ps_field(hw_rps, DPB_INFO(i, j), -+ idx | (1 << 4)); -+ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), -+ a_parity == V4L2_H264_BOTTOM_FIELD_REF); -+ i++; -+ a++; -+ break; -+ } -+ } -+ for (; b < h264_ctx->reflists.num_valid; b++) { -+ u8 idx = reflists[j][b]; -+ if (idx >= ARRAY_SIZE(dec_params->dpb)) -+ continue; -+ if ((dpb[idx].reference & b_parity) == b_parity && -+ (dpb[idx].flags & flags) == long_term) { -+ set_ps_field(hw_rps, DPB_INFO(i, j), -+ idx | (1 << 4)); -+ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), -+ b_parity == V4L2_H264_BOTTOM_FIELD_REF); -+ i++; -+ b++; -+ break; -+ } -+ } -+ } - } - } - } -@@ -968,10 +1021,6 @@ static void config_registers(struct rkvdec_ctx *ctx, - rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15); - } - -- /* -- * Since support frame mode only -- * top_field_order_cnt is the same as bottom_field_order_cnt -- */ - reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt); - writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); - - -From 7b7488414b5d1c23b39bb9b9de376e28c287661d Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 13:55:15 +0200 -Subject: [PATCH] media: uapi: hevc: Add scaling matrix control - -HEVC has a scaling matrix concept. Add support for it. - -Signed-off-by: Jernej Skrabec ---- - .../media/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++ - .../media/v4l/pixfmt-compressed.rst | 1 + - drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++ - include/media/hevc-ctrls.h | 11 +++++ - 4 files changed, 63 insertions(+) - -diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -index 456488f2b5ca..81529b1d8d69 100644 ---- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -@@ -4866,6 +4866,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - - - ``padding[6]`` - - Applications and drivers must set this to zero. - -+``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)`` -+ Specifies the scaling matrix (as extracted from the bitstream) for -+ the associated HEVC slice data. The bitstream parameters are -+ defined according to :ref:`hevc`, section 7.4.5 "Scaling list -+ data semantics". For further documentation, refer to the above -+ specification, unless there is an explicit comment stating -+ otherwise. -+ -+ .. note:: -+ -+ This compound control is not yet part of the public kernel API and -+ it is expected to change. -+ -+.. c:type:: v4l2_ctrl_hevc_scaling_matrix -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``scaling_list_4x4[6][16]`` -+ - -+ * - __u8 -+ - ``scaling_list_8x8[6][64]`` -+ - -+ * - __u8 -+ - ``scaling_list_16x16[6][64]`` -+ - -+ * - __u8 -+ - ``scaling_list_32x32[2][64]`` -+ - -+ * - __u8 -+ - ``scaling_list_dc_coef_16x16[6]`` -+ - -+ * - __u8 -+ - ``scaling_list_dc_coef_32x32[2]`` -+ - -+ - ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` - Specifies the decoding mode to use. Currently exposes slice-based and - frame-based decoding but new modes might be added later on. -diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst -index d585909bc4e2..f817c643761b 100644 ---- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst -+++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst -@@ -200,6 +200,7 @@ Compressed Formats - * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` - * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` - * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` -+ * ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX`` - See the :ref:`associated Codec Control IDs `. - Buffers associated with this pixel format must contain the appropriate - number of macroblocks to decode a full corresponding frame. -diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index a88e962ac8a1..4267ba536013 100644 ---- a/drivers/media/v4l2-core/v4l2-ctrls.c -+++ b/drivers/media/v4l2-core/v4l2-ctrls.c -@@ -1026,6 +1026,7 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; - case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; - case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; - -@@ -1475,6 +1476,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: - *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; - break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: -+ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; -+ break; - case V4L2_CID_UNIT_CELL_SIZE: - *type = V4L2_CTRL_TYPE_AREA; - *flags |= V4L2_CTRL_FLAG_READ_ONLY; -@@ -2167,6 +2171,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, - zero_padding(*p_hevc_slice_params); - break; - -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: -+ break; -+ - case V4L2_CTRL_TYPE_AREA: - area = p; - if (!area->width || !area->height) -@@ -2865,6 +2872,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, - case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: - elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); - break; -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); -+ break; - case V4L2_CTRL_TYPE_AREA: - elem_size = sizeof(struct v4l2_area); - break; -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 1009cf0891cc..1592e52c3614 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -19,6 +19,7 @@ - #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) - #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) - #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) -+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) - #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) - #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) - -@@ -26,6 +27,7 @@ - #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 - #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 - #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 -+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 - - enum v4l2_mpeg_video_hevc_decode_mode { - V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, -@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { - __u64 flags; - }; - -+struct v4l2_ctrl_hevc_scaling_matrix { -+ __u8 scaling_list_4x4[6][16]; -+ __u8 scaling_list_8x8[6][64]; -+ __u8 scaling_list_16x16[6][64]; -+ __u8 scaling_list_32x32[2][64]; -+ __u8 scaling_list_dc_coef_16x16[6]; -+ __u8 scaling_list_dc_coef_32x32[2]; -+}; -+ - #endif - -From 39fccad1853d319b5d6de0352b6106f5a2f9e7eb Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 15:42:28 +0200 -Subject: [PATCH] media: uapi: hevc: Add segment address field - -If HEVC frame consists of multiple slices, segment address has to be -known in order to properly decode it. - -Add segment address field to slice parameters. - -Signed-off-by: Jernej Skrabec ---- - Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++- - include/media/hevc-ctrls.h | 5 ++++- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -index 81529b1d8d69..817773791888 100644 ---- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst -@@ -4661,6 +4661,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - - * - __u32 - - ``data_bit_offset`` - - Offset (in bits) to the video data in the current slice data. -+ * - __u32 -+ - ``slice_segment_addr`` -+ - - * - __u8 - - ``nal_unit_type`` - - -@@ -4738,7 +4741,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - - - ``num_rps_poc_lt_curr`` - - The number of reference pictures in the long-term set. - * - __u8 -- - ``padding[7]`` -+ - ``padding[5]`` - - Applications and drivers must set this to zero. - * - struct :c:type:`v4l2_hevc_dpb_entry` - - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 1592e52c3614..3e2e32098312 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { - __u32 bit_size; - __u32 data_bit_offset; - -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ -+ __u32 slice_segment_addr; -+ - /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ - __u8 nal_unit_type; - __u8 nuh_temporal_id_plus1; -@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { - __u8 num_rps_poc_st_curr_after; - __u8 num_rps_poc_lt_curr; - -- __u8 padding; -+ __u8 padding[5]; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; - -From 393a4406b1b88ebb97b04586f27b0334136aede1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 15:03:46 +0000 -Subject: [PATCH] WIP: media: uapi: hevc: add fields needed for rkvdec - -NOTE: these fields are used by rkvdec hevc backend - -Signed-off-by: Jonas Karlman ---- - include/media/hevc-ctrls.h | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 3e2e32098312..3cc3b47e1417 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -56,6 +56,9 @@ enum v4l2_mpeg_video_hevc_start_code { - /* The controls are not stable at the moment and will likely be reworked. */ - struct v4l2_ctrl_hevc_sps { - /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ -+ __u8 video_parameter_set_id; -+ __u8 seq_parameter_set_id; -+ __u8 chroma_format_idc; - __u16 pic_width_in_luma_samples; - __u16 pic_height_in_luma_samples; - __u8 bit_depth_luma_minus8; -@@ -76,9 +79,8 @@ struct v4l2_ctrl_hevc_sps { - __u8 log2_diff_max_min_pcm_luma_coding_block_size; - __u8 num_short_term_ref_pic_sets; - __u8 num_long_term_ref_pics_sps; -- __u8 chroma_format_idc; - -- __u8 padding; -+ __u8 padding[7]; - - __u64 flags; - }; -@@ -105,7 +107,10 @@ struct v4l2_ctrl_hevc_sps { - - struct v4l2_ctrl_hevc_pps { - /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ -+ __u8 pic_parameter_set_id; - __u8 num_extra_slice_header_bits; -+ __u8 num_ref_idx_l0_default_active_minus1; -+ __u8 num_ref_idx_l1_default_active_minus1; - __s8 init_qp_minus26; - __u8 diff_cu_qp_delta_depth; - __s8 pps_cb_qp_offset; -@@ -118,7 +123,7 @@ struct v4l2_ctrl_hevc_pps { - __s8 pps_tc_offset_div2; - __u8 log2_parallel_merge_level_minus2; - -- __u8 padding[4]; -+ __u8 padding; - __u64 flags; - }; - -@@ -203,7 +208,10 @@ struct v4l2_ctrl_hevc_slice_params { - __u8 num_rps_poc_st_curr_after; - __u8 num_rps_poc_lt_curr; - -- __u8 padding[5]; -+ __u16 short_term_ref_pic_set_size; -+ __u16 long_term_ref_pic_set_size; -+ -+ __u8 padding; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; - -From 6b50e1d090acfd964a80c3821d4cac909b38693c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 15:07:15 +0000 -Subject: [PATCH] HACK: media: uapi: hevc: tiles and num_slices - ---- - include/media/hevc-ctrls.h | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 3cc3b47e1417..b33e1a8141e1 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -80,7 +80,8 @@ struct v4l2_ctrl_hevc_sps { - __u8 num_short_term_ref_pic_sets; - __u8 num_long_term_ref_pics_sps; - -- __u8 padding[7]; -+ __u8 num_slices; -+ __u8 padding[6]; - - __u64 flags; - }; -@@ -174,6 +175,7 @@ struct v4l2_ctrl_hevc_slice_params { - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - __u32 slice_segment_addr; -+ __u32 num_entry_point_offsets; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ - __u8 nal_unit_type; -@@ -211,7 +213,9 @@ struct v4l2_ctrl_hevc_slice_params { - __u16 short_term_ref_pic_set_size; - __u16 long_term_ref_pic_set_size; - -- __u8 padding; -+ __u8 padding[5]; -+ -+ __u32 entry_point_offset_minus1[256]; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; - -From b34391e007c6f8bd42396d954d270457a50ac84c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 23 May 2020 15:17:45 +0000 -Subject: [PATCH] WIP: media: rkvdec: add HEVC backend - -NOTE: cabac table and scailing list code is copied 1:1 from mpp -TODO: fix lowdelay flag and rework the scaling list part - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/rkvdec/Makefile | 2 +- - drivers/staging/media/rkvdec/rkvdec-hevc.c | 2522 ++++++++++++++++++++ - drivers/staging/media/rkvdec/rkvdec-regs.h | 1 + - drivers/staging/media/rkvdec/rkvdec.c | 70 + - drivers/staging/media/rkvdec/rkvdec.h | 1 + - 5 files changed, 2595 insertions(+), 1 deletion(-) - create mode 100644 drivers/staging/media/rkvdec/rkvdec-hevc.c - -diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile -index cb86b429cfaa..a77122641d14 100644 ---- a/drivers/staging/media/rkvdec/Makefile -+++ b/drivers/staging/media/rkvdec/Makefile -@@ -1,3 +1,3 @@ - obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o - --rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o -+rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-hevc.o rkvdec-vp9.o -diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c -new file mode 100644 -index 000000000000..03ba848411c6 ---- /dev/null -+++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c -@@ -0,0 +1,2522 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Rockchip Video Decoder HEVC backend -+ * -+ * Copyright (C) 2019 Collabora, Ltd. -+ * Boris Brezillon -+ * -+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. -+ * Jeffy Chen -+ */ -+ -+#include -+ -+#include "rkvdec.h" -+#include "rkvdec-regs.h" -+ -+/* Size in u8/u32 units. */ -+#define RKV_CABAC_TABLE_SIZE 27456 -+#define RKV_SCALING_LIST_SIZE 1360 -+#define RKV_PPS_SIZE (80 / 4) -+#define RKV_PPS_LEN 64 -+#define RKV_RPS_SIZE (32 / 4) -+#define RKV_RPS_LEN 600 -+ -+struct rkvdec_sps_pps_packet { -+ u32 info[RKV_PPS_SIZE]; -+}; -+ -+struct rkvdec_rps_packet { -+ u32 info[RKV_RPS_SIZE]; -+}; -+ -+struct rkvdec_ps_field { -+ u16 offset; -+ u8 len; -+}; -+ -+#define PS_FIELD(_offset, _len) \ -+ ((struct rkvdec_ps_field){ _offset, _len }) -+ -+/* SPS */ -+#define VIDEO_PARAMETER_SET_ID PS_FIELD(0, 4) -+#define SEQ_PARAMETER_SET_ID PS_FIELD(4, 4) -+#define CHROMA_FORMAT_IDC PS_FIELD(8, 2) -+#define PIC_WIDTH_IN_LUMA_SAMPLES PS_FIELD(10, 13) -+#define PIC_HEIGHT_IN_LUMA_SAMPLES PS_FIELD(23, 13) -+#define BIT_DEPTH_LUMA PS_FIELD(36, 4) -+#define BIT_DEPTH_CHROMA PS_FIELD(40, 4) -+#define LOG2_MAX_PIC_ORDER_CNT_LSB PS_FIELD(44, 5) -+#define LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(49, 2) -+#define LOG2_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(51, 3) -+#define LOG2_MIN_TRANSFORM_BLOCK_SIZE PS_FIELD(54, 3) -+#define LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE PS_FIELD(57, 2) -+#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTER PS_FIELD(59, 3) -+#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA PS_FIELD(62, 3) -+#define SCALING_LIST_ENABLED_FLAG PS_FIELD(65, 1) -+#define AMP_ENABLED_FLAG PS_FIELD(66, 1) -+#define SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG PS_FIELD(67, 1) -+#define PCM_ENABLED_FLAG PS_FIELD(68, 1) -+#define PCM_SAMPLE_BIT_DEPTH_LUMA PS_FIELD(69, 4) -+#define PCM_SAMPLE_BIT_DEPTH_CHROMA PS_FIELD(73, 4) -+#define PCM_LOOP_FILTER_DISABLED_FLAG PS_FIELD(77, 1) -+#define LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(78, 3) -+#define LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(81, 3) -+#define NUM_SHORT_TERM_REF_PIC_SETS PS_FIELD(84, 7) -+#define LONG_TERM_REF_PICS_PRESENT_FLAG PS_FIELD(91, 1) -+#define NUM_LONG_TERM_REF_PICS_SPS PS_FIELD(92, 6) -+#define SPS_TEMPORAL_MVP_ENABLED_FLAG PS_FIELD(98, 1) -+#define STRONG_INTRA_SMOOTHING_ENABLED_FLAG PS_FIELD(99, 1) -+/* PPS */ -+#define PIC_PARAMETER_SET_ID PS_FIELD(128, 6) -+#define PPS_SEQ_PARAMETER_SET_ID PS_FIELD(134, 4) -+#define DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG PS_FIELD(138, 1) -+#define OUTPUT_FLAG_PRESENT_FLAG PS_FIELD(139, 1) -+#define NUM_EXTRA_SLICE_HEADER_BITS PS_FIELD(140, 13) -+#define SIGN_DATA_HIDING_ENABLED_FLAG PS_FIELD(153, 1) -+#define CABAC_INIT_PRESENT_FLAG PS_FIELD(154, 1) -+#define NUM_REF_IDX_L0_DEFAULT_ACTIVE PS_FIELD(155, 4) -+#define NUM_REF_IDX_L1_DEFAULT_ACTIVE PS_FIELD(159, 4) -+#define INIT_QP_MINUS26 PS_FIELD(163, 7) -+#define CONSTRAINED_INTRA_PRED_FLAG PS_FIELD(170, 1) -+#define TRANSFORM_SKIP_ENABLED_FLAG PS_FIELD(171, 1) -+#define CU_QP_DELTA_ENABLED_FLAG PS_FIELD(172, 1) -+#define LOG2_MIN_CU_QP_DELTA_SIZE PS_FIELD(173, 3) -+#define PPS_CB_QP_OFFSET PS_FIELD(176, 5) -+#define PPS_CR_QP_OFFSET PS_FIELD(181, 5) -+#define PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG PS_FIELD(186, 1) -+#define WEIGHTED_PRED_FLAG PS_FIELD(187, 1) -+#define WEIGHTED_BIPRED_FLAG PS_FIELD(188, 1) -+#define TRANSQUANT_BYPASS_ENABLED_FLAG PS_FIELD(189, 1) -+#define TILES_ENABLED_FLAG PS_FIELD(190, 1) -+#define ENTROPY_CODING_SYNC_ENABLED_FLAG PS_FIELD(191, 1) -+#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG PS_FIELD(192, 1) -+#define LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG PS_FIELD(193, 1) -+#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG PS_FIELD(194, 1) -+#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG PS_FIELD(195, 1) -+#define PPS_BETA_OFFSET_DIV2 PS_FIELD(196, 4) -+#define PPS_TC_OFFSET_DIV2 PS_FIELD(200, 4) -+#define LISTS_MODIFICATION_PRESENT_FLAG PS_FIELD(204, 1) -+#define LOG2_PARALLEL_MERGE_LEVEL PS_FIELD(205, 3) -+#define SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG PS_FIELD(208, 1) -+#define NUM_TILE_COLUMNS PS_FIELD(212, 5) -+#define NUM_TILE_ROWS PS_FIELD(217, 5) -+#define COLUMN_WIDTH(i) PS_FIELD(256 + (i * 8), 8) -+#define ROW_HEIGHT(i) PS_FIELD(416 + (i * 8), 8) -+#define SCALING_LIST_ADDRESS PS_FIELD(592, 32) -+ -+/* Data structure describing auxiliary buffer format. */ -+struct rkvdec_hevc_priv_tbl { -+ u8 cabac_table[RKV_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]; -+}; -+ -+struct rkvdec_hevc_run { -+ struct rkvdec_run base; -+ const struct v4l2_ctrl_hevc_slice_params *slices_params; -+ const struct v4l2_ctrl_hevc_sps *sps; -+ const struct v4l2_ctrl_hevc_pps *pps; -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; -+ int num_slices; -+}; -+ -+struct rkvdec_hevc_ctx { -+ struct rkvdec_aux_buf priv_tbl; -+ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; -+}; -+ -+// TODO: refactor scaling list code, was copied 1:1 from mpp -+ -+typedef struct ScalingList { -+ /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, -+ * and size ID 3 only has 2 arrays, not 6. */ -+ u8 sl[4][6][64]; -+ u8 sl_dc[2][6]; -+} scalingList_t; -+ -+typedef struct ScalingFactor_Model { -+ u8 scalingfactor0[1248]; -+ u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ -+ u8 scalingdc[12]; /*N1005 Vienna Meeting*/ -+ u8 reserverd[4]; /*16Bytes align*/ -+} scalingFactor_t; -+ -+#define SCALING_LIST_SIZE_NUM 4 -+ -+static void -+hal_record_scaling_list(scalingFactor_t *pScalingFactor_out, -+ scalingList_t *pScalingList) -+{ -+ int i; -+ u32 g_scalingListNum_model[SCALING_LIST_SIZE_NUM] = {6, 6, 6, 2}; // from C Model -+ u32 nIndex = 0; -+ u32 sizeId, matrixId, listId; -+ u8 *p = pScalingFactor_out->scalingfactor0; -+ u8 tmpBuf[8 * 8]; -+ -+ //output non-default scalingFactor Table (1248 BYTES) -+ for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { -+ for (listId = 0; listId < g_scalingListNum_model[sizeId]; listId++) { -+ if (sizeId < 3) { -+ for (i = 0; i < (sizeId == 0 ? 16 : 64); i++) { -+ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; -+ } -+ } else { -+ for (i = 0; i < 64; i ++) { -+ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; -+ } -+ for (i = 0; i < 128; i ++) { -+ pScalingFactor_out->scalingfactor0[nIndex++] = 0; -+ } -+ } -+ } -+ } -+ //output non-default scalingFactor Table Rotation(96 Bytes) -+ nIndex = 0; -+ for (listId = 0; listId < g_scalingListNum_model[0]; listId++) { -+ u8 temp16[16] = {0}; -+ for (i = 0; i < 16; i ++) { -+ temp16[i] = (u8)pScalingList->sl[0][listId][i]; -+ } -+ for (i = 0; i < 4; i ++) { -+ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i]; -+ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 4]; -+ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 8]; -+ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 12]; -+ } -+ } -+ //output non-default ScalingList_DC_Coeff (12 BYTES) -+ nIndex = 0; -+ for (listId = 0; listId < g_scalingListNum_model[2]; listId++) { //sizeId = 2 -+ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[0][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC -+ } -+ for (listId = 0; listId < g_scalingListNum_model[3]; listId++) { //sizeId = 3 -+ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[1][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC -+ pScalingFactor_out->scalingdc[nIndex++] = 0; -+ pScalingFactor_out->scalingdc[nIndex++] = 0; -+ } -+ -+ //align 16X address -+ nIndex = 0; -+ for (i = 0; i < 4; i ++) { -+ pScalingFactor_out->reserverd[nIndex++] = 0; -+ } -+ -+ //----------------------All above code show the normal store way in HM-------------------------- -+ //--------from now on, the scalingfactor0 is rotated 90', the scalingfactor1 is also rotated 90' -+ -+ //sizeId == 0 -+ for (matrixId = 0; matrixId < 6; matrixId++) { -+ p = pScalingFactor_out->scalingfactor0 + matrixId * 16; -+ -+ for (i = 0; i < 4; i++) { -+ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; -+ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; -+ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; -+ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; -+ } -+ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); -+ } -+ //sizeId == 1 -+ for (matrixId = 0; matrixId < 6; matrixId++) { -+ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + matrixId * 64; -+ -+ for (i = 0; i < 8; i++) { -+ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; -+ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; -+ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; -+ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; -+ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; -+ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; -+ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; -+ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; -+ } -+ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); -+ } -+ //sizeId == 2 -+ for (matrixId = 0; matrixId < 6; matrixId++) { -+ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + matrixId * 64; -+ -+ for (i = 0; i < 8; i++) { -+ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; -+ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; -+ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; -+ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; -+ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; -+ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; -+ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; -+ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; -+ } -+ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); -+ } -+ //sizeId == 3 -+ for (matrixId = 0; matrixId < 6; matrixId++) { -+ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + 6 * 64 + matrixId * 64; -+ -+ for (i = 0; i < 8; i++) { -+ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; -+ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; -+ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; -+ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; -+ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; -+ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; -+ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; -+ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; -+ } -+ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); -+ } -+ -+ //sizeId == 0 -+ for (matrixId = 0; matrixId < 6; matrixId++) { -+ p = pScalingFactor_out->scalingfactor1 + matrixId * 16; -+ -+ for (i = 0; i < 4; i++) { -+ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; -+ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; -+ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; -+ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; -+ } -+ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); -+ } -+} -+ -+static const u8 rkvdec_hevc_cabac_table[RKV_CABAC_TABLE_SIZE] = { -+ 0x07, 0x0f, 0x48, 0x58, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x68, -+ 0x48, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x68, -+ 0x58, 0x60, 0x40, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x60, 0x60, 0x50, 0x58, -+ 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, 0x60, 0x60, -+ 0x50, 0x58, 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, -+ 0x48, 0x48, 0x1f, 0x58, 0x68, 0x68, 0x58, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x48, 0x58, 0x58, -+ 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x50, -+ 0x48, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07, 0x0f, 0x48, 0x68, 0x0f, 0x48, 0x68, 0x40, 0x40, -+ 0x50, 0x50, 0x07, 0x40, 0x50, 0x0f, 0x40, 0x48, 0x07, 0x40, 0x27, 0x50, 0x48, 0x48, 0x40, 0x0f, -+ 0x50, 0x37, 0x1f, 0x1f, 0x50, 0x37, 0x40, 0x27, 0x40, 0x07, 0x0f, 0x17, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0f, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x66, -+ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x67, -+ 0x57, 0x5e, 0x00, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5f, 0x5f, 0x4f, 0x57, -+ 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, 0x5f, 0x5f, -+ 0x4f, 0x57, 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, -+ 0x46, 0x48, 0x20, 0x57, 0x67, 0x67, 0x57, 0x5f, 0x5f, 0x5e, 0x4f, 0x4f, 0x4f, 0x47, 0x57, 0x57, -+ 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x4f, -+ 0x47, 0x1f, 0x1f, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x67, 0x10, 0x47, 0x67, 0x40, 0x40, -+ 0x4f, 0x4e, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x01, 0x27, 0x4e, 0x47, 0x47, 0x00, 0x0f, -+ 0x4f, 0x37, 0x1f, 0x1f, 0x4f, 0x36, 0x00, 0x27, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0e, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x64, -+ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x66, -+ 0x57, 0x5d, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5e, 0x5e, 0x4e, 0x56, -+ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, 0x5e, 0x5e, -+ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, -+ 0x45, 0x48, 0x20, 0x57, 0x66, 0x66, 0x56, 0x5e, 0x5e, 0x5d, 0x4e, 0x4e, 0x4e, 0x46, 0x56, 0x57, -+ 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, -+ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x66, 0x10, 0x47, 0x66, 0x40, 0x40, -+ 0x4f, 0x4d, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x03, 0x27, 0x4d, 0x47, 0x46, 0x01, 0x0f, -+ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x34, 0x01, 0x26, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0d, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x62, -+ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x65, -+ 0x57, 0x5c, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5d, 0x5d, 0x4e, 0x56, -+ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, 0x5d, 0x5d, -+ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, -+ 0x44, 0x48, 0x20, 0x57, 0x65, 0x65, 0x56, 0x5d, 0x5d, 0x5c, 0x4e, 0x4d, 0x4e, 0x45, 0x56, 0x57, -+ 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, -+ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x65, 0x10, 0x47, 0x65, 0x40, 0x40, -+ 0x4f, 0x4c, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x04, 0x27, 0x4c, 0x47, 0x45, 0x01, 0x0f, -+ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x33, 0x01, 0x25, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0c, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0d, 0x40, 0x40, 0x40, 0x0d, 0x60, -+ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x64, -+ 0x56, 0x5b, 0x01, 0x1d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5c, 0x5c, 0x4d, 0x55, -+ 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, 0x5c, 0x5c, -+ 0x4d, 0x55, 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, -+ 0x43, 0x49, 0x21, 0x56, 0x64, 0x64, 0x55, 0x5c, 0x5c, 0x5b, 0x4d, 0x4c, 0x4d, 0x44, 0x55, 0x56, -+ 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x4e, -+ 0x46, 0x1d, 0x1d, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x64, 0x11, 0x46, 0x64, 0x40, 0x40, -+ 0x4e, 0x4b, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x06, 0x27, 0x4b, 0x46, 0x44, 0x02, 0x0f, -+ 0x4e, 0x35, 0x1e, 0x1d, 0x4e, 0x31, 0x02, 0x24, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0b, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5e, -+ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x63, -+ 0x56, 0x59, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5b, 0x5b, 0x4c, 0x54, -+ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, 0x5b, 0x5b, -+ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, -+ 0x41, 0x49, 0x21, 0x56, 0x63, 0x63, 0x54, 0x5b, 0x5b, 0x59, 0x4c, 0x4b, 0x4c, 0x43, 0x54, 0x56, -+ 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, -+ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x63, 0x11, 0x46, 0x63, 0x40, 0x40, -+ 0x4e, 0x49, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x07, 0x27, 0x49, 0x46, 0x43, 0x03, 0x0f, -+ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x30, 0x03, 0x23, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x0a, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5c, -+ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x62, -+ 0x56, 0x58, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5a, 0x5a, 0x4c, 0x54, -+ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, 0x5a, 0x5a, -+ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, -+ 0x40, 0x49, 0x21, 0x56, 0x62, 0x62, 0x54, 0x5a, 0x5a, 0x58, 0x4c, 0x4a, 0x4c, 0x42, 0x54, 0x56, -+ 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, -+ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x62, 0x11, 0x46, 0x62, 0x40, 0x40, -+ 0x4e, 0x48, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x09, 0x27, 0x48, 0x46, 0x42, 0x03, 0x0f, -+ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x2e, 0x03, 0x22, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x09, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0b, 0x40, 0x40, 0x40, 0x0b, 0x5a, -+ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x61, -+ 0x55, 0x57, 0x02, 0x1b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x59, 0x59, 0x4b, 0x53, -+ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, 0x59, 0x59, -+ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, -+ 0x00, 0x4a, 0x22, 0x55, 0x61, 0x61, 0x53, 0x59, 0x59, 0x57, 0x4b, 0x49, 0x4b, 0x41, 0x53, 0x55, -+ 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x4d, -+ 0x45, 0x1b, 0x1b, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x61, 0x12, 0x45, 0x61, 0x40, 0x40, -+ 0x4d, 0x47, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0a, 0x27, 0x47, 0x45, 0x41, 0x04, 0x0f, -+ 0x4d, 0x33, 0x1d, 0x1b, 0x4d, 0x2d, 0x04, 0x21, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x08, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x59, -+ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x60, -+ 0x55, 0x56, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x58, 0x58, 0x4b, 0x53, -+ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, 0x58, 0x58, -+ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, -+ 0x01, 0x4a, 0x22, 0x55, 0x60, 0x60, 0x53, 0x58, 0x58, 0x56, 0x4b, 0x48, 0x4b, 0x40, 0x53, 0x55, -+ 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x4d, -+ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x60, 0x12, 0x45, 0x60, 0x40, 0x40, -+ 0x4d, 0x46, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0c, 0x27, 0x46, 0x45, 0x40, 0x04, 0x0f, -+ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x2b, 0x04, 0x20, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x07, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x57, -+ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x5f, -+ 0x55, 0x54, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x57, 0x57, 0x4a, 0x52, -+ 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, 0x57, 0x57, -+ 0x4a, 0x52, 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, -+ 0x03, 0x4a, 0x22, 0x55, 0x5f, 0x5f, 0x52, 0x57, 0x57, 0x54, 0x4a, 0x47, 0x4a, 0x00, 0x52, 0x55, -+ 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x4d, -+ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x5f, 0x12, 0x45, 0x5f, 0x40, 0x40, -+ 0x4d, 0x44, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0e, 0x27, 0x44, 0x45, 0x00, 0x05, 0x0f, -+ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x29, 0x05, 0x1f, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x06, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x55, -+ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5e, -+ 0x54, 0x53, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x56, 0x56, 0x49, 0x51, -+ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, 0x56, 0x56, -+ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, -+ 0x04, 0x4b, 0x23, 0x54, 0x5e, 0x5e, 0x51, 0x56, 0x56, 0x53, 0x49, 0x46, 0x49, 0x01, 0x51, 0x54, -+ 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, -+ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5e, 0x13, 0x44, 0x5e, 0x40, 0x40, -+ 0x4c, 0x43, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x0f, 0x27, 0x43, 0x44, 0x01, 0x06, 0x0f, -+ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x28, 0x06, 0x1e, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x05, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x53, -+ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5d, -+ 0x54, 0x52, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x55, 0x55, 0x49, 0x51, -+ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, 0x55, 0x55, -+ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, -+ 0x05, 0x4b, 0x23, 0x54, 0x5d, 0x5d, 0x51, 0x55, 0x55, 0x52, 0x49, 0x45, 0x49, 0x02, 0x51, 0x54, -+ 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, -+ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5d, 0x13, 0x44, 0x5d, 0x40, 0x40, -+ 0x4c, 0x42, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x11, 0x27, 0x42, 0x44, 0x02, 0x06, 0x0f, -+ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x26, 0x06, 0x1d, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x04, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x40, 0x40, 0x40, 0x08, 0x51, -+ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5c, -+ 0x54, 0x51, 0x03, 0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x54, 0x54, 0x48, 0x50, -+ 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, 0x54, 0x54, -+ 0x48, 0x50, 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, -+ 0x06, 0x4b, 0x23, 0x54, 0x5c, 0x5c, 0x50, 0x54, 0x54, 0x51, 0x48, 0x44, 0x48, 0x03, 0x50, 0x54, -+ 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x4c, -+ 0x44, 0x18, 0x18, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5c, 0x13, 0x44, 0x5c, 0x40, 0x40, -+ 0x4c, 0x41, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x12, 0x27, 0x41, 0x44, 0x03, 0x07, 0x0f, -+ 0x4c, 0x30, 0x1c, 0x18, 0x4c, 0x25, 0x07, 0x1c, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x03, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4f, -+ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5b, -+ 0x53, 0x4f, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x53, 0x53, 0x47, 0x4f, -+ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, 0x53, 0x53, -+ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, -+ 0x08, 0x4c, 0x24, 0x53, 0x5b, 0x5b, 0x4f, 0x53, 0x53, 0x4f, 0x47, 0x43, 0x47, 0x04, 0x4f, 0x53, -+ 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, -+ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5b, 0x14, 0x43, 0x5b, 0x40, 0x40, -+ 0x4b, 0x00, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x14, 0x27, 0x00, 0x43, 0x04, 0x08, 0x0f, -+ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x23, 0x08, 0x1b, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x02, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4d, -+ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5a, -+ 0x53, 0x4e, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x52, 0x52, 0x47, 0x4f, -+ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, 0x52, 0x52, -+ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, -+ 0x09, 0x4c, 0x24, 0x53, 0x5a, 0x5a, 0x4f, 0x52, 0x52, 0x4e, 0x47, 0x42, 0x47, 0x05, 0x4f, 0x53, -+ 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, -+ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5a, 0x14, 0x43, 0x5a, 0x40, 0x40, -+ 0x4b, 0x01, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x15, 0x27, 0x01, 0x43, 0x05, 0x08, 0x0f, -+ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x22, 0x08, 0x1a, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x01, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x06, 0x4b, -+ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, -+ 0x53, 0x4d, 0x04, 0x16, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, -+ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, 0x51, 0x51, -+ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, -+ 0x0a, 0x4c, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4d, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, -+ 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x4b, -+ 0x43, 0x16, 0x16, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, -+ 0x4b, 0x02, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x17, 0x27, 0x02, 0x43, 0x06, 0x09, 0x0f, -+ 0x4b, 0x2e, 0x1b, 0x16, 0x4b, 0x20, 0x09, 0x19, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x00, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x4a, -+ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, -+ 0x53, 0x4c, 0x04, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, -+ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, 0x51, 0x51, -+ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, -+ 0x0b, 0x4d, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4c, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, -+ 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x4b, -+ 0x43, 0x15, 0x15, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, -+ 0x4b, 0x03, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x18, 0x27, 0x03, 0x43, 0x06, 0x09, 0x0f, -+ 0x4b, 0x2d, 0x1a, 0x15, 0x4b, 0x1e, 0x09, 0x18, 0x04, 0x07, 0x14, 0x12, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x00, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x48, -+ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x58, -+ 0x52, 0x4a, 0x05, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x50, 0x50, 0x45, 0x4d, -+ 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, 0x50, 0x50, -+ 0x45, 0x4d, 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, -+ 0x0d, 0x4d, 0x25, 0x52, 0x58, 0x58, 0x4d, 0x50, 0x50, 0x4a, 0x45, 0x40, 0x45, 0x07, 0x4d, 0x52, -+ 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x4a, -+ 0x42, 0x15, 0x15, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x58, 0x15, 0x42, 0x58, 0x40, 0x40, -+ 0x4a, 0x05, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1a, 0x27, 0x05, 0x42, 0x07, 0x0a, 0x0f, -+ 0x4a, 0x2d, 0x1a, 0x15, 0x4a, 0x1d, 0x0a, 0x18, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x40, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x46, -+ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x57, -+ 0x52, 0x49, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4f, 0x4f, 0x44, 0x4c, -+ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, 0x4f, 0x4f, -+ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, -+ 0x0e, 0x4d, 0x25, 0x52, 0x57, 0x57, 0x4c, 0x4f, 0x4f, 0x49, 0x44, 0x00, 0x44, 0x08, 0x4c, 0x52, -+ 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, -+ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x57, 0x15, 0x42, 0x57, 0x40, 0x40, -+ 0x4a, 0x06, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1c, 0x27, 0x06, 0x42, 0x08, 0x0b, 0x0f, -+ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1b, 0x0b, 0x17, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x41, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x44, -+ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x56, -+ 0x52, 0x48, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4e, 0x4e, 0x44, 0x4c, -+ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, 0x4e, 0x4e, -+ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, -+ 0x0f, 0x4d, 0x25, 0x52, 0x56, 0x56, 0x4c, 0x4e, 0x4e, 0x48, 0x44, 0x01, 0x44, 0x09, 0x4c, 0x52, -+ 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, -+ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x56, 0x15, 0x42, 0x56, 0x40, 0x40, -+ 0x4a, 0x07, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1d, 0x27, 0x07, 0x42, 0x09, 0x0b, 0x0f, -+ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1a, 0x0b, 0x16, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x42, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x40, 0x40, 0x40, 0x03, 0x42, -+ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x55, -+ 0x51, 0x47, 0x06, 0x13, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4d, 0x4d, 0x43, 0x4b, -+ 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, 0x4d, 0x4d, -+ 0x43, 0x4b, 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, -+ 0x10, 0x4e, 0x26, 0x51, 0x55, 0x55, 0x4b, 0x4d, 0x4d, 0x47, 0x43, 0x02, 0x43, 0x0a, 0x4b, 0x51, -+ 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x49, -+ 0x41, 0x13, 0x13, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x55, 0x16, 0x41, 0x55, 0x40, 0x40, -+ 0x49, 0x08, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x1f, 0x27, 0x08, 0x41, 0x0a, 0x0c, 0x0f, -+ 0x49, 0x2b, 0x19, 0x13, 0x49, 0x18, 0x0c, 0x15, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x43, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x40, -+ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x54, -+ 0x51, 0x45, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4c, 0x4c, 0x42, 0x4a, -+ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, 0x4c, 0x4c, -+ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, -+ 0x12, 0x4e, 0x26, 0x51, 0x54, 0x54, 0x4a, 0x4c, 0x4c, 0x45, 0x42, 0x03, 0x42, 0x0b, 0x4a, 0x51, -+ 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, -+ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x54, 0x16, 0x41, 0x54, 0x40, 0x40, -+ 0x49, 0x0a, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x20, 0x27, 0x0a, 0x41, 0x0b, 0x0d, 0x0f, -+ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x17, 0x0d, 0x14, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x44, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x01, -+ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x53, -+ 0x51, 0x44, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4b, 0x42, 0x4a, -+ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, 0x4b, 0x4b, -+ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, -+ 0x13, 0x4e, 0x26, 0x51, 0x53, 0x53, 0x4a, 0x4b, 0x4b, 0x44, 0x42, 0x04, 0x42, 0x0c, 0x4a, 0x51, -+ 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, -+ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x53, 0x16, 0x41, 0x53, 0x40, 0x40, -+ 0x49, 0x0b, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x22, 0x27, 0x0b, 0x41, 0x0c, 0x0d, 0x0f, -+ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x15, 0x0d, 0x13, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x45, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x40, 0x40, 0x40, 0x01, 0x03, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x52, -+ 0x50, 0x43, 0x07, 0x11, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x4a, 0x41, 0x49, -+ 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, 0x4a, 0x4a, -+ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, -+ 0x14, 0x4f, 0x27, 0x50, 0x52, 0x52, 0x49, 0x4a, 0x4a, 0x43, 0x41, 0x05, 0x41, 0x0d, 0x49, 0x50, -+ 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x48, -+ 0x40, 0x11, 0x11, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x52, 0x17, 0x40, 0x52, 0x40, 0x40, -+ 0x48, 0x0c, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x23, 0x27, 0x0c, 0x40, 0x0d, 0x0e, 0x0f, -+ 0x48, 0x29, 0x18, 0x11, 0x48, 0x14, 0x0e, 0x12, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x46, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x04, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x51, -+ 0x50, 0x42, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, -+ 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, 0x49, 0x49, -+ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, -+ 0x15, 0x4f, 0x27, 0x50, 0x51, 0x51, 0x49, 0x49, 0x49, 0x42, 0x41, 0x06, 0x41, 0x0e, 0x49, 0x50, -+ 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x48, -+ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x51, 0x17, 0x40, 0x51, 0x40, 0x40, -+ 0x48, 0x0d, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x25, 0x27, 0x0d, 0x40, 0x0e, 0x0e, 0x0f, -+ 0x48, 0x28, 0x18, 0x10, 0x48, 0x12, 0x0e, 0x11, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x47, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x06, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x50, -+ 0x50, 0x40, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, -+ 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, 0x48, 0x48, -+ 0x40, 0x48, 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, -+ 0x17, 0x4f, 0x27, 0x50, 0x50, 0x50, 0x48, 0x48, 0x48, 0x40, 0x40, 0x07, 0x40, 0x0f, 0x48, 0x50, -+ 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x48, -+ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x50, 0x17, 0x40, 0x50, 0x40, 0x40, -+ 0x48, 0x0f, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x27, 0x27, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, -+ 0x48, 0x28, 0x18, 0x10, 0x48, 0x10, 0x0f, 0x10, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x48, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, -+ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4f, -+ 0x4f, 0x00, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, -+ 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, -+ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, -+ 0x18, 0x50, 0x28, 0x4f, 0x4f, 0x4f, 0x47, 0x47, 0x47, 0x00, 0x00, 0x08, 0x00, 0x10, 0x47, 0x4f, -+ 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, -+ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4f, 0x18, 0x00, 0x4f, 0x40, 0x40, -+ 0x47, 0x10, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x28, 0x27, 0x10, 0x00, 0x10, 0x10, 0x0f, -+ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0f, 0x10, 0x0f, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x49, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, -+ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4e, -+ 0x4f, 0x01, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x46, 0x00, 0x47, -+ 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, 0x46, 0x46, -+ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, -+ 0x19, 0x50, 0x28, 0x4f, 0x4e, 0x4e, 0x47, 0x46, 0x46, 0x01, 0x00, 0x09, 0x00, 0x11, 0x47, 0x4f, -+ 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, -+ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4e, 0x18, 0x00, 0x4e, 0x40, 0x40, -+ 0x47, 0x11, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2a, 0x27, 0x11, 0x00, 0x11, 0x10, 0x0f, -+ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0d, 0x10, 0x0e, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4a, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x40, 0x40, 0x40, 0x41, 0x0c, -+ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4d, -+ 0x4f, 0x02, 0x08, 0x0e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x45, 0x45, 0x01, 0x46, -+ 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, 0x45, 0x45, -+ 0x01, 0x46, 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, -+ 0x1a, 0x50, 0x28, 0x4f, 0x4d, 0x4d, 0x46, 0x45, 0x45, 0x02, 0x01, 0x0a, 0x01, 0x12, 0x46, 0x4f, -+ 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x47, -+ 0x00, 0x0e, 0x0e, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4d, 0x18, 0x00, 0x4d, 0x40, 0x40, -+ 0x47, 0x12, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2b, 0x27, 0x12, 0x00, 0x12, 0x11, 0x0f, -+ 0x47, 0x26, 0x17, 0x0e, 0x47, 0x0c, 0x11, 0x0d, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4b, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x0e, -+ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4c, -+ 0x4e, 0x04, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x44, 0x02, 0x45, -+ 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, 0x44, 0x44, -+ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, -+ 0x1c, 0x51, 0x29, 0x4e, 0x4c, 0x4c, 0x45, 0x44, 0x44, 0x04, 0x02, 0x0b, 0x02, 0x13, 0x45, 0x4e, -+ 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, -+ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4c, 0x19, 0x01, 0x4c, 0x40, 0x40, -+ 0x46, 0x14, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2d, 0x27, 0x14, 0x01, 0x13, 0x12, 0x0f, -+ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x0a, 0x12, 0x0c, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4c, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x10, -+ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4b, -+ 0x4e, 0x05, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x43, 0x43, 0x02, 0x45, -+ 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, 0x43, 0x43, -+ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, -+ 0x1d, 0x51, 0x29, 0x4e, 0x4b, 0x4b, 0x45, 0x43, 0x43, 0x05, 0x02, 0x0c, 0x02, 0x14, 0x45, 0x4e, -+ 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, -+ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4b, 0x19, 0x01, 0x4b, 0x40, 0x40, -+ 0x46, 0x15, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2e, 0x27, 0x15, 0x01, 0x14, 0x12, 0x0f, -+ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x09, 0x12, 0x0b, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4d, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x40, 0x40, 0x40, 0x43, 0x12, -+ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, -+ 0x4e, 0x06, 0x09, 0x0c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, -+ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, 0x42, 0x42, -+ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, -+ 0x1e, 0x51, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x06, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, -+ 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x46, -+ 0x01, 0x0c, 0x0c, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, -+ 0x46, 0x16, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x30, 0x27, 0x16, 0x01, 0x15, 0x13, 0x0f, -+ 0x46, 0x24, 0x16, 0x0c, 0x46, 0x07, 0x13, 0x0a, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4e, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x13, -+ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, -+ 0x4e, 0x07, 0x09, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, -+ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, 0x42, 0x42, -+ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, -+ 0x1f, 0x52, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x07, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, -+ 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x46, -+ 0x01, 0x0b, 0x0b, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, -+ 0x46, 0x17, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x31, 0x27, 0x17, 0x01, 0x15, 0x13, 0x0f, -+ 0x46, 0x23, 0x15, 0x0b, 0x46, 0x05, 0x13, 0x09, 0x09, 0x07, 0x19, 0x0d, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4e, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x15, -+ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x49, -+ 0x4d, 0x09, 0x0a, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x41, 0x41, 0x04, 0x43, -+ 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, 0x41, 0x41, -+ 0x04, 0x43, 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, -+ 0x21, 0x52, 0x2a, 0x4d, 0x49, 0x49, 0x43, 0x41, 0x41, 0x09, 0x04, 0x0e, 0x04, 0x16, 0x43, 0x4d, -+ 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x45, -+ 0x02, 0x0b, 0x0b, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x49, 0x1a, 0x02, 0x49, 0x40, 0x40, -+ 0x45, 0x19, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x33, 0x27, 0x19, 0x02, 0x16, 0x14, 0x0f, -+ 0x45, 0x23, 0x15, 0x0b, 0x45, 0x04, 0x14, 0x09, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4f, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x17, -+ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x48, -+ 0x4d, 0x0a, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x05, 0x42, -+ 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, 0x40, 0x40, -+ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, -+ 0x22, 0x52, 0x2a, 0x4d, 0x48, 0x48, 0x42, 0x40, 0x40, 0x0a, 0x05, 0x0f, 0x05, 0x17, 0x42, 0x4d, -+ 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, -+ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x48, 0x1a, 0x02, 0x48, 0x40, 0x40, -+ 0x45, 0x1a, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x35, 0x27, 0x1a, 0x02, 0x17, 0x15, 0x0f, -+ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x02, 0x15, 0x08, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x50, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x19, -+ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x47, -+ 0x4d, 0x0b, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x00, 0x00, 0x05, 0x42, -+ 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, 0x00, 0x00, -+ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, -+ 0x23, 0x52, 0x2a, 0x4d, 0x47, 0x47, 0x42, 0x00, 0x00, 0x0b, 0x05, 0x10, 0x05, 0x18, 0x42, 0x4d, -+ 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, -+ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x47, 0x1a, 0x02, 0x47, 0x40, 0x40, -+ 0x45, 0x1b, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x36, 0x27, 0x1b, 0x02, 0x18, 0x15, 0x0f, -+ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x01, 0x15, 0x07, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x51, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x40, 0x40, 0x40, 0x46, 0x1b, -+ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x46, -+ 0x4c, 0x0c, 0x0b, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x01, 0x01, 0x06, 0x41, -+ 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, 0x01, 0x01, -+ 0x06, 0x41, 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, -+ 0x24, 0x53, 0x2b, 0x4c, 0x46, 0x46, 0x41, 0x01, 0x01, 0x0c, 0x06, 0x11, 0x06, 0x19, 0x41, 0x4c, -+ 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x44, -+ 0x03, 0x09, 0x09, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x46, 0x1b, 0x03, 0x46, 0x40, 0x40, -+ 0x44, 0x1c, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x38, 0x27, 0x1c, 0x03, 0x19, 0x16, 0x0f, -+ 0x44, 0x21, 0x14, 0x09, 0x44, 0x40, 0x16, 0x06, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x52, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1d, -+ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x45, -+ 0x4c, 0x0e, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x02, 0x02, 0x07, 0x40, -+ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, 0x02, 0x02, -+ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, -+ 0x26, 0x53, 0x2b, 0x4c, 0x45, 0x45, 0x40, 0x02, 0x02, 0x0e, 0x07, 0x12, 0x07, 0x1a, 0x40, 0x4c, -+ 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, -+ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x45, 0x1b, 0x03, 0x45, 0x40, 0x40, -+ 0x44, 0x1e, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x39, 0x27, 0x1e, 0x03, 0x1a, 0x17, 0x0f, -+ 0x44, 0x20, 0x14, 0x08, 0x44, 0x41, 0x17, 0x05, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x53, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1f, -+ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x44, -+ 0x4c, 0x0f, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x03, 0x03, 0x07, 0x40, -+ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, 0x03, 0x03, -+ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, -+ 0x27, 0x53, 0x2b, 0x4c, 0x44, 0x44, 0x40, 0x03, 0x03, 0x0f, 0x07, 0x13, 0x07, 0x1b, 0x40, 0x4c, -+ 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, -+ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x44, 0x1b, 0x03, 0x44, 0x40, 0x40, -+ 0x44, 0x1f, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x3b, 0x27, 0x1f, 0x03, 0x1b, 0x17, 0x0f, -+ 0x44, 0x20, 0x14, 0x08, 0x44, 0x43, 0x17, 0x04, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x54, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x40, 0x40, 0x40, 0x48, 0x21, -+ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x43, -+ 0x4b, 0x10, 0x0c, 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x04, 0x04, 0x08, 0x00, -+ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, 0x04, 0x04, -+ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, -+ 0x28, 0x54, 0x2c, 0x4b, 0x43, 0x43, 0x00, 0x04, 0x04, 0x10, 0x08, 0x14, 0x08, 0x1c, 0x00, 0x4b, -+ 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x43, -+ 0x04, 0x07, 0x07, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x43, 0x1c, 0x04, 0x43, 0x40, 0x40, -+ 0x43, 0x20, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3c, 0x27, 0x20, 0x04, 0x1c, 0x18, 0x0f, -+ 0x43, 0x1f, 0x13, 0x07, 0x43, 0x44, 0x18, 0x03, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x55, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x22, -+ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x42, -+ 0x4b, 0x11, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x05, 0x05, 0x08, 0x00, -+ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, 0x05, 0x05, -+ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, -+ 0x29, 0x54, 0x2c, 0x4b, 0x42, 0x42, 0x00, 0x05, 0x05, 0x11, 0x08, 0x15, 0x08, 0x1d, 0x00, 0x4b, -+ 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x43, -+ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x42, 0x1c, 0x04, 0x42, 0x40, 0x40, -+ 0x43, 0x21, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x21, 0x04, 0x1d, 0x18, 0x0f, -+ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x46, 0x18, 0x02, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x56, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x24, -+ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x41, -+ 0x4b, 0x13, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x06, 0x06, 0x09, 0x01, -+ 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, 0x06, 0x06, -+ 0x09, 0x01, 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, -+ 0x2b, 0x54, 0x2c, 0x4b, 0x41, 0x41, 0x01, 0x06, 0x06, 0x13, 0x09, 0x16, 0x09, 0x1e, 0x01, 0x4b, -+ 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x43, -+ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x41, 0x1c, 0x04, 0x41, 0x40, 0x40, -+ 0x43, 0x23, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x23, 0x04, 0x1e, 0x19, 0x0f, -+ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x48, 0x19, 0x01, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x57, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x26, -+ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x40, -+ 0x4a, 0x14, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x07, 0x07, 0x0a, 0x02, -+ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, 0x07, 0x07, -+ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, -+ 0x2c, 0x55, 0x2d, 0x4a, 0x40, 0x40, 0x02, 0x07, 0x07, 0x14, 0x0a, 0x17, 0x0a, 0x1f, 0x02, 0x4a, -+ 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, -+ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x40, 0x1d, 0x05, 0x40, 0x40, 0x40, -+ 0x42, 0x24, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x24, 0x05, 0x1f, 0x1a, 0x0f, -+ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x49, 0x1a, 0x00, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x58, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x28, -+ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x00, -+ 0x4a, 0x15, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x08, 0x08, 0x0a, 0x02, -+ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, 0x08, 0x08, -+ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, -+ 0x2d, 0x55, 0x2d, 0x4a, 0x00, 0x00, 0x02, 0x08, 0x08, 0x15, 0x0a, 0x18, 0x0a, 0x20, 0x02, 0x4a, -+ 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, -+ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x00, 0x1d, 0x05, 0x00, 0x40, 0x40, -+ 0x42, 0x25, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x25, 0x05, 0x20, 0x1a, 0x0f, -+ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x4b, 0x1a, 0x40, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x59, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x40, 0x40, 0x40, 0x4b, 0x2a, -+ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x01, -+ 0x4a, 0x16, 0x0d, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x09, 0x09, 0x0b, 0x03, -+ 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, 0x09, 0x09, -+ 0x0b, 0x03, 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, -+ 0x2e, 0x55, 0x2d, 0x4a, 0x01, 0x01, 0x03, 0x09, 0x09, 0x16, 0x0b, 0x19, 0x0b, 0x21, 0x03, 0x4a, -+ 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x42, -+ 0x05, 0x04, 0x04, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x01, 0x1d, 0x05, 0x01, 0x40, 0x40, -+ 0x42, 0x26, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x26, 0x05, 0x21, 0x1b, 0x0f, -+ 0x42, 0x1c, 0x12, 0x04, 0x42, 0x4c, 0x1b, 0x41, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5a, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2c, -+ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x02, -+ 0x49, 0x18, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0a, 0x0a, 0x0c, 0x04, -+ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, 0x0a, 0x0a, -+ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, -+ 0x30, 0x56, 0x2e, 0x49, 0x02, 0x02, 0x04, 0x0a, 0x0a, 0x18, 0x0c, 0x1a, 0x0c, 0x22, 0x04, 0x49, -+ 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, -+ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x02, 0x1e, 0x06, 0x02, 0x40, 0x40, -+ 0x41, 0x28, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x28, 0x06, 0x22, 0x1c, 0x0f, -+ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4e, 0x1c, 0x42, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5b, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2e, -+ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x03, -+ 0x49, 0x19, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0b, 0x0b, 0x0c, 0x04, -+ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, 0x0b, 0x0b, -+ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, -+ 0x31, 0x56, 0x2e, 0x49, 0x03, 0x03, 0x04, 0x0b, 0x0b, 0x19, 0x0c, 0x1b, 0x0c, 0x23, 0x04, 0x49, -+ 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, -+ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x03, 0x1e, 0x06, 0x03, 0x40, 0x40, -+ 0x41, 0x29, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x29, 0x06, 0x23, 0x1c, 0x0f, -+ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4f, 0x1c, 0x43, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5c, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x4d, 0x30, -+ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, -+ 0x49, 0x1a, 0x0e, 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, -+ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, 0x0c, 0x0c, -+ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, -+ 0x32, 0x56, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1a, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, -+ 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x41, -+ 0x06, 0x02, 0x02, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, -+ 0x41, 0x2a, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2a, 0x06, 0x24, 0x1d, 0x0f, -+ 0x41, 0x1a, 0x11, 0x02, 0x41, 0x51, 0x1d, 0x44, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5d, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x31, -+ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, -+ 0x49, 0x1b, 0x0e, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, -+ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, 0x0c, 0x0c, -+ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, -+ 0x33, 0x57, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1b, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, -+ 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x41, -+ 0x06, 0x01, 0x01, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, -+ 0x41, 0x2b, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2b, 0x06, 0x24, 0x1d, 0x0f, -+ 0x41, 0x19, 0x10, 0x01, 0x41, 0x53, 0x1d, 0x45, 0x0e, 0x07, 0x1e, 0x08, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5d, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x33, -+ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x05, -+ 0x48, 0x1d, 0x0f, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0d, 0x0d, 0x0e, 0x06, -+ 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, 0x0d, 0x0d, -+ 0x0e, 0x06, 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, -+ 0x35, 0x57, 0x2f, 0x48, 0x05, 0x05, 0x06, 0x0d, 0x0d, 0x1d, 0x0e, 0x1d, 0x0e, 0x25, 0x06, 0x48, -+ 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x40, -+ 0x07, 0x01, 0x01, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x05, 0x1f, 0x07, 0x05, 0x40, 0x40, -+ 0x40, 0x2d, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2d, 0x07, 0x25, 0x1e, 0x0f, -+ 0x40, 0x19, 0x10, 0x01, 0x40, 0x54, 0x1e, 0x45, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5e, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x35, -+ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x06, -+ 0x48, 0x1e, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0e, 0x0e, 0x0f, 0x07, -+ 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, 0x0e, 0x0e, -+ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, -+ 0x36, 0x57, 0x2f, 0x48, 0x06, 0x06, 0x07, 0x0e, 0x0e, 0x1e, 0x0f, 0x1e, 0x0f, 0x26, 0x07, 0x48, -+ 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, -+ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x40, 0x40, -+ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2e, 0x07, 0x26, 0x1f, 0x0f, -+ 0x40, 0x18, 0x10, 0x00, 0x40, 0x56, 0x1f, 0x46, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x5f, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x37, -+ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x07, -+ 0x48, 0x1f, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x07, -+ 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, 0x0f, 0x0f, -+ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, -+ 0x37, 0x57, 0x2f, 0x48, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x0f, 0x1f, 0x0f, 0x27, 0x07, 0x48, -+ 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, -+ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x07, 0x1f, 0x07, 0x07, 0x40, 0x40, -+ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2f, 0x07, 0x27, 0x1f, 0x0f, -+ 0x40, 0x18, 0x10, 0x00, 0x40, 0x57, 0x1f, 0x47, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x07, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x48, 0x40, 0x40, 0x40, 0x0f, -+ 0x48, 0x68, 0x60, 0x40, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x50, 0x40, 0x60, 0x07, -+ 0x68, 0x27, 0x48, 0x17, 0x40, 0x50, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x60, 0x60, -+ 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, 0x58, 0x60, -+ 0x60, 0x60, 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, -+ 0x07, 0x50, 0x58, 0x40, 0x48, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x07, 0x1f, 0x17, 0x50, -+ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, -+ 0x07, 0x48, 0x48, 0x48, 0x07, 0x48, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, -+ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x07, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x07, 0x1f, 0x48, 0x17, 0x48, 0x40, 0x48, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x07, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, -+ 0x47, 0x66, 0x5f, 0x00, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x4f, 0x00, 0x5e, 0x07, -+ 0x67, 0x27, 0x47, 0x17, 0x40, 0x4f, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x5e, 0x5f, -+ 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, 0x57, 0x5f, -+ 0x5e, 0x5f, 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, -+ 0x08, 0x4f, 0x56, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x07, 0x1f, 0x17, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x47, 0x47, 0x47, 0x08, 0x47, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, -+ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x08, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1f, 0x47, 0x17, 0x46, 0x00, 0x47, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x06, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, -+ 0x47, 0x64, 0x5e, 0x01, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5d, 0x07, -+ 0x66, 0x27, 0x46, 0x17, 0x40, 0x4f, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x5d, 0x5e, -+ 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, 0x56, 0x5e, -+ 0x5d, 0x5e, 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, -+ 0x09, 0x4f, 0x54, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x07, 0x1f, 0x16, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x46, 0x46, 0x46, 0x09, 0x46, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, -+ 0x40, 0x2e, 0x2e, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x46, 0x17, 0x45, 0x01, 0x46, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x06, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, -+ 0x47, 0x63, 0x5d, 0x01, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5c, 0x07, -+ 0x65, 0x27, 0x45, 0x17, 0x40, 0x4f, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x5c, 0x5d, -+ 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, 0x56, 0x5d, -+ 0x5c, 0x5d, 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, -+ 0x09, 0x4f, 0x52, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x07, 0x1f, 0x16, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x46, 0x46, 0x45, 0x09, 0x45, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, -+ 0x40, 0x2d, 0x2d, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, -+ 0x07, 0x3d, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x45, 0x17, 0x44, 0x01, 0x45, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x05, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, -+ 0x46, 0x61, 0x5c, 0x02, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x4d, 0x01, 0x5b, 0x07, -+ 0x64, 0x27, 0x44, 0x16, 0x40, 0x4e, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x5b, 0x5c, -+ 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, 0x55, 0x5c, -+ 0x5b, 0x5c, 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, -+ 0x0a, 0x4e, 0x50, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x07, 0x1e, 0x15, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x45, 0x45, 0x44, 0x0a, 0x44, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, -+ 0x40, 0x2c, 0x2c, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x09, -+ 0x06, 0x3c, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1d, 0x44, 0x16, 0x43, 0x02, 0x44, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x04, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, -+ 0x46, 0x60, 0x5b, 0x03, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x59, 0x07, -+ 0x63, 0x27, 0x43, 0x16, 0x40, 0x4e, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x59, 0x5b, -+ 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, 0x54, 0x5b, -+ 0x59, 0x5b, 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, -+ 0x0b, 0x4e, 0x4e, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x07, 0x1e, 0x14, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x44, 0x44, 0x43, 0x0b, 0x43, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, -+ 0x40, 0x2b, 0x2b, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, -+ 0x06, 0x3b, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x43, 0x16, 0x41, 0x03, 0x43, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x04, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, -+ 0x46, 0x5e, 0x5a, 0x03, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x58, 0x07, -+ 0x62, 0x27, 0x42, 0x16, 0x40, 0x4e, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x58, 0x5a, -+ 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, 0x54, 0x5a, -+ 0x58, 0x5a, 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, -+ 0x0b, 0x4e, 0x4c, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x07, 0x1e, 0x14, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x44, 0x44, 0x42, 0x0b, 0x42, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, -+ 0x40, 0x2a, 0x2a, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, -+ 0x06, 0x3a, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x42, 0x16, 0x40, 0x03, 0x42, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x03, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, -+ 0x45, 0x5d, 0x59, 0x04, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x57, 0x07, -+ 0x61, 0x27, 0x41, 0x15, 0x40, 0x4d, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x57, 0x59, -+ 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, 0x53, 0x59, -+ 0x57, 0x59, 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, -+ 0x0c, 0x4d, 0x4a, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x07, 0x1d, 0x13, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x43, 0x43, 0x41, 0x0c, 0x41, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, -+ 0x40, 0x29, 0x29, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, -+ 0x05, 0x39, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1b, 0x41, 0x15, 0x00, 0x04, 0x41, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x02, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, -+ 0x45, 0x5b, 0x58, 0x04, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x56, 0x07, -+ 0x60, 0x27, 0x40, 0x15, 0x40, 0x4d, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x56, 0x58, -+ 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, 0x53, 0x58, -+ 0x56, 0x58, 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, -+ 0x0c, 0x4d, 0x49, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x07, 0x1d, 0x12, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x43, 0x43, 0x40, 0x0c, 0x40, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, -+ 0x40, 0x28, 0x28, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, -+ 0x05, 0x38, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x40, 0x15, 0x01, 0x04, 0x40, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x02, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, -+ 0x45, 0x59, 0x57, 0x05, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x4a, 0x02, 0x54, 0x07, -+ 0x5f, 0x27, 0x00, 0x15, 0x40, 0x4d, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x54, 0x57, -+ 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, 0x52, 0x57, -+ 0x54, 0x57, 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, -+ 0x0d, 0x4d, 0x47, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x07, 0x1d, 0x12, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x42, 0x42, 0x00, 0x0d, 0x00, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, -+ 0x40, 0x27, 0x27, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x0a, -+ 0x05, 0x37, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x00, 0x15, 0x03, 0x05, 0x00, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x01, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, -+ 0x44, 0x58, 0x56, 0x06, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x53, 0x07, -+ 0x5e, 0x27, 0x01, 0x14, 0x40, 0x4c, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x53, 0x56, -+ 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, 0x51, 0x56, -+ 0x53, 0x56, 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, -+ 0x0e, 0x4c, 0x45, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x07, 0x1c, 0x11, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x41, 0x41, 0x01, 0x0e, 0x01, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, -+ 0x40, 0x26, 0x26, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, -+ 0x04, 0x36, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x01, 0x14, 0x04, 0x06, 0x01, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x01, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, -+ 0x44, 0x56, 0x55, 0x06, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x52, 0x07, -+ 0x5d, 0x27, 0x02, 0x14, 0x40, 0x4c, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x52, 0x55, -+ 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, 0x51, 0x55, -+ 0x52, 0x55, 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, -+ 0x0e, 0x4c, 0x43, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x07, 0x1c, 0x11, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x41, 0x41, 0x02, 0x0e, 0x02, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, -+ 0x40, 0x25, 0x25, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, -+ 0x04, 0x35, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x02, 0x14, 0x05, 0x06, 0x02, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x00, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, -+ 0x44, 0x55, 0x54, 0x07, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x48, 0x03, 0x51, 0x07, -+ 0x5c, 0x27, 0x03, 0x14, 0x40, 0x4c, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x51, 0x54, -+ 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, 0x50, 0x54, -+ 0x51, 0x54, 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, -+ 0x0f, 0x4c, 0x41, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x07, 0x1c, 0x10, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x40, 0x40, 0x03, 0x0f, 0x03, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, -+ 0x40, 0x24, 0x24, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x0b, -+ 0x04, 0x34, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x18, 0x03, 0x14, 0x06, 0x07, 0x03, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x40, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, -+ 0x43, 0x53, 0x53, 0x08, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4f, 0x07, -+ 0x5b, 0x27, 0x04, 0x13, 0x40, 0x4b, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x4f, 0x53, -+ 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, 0x4f, 0x53, -+ 0x4f, 0x53, 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, -+ 0x10, 0x4b, 0x00, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x07, 0x1b, 0x0f, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, -+ 0x40, 0x23, 0x23, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, -+ 0x03, 0x33, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x04, 0x13, 0x08, 0x08, 0x04, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x40, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, -+ 0x43, 0x52, 0x52, 0x08, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4e, 0x07, -+ 0x5a, 0x27, 0x05, 0x13, 0x40, 0x4b, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x4e, 0x52, -+ 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, 0x4f, 0x52, -+ 0x4e, 0x52, 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, -+ 0x10, 0x4b, 0x02, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x07, 0x1b, 0x0f, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x00, 0x00, 0x05, 0x10, 0x05, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, -+ 0x40, 0x22, 0x22, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, -+ 0x03, 0x32, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x05, 0x13, 0x09, 0x08, 0x05, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x41, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, -+ 0x43, 0x50, 0x51, 0x09, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x46, 0x04, 0x4d, 0x07, -+ 0x59, 0x27, 0x06, 0x13, 0x40, 0x4b, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4d, 0x51, -+ 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, 0x4e, 0x51, -+ 0x4d, 0x51, 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, -+ 0x11, 0x4b, 0x04, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x07, 0x1b, 0x0e, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, -+ 0x40, 0x21, 0x21, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, -+ 0x03, 0x31, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x16, 0x06, 0x13, 0x0a, 0x09, 0x06, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x42, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, -+ 0x43, 0x4f, 0x51, 0x09, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x46, 0x04, 0x4c, 0x07, -+ 0x59, 0x27, 0x06, 0x12, 0x40, 0x4b, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4c, 0x51, -+ 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, 0x4e, 0x51, -+ 0x4c, 0x51, 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, -+ 0x11, 0x4b, 0x05, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x07, 0x1a, 0x0d, 0x4b, -+ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, -+ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, -+ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, -+ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0c, 0x15, 0x06, 0x12, 0x0b, 0x09, 0x06, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x42, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, -+ 0x42, 0x4d, 0x50, 0x0a, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x45, 0x05, 0x4a, 0x07, -+ 0x58, 0x27, 0x07, 0x12, 0x40, 0x4a, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x4a, 0x50, -+ 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, 0x4d, 0x50, -+ 0x4a, 0x50, 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, -+ 0x12, 0x4a, 0x07, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x07, 0x1a, 0x0d, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x02, 0x02, 0x07, 0x12, 0x07, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, -+ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0d, -+ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x15, 0x07, 0x12, 0x0d, 0x0a, 0x07, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x43, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, -+ 0x42, 0x4b, 0x4f, 0x0b, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x49, 0x07, -+ 0x57, 0x27, 0x08, 0x12, 0x40, 0x4a, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x49, 0x4f, -+ 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, 0x4c, 0x4f, -+ 0x49, 0x4f, 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, -+ 0x13, 0x4a, 0x09, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x07, 0x1a, 0x0c, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x03, 0x03, 0x08, 0x13, 0x08, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, -+ 0x40, 0x1f, 0x1f, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, -+ 0x02, 0x2f, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x08, 0x12, 0x0e, 0x0b, 0x08, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x43, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, -+ 0x42, 0x4a, 0x4e, 0x0b, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x48, 0x07, -+ 0x56, 0x27, 0x09, 0x12, 0x40, 0x4a, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x48, 0x4e, -+ 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, 0x4c, 0x4e, -+ 0x48, 0x4e, 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, -+ 0x13, 0x4a, 0x0b, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x07, 0x1a, 0x0c, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x03, 0x03, 0x09, 0x13, 0x09, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, -+ 0x40, 0x1e, 0x1e, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, -+ 0x02, 0x2e, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x09, 0x12, 0x0f, 0x0b, 0x09, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x44, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, -+ 0x41, 0x48, 0x4d, 0x0c, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x43, 0x06, 0x47, 0x07, -+ 0x55, 0x27, 0x0a, 0x11, 0x40, 0x49, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x47, 0x4d, -+ 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, 0x4b, 0x4d, -+ 0x47, 0x4d, 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, -+ 0x14, 0x49, 0x0d, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x07, 0x19, 0x0b, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x04, 0x04, 0x0a, 0x14, 0x0a, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, -+ 0x40, 0x1d, 0x1d, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0e, -+ 0x01, 0x2d, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x13, 0x0a, 0x11, 0x10, 0x0c, 0x0a, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x45, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, -+ 0x41, 0x47, 0x4c, 0x0d, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x42, 0x06, 0x45, 0x07, -+ 0x54, 0x27, 0x0b, 0x11, 0x40, 0x49, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x45, 0x4c, -+ 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, 0x4a, 0x4c, -+ 0x45, 0x4c, 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, -+ 0x15, 0x49, 0x0f, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x07, 0x19, 0x0a, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x05, 0x05, 0x0b, 0x15, 0x0b, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, -+ 0x40, 0x1c, 0x1c, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, -+ 0x01, 0x2c, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0b, 0x11, 0x12, 0x0d, 0x0b, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x45, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, -+ 0x41, 0x45, 0x4b, 0x0d, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x42, 0x06, 0x44, 0x07, -+ 0x53, 0x27, 0x0c, 0x11, 0x40, 0x49, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x44, 0x4b, -+ 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, 0x4a, 0x4b, -+ 0x44, 0x4b, 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, -+ 0x15, 0x49, 0x11, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x07, 0x19, 0x0a, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x05, 0x05, 0x0c, 0x15, 0x0c, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, -+ 0x40, 0x1b, 0x1b, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, -+ 0x01, 0x2b, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0c, 0x11, 0x13, 0x0d, 0x0c, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x46, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, -+ 0x40, 0x44, 0x4a, 0x0e, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x41, 0x07, 0x43, 0x07, -+ 0x52, 0x27, 0x0d, 0x10, 0x40, 0x48, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x43, 0x4a, -+ 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, 0x49, 0x4a, -+ 0x43, 0x4a, 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, -+ 0x16, 0x48, 0x13, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x07, 0x18, 0x09, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x06, 0x06, 0x0d, 0x16, 0x0d, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, -+ 0x40, 0x1a, 0x1a, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, -+ 0x00, 0x2a, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x11, 0x0d, 0x10, 0x14, 0x0e, 0x0d, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x47, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, -+ 0x40, 0x42, 0x49, 0x0e, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x41, 0x07, 0x42, 0x07, -+ 0x51, 0x27, 0x0e, 0x10, 0x40, 0x48, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x42, 0x49, -+ 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, 0x49, 0x49, -+ 0x42, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, -+ 0x16, 0x48, 0x14, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x07, 0x18, 0x08, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x06, 0x06, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, -+ 0x40, 0x19, 0x19, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, -+ 0x00, 0x29, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x47, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, -+ 0x40, 0x40, 0x48, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x40, 0x07, 0x40, 0x07, -+ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x48, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, -+ 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, -+ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, -+ 0x17, 0x48, 0x16, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x07, 0x18, 0x08, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, -+ 0x40, 0x18, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, -+ 0x00, 0x28, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x48, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, -+ 0x00, 0x00, 0x47, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x00, 0x08, 0x00, 0x07, -+ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x47, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, -+ 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, -+ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, -+ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x07, 0x17, 0x07, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, -+ 0x40, 0x17, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, -+ 0x40, 0x27, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x48, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, -+ 0x00, 0x02, 0x46, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x00, 0x08, 0x01, 0x07, -+ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x47, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x01, 0x46, -+ 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, 0x47, 0x46, -+ 0x01, 0x46, 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, -+ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x07, 0x17, 0x07, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x08, 0x08, 0x11, 0x18, 0x11, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, -+ 0x40, 0x16, 0x16, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, -+ 0x40, 0x26, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x11, 0x0f, 0x19, 0x10, 0x11, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x49, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, -+ 0x00, 0x03, 0x45, 0x11, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x01, 0x08, 0x02, 0x07, -+ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x47, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x02, 0x45, -+ 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, 0x46, 0x45, -+ 0x02, 0x45, 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, -+ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x07, 0x17, 0x06, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x09, 0x09, 0x12, 0x19, 0x12, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, -+ 0x40, 0x15, 0x15, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x10, -+ 0x40, 0x25, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0e, 0x12, 0x0f, 0x1a, 0x11, 0x12, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4a, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, -+ 0x01, 0x05, 0x44, 0x12, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x02, 0x09, 0x04, 0x07, -+ 0x4c, 0x27, 0x13, 0x0e, 0x40, 0x46, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x04, 0x44, -+ 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, 0x45, 0x44, -+ 0x04, 0x44, 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, -+ 0x1a, 0x46, 0x1e, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x07, 0x16, 0x05, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x0a, 0x0a, 0x13, 0x1a, 0x13, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, -+ 0x40, 0x14, 0x14, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, -+ 0x41, 0x24, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x13, 0x0e, 0x1c, 0x12, 0x13, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4a, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, -+ 0x01, 0x06, 0x43, 0x12, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x02, 0x09, 0x05, 0x07, -+ 0x4b, 0x27, 0x14, 0x0e, 0x40, 0x46, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x05, 0x43, -+ 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, 0x45, 0x43, -+ 0x05, 0x43, 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, -+ 0x1a, 0x46, 0x20, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x07, 0x16, 0x05, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x0a, 0x0a, 0x14, 0x1a, 0x14, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, -+ 0x40, 0x13, 0x13, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, -+ 0x41, 0x23, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x14, 0x0e, 0x1d, 0x12, 0x14, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4b, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, -+ 0x01, 0x08, 0x42, 0x13, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x03, 0x09, 0x06, 0x07, -+ 0x4a, 0x27, 0x15, 0x0e, 0x40, 0x46, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x06, 0x42, -+ 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, 0x44, 0x42, -+ 0x06, 0x42, 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, -+ 0x1b, 0x46, 0x22, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x07, 0x16, 0x04, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, -+ 0x40, 0x12, 0x12, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, -+ 0x41, 0x22, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0c, 0x15, 0x0e, 0x1e, 0x13, 0x15, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4c, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, -+ 0x01, 0x09, 0x42, 0x13, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x03, 0x09, 0x07, 0x07, -+ 0x4a, 0x27, 0x15, 0x0d, 0x40, 0x46, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x07, 0x42, -+ 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, 0x44, 0x42, -+ 0x07, 0x42, 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, -+ 0x1b, 0x46, 0x23, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x07, 0x15, 0x03, 0x46, -+ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, -+ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, -+ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, -+ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x11, 0x0b, 0x15, 0x0d, 0x1f, 0x13, 0x15, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4c, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, -+ 0x02, 0x0b, 0x41, 0x14, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x04, 0x0a, 0x09, 0x07, -+ 0x49, 0x27, 0x16, 0x0d, 0x40, 0x45, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x09, 0x41, -+ 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, 0x43, 0x41, -+ 0x09, 0x41, 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, -+ 0x1c, 0x45, 0x25, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x07, 0x15, 0x03, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0c, 0x0c, 0x16, 0x1c, 0x16, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, -+ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x12, -+ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0b, 0x16, 0x0d, 0x21, 0x14, 0x16, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4d, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, -+ 0x02, 0x0d, 0x40, 0x15, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0a, 0x07, -+ 0x48, 0x27, 0x17, 0x0d, 0x40, 0x45, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x0a, 0x40, -+ 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, 0x42, 0x40, -+ 0x0a, 0x40, 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, -+ 0x1d, 0x45, 0x27, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x07, 0x15, 0x02, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0d, 0x0d, 0x17, 0x1d, 0x17, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, -+ 0x40, 0x10, 0x10, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, -+ 0x42, 0x20, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x17, 0x0d, 0x22, 0x15, 0x17, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4d, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, -+ 0x02, 0x0e, 0x00, 0x15, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0b, 0x07, -+ 0x47, 0x27, 0x18, 0x0d, 0x40, 0x45, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x0b, 0x00, -+ 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, 0x42, 0x00, -+ 0x0b, 0x00, 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, -+ 0x1d, 0x45, 0x29, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x07, 0x15, 0x02, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0d, 0x0d, 0x18, 0x1d, 0x18, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, -+ 0x40, 0x0f, 0x0f, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, -+ 0x42, 0x1f, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x18, 0x0d, 0x23, 0x15, 0x18, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, -+ 0x03, 0x10, 0x01, 0x16, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x06, 0x0b, 0x0c, 0x07, -+ 0x46, 0x27, 0x19, 0x0c, 0x40, 0x44, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x0c, 0x01, -+ 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, 0x41, 0x01, -+ 0x0c, 0x01, 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, -+ 0x1e, 0x44, 0x2b, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x07, 0x14, 0x01, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0e, 0x0e, 0x19, 0x1e, 0x19, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, -+ 0x40, 0x0e, 0x0e, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x13, -+ 0x43, 0x1e, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x09, 0x19, 0x0c, 0x24, 0x16, 0x19, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4f, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, -+ 0x03, 0x11, 0x02, 0x17, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0e, 0x07, -+ 0x45, 0x27, 0x1a, 0x0c, 0x40, 0x44, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x0e, 0x02, -+ 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, 0x40, 0x02, -+ 0x0e, 0x02, 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, -+ 0x1f, 0x44, 0x2d, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0f, 0x0f, 0x1a, 0x1f, 0x1a, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, -+ 0x40, 0x0d, 0x0d, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, -+ 0x43, 0x1d, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1a, 0x0c, 0x26, 0x17, 0x1a, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x4f, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, -+ 0x03, 0x13, 0x03, 0x17, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0f, 0x07, -+ 0x44, 0x27, 0x1b, 0x0c, 0x40, 0x44, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x0f, 0x03, -+ 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, 0x40, 0x03, -+ 0x0f, 0x03, 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, -+ 0x1f, 0x44, 0x2f, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0f, 0x0f, 0x1b, 0x1f, 0x1b, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, -+ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, -+ 0x43, 0x1c, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1b, 0x0c, 0x27, 0x17, 0x1b, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x50, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, -+ 0x04, 0x14, 0x04, 0x18, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x10, 0x07, -+ 0x43, 0x27, 0x1c, 0x0b, 0x40, 0x43, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x10, 0x04, -+ 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, 0x00, 0x04, -+ 0x10, 0x04, 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, -+ 0x20, 0x43, 0x31, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x07, 0x13, 0x40, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x10, 0x10, 0x1c, 0x20, 0x1c, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, -+ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, -+ 0x44, 0x1b, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x07, 0x1c, 0x0b, 0x28, 0x18, 0x1c, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x51, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, -+ 0x04, 0x16, 0x05, 0x18, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x11, 0x07, -+ 0x42, 0x27, 0x1d, 0x0b, 0x40, 0x43, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x11, 0x05, -+ 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, 0x00, 0x05, -+ 0x11, 0x05, 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, -+ 0x20, 0x43, 0x32, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x07, 0x13, 0x41, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x10, 0x10, 0x1d, 0x20, 0x1d, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, -+ 0x40, 0x0a, 0x0a, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, -+ 0x44, 0x1a, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1d, 0x0b, 0x29, 0x18, 0x1d, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x51, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, -+ 0x04, 0x18, 0x06, 0x19, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x09, 0x0c, 0x13, 0x07, -+ 0x41, 0x27, 0x1e, 0x0b, 0x40, 0x43, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x13, 0x06, -+ 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, 0x01, 0x06, -+ 0x13, 0x06, 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, -+ 0x21, 0x43, 0x34, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x07, 0x13, 0x41, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x11, 0x11, 0x1e, 0x21, 0x1e, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, -+ 0x40, 0x09, 0x09, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x14, -+ 0x44, 0x19, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1e, 0x0b, 0x2b, 0x19, 0x1e, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x52, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, -+ 0x05, 0x19, 0x07, 0x1a, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x14, 0x07, -+ 0x40, 0x27, 0x1f, 0x0a, 0x40, 0x42, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x14, 0x07, -+ 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, 0x02, 0x07, -+ 0x14, 0x07, 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, -+ 0x22, 0x42, 0x36, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x07, 0x12, 0x42, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x12, 0x12, 0x1f, 0x22, 0x1f, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, -+ 0x40, 0x08, 0x08, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, -+ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x1f, 0x0a, 0x2c, 0x1a, 0x1f, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x52, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, -+ 0x05, 0x1b, 0x08, 0x1a, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x15, 0x07, -+ 0x00, 0x27, 0x20, 0x0a, 0x40, 0x42, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x15, 0x08, -+ 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, 0x02, 0x08, -+ 0x15, 0x08, 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, -+ 0x22, 0x42, 0x38, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x07, 0x12, 0x42, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x12, 0x12, 0x20, 0x22, 0x20, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, -+ 0x40, 0x07, 0x07, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, -+ 0x45, 0x17, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x20, 0x0a, 0x2d, 0x1a, 0x20, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x53, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, -+ 0x05, 0x1c, 0x09, 0x1b, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0d, 0x16, 0x07, -+ 0x01, 0x27, 0x21, 0x0a, 0x40, 0x42, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x16, 0x09, -+ 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, 0x03, 0x09, -+ 0x16, 0x09, 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, -+ 0x23, 0x42, 0x3a, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x07, 0x12, 0x43, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x13, 0x13, 0x21, 0x23, 0x21, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, -+ 0x40, 0x06, 0x06, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x15, -+ 0x45, 0x16, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x04, 0x21, 0x0a, 0x2e, 0x1b, 0x21, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x54, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, -+ 0x06, 0x1e, 0x0a, 0x1c, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x18, 0x07, -+ 0x02, 0x27, 0x22, 0x09, 0x40, 0x41, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x18, 0x0a, -+ 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, 0x04, 0x0a, -+ 0x18, 0x0a, 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, -+ 0x24, 0x41, 0x3c, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x07, 0x11, 0x44, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x14, 0x14, 0x22, 0x24, 0x22, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, -+ 0x40, 0x05, 0x05, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, -+ 0x46, 0x15, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x22, 0x09, 0x30, 0x1c, 0x22, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x54, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, -+ 0x06, 0x1f, 0x0b, 0x1c, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x19, 0x07, -+ 0x03, 0x27, 0x23, 0x09, 0x40, 0x41, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x19, 0x0b, -+ 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, 0x04, 0x0b, -+ 0x19, 0x0b, 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, -+ 0x24, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x07, 0x11, 0x44, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x14, 0x14, 0x23, 0x24, 0x23, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, -+ 0x40, 0x04, 0x04, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, -+ 0x46, 0x14, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x23, 0x09, 0x31, 0x1c, 0x23, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x55, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, -+ 0x06, 0x21, 0x0c, 0x1d, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0d, 0x0e, 0x1a, 0x07, -+ 0x04, 0x27, 0x24, 0x09, 0x40, 0x41, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1a, 0x0c, -+ 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, 0x05, 0x0c, -+ 0x1a, 0x0c, 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, -+ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x07, 0x11, 0x45, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, -+ 0x40, 0x03, 0x03, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, -+ 0x46, 0x13, 0x11, 0x09, 0x40, 0x09, 0x16, 0x02, 0x24, 0x09, 0x32, 0x1d, 0x24, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x56, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, -+ 0x06, 0x22, 0x0c, 0x1d, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0d, 0x0e, 0x1b, 0x07, -+ 0x04, 0x27, 0x24, 0x08, 0x40, 0x41, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1b, 0x0c, -+ 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, 0x05, 0x0c, -+ 0x1b, 0x0c, 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, -+ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x07, 0x10, 0x46, 0x41, -+ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, -+ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, -+ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, -+ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x16, 0x01, 0x24, 0x08, 0x33, 0x1d, 0x24, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x56, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, -+ 0x07, 0x24, 0x0d, 0x1e, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0e, 0x0f, 0x1d, 0x07, -+ 0x05, 0x27, 0x25, 0x08, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x1d, 0x0d, -+ 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, 0x06, 0x0d, -+ 0x1d, 0x0d, 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, -+ 0x26, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x07, 0x10, 0x46, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x16, 0x16, 0x25, 0x26, 0x25, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, -+ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x17, -+ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x17, 0x01, 0x25, 0x08, 0x35, 0x1e, 0x25, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x57, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, -+ 0x07, 0x26, 0x0e, 0x1f, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1e, 0x07, -+ 0x06, 0x27, 0x26, 0x08, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x1e, 0x0e, -+ 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, 0x07, 0x0e, -+ 0x1e, 0x0e, 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, -+ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x07, 0x10, 0x47, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x17, 0x17, 0x26, 0x27, 0x26, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, -+ 0x40, 0x01, 0x01, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, -+ 0x47, 0x11, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x26, 0x08, 0x36, 0x1f, 0x26, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x57, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, -+ 0x07, 0x27, 0x0f, 0x1f, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1f, 0x07, -+ 0x07, 0x27, 0x27, 0x08, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x1f, 0x0f, -+ 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, 0x07, 0x0f, -+ 0x1f, 0x0f, 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, -+ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x07, 0x10, 0x47, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x17, 0x17, 0x27, 0x27, 0x27, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, -+ 0x40, 0x00, 0x00, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, -+ 0x47, 0x10, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x27, 0x08, 0x37, 0x1f, 0x27, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x1f, 0x40, 0x48, 0x40, 0x40, 0x17, 0x0f, -+ 0x48, 0x68, 0x40, 0x07, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x40, 0x07, -+ 0x68, 0x27, 0x50, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x50, 0x60, -+ 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, 0x58, 0x60, -+ 0x50, 0x60, 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, -+ 0x07, 0x50, 0x58, 0x40, 0x40, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x50, 0x1f, 0x17, 0x50, -+ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, -+ 0x07, 0x40, 0x40, 0x40, 0x07, 0x40, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, -+ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x40, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x48, 0x17, 0x48, 0x48, 0x48, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x20, 0x40, 0x47, 0x40, 0x40, 0x17, 0x0f, -+ 0x47, 0x66, 0x40, 0x08, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x00, 0x07, -+ 0x67, 0x27, 0x4e, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x4f, 0x5f, -+ 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, 0x57, 0x5f, -+ 0x4f, 0x5f, 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, -+ 0x08, 0x4f, 0x56, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x4f, 0x1f, 0x17, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, -+ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x00, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x47, 0x17, 0x46, 0x47, 0x47, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, -+ 0x47, 0x64, 0x40, 0x08, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, -+ 0x66, 0x27, 0x4d, 0x17, 0x40, 0x07, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x4e, 0x5e, -+ 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, 0x56, 0x5e, -+ 0x4e, 0x5e, 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, -+ 0x09, 0x4f, 0x54, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x4e, 0x1f, 0x16, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, -+ 0x40, 0x2e, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x46, 0x17, 0x45, 0x46, 0x46, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, -+ 0x47, 0x63, 0x40, 0x08, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, -+ 0x65, 0x27, 0x4c, 0x17, 0x40, 0x07, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x4e, 0x5d, -+ 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, 0x56, 0x5d, -+ 0x4e, 0x5d, 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, -+ 0x09, 0x4f, 0x52, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x4e, 0x1f, 0x16, 0x4f, -+ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, -+ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, -+ 0x40, 0x2d, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, -+ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x45, 0x17, 0x44, 0x45, 0x45, 0x17, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x21, 0x40, 0x46, 0x40, 0x40, 0x15, 0x0f, -+ 0x46, 0x61, 0x40, 0x09, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x02, 0x07, -+ 0x64, 0x27, 0x4b, 0x16, 0x40, 0x06, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x4d, 0x5c, -+ 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, 0x55, 0x5c, -+ 0x4d, 0x5c, 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, -+ 0x0a, 0x4e, 0x50, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x4d, 0x1e, 0x15, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x01, 0x01, 0x02, 0x0a, 0x02, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, -+ 0x40, 0x2c, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x02, -+ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x44, 0x16, 0x43, 0x44, 0x44, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, -+ 0x46, 0x60, 0x40, 0x09, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, -+ 0x63, 0x27, 0x49, 0x16, 0x40, 0x06, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x4c, 0x5b, -+ 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, 0x54, 0x5b, -+ 0x4c, 0x5b, 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, -+ 0x0b, 0x4e, 0x4e, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x4c, 0x1e, 0x14, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, -+ 0x40, 0x2b, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, -+ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x43, 0x16, 0x41, 0x43, 0x43, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, -+ 0x46, 0x5e, 0x40, 0x09, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, -+ 0x62, 0x27, 0x48, 0x16, 0x40, 0x06, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x4c, 0x5a, -+ 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, 0x54, 0x5a, -+ 0x4c, 0x5a, 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, -+ 0x0b, 0x4e, 0x4c, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x4c, 0x1e, 0x14, 0x4e, -+ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, -+ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, -+ 0x40, 0x2a, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, -+ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x42, 0x16, 0x40, 0x42, 0x42, 0x16, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x22, 0x40, 0x45, 0x40, 0x40, 0x13, 0x0f, -+ 0x45, 0x5d, 0x40, 0x0a, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, -+ 0x61, 0x27, 0x47, 0x15, 0x40, 0x05, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x4b, 0x59, -+ 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, 0x53, 0x59, -+ 0x4b, 0x59, 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, -+ 0x0c, 0x4d, 0x4a, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x4b, 0x1d, 0x13, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, -+ 0x40, 0x29, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, -+ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x41, 0x15, 0x00, 0x41, 0x41, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, -+ 0x45, 0x5b, 0x40, 0x0a, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, -+ 0x60, 0x27, 0x46, 0x15, 0x40, 0x05, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x4b, 0x58, -+ 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, 0x53, 0x58, -+ 0x4b, 0x58, 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, -+ 0x0c, 0x4d, 0x49, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x4b, 0x1d, 0x12, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, -+ 0x40, 0x28, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, -+ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x40, 0x15, 0x01, 0x40, 0x40, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, -+ 0x45, 0x59, 0x40, 0x0a, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x05, 0x07, -+ 0x5f, 0x27, 0x44, 0x15, 0x40, 0x05, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x4a, 0x57, -+ 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, 0x52, 0x57, -+ 0x4a, 0x57, 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, -+ 0x0d, 0x4d, 0x47, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x4a, 0x1d, 0x12, 0x4d, -+ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, -+ 0x07, 0x02, 0x02, 0x05, 0x0d, 0x05, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, -+ 0x40, 0x27, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x05, -+ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x00, 0x15, 0x03, 0x00, 0x00, 0x15, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, -+ 0x44, 0x58, 0x40, 0x0b, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, -+ 0x5e, 0x27, 0x43, 0x14, 0x40, 0x04, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x49, 0x56, -+ 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, 0x51, 0x56, -+ 0x49, 0x56, 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, -+ 0x0e, 0x4c, 0x45, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x49, 0x1c, 0x11, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, -+ 0x40, 0x26, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, -+ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x01, 0x14, 0x04, 0x01, 0x01, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, -+ 0x44, 0x56, 0x40, 0x0b, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, -+ 0x5d, 0x27, 0x42, 0x14, 0x40, 0x04, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x49, 0x55, -+ 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, 0x51, 0x55, -+ 0x49, 0x55, 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, -+ 0x0e, 0x4c, 0x43, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x49, 0x1c, 0x11, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, -+ 0x40, 0x25, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, -+ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x02, 0x14, 0x05, 0x02, 0x02, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x23, 0x40, 0x44, 0x40, 0x40, 0x10, 0x0f, -+ 0x44, 0x55, 0x40, 0x0b, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x3d, 0x14, 0x07, 0x07, -+ 0x5c, 0x27, 0x41, 0x14, 0x40, 0x04, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x48, 0x54, -+ 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, 0x50, 0x54, -+ 0x48, 0x54, 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, -+ 0x0f, 0x4c, 0x41, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x48, 0x1c, 0x10, 0x4c, -+ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, -+ 0x07, 0x03, 0x03, 0x07, 0x0f, 0x07, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, -+ 0x40, 0x24, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x07, -+ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x03, 0x14, 0x06, 0x03, 0x03, 0x14, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, -+ 0x43, 0x53, 0x40, 0x0c, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x3b, 0x13, 0x08, 0x07, -+ 0x5b, 0x27, 0x00, 0x13, 0x40, 0x03, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x47, 0x53, -+ 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, 0x4f, 0x53, -+ 0x47, 0x53, 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, -+ 0x10, 0x4b, 0x00, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x47, 0x1b, 0x0f, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, -+ 0x40, 0x23, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, -+ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x04, 0x13, 0x08, 0x04, 0x04, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, -+ 0x43, 0x52, 0x40, 0x0c, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x3a, 0x13, 0x08, 0x07, -+ 0x5a, 0x27, 0x01, 0x13, 0x40, 0x03, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x47, 0x52, -+ 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, 0x4f, 0x52, -+ 0x47, 0x52, 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, -+ 0x10, 0x4b, 0x02, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x47, 0x1b, 0x0f, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, -+ 0x40, 0x22, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, -+ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x05, 0x13, 0x09, 0x05, 0x05, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0e, 0x0f, -+ 0x43, 0x50, 0x40, 0x0c, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x38, 0x13, 0x09, 0x07, -+ 0x59, 0x27, 0x02, 0x13, 0x40, 0x03, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, -+ 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, 0x4e, 0x51, -+ 0x46, 0x51, 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, -+ 0x11, 0x4b, 0x04, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x46, 0x1b, 0x0e, 0x4b, -+ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, -+ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, -+ 0x40, 0x21, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, -+ 0x03, 0x3d, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x06, 0x13, 0x0a, 0x06, 0x06, 0x13, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0d, 0x0f, -+ 0x43, 0x4f, 0x40, 0x0c, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x36, 0x12, 0x09, 0x07, -+ 0x59, 0x27, 0x03, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, -+ 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, 0x4e, 0x51, -+ 0x46, 0x51, 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, -+ 0x11, 0x4b, 0x05, 0x40, 0x45, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x46, 0x1a, 0x0d, 0x4b, -+ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, -+ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, -+ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, -+ 0x02, 0x3b, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x06, 0x12, 0x0b, 0x06, 0x06, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0d, 0x0f, -+ 0x42, 0x4d, 0x40, 0x0d, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x35, 0x12, 0x0a, 0x07, -+ 0x58, 0x27, 0x05, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x45, 0x50, -+ 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, 0x4d, 0x50, -+ 0x45, 0x50, 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, -+ 0x12, 0x4a, 0x07, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x45, 0x1a, 0x0d, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x05, 0x05, 0x0a, 0x12, 0x0a, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, -+ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0a, -+ 0x02, 0x3a, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x07, 0x12, 0x0d, 0x07, 0x07, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, -+ 0x42, 0x4b, 0x40, 0x0d, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x33, 0x12, 0x0b, 0x07, -+ 0x57, 0x27, 0x06, 0x12, 0x40, 0x02, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x44, 0x4f, -+ 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, 0x4c, 0x4f, -+ 0x44, 0x4f, 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, -+ 0x13, 0x4a, 0x09, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x44, 0x1a, 0x0c, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, -+ 0x40, 0x1f, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, -+ 0x02, 0x39, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x08, 0x12, 0x0e, 0x08, 0x08, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, -+ 0x42, 0x4a, 0x40, 0x0d, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x32, 0x12, 0x0b, 0x07, -+ 0x56, 0x27, 0x07, 0x12, 0x40, 0x02, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x44, 0x4e, -+ 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, 0x4c, 0x4e, -+ 0x44, 0x4e, 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, -+ 0x13, 0x4a, 0x0b, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x44, 0x1a, 0x0c, 0x4a, -+ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, -+ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, -+ 0x40, 0x1e, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, -+ 0x02, 0x38, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x09, 0x12, 0x0f, 0x09, 0x09, 0x12, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0b, 0x0f, -+ 0x41, 0x48, 0x40, 0x0e, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x30, 0x11, 0x0c, 0x07, -+ 0x55, 0x27, 0x08, 0x11, 0x40, 0x01, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x43, 0x4d, -+ 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, 0x4b, 0x4d, -+ 0x43, 0x4d, 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, -+ 0x14, 0x49, 0x0d, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x43, 0x19, 0x0b, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x06, 0x06, 0x0c, 0x14, 0x0c, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, -+ 0x40, 0x1d, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0c, -+ 0x01, 0x36, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x0a, 0x11, 0x10, 0x0a, 0x0a, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, -+ 0x41, 0x47, 0x40, 0x0e, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x2f, 0x11, 0x0d, 0x07, -+ 0x54, 0x27, 0x0a, 0x11, 0x40, 0x01, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x42, 0x4c, -+ 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, 0x4a, 0x4c, -+ 0x42, 0x4c, 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, -+ 0x15, 0x49, 0x0f, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x42, 0x19, 0x0a, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, -+ 0x40, 0x1c, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, -+ 0x01, 0x35, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0b, 0x11, 0x12, 0x0b, 0x0b, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, -+ 0x41, 0x45, 0x40, 0x0e, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x2d, 0x11, 0x0d, 0x07, -+ 0x53, 0x27, 0x0b, 0x11, 0x40, 0x01, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x42, 0x4b, -+ 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, 0x4a, 0x4b, -+ 0x42, 0x4b, 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, -+ 0x15, 0x49, 0x11, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x42, 0x19, 0x0a, 0x49, -+ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, -+ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, -+ 0x40, 0x1b, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, -+ 0x01, 0x34, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0c, 0x11, 0x13, 0x0c, 0x0c, 0x11, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, -+ 0x40, 0x44, 0x40, 0x0f, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x2c, 0x10, 0x0e, 0x07, -+ 0x52, 0x27, 0x0c, 0x10, 0x40, 0x00, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x41, 0x4a, -+ 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, 0x49, 0x4a, -+ 0x41, 0x4a, 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, -+ 0x16, 0x48, 0x13, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x41, 0x18, 0x09, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, -+ 0x40, 0x1a, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, -+ 0x00, 0x33, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x0d, 0x10, 0x14, 0x0d, 0x0d, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, -+ 0x40, 0x42, 0x40, 0x0f, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x2a, 0x10, 0x0e, 0x07, -+ 0x51, 0x27, 0x0d, 0x10, 0x40, 0x00, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, -+ 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, 0x49, 0x49, -+ 0x41, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, -+ 0x16, 0x48, 0x14, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x41, 0x18, 0x08, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, -+ 0x40, 0x19, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, -+ 0x00, 0x31, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, -+ 0x40, 0x40, 0x40, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x28, 0x10, 0x0f, 0x07, -+ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x00, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, -+ 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, -+ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, -+ 0x17, 0x48, 0x16, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x40, 0x18, 0x08, 0x48, -+ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, -+ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, -+ 0x40, 0x18, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, -+ 0x00, 0x30, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, -+ 0x00, 0x00, 0x40, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x27, 0x0f, 0x10, 0x07, -+ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, -+ 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, -+ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, -+ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x00, 0x17, 0x07, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, -+ 0x40, 0x17, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, -+ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, -+ 0x00, 0x02, 0x40, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x25, 0x0f, 0x10, 0x07, -+ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x00, 0x46, -+ 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, 0x47, 0x46, -+ 0x00, 0x46, 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, -+ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x00, 0x17, 0x07, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, -+ 0x40, 0x16, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, -+ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x11, 0x0f, 0x19, 0x11, 0x11, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x28, 0x40, 0x00, 0x40, 0x40, 0x06, 0x0f, -+ 0x00, 0x03, 0x40, 0x10, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x24, 0x0f, 0x11, 0x07, -+ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x01, 0x45, -+ 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, 0x46, 0x45, -+ 0x01, 0x45, 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, -+ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x01, 0x17, 0x06, 0x47, -+ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, -+ 0x07, 0x08, 0x08, 0x11, 0x19, 0x11, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, -+ 0x40, 0x15, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x11, -+ 0x40, 0x2c, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x12, 0x0f, 0x1a, 0x12, 0x12, 0x0f, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, -+ 0x01, 0x05, 0x40, 0x11, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x22, 0x0e, 0x12, 0x07, -+ 0x4c, 0x27, 0x14, 0x0e, 0x40, 0x41, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x02, 0x44, -+ 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, 0x45, 0x44, -+ 0x02, 0x44, 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, -+ 0x1a, 0x46, 0x1e, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x02, 0x16, 0x05, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, -+ 0x40, 0x14, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, -+ 0x41, 0x2b, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x13, 0x0e, 0x1c, 0x13, 0x13, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, -+ 0x01, 0x06, 0x40, 0x11, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x21, 0x0e, 0x12, 0x07, -+ 0x4b, 0x27, 0x15, 0x0e, 0x40, 0x41, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x02, 0x43, -+ 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, 0x45, 0x43, -+ 0x02, 0x43, 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, -+ 0x1a, 0x46, 0x20, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x02, 0x16, 0x05, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, -+ 0x40, 0x13, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, -+ 0x41, 0x2a, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x14, 0x0e, 0x1d, 0x14, 0x14, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x29, 0x40, 0x01, 0x40, 0x40, 0x04, 0x0f, -+ 0x01, 0x08, 0x40, 0x11, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x1f, 0x0e, 0x13, 0x07, -+ 0x4a, 0x27, 0x16, 0x0e, 0x40, 0x41, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, -+ 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, 0x44, 0x42, -+ 0x03, 0x42, 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, -+ 0x1b, 0x46, 0x22, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x03, 0x16, 0x04, 0x46, -+ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, -+ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, -+ 0x40, 0x12, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, -+ 0x41, 0x29, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x15, 0x0e, 0x1e, 0x15, 0x15, 0x0e, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x29, 0x40, 0x01, 0x40, 0x40, 0x03, 0x0f, -+ 0x01, 0x09, 0x40, 0x11, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x1d, 0x0d, 0x13, 0x07, -+ 0x4a, 0x27, 0x17, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, -+ 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, 0x44, 0x42, -+ 0x03, 0x42, 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, -+ 0x1b, 0x46, 0x23, 0x40, 0x4a, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x03, 0x15, 0x03, 0x46, -+ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, -+ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, -+ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, -+ 0x42, 0x27, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x15, 0x0d, 0x1f, 0x15, 0x15, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x03, 0x0f, -+ 0x02, 0x0b, 0x40, 0x12, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x1c, 0x0d, 0x14, 0x07, -+ 0x49, 0x27, 0x19, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x04, 0x41, -+ 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, 0x43, 0x41, -+ 0x04, 0x41, 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, -+ 0x1c, 0x45, 0x25, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x04, 0x15, 0x03, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0a, 0x0a, 0x14, 0x1c, 0x14, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, -+ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x14, -+ 0x42, 0x26, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x16, 0x0d, 0x21, 0x16, 0x16, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, -+ 0x02, 0x0d, 0x40, 0x12, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x1a, 0x0d, 0x15, 0x07, -+ 0x48, 0x27, 0x1a, 0x0d, 0x40, 0x42, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x05, 0x40, -+ 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, 0x42, 0x40, -+ 0x05, 0x40, 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, -+ 0x1d, 0x45, 0x27, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x05, 0x15, 0x02, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, -+ 0x40, 0x10, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, -+ 0x42, 0x25, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x17, 0x0d, 0x22, 0x17, 0x17, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, -+ 0x02, 0x0e, 0x40, 0x12, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x19, 0x0d, 0x15, 0x07, -+ 0x47, 0x27, 0x1b, 0x0d, 0x40, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x05, 0x00, -+ 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, 0x42, 0x00, -+ 0x05, 0x00, 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, -+ 0x1d, 0x45, 0x29, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x05, 0x15, 0x02, 0x45, -+ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, -+ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, -+ 0x40, 0x0f, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, -+ 0x42, 0x24, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x18, 0x0d, 0x23, 0x18, 0x18, 0x0d, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x01, 0x0f, -+ 0x03, 0x10, 0x40, 0x13, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x17, 0x0c, 0x16, 0x07, -+ 0x46, 0x27, 0x1c, 0x0c, 0x40, 0x43, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x06, 0x01, -+ 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, 0x41, 0x01, -+ 0x06, 0x01, 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, -+ 0x1e, 0x44, 0x2b, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x06, 0x14, 0x01, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0b, 0x0b, 0x16, 0x1e, 0x16, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, -+ 0x40, 0x0e, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x16, -+ 0x43, 0x22, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x19, 0x0c, 0x24, 0x19, 0x19, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, -+ 0x03, 0x11, 0x40, 0x13, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x16, 0x0c, 0x17, 0x07, -+ 0x45, 0x27, 0x1e, 0x0c, 0x40, 0x43, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x07, 0x02, -+ 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, 0x40, 0x02, -+ 0x07, 0x02, 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, -+ 0x1f, 0x44, 0x2d, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, -+ 0x40, 0x0d, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, -+ 0x43, 0x21, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1a, 0x0c, 0x26, 0x1a, 0x1a, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, -+ 0x03, 0x13, 0x40, 0x13, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x14, 0x0c, 0x17, 0x07, -+ 0x44, 0x27, 0x1f, 0x0c, 0x40, 0x43, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x07, 0x03, -+ 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, 0x40, 0x03, -+ 0x07, 0x03, 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, -+ 0x1f, 0x44, 0x2f, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, -+ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, -+ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, -+ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, -+ 0x43, 0x20, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1b, 0x0c, 0x27, 0x1b, 0x1b, 0x0c, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, -+ 0x04, 0x14, 0x40, 0x14, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x13, 0x0b, 0x18, 0x07, -+ 0x43, 0x27, 0x20, 0x0b, 0x40, 0x44, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x08, 0x04, -+ 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, 0x00, 0x04, -+ 0x08, 0x04, 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, -+ 0x20, 0x43, 0x31, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x08, 0x13, 0x40, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, -+ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, -+ 0x44, 0x1f, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x1c, 0x0b, 0x28, 0x1c, 0x1c, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, -+ 0x04, 0x16, 0x40, 0x14, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x11, 0x0b, 0x18, 0x07, -+ 0x42, 0x27, 0x21, 0x0b, 0x40, 0x44, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x08, 0x05, -+ 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, 0x00, 0x05, -+ 0x08, 0x05, 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, -+ 0x20, 0x43, 0x32, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x08, 0x13, 0x41, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, -+ 0x40, 0x0a, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, -+ 0x44, 0x1d, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1d, 0x0b, 0x29, 0x1d, 0x1d, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, -+ 0x04, 0x18, 0x40, 0x14, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x0f, 0x0b, 0x19, 0x07, -+ 0x41, 0x27, 0x23, 0x0b, 0x40, 0x44, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x09, 0x06, -+ 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, 0x01, 0x06, -+ 0x09, 0x06, 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, -+ 0x21, 0x43, 0x34, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x09, 0x13, 0x41, 0x43, -+ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, -+ 0x07, 0x0c, 0x0c, 0x19, 0x21, 0x19, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, -+ 0x40, 0x09, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x19, -+ 0x44, 0x1c, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1e, 0x0b, 0x2b, 0x1e, 0x1e, 0x0b, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, -+ 0x05, 0x19, 0x40, 0x15, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0e, 0x0a, 0x1a, 0x07, -+ 0x40, 0x27, 0x24, 0x0a, 0x40, 0x45, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x0a, 0x07, -+ 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, 0x02, 0x07, -+ 0x0a, 0x07, 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, -+ 0x22, 0x42, 0x36, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x0a, 0x12, 0x42, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, -+ 0x40, 0x08, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, -+ 0x45, 0x1b, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x1f, 0x0a, 0x2c, 0x1f, 0x1f, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, -+ 0x05, 0x1b, 0x40, 0x15, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0c, 0x0a, 0x1a, 0x07, -+ 0x00, 0x27, 0x25, 0x0a, 0x40, 0x45, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x0a, 0x08, -+ 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, 0x02, 0x08, -+ 0x0a, 0x08, 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, -+ 0x22, 0x42, 0x38, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x0a, 0x12, 0x42, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, -+ 0x40, 0x07, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, -+ 0x45, 0x1a, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x20, 0x0a, 0x2d, 0x20, 0x20, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x43, 0x0f, -+ 0x05, 0x1c, 0x40, 0x15, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0a, 0x1b, 0x07, -+ 0x01, 0x27, 0x26, 0x0a, 0x40, 0x45, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x0b, 0x09, -+ 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, 0x03, 0x09, -+ 0x0b, 0x09, 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, -+ 0x23, 0x42, 0x3a, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x0b, 0x12, 0x43, 0x42, -+ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, -+ 0x07, 0x0d, 0x0d, 0x1b, 0x23, 0x1b, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, -+ 0x40, 0x06, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x1b, -+ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x21, 0x0a, 0x2e, 0x21, 0x21, 0x0a, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, -+ 0x06, 0x1e, 0x40, 0x16, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x09, 0x09, 0x1c, 0x07, -+ 0x02, 0x27, 0x28, 0x09, 0x40, 0x46, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x0c, 0x0a, -+ 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, 0x04, 0x0a, -+ 0x0c, 0x0a, 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, -+ 0x24, 0x41, 0x3c, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x0c, 0x11, 0x44, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, -+ 0x40, 0x05, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, -+ 0x46, 0x17, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x22, 0x09, 0x30, 0x22, 0x22, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, -+ 0x06, 0x1f, 0x40, 0x16, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x08, 0x09, 0x1c, 0x07, -+ 0x03, 0x27, 0x29, 0x09, 0x40, 0x46, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x0c, 0x0b, -+ 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, 0x04, 0x0b, -+ 0x0c, 0x0b, 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, -+ 0x24, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x0c, 0x11, 0x44, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, -+ 0x40, 0x04, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, -+ 0x46, 0x16, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x23, 0x09, 0x31, 0x23, 0x23, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x45, 0x0f, -+ 0x06, 0x21, 0x40, 0x16, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x06, 0x09, 0x1d, 0x07, -+ 0x04, 0x27, 0x2a, 0x09, 0x40, 0x46, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, -+ 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, 0x05, 0x0c, -+ 0x0d, 0x0c, 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, -+ 0x25, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x0d, 0x11, 0x45, 0x41, -+ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, -+ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, -+ 0x40, 0x03, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, -+ 0x46, 0x15, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x24, 0x09, 0x32, 0x24, 0x24, 0x09, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x46, 0x0f, -+ 0x06, 0x22, 0x40, 0x16, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x04, 0x08, 0x1d, 0x07, -+ 0x04, 0x27, 0x2b, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, -+ 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, 0x05, 0x0c, -+ 0x0d, 0x0c, 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, -+ 0x25, 0x41, 0x3e, 0x40, 0x4f, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x0d, 0x10, 0x46, 0x41, -+ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, -+ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, -+ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, -+ 0x47, 0x13, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x24, 0x08, 0x33, 0x24, 0x24, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x46, 0x0f, -+ 0x07, 0x24, 0x40, 0x17, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x03, 0x08, 0x1e, 0x07, -+ 0x05, 0x27, 0x2d, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x0e, 0x0d, -+ 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, 0x06, 0x0d, -+ 0x0e, 0x0d, 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, -+ 0x26, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x0e, 0x10, 0x46, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x0f, 0x0f, 0x1e, 0x26, 0x1e, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, -+ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x1e, -+ 0x47, 0x12, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x25, 0x08, 0x35, 0x25, 0x25, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, -+ 0x07, 0x26, 0x40, 0x17, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x01, 0x08, 0x1f, 0x07, -+ 0x06, 0x27, 0x2e, 0x08, 0x40, 0x47, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x0f, 0x0e, -+ 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, 0x07, 0x0e, -+ 0x0f, 0x0e, 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, -+ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x0f, 0x10, 0x47, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, -+ 0x40, 0x01, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, -+ 0x47, 0x11, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x26, 0x08, 0x36, 0x26, 0x26, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x07, 0x3e, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, -+ 0x07, 0x27, 0x40, 0x17, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x00, 0x08, 0x1f, 0x07, -+ 0x07, 0x27, 0x2f, 0x08, 0x40, 0x47, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, -+ 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, 0x07, 0x0f, -+ 0x0f, 0x0f, 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, -+ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x0f, 0x10, 0x47, 0x40, -+ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, -+ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, -+ 0x40, 0x00, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, -+ 0x47, 0x10, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x27, 0x08, 0x37, 0x27, 0x27, 0x08, 0x40, 0x40, -+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+}; -+ -+static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) -+{ -+ u8 bit = field.offset % 32, word = field.offset / 32; -+ u64 mask = GENMASK_ULL(bit + field.len - 1, bit); -+ u64 val = ((u64)value << bit) & mask; -+ -+ buf[word] &= ~mask; -+ buf[word] |= val; -+ if (bit + field.len > 32) { -+ buf[word + 1] &= ~(mask >> 32); -+ buf[word + 1] |= val >> 32; -+ } -+} -+ -+static void assemble_hw_pps(struct rkvdec_ctx *ctx, -+ struct rkvdec_hevc_run *run) -+{ -+ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; -+ const struct v4l2_ctrl_hevc_sps *sps = run->sps; -+ const struct v4l2_ctrl_hevc_pps *pps = run->pps; -+ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; -+ struct rkvdec_sps_pps_packet *hw_ps; -+ u32 min_cb_log2_size_y, ctb_log2_size_y, ctb_size_y; -+ u32 log2_min_cu_qp_delta_size; -+ dma_addr_t scaling_list_address; -+ u32 scaling_distance; -+ int i; -+ -+ /* -+ * HW read the SPS/PPS information from PPS packet index by PPS id. -+ * offset from the base can be calculated by PPS_id * 80 (size per PPS -+ * packet unit). so the driver copy SPS/PPS information to the exact PPS -+ * packet unit for HW accessing. -+ */ -+ hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id]; -+ memset(hw_ps, 0, sizeof(*hw_ps)); -+ -+ min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; -+ ctb_log2_size_y = min_cb_log2_size_y + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_y = 1 << ctb_log2_size_y; -+ -+#define WRITE_PPS(value, field) set_ps_field(hw_ps->info, field, value) -+ /* write sps */ -+ WRITE_PPS(sps->video_parameter_set_id, VIDEO_PARAMETER_SET_ID); -+ WRITE_PPS(sps->seq_parameter_set_id, SEQ_PARAMETER_SET_ID); -+ WRITE_PPS(1, CHROMA_FORMAT_IDC); -+ WRITE_PPS(sps->pic_width_in_luma_samples, PIC_WIDTH_IN_LUMA_SAMPLES); -+ WRITE_PPS(sps->pic_height_in_luma_samples, PIC_HEIGHT_IN_LUMA_SAMPLES); -+ WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); -+ WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); -+ WRITE_PPS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, -+ LOG2_MAX_PIC_ORDER_CNT_LSB); -+ WRITE_PPS(sps->log2_diff_max_min_luma_coding_block_size, -+ LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE); -+ WRITE_PPS(sps->log2_min_luma_coding_block_size_minus3 + 3, -+ LOG2_MIN_LUMA_CODING_BLOCK_SIZE); -+ WRITE_PPS(sps->log2_min_luma_transform_block_size_minus2 + 2, -+ LOG2_MIN_TRANSFORM_BLOCK_SIZE); -+ WRITE_PPS(sps->log2_diff_max_min_luma_transform_block_size, -+ LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE); -+ WRITE_PPS(sps->max_transform_hierarchy_depth_inter, -+ MAX_TRANSFORM_HIERARCHY_DEPTH_INTER); -+ WRITE_PPS(sps->max_transform_hierarchy_depth_intra, -+ MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED), -+ SCALING_LIST_ENABLED_FLAG); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED), -+ AMP_ENABLED_FLAG); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET), -+ SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG); -+ if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) { -+ WRITE_PPS(1, PCM_ENABLED_FLAG); -+ WRITE_PPS(sps->pcm_sample_bit_depth_luma_minus1 + 1, -+ PCM_SAMPLE_BIT_DEPTH_LUMA); -+ WRITE_PPS(sps->pcm_sample_bit_depth_chroma_minus1 + 1, -+ PCM_SAMPLE_BIT_DEPTH_CHROMA); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED), -+ PCM_LOOP_FILTER_DISABLED_FLAG); -+ WRITE_PPS(sps->log2_diff_max_min_pcm_luma_coding_block_size, -+ LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE); -+ WRITE_PPS(sps->log2_min_pcm_luma_coding_block_size_minus3 + 3, -+ LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE); -+ } -+ WRITE_PPS(sps->num_short_term_ref_pic_sets, NUM_SHORT_TERM_REF_PIC_SETS); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT), -+ LONG_TERM_REF_PICS_PRESENT_FLAG); -+ WRITE_PPS(sps->num_long_term_ref_pics_sps, NUM_LONG_TERM_REF_PICS_SPS); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED), -+ SPS_TEMPORAL_MVP_ENABLED_FLAG); -+ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED), -+ STRONG_INTRA_SMOOTHING_ENABLED_FLAG); -+ //WRITE_PPS(0, PS_FIELD(100, 7)); -+ //WRITE_PPS(0x1fffff, PS_FIELD(107, 21)); -+ -+ /* write pps */ -+ WRITE_PPS(pps->pic_parameter_set_id, PIC_PARAMETER_SET_ID); -+ WRITE_PPS(sps->seq_parameter_set_id, PPS_SEQ_PARAMETER_SET_ID); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT), -+ DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT), -+ OUTPUT_FLAG_PRESENT_FLAG); -+ WRITE_PPS(pps->num_extra_slice_header_bits, NUM_EXTRA_SLICE_HEADER_BITS); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED), -+ SIGN_DATA_HIDING_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT), -+ CABAC_INIT_PRESENT_FLAG); -+ WRITE_PPS(pps->num_ref_idx_l0_default_active_minus1 + 1, -+ NUM_REF_IDX_L0_DEFAULT_ACTIVE); -+ WRITE_PPS(pps->num_ref_idx_l1_default_active_minus1 + 1, -+ NUM_REF_IDX_L1_DEFAULT_ACTIVE); -+ WRITE_PPS(pps->init_qp_minus26, INIT_QP_MINUS26); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED), -+ CONSTRAINED_INTRA_PRED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED), -+ TRANSFORM_SKIP_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED), -+ CU_QP_DELTA_ENABLED_FLAG); -+ -+ log2_min_cu_qp_delta_size = ctb_log2_size_y - pps->diff_cu_qp_delta_depth; -+ WRITE_PPS(log2_min_cu_qp_delta_size, LOG2_MIN_CU_QP_DELTA_SIZE); -+ -+ WRITE_PPS(pps->pps_cb_qp_offset, PPS_CB_QP_OFFSET); -+ WRITE_PPS(pps->pps_cr_qp_offset, PPS_CR_QP_OFFSET); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT), -+ PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED), -+ WEIGHTED_PRED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED), -+ WEIGHTED_BIPRED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED), -+ TRANSQUANT_BYPASS_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED), -+ TILES_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED), -+ ENTROPY_CODING_SYNC_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED), -+ PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED), -+ LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED), -+ DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER), -+ PPS_DEBLOCKING_FILTER_DISABLED_FLAG); -+ WRITE_PPS(pps->pps_beta_offset_div2, PPS_BETA_OFFSET_DIV2); -+ WRITE_PPS(pps->pps_tc_offset_div2, PPS_TC_OFFSET_DIV2); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT), -+ LISTS_MODIFICATION_PRESENT_FLAG); -+ WRITE_PPS(pps->log2_parallel_merge_level_minus2 + 2, LOG2_PARALLEL_MERGE_LEVEL); -+ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT), -+ SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG); -+ //WRITE_PPS(0, PS_FIELD(209, 3)); -+ WRITE_PPS(pps->num_tile_columns_minus1 + 1, NUM_TILE_COLUMNS); -+ WRITE_PPS(pps->num_tile_rows_minus1 + 1, NUM_TILE_ROWS); -+ //WRITE_PPS(0x2, PS_FIELD(222, 2)); -+ //WRITE_PPS(0xffffffff, PS_FIELD(224, 32)); -+ -+ if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) { -+ for (i = 0; i <= pps->num_tile_columns_minus1; i++) -+ WRITE_PPS(pps->column_width_minus1[i], COLUMN_WIDTH(i)); -+ for (i = 0; i <= pps->num_tile_rows_minus1; i++) -+ WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i)); -+ } else { -+ WRITE_PPS(round_up(sps->pic_width_in_luma_samples, ctb_size_y) - 1, -+ COLUMN_WIDTH(0)); -+ WRITE_PPS(round_up(sps->pic_height_in_luma_samples, ctb_size_y) - 1, -+ ROW_HEIGHT(0)); -+ } -+ -+ scaling_distance = offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); -+ scaling_list_address = hevc_ctx->priv_tbl.dma + scaling_distance; -+ WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS); -+ //WRITE_PPS(0xffff, PS_FIELD(624, 16)); -+} -+ -+static void assemble_hw_rps(struct rkvdec_ctx *ctx, -+ struct rkvdec_hevc_run *run) -+{ -+ const struct v4l2_ctrl_hevc_slice_params *sl_params; -+ const struct v4l2_hevc_dpb_entry *dpb; -+ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; -+ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; -+ struct rkvdec_rps_packet *hw_ps; -+ int i, j; -+ -+#define WRITE_RPS(value, field) set_ps_field(hw_ps->info, field, value) -+ -+#define REF_PIC_LONG_TERM_L0(i) PS_FIELD(i * 5, 1) -+#define REF_PIC_IDX_L0(i) PS_FIELD(1 + (i * 5), 4) -+#define REF_PIC_LONG_TERM_L1(i) PS_FIELD((i < 5 ? 75 : 132) + (i * 5), 1) -+#define REF_PIC_IDX_L1(i) PS_FIELD((i < 4 ? 76 : 128) + (i * 5), 4) -+ -+#define LOWDELAY PS_FIELD(182, 1) -+#define SHORT_TERM_REF_PIC_SET_SIZE PS_FIELD(183, 10) -+#define LONG_TERM_REF_PIC_SET_SIZE PS_FIELD(193, 9) -+#define NUM_RPS_POC PS_FIELD(202, 4) -+ -+ for (j = 0; j < run->num_slices; j++) { -+ sl_params = &run->slices_params[j]; -+ dpb = sl_params->dpb; -+ -+ hw_ps = &priv_tbl->rps[j]; -+ memset(hw_ps, 0, sizeof(*hw_ps)); -+ -+ for (i = 0; i <= sl_params->num_ref_idx_l0_active_minus1; i++) { -+ WRITE_RPS(!!(dpb[sl_params->ref_idx_l0[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), -+ REF_PIC_LONG_TERM_L0(i)); -+ WRITE_RPS(sl_params->ref_idx_l0[i], REF_PIC_IDX_L0(i)); -+ } -+ -+ for (i = 0; i <= sl_params->num_ref_idx_l1_active_minus1; i++) { -+ WRITE_RPS(!!(dpb[sl_params->ref_idx_l1[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), -+ REF_PIC_LONG_TERM_L1(i)); -+ WRITE_RPS(sl_params->ref_idx_l1[i], REF_PIC_IDX_L1(i)); -+ } -+ -+ //WRITE_RPS(0xffffffff, PS_FIELD(96, 32)); -+ -+ // TODO: lowdelay -+ WRITE_RPS(0, LOWDELAY); -+ -+ // NOTE: these two differs from mpp -+ WRITE_RPS(sl_params->short_term_ref_pic_set_size, -+ SHORT_TERM_REF_PIC_SET_SIZE); -+ WRITE_RPS(sl_params->long_term_ref_pic_set_size, -+ LONG_TERM_REF_PIC_SET_SIZE); -+ -+ WRITE_RPS(sl_params->num_rps_poc_st_curr_before + -+ sl_params->num_rps_poc_st_curr_after + -+ sl_params->num_rps_poc_lt_curr, -+ NUM_RPS_POC); -+ -+ //WRITE_RPS(0x3ffff, PS_FIELD(206, 18)); -+ //WRITE_RPS(0xffffffff, PS_FIELD(224, 32)); -+ } -+} -+ -+static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, -+ struct rkvdec_hevc_run *run) -+{ -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix; -+ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; -+ struct rkvdec_hevc_priv_tbl *tbl = hevc_ctx->priv_tbl.cpu; -+ u8 *dst; -+ scalingList_t sl; -+ int i, j; -+ -+ if (!memcmp((void*)&hevc_ctx->scaling_matrix_cache, scaling, -+ sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) -+ return; -+ -+ memset(&sl, 0, sizeof(scalingList_t)); -+ -+ for (i = 0; i < 6; i++) { -+ for (j = 0; j < 16; j++) -+ sl.sl[0][i][j] = scaling->scaling_list_4x4[i][j]; -+ for (j = 0; j < 64; j++) { -+ sl.sl[1][i][j] = scaling->scaling_list_8x8[i][j]; -+ sl.sl[2][i][j] = scaling->scaling_list_16x16[i][j]; -+ if (i < 2) -+ sl.sl[3][i][j] = scaling->scaling_list_32x32[i][j]; -+ } -+ sl.sl_dc[0][i] = scaling->scaling_list_dc_coef_16x16[i]; -+ if (i < 2) -+ sl.sl_dc[1][i] = scaling->scaling_list_dc_coef_32x32[i]; -+ } -+ -+ dst = tbl->scaling_list; -+ hal_record_scaling_list((scalingFactor_t *)dst, &sl); -+ -+ 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 = ctx->fh.m2m_ctx; -+ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; -+ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; -+ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; -+ int buf_idx = -1; -+ -+ if (dpb_idx < sl_params->num_active_dpb_entries) -+ buf_idx = vb2_find_timestamp(cap_q, -+ dpb[dpb_idx].timestamp, 0); -+ -+ /* -+ * If a DPB entry is unused or invalid, address of current destination -+ * buffer is returned. -+ */ -+ if (buf_idx < 0) -+ return &run->base.bufs.dst->vb2_buf; -+ -+ return vb2_get_buffer(cap_q, buf_idx); -+} -+ -+static void config_registers(struct rkvdec_ctx *ctx, -+ struct rkvdec_hevc_run *run) -+{ -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; -+ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; -+ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; -+ dma_addr_t priv_start_addr = hevc_ctx->priv_tbl.dma; -+ const struct v4l2_pix_format_mplane *dst_fmt; -+ struct vb2_v4l2_buffer *src_buf = run->base.bufs.src; -+ struct vb2_v4l2_buffer *dst_buf = run->base.bufs.dst; -+ const struct v4l2_format *f; -+ dma_addr_t rlc_addr; -+ dma_addr_t refer_addr; -+ u32 rlc_len; -+ u32 hor_virstride; -+ u32 ver_virstride; -+ u32 y_virstride; -+ u32 uv_virstride; -+ u32 yuv_virstride; -+ u32 offset; -+ dma_addr_t dst_addr; -+ u32 reg, i; -+ -+ reg = RKVDEC_MODE(RKVDEC_MODE_HEVC); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL); -+ -+ f = &ctx->decoded_fmt; -+ dst_fmt = &f->fmt.pix_mp; -+ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; -+ ver_virstride = dst_fmt->height; -+ y_virstride = hor_virstride * ver_virstride; -+ uv_virstride = y_virstride / 2; -+ yuv_virstride = y_virstride + uv_virstride; -+ -+ reg = 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); -+ -+ /* config rlc base address */ -+ rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); -+ writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); -+ -+ rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0); -+ reg = RKVDEC_STRM_LEN(round_up(rlc_len, 16) + 64); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN); -+ -+ /* config cabac table */ -+ offset = offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); -+ writel_relaxed(priv_start_addr + offset, -+ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); -+ -+ /* config output base address */ -+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); -+ writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); -+ -+ reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); -+ -+ reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); -+ -+ /* config ref pic address */ -+ for (i = 0; i < 15; i++) { -+ struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i); -+ -+ if (i < 4 && sl_params->num_active_dpb_entries) { -+ reg = GENMASK(sl_params->num_active_dpb_entries - 1, 0); -+ reg = (reg >> (i * 4)) & 0xf; -+ } else -+ reg = 0; -+ -+ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0); -+ writel_relaxed(refer_addr | reg, -+ rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i)); -+ -+ reg = RKVDEC_POC_REFER(i < sl_params->num_active_dpb_entries ? dpb[i].pic_order_cnt[0] : 0); -+ writel_relaxed(reg, -+ rkvdec->regs + RKVDEC_REG_H264_POC_REFER0(i)); -+ } -+ -+ reg = RKVDEC_CUR_POC(sl_params->slice_pic_order_cnt); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); -+ -+ /* config hw pps address */ -+ offset = offsetof(struct rkvdec_hevc_priv_tbl, param_set); -+ writel_relaxed(priv_start_addr + offset, -+ rkvdec->regs + RKVDEC_REG_PPS_BASE); -+ -+ /* config hw rps address */ -+ offset = offsetof(struct rkvdec_hevc_priv_tbl, rps); -+ writel_relaxed(priv_start_addr + offset, -+ rkvdec->regs + RKVDEC_REG_RPS_BASE); -+ -+ reg = RKVDEC_AXI_DDR_RDATA(0); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA); -+ -+ reg = RKVDEC_AXI_DDR_WDATA(0); -+ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA); -+} -+ -+#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 = &f->fmt.pix_mp; -+ -+ fmt->num_planes = 1; -+ if (!fmt->plane_fmt[0].sizeimage) -+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * -+ RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; -+ return 0; -+} -+ -+static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ struct rkvdec_hevc_priv_tbl *priv_tbl; -+ struct rkvdec_hevc_ctx *hevc_ctx; -+ int ret; -+ -+ hevc_ctx = kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); -+ if (!hevc_ctx) -+ return -ENOMEM; -+ -+ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), -+ &hevc_ctx->priv_tbl.dma, GFP_KERNEL); -+ if (!priv_tbl) { -+ ret = -ENOMEM; -+ goto err_free_ctx; -+ } -+ -+ hevc_ctx->priv_tbl.size = sizeof(*priv_tbl); -+ hevc_ctx->priv_tbl.cpu = priv_tbl; -+ memset(priv_tbl, 0, sizeof(*priv_tbl)); -+ memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, -+ sizeof(rkvdec_hevc_cabac_table)); -+ -+ ctx->priv = 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 = ctx->priv; -+ struct rkvdec_dev *rkvdec = 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 void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, -+ struct rkvdec_hevc_run *run) -+{ -+ struct v4l2_ctrl *ctrl; -+ -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); -+ run->slices_params = ctrl ? ctrl->p_cur.p : NULL; -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_HEVC_SPS); -+ run->sps = ctrl ? ctrl->p_cur.p : NULL; -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_HEVC_PPS); -+ run->pps = ctrl ? ctrl->p_cur.p : NULL; -+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, -+ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); -+ run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL; -+ -+ rkvdec_run_preamble(ctx, &run->base); -+ -+ // HACK: we need num slices from somewhere -+ run->num_slices = run->sps->num_slices; -+} -+ -+static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) -+{ -+ struct rkvdec_dev *rkvdec = ctx->dev; -+ struct rkvdec_hevc_run run; -+ -+ rkvdec_hevc_run_preamble(ctx, &run); -+ -+ assemble_hw_scaling_list(ctx, &run); -+ assemble_hw_pps(ctx, &run); -+ assemble_hw_rps(ctx, &run); -+ config_registers(ctx, &run); -+ -+ rkvdec_run_postamble(ctx, &run.base); -+ -+ // sw_cabac_error_e - cabac error enable -+ writel_relaxed(0xfdfffffd, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); -+ // slice end error enable = BIT(28) -+ // frame end error enable = BIT(29) -+ writel_relaxed(0x30000000, rkvdec->regs + RKVDEC_REG_H264_ERR_E); -+ -+ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); -+ -+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); -+ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); -+ -+ /* Start decoding! */ -+ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | -+ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, -+ rkvdec->regs + RKVDEC_REG_INTERRUPT); -+ -+ return 0; -+} -+ -+const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { -+ .adjust_fmt = rkvdec_hevc_adjust_fmt, -+ .start = rkvdec_hevc_start, -+ .stop = rkvdec_hevc_stop, -+ .run = rkvdec_hevc_run, -+}; -diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h -index 15b9bee92016..83bf790ed9b7 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-regs.h -+++ b/drivers/staging/media/rkvdec/rkvdec-regs.h -@@ -43,6 +43,7 @@ - #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) -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index e1eec79fe9a2..880a70c9291e 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -159,6 +159,61 @@ static const u32 rkvdec_h264_decoded_fmts[] = { - V4L2_PIX_FMT_NV20, - }; - -+static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { -+ { -+ .mandatory = true, -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, -+ // HACK: match ffmpeg v4l2 request api hwaccel size, -+ // we should support variable length up to 600 slices -+ .cfg.dims = { 16 }, -+ }, -+ { -+ .mandatory = true, -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, -+ }, -+ { -+ .mandatory = true, -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, -+ }, -+ { -+ .mandatory = true, -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, -+ .cfg.min = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, -+ .cfg.max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, -+ .cfg.def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, -+ .cfg.min = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, -+ .cfg.def = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, -+ .cfg.max = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, -+ .cfg.min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, -+ .cfg.max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, -+ .cfg.def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, -+ }, -+ { -+ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, -+ .cfg.min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, -+ .cfg.max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, -+ }, -+}; -+ -+static const struct rkvdec_ctrls rkvdec_hevc_ctrls = { -+ .ctrls = rkvdec_hevc_ctrl_descs, -+ .num_ctrls = ARRAY_SIZE(rkvdec_hevc_ctrl_descs), -+}; -+ -+static const u32 rkvdec_hevc_decoded_fmts[] = { -+ V4L2_PIX_FMT_NV12, -+ V4L2_PIX_FMT_NV15, -+}; -+ - static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { - { - .mandatory = true, -@@ -209,6 +264,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { - .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), - .decoded_fmts = rkvdec_h264_decoded_fmts, - }, -+ { -+ .fourcc = V4L2_PIX_FMT_HEVC_SLICE, -+ .frmsize = { -+ .min_width = 64, -+ .max_width = 4096, -+ .step_width = 64, -+ .min_height = 64, -+ .max_height = 2304, -+ .step_height = 16, -+ }, -+ .ctrls = &rkvdec_hevc_ctrls, -+ .ops = &rkvdec_hevc_fmt_ops, -+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_hevc_decoded_fmts), -+ .decoded_fmts = rkvdec_hevc_decoded_fmts, -+ }, - { - .fourcc = V4L2_PIX_FMT_VP9_FRAME, - .frmsize = { -diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h -index 5f66f07acac5..d5600c6a4c17 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.h -+++ b/drivers/staging/media/rkvdec/rkvdec.h -@@ -123,6 +123,7 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); - void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); - - extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; -+extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; - extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; - - #endif /* RKVDEC_H_ */ - -From a9609c4fd9f76a35c3f84e32002a26ff857940f8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 1 Aug 2020 12:24:58 +0000 -Subject: [PATCH] WIP: media: rkvdec: add HEVC format validation - ---- - drivers/staging/media/rkvdec/rkvdec-hevc.c | 11 +++++++++++ - drivers/staging/media/rkvdec/rkvdec.c | 23 +++++++++++++++++++++- - 2 files changed, 33 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c -index 03ba848411c6..b8ad7fc2271c 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-hevc.c -+++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c -@@ -2415,6 +2415,16 @@ static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, - return 0; - } - -+static u32 rkvdec_hevc_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) -+{ -+ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; -+ -+ if (sps->bit_depth_luma_minus8 == 2) -+ return V4L2_PIX_FMT_NV15; -+ else -+ return V4L2_PIX_FMT_NV12; -+} -+ - static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) - { - struct rkvdec_dev *rkvdec = ctx->dev; -@@ -2516,6 +2526,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) - - const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { - .adjust_fmt = rkvdec_hevc_adjust_fmt, -+ .valid_fmt = rkvdec_hevc_valid_fmt, - .start = rkvdec_hevc_start, - .stop = rkvdec_hevc_stop, - .run = rkvdec_hevc_run, -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 880a70c9291e..5eec0ed710b2 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -76,6 +76,26 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) - if (width > ctx->coded_fmt.fmt.pix_mp.width || - height > ctx->coded_fmt.fmt.pix_mp.height) - return -EINVAL; -+ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { -+ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; -+ -+ if (sps->chroma_format_idc > 1) -+ /* Only 4:0:0 and 4:2:0 are supported */ -+ return -EINVAL; -+ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) -+ /* Luma and chroma bit depth mismatch */ -+ return -EINVAL; -+ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) -+ /* Only 8-bit and 10-bit is supported */ -+ return -EINVAL; -+ -+ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) -+ /* Only current valid format */ -+ 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; - } -@@ -84,7 +104,7 @@ static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) - { - struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); - -- if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { -+ if (!ctx->valid_fmt) { - ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); - if (ctx->valid_fmt) { - struct v4l2_pix_format_mplane *pix_mp; -@@ -170,6 +190,7 @@ static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { - { - .mandatory = true, - .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, -+ .cfg.ops = &rkvdec_ctrl_ops, - }, - { - .mandatory = true, - -From b0827a52d53f0f561e658eb77ed446738d5e12ea Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 29 Oct 2019 01:26:02 +0000 -Subject: [PATCH] RFC: media: hantro: Fix H264 decoding of field encoded - content - -This still need code cleanup and formatting - -Signed-off-by: Jonas Karlman ---- - .../staging/media/hantro/hantro_g1_h264_dec.c | 17 +--- - drivers/staging/media/hantro/hantro_h264.c | 81 ++++++++++++++++--- - drivers/staging/media/hantro/hantro_hw.h | 2 + - 3 files changed, 74 insertions(+), 26 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -index 845bef73d218..869ee261a5db 100644 ---- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c -+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -@@ -130,25 +130,12 @@ static void set_ref(struct hantro_ctx *ctx) - struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; - const u8 *b0_reflist, *b1_reflist, *p_reflist; - struct hantro_dev *vpu = ctx->dev; -- u32 dpb_longterm = 0; -- u32 dpb_valid = 0; - int reg_num; - u32 reg; - int i; - -- /* -- * Set up bit maps of valid and long term DPBs. -- * NOTE: The bits are reversed, i.e. MSb is DPB 0. -- */ -- for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) -- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -- -- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -- } -- vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF); -- vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF); -+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); -+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); - - /* - * Set up reference frame picture numbers. -diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c -index b1bdc00ac262..bc2af450a94c 100644 ---- a/drivers/staging/media/hantro/hantro_h264.c -+++ b/drivers/staging/media/hantro/hantro_h264.c -@@ -227,17 +227,67 @@ static void prepare_table(struct hantro_ctx *ctx) - { - const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; - const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; -+ const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; - struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu; - const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -+ u32 dpb_longterm = 0; -+ u32 dpb_valid = 0; - int i; - -+ /* -+ * Set up bit maps of valid and long term DPBs. -+ * NOTE: The bits are reversed, i.e. MSb is DPB 0. -+ */ -+ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { -+ for (i = 0; i < HANTRO_H264_DPB_SIZE * 2; ++i) { -+ // check for correct reference use -+ enum v4l2_h264_field_reference parity = (i & 0x1) ? -+ V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; -+ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE && -+ dpb[i / 2].reference & parity) -+ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); -+ -+ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -+ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); -+ } -+ -+ ctx->h264_dec.dpb_valid = dpb_valid; -+ ctx->h264_dec.dpb_longterm = dpb_longterm; -+ } else { -+ for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) -+ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -+ -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -+ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -+ } -+ -+ ctx->h264_dec.dpb_valid = dpb_valid << 16; -+ ctx->h264_dec.dpb_longterm = dpb_longterm << 16; -+ } -+ - for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -- tbl->poc[i * 2] = dpb[i].top_field_order_cnt; -- tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { -+ tbl->poc[i * 2] = dpb[i].top_field_order_cnt; -+ tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; -+ } else { -+ tbl->poc[i * 2] = 0; -+ tbl->poc[i * 2 + 1] = 0; -+ } - } - -- tbl->poc[32] = dec_param->top_field_order_cnt; -- tbl->poc[33] = dec_param->bottom_field_order_cnt; -+ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || !(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { -+ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) -+ tbl->poc[32] = (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ? -+ dec_param->bottom_field_order_cnt : -+ dec_param->top_field_order_cnt; -+ else -+ tbl->poc[32] = min(dec_param->top_field_order_cnt, dec_param->bottom_field_order_cnt); -+ tbl->poc[33] = 0; -+ } else { -+ tbl->poc[32] = dec_param->top_field_order_cnt; -+ tbl->poc[33] = dec_param->bottom_field_order_cnt; -+ } - - assemble_scaling_list(ctx); - } -@@ -245,8 +295,7 @@ static void prepare_table(struct hantro_ctx *ctx) - static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, - const struct v4l2_h264_dpb_entry *b) - { -- return a->top_field_order_cnt == b->top_field_order_cnt && -- a->bottom_field_order_cnt == b->bottom_field_order_cnt; -+ return a->reference_ts == b->reference_ts; - } - - static void update_dpb(struct hantro_ctx *ctx) -@@ -260,13 +309,13 @@ static void update_dpb(struct hantro_ctx *ctx) - - /* Disable all entries by default. */ - for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) -- ctx->h264_dec.dpb[i].flags &= ~V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; -+ ctx->h264_dec.dpb[i].flags = 0; - - /* Try to match new DPB entries with existing ones by their POCs. */ - for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) { - const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i]; - -- if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) -+ if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID)) - continue; - - /* -@@ -277,8 +326,7 @@ static void update_dpb(struct hantro_ctx *ctx) - struct v4l2_h264_dpb_entry *cdpb; - - cdpb = &ctx->h264_dec.dpb[j]; -- if (cdpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE || -- !dpb_entry_match(cdpb, ndpb)) -+ if (!dpb_entry_match(cdpb, ndpb)) - continue; - - *cdpb = *ndpb; -@@ -314,7 +362,10 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - unsigned int dpb_idx) - { - struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -+ const struct v4l2_ctrl_h264_decode_params *dec_param = ctx->h264_dec.ctrls.decode; - dma_addr_t dma_addr = 0; -+ s32 cur_poc; -+ u32 flags; - - if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) - dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts); -@@ -332,7 +383,15 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - dma_addr = hantro_get_dec_buf_addr(ctx, buf); - } - -- return dma_addr; -+ cur_poc = dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD ? -+ dec_param->bottom_field_order_cnt : -+ dec_param->top_field_order_cnt; -+ flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0; -+ flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) < -+ abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ? -+ 0x1 : 0; -+ -+ return dma_addr | flags; - } - - int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 219283a06f52..7e35140a4f22 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -90,6 +90,8 @@ struct hantro_h264_dec_hw_ctx { - struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE]; - struct hantro_h264_dec_reflists reflists; - struct hantro_h264_dec_ctrls ctrls; -+ u32 dpb_longterm; -+ u32 dpb_valid; - }; - - /** - -From 9d86dd7c5559c7f2e1cf8f7bcab79720aeb09703 Mon Sep 17 00:00:00 2001 -From: Randy Li -Date: Sun, 6 Jan 2019 01:48:37 +0800 -Subject: [PATCH] soc: rockchip: power-domain: export idle request - -We need to put the power status of HEVC IP into IDLE unless -we can't reset that IP or the SoC would crash down. -rockchip_pmu_idle_request(dev, true)---> enter idle -rockchip_pmu_idle_request(dev, false)---> exit idle - -Signed-off-by: Caesar Wang -Signed-off-by: Jeffy Chen -Signed-off-by: Randy Li ---- - drivers/soc/rockchip/pm_domains.c | 23 +++++++++++++++++++++++ - include/linux/rockchip_pmu.h | 15 +++++++++++++++ - include/soc/rockchip/pm_domains.h | 18 ++++++++++++++++++ - 3 files changed, 56 insertions(+) - create mode 100644 include/linux/rockchip_pmu.h - create mode 100644 include/soc/rockchip/pm_domains.h - -diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c -index c6b33f7c43df..3688e9e67872 100644 ---- a/drivers/soc/rockchip/pm_domains.c -+++ b/drivers/soc/rockchip/pm_domains.c -@@ -197,6 +197,29 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, - return 0; - } - -+int rockchip_pmu_idle_request(struct device *dev, bool idle) -+{ -+ struct generic_pm_domain *genpd; -+ struct rockchip_pm_domain *pd; -+ int ret; -+ -+ if (IS_ERR_OR_NULL(dev)) -+ return -EINVAL; -+ -+ if (IS_ERR_OR_NULL(dev->pm_domain)) -+ return -EINVAL; -+ -+ genpd = pd_to_genpd(dev->pm_domain); -+ pd = to_rockchip_pd(genpd); -+ -+ mutex_lock(&pd->pmu->mutex); -+ ret = rockchip_pmu_set_idle_request(pd, idle); -+ mutex_unlock(&pd->pmu->mutex); -+ -+ return ret; -+} -+EXPORT_SYMBOL(rockchip_pmu_idle_request); -+ - static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) - { - int i; -diff --git a/include/linux/rockchip_pmu.h b/include/linux/rockchip_pmu.h -new file mode 100644 -index 000000000000..720b3314e71a ---- /dev/null -+++ b/include/linux/rockchip_pmu.h -@@ -0,0 +1,15 @@ -+/* -+ * pm_domain.h - Definitions and headers related to device power domains. -+ * -+ * Copyright (C) 2017 Randy Li . -+ * -+ * This file is released under the GPLv2. -+ */ -+ -+#ifndef _LINUX_ROCKCHIP_PM_H -+#define _LINUX_ROCKCHIP_PM_H -+#include -+ -+int rockchip_pmu_idle_request(struct device *dev, bool idle); -+ -+#endif /* _LINUX_ROCKCHIP_PM_H */ -diff --git a/include/soc/rockchip/pm_domains.h b/include/soc/rockchip/pm_domains.h -new file mode 100644 -index 000000000000..690db6118636 ---- /dev/null -+++ b/include/soc/rockchip/pm_domains.h -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __SOC_ROCKCHIP_PM_DOMAINS_H -+#define __SOC_ROCKCHIP_PM_DOMAINS_H -+ -+#include -+ -+struct device; -+ -+#ifdef CONFIG_ROCKCHIP_PM_DOMAINS -+int rockchip_pmu_idle_request(struct device *dev, bool idle); -+#else -+static inline int rockchip_pmu_idle_request(struct device *dev, bool idle) -+{ -+ return -ENOTSUPP; -+} -+#endif -+ -+#endif - -From e34147ff2737bf9ba728c42c7968f10574e127ca Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 20 May 2020 17:04:47 +0200 -Subject: [PATCH] media: rkvdec: implement reset controls - ---- - .../bindings/media/rockchip,vdec.yaml | 19 ++++++ - drivers/staging/media/rkvdec/rkvdec-regs.h | 5 ++ - drivers/staging/media/rkvdec/rkvdec.c | 60 +++++++++++++++++++ - drivers/staging/media/rkvdec/rkvdec.h | 11 +++- - 4 files changed, 94 insertions(+), 1 deletion(-) - -diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml -index 8d35c327018b..dfafdb671798 100644 ---- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml -+++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml -@@ -43,6 +43,18 @@ properties: - iommus: - maxItems: 1 - -+ resets: -+ maxItems: 6 -+ -+ reset-names: -+ items: -+ - const: video_h -+ - const: video_a -+ - const: video_core -+ - const: video_cabac -+ - const: niu_a -+ - const: niu_h -+ - required: - - compatible - - reg -@@ -50,6 +62,8 @@ required: - - clocks - - clock-names - - power-domains -+ - resets -+ - reset-names - - additionalProperties: false - -@@ -68,6 +82,11 @@ examples: - clock-names = "axi", "ahb", "cabac", "core"; - power-domains = <&power RK3399_PD_VDU>; - iommus = <&vdec_mmu>; -+ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, -+ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, -+ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; -+ reset-names = "video_h", "video_a", "video_core", "video_cabac", -+ "niu_a", "niu_h"; - }; - - ... -diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h -index 83bf790ed9b7..4addfaefdfb4 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-regs.h -+++ b/drivers/staging/media/rkvdec/rkvdec-regs.h -@@ -28,6 +28,11 @@ - #define RKVDEC_SOFTRST_EN_P BIT(20) - #define RKVDEC_FORCE_SOFTRESET_VALID BIT(21) - #define RKVDEC_SOFTRESET_RDY BIT(22) -+#define RKVDEC_ERR_MASK (RKVDEC_BUS_STA \ -+ | RKVDEC_ERR_STA \ -+ | RKVDEC_TIMEOUT_STA \ -+ | RKVDEC_BUF_EMPTY_STA \ -+ | RKVDEC_COLMV_REF_ERR_STA ) - - #define RKVDEC_REG_SYSCTRL 0x008 - #define RKVDEC_IN_ENDIAN BIT(0) -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 5eec0ed710b2..b736d7ad5558 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -10,12 +10,15 @@ - */ - - #include -+#include - #include - #include - #include - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -882,6 +885,11 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx, - - pm_runtime_mark_last_busy(rkvdec->dev); - pm_runtime_put_autosuspend(rkvdec->dev); -+ -+ if (result == VB2_BUF_STATE_ERROR && -+ rkvdec->reset_mask == RESET_NONE) -+ rkvdec->reset_mask |= RESET_SOFT; -+ - rkvdec_job_finish_no_pm(ctx, result); - } - -@@ -919,6 +927,40 @@ static void rkvdec_device_run(void *priv) - - if (WARN_ON(!desc)) - return; -+ if (rkvdec->reset_mask != RESET_NONE) { -+ -+ if (rkvdec->reset_mask & RESET_SOFT) { -+ writel(RKVDEC_SOFTRST_EN_P, -+ rkvdec->regs + RKVDEC_REG_INTERRUPT); -+ udelay(RKVDEC_RESET_DELAY); -+ if (readl(rkvdec->regs + RKVDEC_REG_INTERRUPT) -+ & RKVDEC_SOFTRESET_RDY) -+ dev_info_ratelimited(rkvdec->dev, -+ "softreset failed\n"); -+ else -+ dev_notice_ratelimited(rkvdec->dev, -+ "softreset done\n"); -+ } -+ -+ if (rkvdec->reset_mask & RESET_HARD) { -+ pm_runtime_suspend(rkvdec->dev); -+ rockchip_pmu_idle_request(rkvdec->dev, true); -+ ret = reset_control_assert(rkvdec->rstc); -+ if (!ret) { -+ udelay(RKVDEC_RESET_DELAY); -+ ret = reset_control_deassert(rkvdec->rstc); -+ } -+ rockchip_pmu_idle_request(rkvdec->dev, false); -+ if (ret) -+ dev_notice_ratelimited(rkvdec->dev, -+ "hardreset failed\n"); -+ else -+ dev_notice_ratelimited(rkvdec->dev, -+ "hardreset done\n"); -+ } -+ -+ rkvdec->reset_mask = RESET_NONE; -+ } - - ret = pm_runtime_get_sync(rkvdec->dev); - if (ret < 0) { -@@ -1186,6 +1228,11 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) - if (cancel_delayed_work(&rkvdec->watchdog_work)) { - struct rkvdec_ctx *ctx; - -+ if (state == VB2_BUF_STATE_ERROR) { -+ rkvdec->reset_mask |= (status & RKVDEC_ERR_MASK) ? -+ RESET_HARD : RESET_SOFT; -+ } -+ - ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); - rkvdec_job_finish(ctx, state); - } -@@ -1203,6 +1250,7 @@ static void rkvdec_watchdog_func(struct work_struct *work) - ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); - if (ctx) { - dev_err(rkvdec->dev, "Frame processing timed out!\n"); -+ rkvdec->reset_mask |= RESET_HARD; - writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, - rkvdec->regs + RKVDEC_REG_INTERRUPT); - writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); -@@ -1282,6 +1330,18 @@ static int rkvdec_probe(struct platform_device *pdev) - return ret; - } - -+ -+ rkvdec->rstc = devm_reset_control_array_get(&pdev->dev, false, true); -+ if (IS_ERR(rkvdec->rstc)) { -+ dev_err(&pdev->dev, -+ "get resets failed %ld\n", PTR_ERR(rkvdec->rstc)); -+ return PTR_ERR(rkvdec->rstc); -+ } else { -+ dev_dbg(&pdev->dev, -+ "requested %d resets\n", -+ reset_control_get_count(&pdev->dev)); -+ } -+ - pm_runtime_set_autosuspend_delay(&pdev->dev, 100); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(&pdev->dev); -diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h -index d5600c6a4c17..975fe4b5dd68 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.h -+++ b/drivers/staging/media/rkvdec/rkvdec.h -@@ -11,10 +11,11 @@ - #ifndef RKVDEC_H_ - #define RKVDEC_H_ - -+#include - #include -+#include - #include - #include --#include - - #include - #include -@@ -22,6 +23,12 @@ - #include - #include - -+#define RESET_NONE 0 -+#define RESET_SOFT BIT(0) -+#define RESET_HARD BIT(1) -+ -+#define RKVDEC_RESET_DELAY 5 -+ - struct rkvdec_ctx; - - struct rkvdec_ctrl_desc { -@@ -95,6 +102,8 @@ struct rkvdec_dev { - void __iomem *regs; - struct mutex vdev_lock; /* serializes ioctls */ - struct delayed_work watchdog_work; -+ struct reset_control *rstc; -+ u8 reset_mask; - }; - - struct rkvdec_ctx { - -From 6261fb0dde9dfddc3cfed72c8445946993314ff6 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 11:38:04 +0200 -Subject: [PATCH] WIP: arm64: dts: add resets to vdec for RK3399 - ---- - arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 3e44bf8eac5c..81b4b8714e3f 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -1284,6 +1284,11 @@ vdec: video-codec@ff660000 { - clock-names = "axi", "ahb", "cabac", "core"; - iommus = <&vdec_mmu>; - power-domains = <&power RK3399_PD_VDU>; -+ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, -+ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, -+ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; -+ reset-names = "video_h", "video_a", "video_core", "video_cabac", -+ "niu_a", "niu_h"; - }; - - vdec_mmu: iommu@ff660480 { - -From c2a32797230aece341856e09b0139cf3d259e07b Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 12:36:13 +0200 -Subject: [PATCH] media: hantro: add Rockchip RK3228 - -RK3228 has the same VPU IP-Block as RK3399 has and at the current state -the driver can be taken as is. -This adds just a new compatible string to bindings file if any future -ajustment for this SoC is necessary. ---- - Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -index c81dbc3e8960..ddbda080950e 100644 ---- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -@@ -16,6 +16,7 @@ description: - properties: - compatible: - enum: -+ - rockchip,rk3228-vpu - - rockchip,rk3288-vpu - - rockchip,rk3328-vpu - - rockchip,rk3399-vpu - -From 86ac3c31aadac54e5c4a941ae25147b8e1045676 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 12:38:24 +0200 -Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK322x - -This adds VPU node to RK3228. While at it also add the required power-domain -controller and qos node to make the VPU work on this SoC. ---- - arch/arm/boot/dts/rk322x.dtsi | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index f98a945c68d3..b233baeb20ef 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -680,6 +680,18 @@ opp-500000000 { - }; - }; - -+ vpu: video-codec@20020000 { -+ compatible = "rockchip,rk3228-vpu", "rockchip,rk3399-vpu"; -+ reg = <0x20020000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ clock-names = "aclk", "hclk"; -+ iommus = <&vpu_mmu>; -+ power-domains = <&power RK3228_PD_VPU>; -+ }; -+ - vpu_mmu: iommu@20020800 { - compatible = "rockchip,iommu"; - reg = <0x20020800 0x100>; -@@ -687,8 +699,8 @@ vpu_mmu: iommu@20020800 { - interrupt-names = "vpu_mmu"; - clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ #iommu-cells = <0>; -+ power-domains = <&power RK3228_PD_VPU>; - }; - - vdec_mmu: iommu@20030480 { - -From 2542e122786d27dfcf4bf2a60b2d91a4ae3a48dd Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 14:11:57 +0200 -Subject: [PATCH] media: hantro: add support for RK3188 - -RK3188s VPU IP-Block is the predecessor from what RK3288 has. - -While most of the registers match in the current state of the driver -there are some HW differences: - - supports resultion up to 1920x1088 only - - has one aclk and one hclk per vdpu/vepu - - doesn't have the 'G1_REG_SOFT_RESET' register - - ACLKs can be clocked up to 300 MHz only - - no MMU for VPU -These make it necessary to add another variant to the driver. - -This should be also reuseable for RK3066 but has not been tested, -so I'm not adding it here. ---- - .../bindings/media/rockchip-vpu.yaml | 7 +- - drivers/staging/media/hantro/hantro_drv.c | 1 + - drivers/staging/media/hantro/hantro_hw.h | 1 + - drivers/staging/media/hantro/rk3288_vpu_hw.c | 116 ++++++++++++++++++ - 4 files changed, 124 insertions(+), 1 deletion(-) - -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -index ddbda080950e..1f0b3685fa85 100644 ---- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -@@ -16,6 +16,7 @@ description: - properties: - compatible: - enum: -+ - rockchip,rk3188-vpu - - rockchip,rk3228-vpu - - rockchip,rk3288-vpu - - rockchip,rk3328-vpu -@@ -36,12 +37,16 @@ properties: - - const: vdpu - - clocks: -- maxItems: 2 -+ maxItems: 4 - - clock-names: - items: - - const: aclk -+ - const: aclk_vdpu -+ - const: aclk_vepu - - const: hclk -+ - const: hclk_vdpu -+ - const: hclk_vepu - - power-domains: - maxItems: 1 -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index 3cd00cc0a364..ecc0938b7f35 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -475,6 +475,7 @@ static const struct of_device_id of_hantro_match[] = { - { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, - { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, - { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, -+ { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, - #endif - #ifdef CONFIG_VIDEO_HANTRO_IMX8M - { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 7e35140a4f22..22b0ed01f673 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -152,6 +152,7 @@ enum hantro_enc_fmt { - RK3288_VPU_ENC_FMT_UYVY422 = 3, - }; - -+extern const struct hantro_variant rk3188_vpu_variant; - extern const struct hantro_variant rk3399_vpu_variant; - extern const struct hantro_variant rk3328_vpu_variant; - extern const struct hantro_variant rk3288_vpu_variant; -diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c -index 7b299ee3e93d..1ac00695a864 100644 ---- a/drivers/staging/media/hantro/rk3288_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c -@@ -13,6 +13,7 @@ - #include "hantro_g1_regs.h" - #include "hantro_h1_regs.h" - -+#define RK3188_ACLK_MAX_FREQ (300 * 1000 * 1000) - #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) - - /* -@@ -63,6 +64,52 @@ static const struct hantro_fmt rk3288_vpu_postproc_fmts[] = { - }, - }; - -+static const struct hantro_fmt rk3188_vpu_dec_fmts[] = { -+ { -+ .fourcc = V4L2_PIX_FMT_NV12, -+ .codec_mode = HANTRO_MODE_NONE, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_H264_SLICE, -+ .codec_mode = HANTRO_MODE_H264_DEC, -+ .max_depth = 2, -+ .frmsize = { -+ .min_width = 48, -+ .max_width = 1920, -+ .step_width = MB_DIM, -+ .min_height = 48, -+ .max_height = 1088, -+ .step_height = MB_DIM, -+ }, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, -+ .codec_mode = HANTRO_MODE_MPEG2_DEC, -+ .max_depth = 2, -+ .frmsize = { -+ .min_width = 48, -+ .max_width = 1920, -+ .step_width = MB_DIM, -+ .min_height = 48, -+ .max_height = 1088, -+ .step_height = MB_DIM, -+ }, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_VP8_FRAME, -+ .codec_mode = HANTRO_MODE_VP8_DEC, -+ .max_depth = 2, -+ .frmsize = { -+ .min_width = 48, -+ .max_width = 1920, -+ .step_width = MB_DIM, -+ .min_height = 48, -+ .max_height = 1088, -+ .step_height = MB_DIM, -+ }, -+ }, -+}; -+ - static const struct hantro_fmt rk3288_vpu_dec_fmts[] = { - { - .fourcc = V4L2_PIX_FMT_NV12, -@@ -145,6 +192,14 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+static int rk3188_vpu_hw_init(struct hantro_dev *vpu) -+{ -+ /* Bump ACLKs to max. possible freq. to improve performance. */ -+ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); -+ clk_set_rate(vpu->clocks[2].clk, RK3188_ACLK_MAX_FREQ); -+ return 0; -+} -+ - static int rk3288_vpu_hw_init(struct hantro_dev *vpu) - { - /* Bump ACLK to max. possible freq. to improve performance. */ -@@ -161,6 +216,15 @@ static void rk3288_vpu_enc_reset(struct hantro_ctx *ctx) - vepu_write(vpu, 0, H1_REG_AXI_CTRL); - } - -+ -+static void rk3188_vpu_dec_reset(struct hantro_ctx *ctx) -+{ -+ struct hantro_dev *vpu = ctx->dev; -+ -+ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT); -+ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); -+} -+ - static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) - { - struct hantro_dev *vpu = ctx->dev; -@@ -174,6 +238,33 @@ static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) - * Supported codec ops. - */ - -+static const struct hantro_codec_ops rk3188_vpu_codec_ops[] = { -+ [HANTRO_MODE_JPEG_ENC] = { -+ .run = hantro_h1_jpeg_enc_run, -+ .reset = rk3288_vpu_enc_reset, -+ .init = hantro_jpeg_enc_init, -+ .exit = hantro_jpeg_enc_exit, -+ }, -+ [HANTRO_MODE_H264_DEC] = { -+ .run = hantro_g1_h264_dec_run, -+ .reset = rk3188_vpu_dec_reset, -+ .init = hantro_h264_dec_init, -+ .exit = hantro_h264_dec_exit, -+ }, -+ [HANTRO_MODE_MPEG2_DEC] = { -+ .run = hantro_g1_mpeg2_dec_run, -+ .reset = rk3188_vpu_dec_reset, -+ .init = hantro_mpeg2_dec_init, -+ .exit = hantro_mpeg2_dec_exit, -+ }, -+ [HANTRO_MODE_VP8_DEC] = { -+ .run = hantro_g1_vp8_dec_run, -+ .reset = rk3188_vpu_dec_reset, -+ .init = hantro_vp8_dec_init, -+ .exit = hantro_vp8_dec_exit, -+ }, -+}; -+ - static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { - [HANTRO_MODE_JPEG_ENC] = { - .run = hantro_h1_jpeg_enc_run, -@@ -211,10 +302,35 @@ static const struct hantro_irq rk3288_irqs[] = { - { "vdpu", rk3288_vdpu_irq }, - }; - -+static const char * const rk3188_clk_names[] = { -+ "aclk_vdpu", "hclk_vdpu", -+ "aclk_vepu", "hclk_vepu", -+}; -+ - static const char * const rk3288_clk_names[] = { - "aclk", "hclk" - }; - -+const struct hantro_variant rk3188_vpu_variant = { -+ .enc_offset = 0x0, -+ .enc_fmts = rk3288_vpu_enc_fmts, -+ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), -+ .dec_offset = 0x400, -+ .dec_fmts = rk3188_vpu_dec_fmts, -+ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), -+ .postproc_fmts = rk3288_vpu_postproc_fmts, -+ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), -+ .postproc_regs = &hantro_g1_postproc_regs, -+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | -+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, -+ .codec_ops = rk3188_vpu_codec_ops, -+ .irqs = rk3288_irqs, -+ .num_irqs = ARRAY_SIZE(rk3288_irqs), -+ .init = rk3188_vpu_hw_init, -+ .clk_names = rk3188_clk_names, -+ .num_clocks = ARRAY_SIZE(rk3188_clk_names) -+}; -+ - const struct hantro_variant rk3288_vpu_variant = { - .enc_offset = 0x0, - .enc_fmts = rk3288_vpu_enc_fmts, - -From d99de1ed4674749d5c52b0acd9e22e04a08cf28b Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 14:12:35 +0200 -Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3188 - -Add VPU node to RK3188s dtsi. ---- - arch/arm/boot/dts/rk3188.dtsi | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi -index 79742ea997eb..74bb2525715c 100644 ---- a/arch/arm/boot/dts/rk3188.dtsi -+++ b/arch/arm/boot/dts/rk3188.dtsi -@@ -141,6 +141,19 @@ smp-sram@0 { - }; - }; - -+ vpu: video-codec@10104000 { -+ compatible = "rockchip,rk3188-vpu"; -+ reg = <0x10104000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VDPU>, <&cru HCLK_VDPU>, -+ <&cru ACLK_VEPU>, <&cru HCLK_VEPU>; -+ clock-names = "aclk_vdpu", "hclk_vdpu", -+ "aclk_vepu", "hclk_vepu"; -+ power-domains = <&power RK3188_PD_VIDEO>; -+ }; -+ - vop0: vop@1010c000 { - compatible = "rockchip,rk3188-vop"; - reg = <0x1010c000 0x1000>; - -From 0c4979901a6b29b3033b0c961d33cb8be9f7d46b Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 17:24:12 +0200 -Subject: [PATCH] media: hantro: add support for Rockchip RK3036 - -RK3036 shares the hantro VPU IP Block with RK3288. -HW differences are: -- supports decoding up to 1920x1088 only -- ACLK can be clocked at max. 300MHz -This makes adding another variant to the driver necessary here also. - -However RK3036 TRM does not mention that it has an encoder also. I verfied -this on my devices and it worked for JPEG encoding. Since the identification -register share the id with RK3288 and the fact that it has an interrupt for -video encoding, makes me think that the encoding IP is the same. - -This variant could also be used for RK312x, but has not been tested. ---- - drivers/staging/media/hantro/hantro_drv.c | 1 + - drivers/staging/media/hantro/hantro_hw.h | 1 + - drivers/staging/media/hantro/rk3288_vpu_hw.c | 27 ++++++++++++++++++++ - 3 files changed, 29 insertions(+) - -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index ecc0938b7f35..ee59fad9a2f3 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -476,6 +476,7 @@ static const struct of_device_id of_hantro_match[] = { - { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, - { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, - { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, -+ { .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, }, - #endif - #ifdef CONFIG_VIDEO_HANTRO_IMX8M - { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 22b0ed01f673..ede7acec5e9f 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -152,6 +152,7 @@ enum hantro_enc_fmt { - RK3288_VPU_ENC_FMT_UYVY422 = 3, - }; - -+extern const struct hantro_variant rk3036_vpu_variant; - extern const struct hantro_variant rk3188_vpu_variant; - extern const struct hantro_variant rk3399_vpu_variant; - extern const struct hantro_variant rk3328_vpu_variant; -diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c -index 1ac00695a864..b5887fdae250 100644 ---- a/drivers/staging/media/hantro/rk3288_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c -@@ -192,6 +192,13 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+static int rk3036_vpu_hw_init(struct hantro_dev *vpu) -+{ -+ /* Bump ACLK to max. possible freq. to improve performance. */ -+ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); -+ return 0; -+} -+ - static int rk3188_vpu_hw_init(struct hantro_dev *vpu) - { - /* Bump ACLKs to max. possible freq. to improve performance. */ -@@ -311,6 +318,26 @@ static const char * const rk3288_clk_names[] = { - "aclk", "hclk" - }; - -+const struct hantro_variant rk3036_vpu_variant = { -+ .enc_offset = 0x0, -+ .enc_fmts = rk3288_vpu_enc_fmts, -+ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), -+ .dec_offset = 0x400, -+ .dec_fmts = rk3188_vpu_dec_fmts, -+ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), -+ .postproc_fmts = rk3288_vpu_postproc_fmts, -+ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), -+ .postproc_regs = &hantro_g1_postproc_regs, -+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | -+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, -+ .codec_ops = rk3288_vpu_codec_ops, -+ .irqs = rk3288_irqs, -+ .num_irqs = ARRAY_SIZE(rk3288_irqs), -+ .init = rk3036_vpu_hw_init, -+ .clk_names = rk3288_clk_names, -+ .num_clocks = ARRAY_SIZE(rk3288_clk_names) -+}; -+ - const struct hantro_variant rk3188_vpu_variant = { - .enc_offset = 0x0, - .enc_fmts = rk3288_vpu_enc_fmts, - -From 3d1b0b0c9d0188fa39b42e24bf973bb051c032b1 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 17:42:55 +0200 -Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3036 - -This adds VPU node to RK3036. While at it also add the required mmu, -power-domain controller and qos node to make the VPU work on this SoC. ---- - arch/arm/boot/dts/rk3036.dtsi | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi -index a86e1dc7fb5b..ef8ceed78f73 100644 ---- a/arch/arm/boot/dts/rk3036.dtsi -+++ b/arch/arm/boot/dts/rk3036.dtsi -@@ -136,6 +136,29 @@ gpu: gpu@10090000 { - status = "disabled"; - }; - -+ vpu: video-codec@10108000 { -+ compatible = "rockchip,rk3036-vpu"; -+ reg = <0x10108000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; -+ clock-names = "aclk", "hclk"; -+ iommus = <&vpu_mmu>; -+ power-domains = <&power RK3036_PD_VPU>; -+ }; -+ -+ vpu_mmu: iommu@10108800 { -+ compatible = "rockchip,iommu"; -+ reg = <0x10108800 0x100>; -+ interrupts = ; -+ interrupt-names = "vpu_mmu"; -+ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; -+ clock-names = "aclk", "iface"; -+ power-domains = <&power RK3036_PD_VPU>; -+ #iommu-cells = <0>; -+ }; -+ - vop: vop@10118000 { - compatible = "rockchip,rk3036-vop"; - reg = <0x10118000 0x19c>; - -From 996f741a44faecc4b9485ee0b8258b3e3441474e Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 17:54:22 +0200 -Subject: [PATCH] media: hantro: adapt Kconfig help text - -Add RK3036, RK3066, RK3188 and RK322x to Kconfig help -text ---- - drivers/staging/media/hantro/Kconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig -index 5b6cf9f62b1a..ef8bd5067be8 100644 ---- a/drivers/staging/media/hantro/Kconfig -+++ b/drivers/staging/media/hantro/Kconfig -@@ -30,4 +30,5 @@ config VIDEO_HANTRO_ROCKCHIP - depends on ARCH_ROCKCHIP || COMPILE_TEST - default y - help -- Enable support for RK3288, RK3328, and RK3399 SoCs. -+ Enable support for RK3036, RK3066, RK3188, RK322x -+ RK3288, RK3328 and RK3399 SoCs. - -From 839059f221d04ef0a6c7e03bcade1e50148d06cd Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 23 May 2020 14:22:54 +0200 -Subject: [PATCH] ARM: dts: rockchip: add vdec node for RK322x - -RK322x has the same VDEC IP block as RK3399 has and the driver in its -current state can be used as is. -Other than RK3399 its SCLKs have also to set to a fixed value to make it -work correctly. Rather than doing this in the driver it is done via -"assigned-clocks" in the vdec node. ---- - arch/arm/boot/dts/rk322x.dtsi | 25 +++++++++++++++++++++++-- - 1 file changed, 23 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index b233baeb20ef..de5727e0bc94 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -703,6 +703,27 @@ vpu_mmu: iommu@20020800 { - power-domains = <&power RK3228_PD_VPU>; - }; - -+ vdec: video-codec@20030000 { -+ compatible = "rockchip,rk322x-vdec", "rockchip,rk3399-vdec"; -+ reg = <0x20030000 0x400>; -+ interrupts = ; -+ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; -+ clock-names = "axi", "ahb", "cabac", "core"; -+ assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>, -+ <&cru SCLK_VDEC_CORE>; -+ assigned-clock-rates = <500000000>, <300000000>, -+ <300000000>; -+ resets = <&cru SRST_RKVDEC_H>, <&cru SRST_RKVDEC_A>, -+ <&cru SRST_RKVDEC_CORE>, <&cru SRST_RKVDEC_CABAC>, -+ <&cru SRST_RKVDEC_NOC_A>, <&cru SRST_RKVDEC_NOC_H>; -+ reset-names = "video_h", "video_a", -+ "video_core", "video_cabac", -+ "niu_a", "niu_h"; -+ power-domains = <&power RK3228_PD_RKVDEC>; -+ iommus = <&vdec_mmu>; -+ }; -+ - vdec_mmu: iommu@20030480 { - compatible = "rockchip,iommu"; - reg = <0x20030480 0x40>, <0x200304c0 0x40>; -@@ -710,8 +731,8 @@ vdec_mmu: iommu@20030480 { - interrupt-names = "vdec_mmu"; - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3228_PD_RKVDEC>; -+ #iommu-cells = <0>; - }; - - vop: vop@20050000 { - -From 7123c3d575df39ea102be56374fbc82a02d59ff2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 19 Aug 2020 21:12:54 +0200 -Subject: [PATCH] arm64: dts: rockchip: add rkvdec node for RK3328 - -Signed-off-by: Alex Bee ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 26 +++++++++++++++++++++++- - 1 file changed, 25 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index abe7f1573825..9a7a5c1adaa8 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -327,6 +327,10 @@ pd_hevc@RK3328_PD_HEVC { - }; - pd_video@RK3328_PD_VIDEO { - reg = ; -+ clocks = <&cru ACLK_RKVDEC>, -+ <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, -+ <&cru SCLK_VDEC_CORE>; - }; - pd_vpu@RK3328_PD_VPU { - reg = ; -@@ -672,6 +676,26 @@ vpu_mmu: iommu@ff350800 { - power-domains = <&power RK3328_PD_VPU>; - }; - -+ rkvdec: video-codec@ff360000 { -+ compatible = "rockchip,rk3399-vdec"; -+ reg = <0x0 0xff360000 0x0 0x480>; -+ interrupts = ; -+ interrupt-names = "vdpu"; -+ assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; -+ assigned-clock-rates = <500000000>, <300000000>, <250000000>; -+ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; -+ clock-names = "axi", "ahb", "cabac", "core"; -+ iommus = <&rkvdec_mmu>; -+ power-domains = <&power RK3328_PD_VIDEO>; -+ resets = <&cru SRST_VDEC_H>, <&cru SRST_VDEC_A>, -+ <&cru SRST_VDEC_CORE>, <&cru SRST_VDEC_CABAC>, -+ <&cru SRST_VDEC_NIU_A>, <&cru SRST_VDEC_NIU_H>; -+ reset-names = "video_h", "video_a", -+ "video_core", "video_cabac", -+ "niu_a", "niu_h"; -+ } -+ - rkvdec_mmu: iommu@ff360480 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff360480 0x0 0x40>, <0x0 0xff3604c0 0x0 0x40>; -@@ -680,7 +704,7 @@ rkvdec_mmu: iommu@ff360480 { - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3328_PD_VIDEO>; - }; - - vop: vop@ff370000 { - -From e6885f7f00a88d6b7c7938b77874e466e48ba9d9 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 13:27:12 +0200 -Subject: [PATCH] media: hantro: adapt to match 5.11 H.264 uapi changes - -Signed-off-by: Alex Bee ---- - drivers/staging/media/hantro/hantro_h264.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c -index bc2af450a94c..7bdefcc2fc77 100644 ---- a/drivers/staging/media/hantro/hantro_h264.c -+++ b/drivers/staging/media/hantro/hantro_h264.c -@@ -241,10 +241,10 @@ static void prepare_table(struct hantro_ctx *ctx) - if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { - for (i = 0; i < HANTRO_H264_DPB_SIZE * 2; ++i) { - // check for correct reference use -- enum v4l2_h264_field_reference parity = (i & 0x1) ? -+ u8 parity = (i & 0x1) ? - V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; - if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE && -- dpb[i / 2].reference & parity) -+ dpb[i / 2].fields & parity) - dpb_valid |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); - - if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) - -From 133d19f65874d3a3c7302ea7e2c1423e4b574545 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 13:42:01 +0200 -Subject: [PATCH] media: rkvdec: adapt to match 5.11 H.264 uapi changes - -Signed-off-by: Alex Bee ---- - drivers/staging/media/rkvdec/rkvdec-h264.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index d4f27ef7addd..627cd4efabef 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -783,10 +783,10 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - } - - for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { -- enum v4l2_h264_field_reference a_parity = -+ u8 a_parity = - (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) - ? V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; -- enum v4l2_h264_field_reference b_parity = -+ u8 b_parity = - (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) - ? V4L2_H264_TOP_FIELD_REF : V4L2_H264_BOTTOM_FIELD_REF; - u32 flags = V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; -@@ -802,7 +802,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - u8 idx = reflists[j][a]; - if (idx >= ARRAY_SIZE(dec_params->dpb)) - continue; -- if ((dpb[idx].reference & a_parity) == a_parity && -+ if ((dpb[idx].fields & a_parity) == a_parity && - (dpb[idx].flags & flags) == long_term) { - set_ps_field(hw_rps, DPB_INFO(i, j), - idx | (1 << 4)); -@@ -817,7 +817,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, - u8 idx = reflists[j][b]; - if (idx >= ARRAY_SIZE(dec_params->dpb)) - continue; -- if ((dpb[idx].reference & b_parity) == b_parity && -+ if ((dpb[idx].fields & b_parity) == b_parity && - (dpb[idx].flags & flags) == long_term) { - set_ps_field(hw_rps, DPB_INFO(i, j), - idx | (1 << 4)); - -From 44db6f132cfe12d3042e521d55d01e71b3b68f92 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Thu, 23 Jul 2020 17:25:12 +0200 -Subject: [PATCH] ARM: dts: add vpu node for RK3066 - -Signed-off-by: Alex Bee ---- - arch/arm/boot/dts/rk3066a.dtsi | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi -index f71529e6949f..d9984d0f8f23 100644 ---- a/arch/arm/boot/dts/rk3066a.dtsi -+++ b/arch/arm/boot/dts/rk3066a.dtsi -@@ -194,6 +194,19 @@ smp-sram@0 { - }; - }; - -+ vpu: video-codec@10104000 { -+ compatible = "rockchip,rk3188-vpu"; -+ reg = <0x10104000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VDPU>, <&cru HCLK_VDPU>, -+ <&cru ACLK_VEPU>, <&cru HCLK_VEPU>; -+ clock-names = "aclk_vdpu", "hclk_vdpu", -+ "aclk_vepu", "hclk_vepu"; -+ power-domains = <&power RK3066_PD_VIDEO>; -+ }; -+ - vop0: vop@1010c000 { - compatible = "rockchip,rk3066-vop"; - reg = <0x1010c000 0x19c>; - -From 4b90b0c9d234efda1e91a2a4ffb8fd01882225ea Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 11 Oct 2020 17:03:12 +0200 -Subject: [PATCH] dt-bindings: media: Add Rockchip IEP binding - -* Add some meaningful message here * - -Signed-off-by: Alex Bee ---- - .../bindings/media/rockchip-iep.yaml | 88 +++++++++++++++++++ - 1 file changed, 88 insertions(+) - create mode 100644 Documentation/devicetree/bindings/media/rockchip-iep.yaml - -diff --git a/Documentation/devicetree/bindings/media/rockchip-iep.yaml b/Documentation/devicetree/bindings/media/rockchip-iep.yaml -new file mode 100644 -index 000000000000..0be78de932db ---- /dev/null -+++ b/Documentation/devicetree/bindings/media/rockchip-iep.yaml -@@ -0,0 +1,88 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/media/rockchip-iep.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Rockchip Image Enhancement Processor (IEP) -+ -+description: -+ Rockchip IEP supports various image enhancement operations for YUV and RGB domains. -+ Deinterlacing, spatial and temporal sampling noise reduction are supported by the -+ YUV block. Gamma adjustment, edge enhancement, detail enhancement are supported in -+ the RGB block. Brightness, Saturation, Contrast, Hue adjustment is supported for -+ both domains. Furthermore it supports converting RGB to YUV / YUV to RGB. -+ -+maintainers: -+ - Heiko Stuebner -+ -+properties: -+ compatible: -+ oneOf: -+ - const: rockchip,rk3228-iep -+ - items: -+ - enum: -+ - rockchip,rk3288-iep -+ - rockchip,rk3328-iep -+ - rockchip,rk3368-iep -+ - rockchip,rk3399-iep -+ - const: rockchip,rk3228-iep -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 2 -+ -+ clock-names: -+ items: -+ - const: axi -+ - const: ahb -+ -+ power-domains: -+ maxItems: 1 -+ -+ iommus: -+ maxItems: 1 -+ -+ resets: -+ maxItems: 2 -+ -+ reset-names: -+ items: -+ - const: axi -+ - const: ahb -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - clock-names -+ - resets -+ - reset-names -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ iep: iep@20070000 { -+ compatible = "rockchip,rk3228-iep"; -+ reg = <0x20070000 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_IEP_A>, -+ <&cru SRST_IEP_H>; -+ reset-names = "axi", "ahb"; -+ power-domains = <&power RK3228_PD_VIO>; -+ iommus = <&iep_mmu>; -+ }; - -From 76673c3abd13bcdb53915d9c0e909d287a13b41d Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 11 Oct 2020 21:24:10 +0200 -Subject: [PATCH] media: rockchip: Add Rockchip IEP driver - -* Add some meaningful message here * - -Signed-off-by: Alex Bee ---- - drivers/media/platform/Kconfig | 14 + - drivers/media/platform/Makefile | 1 + - drivers/media/platform/rockchip/iep/Makefile | 5 + - .../media/platform/rockchip/iep/iep-regs.h | 291 +++++ - drivers/media/platform/rockchip/iep/iep.c | 1121 +++++++++++++++++ - drivers/media/platform/rockchip/iep/iep.h | 114 ++ - 6 files changed, 1546 insertions(+) - create mode 100644 drivers/media/platform/rockchip/iep/Makefile - create mode 100644 drivers/media/platform/rockchip/iep/iep-regs.h - create mode 100644 drivers/media/platform/rockchip/iep/iep.c - create mode 100644 drivers/media/platform/rockchip/iep/iep.h - -diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 7e152bbb4fa6..eee78b20c791 100644 ---- a/drivers/media/platform/Kconfig -+++ b/drivers/media/platform/Kconfig -@@ -462,6 +462,20 @@ config VIDEO_RENESAS_VSP1 - To compile this driver as a module, choose M here: the module - will be called vsp1. - -+config VIDEO_ROCKCHIP_IEP -+ tristate "Rockchip Image Enhancement Processor" -+ depends on VIDEO_DEV && VIDEO_V4L2 -+ depends on ARCH_ROCKCHIP || COMPILE_TEST -+ select VIDEOBUF2_DMA_CONTIG -+ select V4L2_MEM2MEM_DEV -+ help -+ This is a v4l2 driver for Rockchip Image Enhancement Processor (IEP) -+ found in most Rockchip RK3xxx SoCs. -+ Rockchip IEP supports various enhancement operations for RGB and YUV -+ images. The driver currently implements YUV deinterlacing only. -+ To compile this driver as a module, choose M here: the module -+ will be called rockchip-iep -+ - config VIDEO_ROCKCHIP_RGA - tristate "Rockchip Raster 2d Graphic Acceleration Unit" - depends on VIDEO_DEV && VIDEO_V4L2 -diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 62b6cdc8c730..f99a873818d5 100644 ---- a/drivers/media/platform/Makefile -+++ b/drivers/media/platform/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o - obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o - obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ - -+obj-$(CONFIG_VIDEO_ROCKCHIP_IEP) += rockchip/iep/ - obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/ - - obj-y += omap/ -diff --git a/drivers/media/platform/rockchip/iep/Makefile b/drivers/media/platform/rockchip/iep/Makefile -new file mode 100644 -index 000000000000..5c89b3277469 ---- /dev/null -+++ b/drivers/media/platform/rockchip/iep/Makefile -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+ -+rockchip-iep-objs := iep.o -+ -+obj-$(CONFIG_VIDEO_ROCKCHIP_IEP) += rockchip-iep.o -diff --git a/drivers/media/platform/rockchip/iep/iep-regs.h b/drivers/media/platform/rockchip/iep/iep-regs.h -new file mode 100644 -index 000000000000..a68685ef3604 ---- /dev/null -+++ b/drivers/media/platform/rockchip/iep/iep-regs.h -@@ -0,0 +1,291 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Rockchip Image Enhancement Processor (IEP) driver -+ * -+ * Copyright (C) 2020 Alex Bee -+ * -+ */ -+ -+#ifndef __IEP_REGS_H__ -+#define __IEP_REGS_H__ -+ -+/* IEP Registers addresses */ -+#define IEP_CONFIG0 0x000 /* Configuration register0 */ -+#define IEP_VOP_DIRECT_PATH BIT(0) -+#define IEP_DEIN_HIGH_FREQ_SHFT 1 -+#define IEP_DEIN_HIGH_FREQ_MASK (0x7f << IEP_DEIN_HIGH_FREQ_SHFT) -+#define IEP_DEIN_MODE_SHFT 8 -+#define IEP_DEIN_MODE_MASK (7 << IEP_DEIN_MODE_SHFT) -+#define IEP_DEIN_HIGH_FREQ_EN BIT(11) -+#define IEP_DEIN_EDGE_INTPOL_EN BIT(12) -+#define IEP_YUV_DENOISE_EN BIT(13) -+#define IEP_YUV_ENHNC_EN BIT(14) -+#define IEP_DEIN_EDGE_INTPOL_SMTH_EN BIT(15) -+#define IEP_RGB_CLR_ENHNC_EN BIT(16) -+#define IEP_RGB_CNTRST_ENHNC_EN BIT(17) -+#define IEP_RGB_ENHNC_MODE_BYPASS (0 << 18) -+#define IEP_RGB_ENHNC_MODE_DNS BIT(18) -+#define IEP_RGB_ENHNC_MODE_DTL (2 << 18) -+#define IEP_RGB_ENHNC_MODE_EDG (3 << 18) -+#define IEP_RGB_ENHNC_MODE_MASK (3 << 18) -+#define IEP_RGB_CNTRST_ENHNC_DDE_FRST BIT(20) -+#define IEP_DEIN_EDGE_INTPOL_RADIUS_SHFT 21 -+#define IEP_DEIN_EDGE_INTPOL_RADIUS_MASK (3 << IEP_DEIN_EDGE_INTPOL_RADIUS_SHFT) -+#define IEP_DEIN_EDGE_INTPOL_SELECT BIT(23) -+ -+#define IEP_CONFIG1 0x004 /* Configuration register1 */ -+#define IEP_SRC_FMT_SHFT 0 -+#define IEP_SRC_FMT_MASK (3 << IEP_SRC_FMT_SHFT) -+#define IEP_SRC_RGB_SWP_SHFT 2 -+#define IEP_SRC_RGB_SWP_MASK (2 << IEP_SRC_RGB_SWP_SHFT) -+#define IEP_SRC_YUV_SWP_SHFT 4 -+#define IEP_SRC_YUV_SWP_MASK (3 << IEP_SRC_YUV_SWP_SHFT) -+#define IEP_DST_FMT_SHFT 8 -+#define IEP_DST_FMT_MASK (3 << IEP_DST_FMT_SHFT) -+#define IEP_DST_RGB_SWP_SHFT 10 -+#define IEP_DST_RGB_SWP_MASK (2 << IEP_DST_RGB_SWP_SHFT) -+#define IEP_DST_YUV_SWP_SHFT 12 -+#define IEP_DST_YUV_SWP_MASK (3 << IEP_DST_YUV_SWP_SHFT) -+#define IEP_DTH_UP_EN BIT(14) -+#define IEP_DTH_DWN_EN BIT(15) -+#define IEP_YUV2RGB_COE_BT601_1 (0 << 16) -+#define IEP_YUV2RGB_COE_BT601_F BIT(16) -+#define IEP_YUV2RGB_COE_BT709_1 (2 << 16) -+#define IEP_YUV2RGB_COE_BT709_F (3 << 16) -+#define IEP_YUV2RGB_COE_MASK (3 << 16) -+#define IEP_RGB2YUV_COE_BT601_1 (0 << 18) -+#define IEP_RGB2YUV_COE_BT601_F BIT(18) -+#define IEP_RGB2YUV_COE_BT709_1 (2 << 18) -+#define IEP_RGB2YUV_COE_BT709_F (3 << 18) -+#define IEP_RGB2YUV_COE_MASK (3 << 18) -+#define IEP_YUV2RGB_EN BIT(20) -+#define IEP_RGB2YUV_EN BIT(21) -+#define IEP_YUV2RGB_CLIP_EN BIT(22) -+#define IEP_RGB2YUV_CLIP_EN BIT(23) -+#define IEP_GLB_ALPHA_SHFT 24 -+#define IEP_GLB_ALPHA_MASK (0x7f << IEP_GLB_ALPHA_SHFT) -+ -+#define IEP_STATUS 0x008 /* Status register */ -+#define IEP_STATUS_YUV_DNS BIT(0) -+#define IEP_STATUS_SCL BIT(1) -+#define IEP_STATUS_DIL BIT(2) -+#define IEP_STATUS_DDE BIT(3) -+#define IEP_STATUS_DMA_WR_YUV BIT(4) -+#define IEP_STATUS_DMA_RE_YUV BIT(5) -+#define IEP_STATUS_DMA_WR_RGB BIT(6) -+#define IEP_STATUS_DMA_RE_RGB BIT(7) -+#define IEP_STATUS_VOP_DIRECT_PATH BIT(8) -+#define IEP_STATUS_DMA_IA_WR_YUV BIT(16) -+#define IEP_STATUS_DMA_IA_RE_YUV BIT(17) -+#define IEP_STATUS_DMA_IA_WR_RGB BIT(18) -+#define IEP_STATUS_DMA_IA_RE_RGB BIT(19) -+ -+#define IEP_INT 0x00c /* Interrupt register*/ -+#define IEP_INT_FRAME_DONE BIT(0) /* Frame process done interrupt */ -+#define IEP_INT_FRAME_DONE_EN BIT(8) /* Frame process done interrupt enable */ -+#define IEP_INT_FRAME_DONE_CLR BIT(16) /* Frame process done interrupt clear */ -+ -+#define IEP_FRM_START 0x010 /* Frame start */ -+#define IEP_SRST 0x014 /* Soft reset */ -+#define IEP_CONFIG_DONE 0x018 /* Configuration done */ -+#define IEP_FRM_CNT 0x01c /* Frame counter */ -+ -+#define IEP_VIR_IMG_WIDTH 0x020 /* Image virtual width */ -+#define IEP_IMG_SCL_FCT 0x024 /* Scaling factor */ -+#define IEP_SRC_IMG_SIZE 0x028 /* src image width/height */ -+#define IEP_DST_IMG_SIZE 0x02c /* dst image width/height */ -+#define IEP_DST_IMG_WIDTH_TILE0 0x030 /* dst image tile0 width */ -+#define IEP_DST_IMG_WIDTH_TILE1 0x034 /* dst image tile1 width */ -+#define IEP_DST_IMG_WIDTH_TILE2 0x038 /* dst image tile2 width */ -+#define IEP_DST_IMG_WIDTH_TILE3 0x03c /* dst image tile3 width */ -+ -+#define IEP_ENH_YUV_CNFG_0 0x040 /* Brightness, contrast, saturation adjustment */ -+#define IEP_YUV_BRIGHTNESS_SHFT 0 -+#define IEP_YUV_BRIGHTNESS_MASK (0x3f << IEP_YUV_BRIGHTNESS_SHFT) -+#define IEP_YUV_CONTRAST_SHFT 8 -+#define IEP_YUV_CONTRAST_MASK (0xff << IEP_YUV_CONTRAST_SHFT) -+#define IEP_YUV_SATURATION_SHFT 16 -+#define IEP_YUV_SATURATION_MASK (0x1ff << IEP_YUV_SATURATION_SHFT) -+ -+#define IEP_ENH_YUV_CNFG_1 0x044 /* Hue configuration */ -+#define IEP_YUV_COS_HUE_SHFT 0 -+#define IEP_YUV_COS_HUE_MASK (0xff << IEP_YUV_COS_HUE_SHFT) -+#define IEP_YUV_SIN_HUE_SHFT 8 -+#define IEP_YUV_SIN_HUE_MASK (0xff << IEP_YUV_SIN_HUE_SHFT) -+ -+#define IEP_ENH_YUV_CNFG_2 0x048 /* Color bar configuration */ -+#define IEP_YUV_COLOR_BAR_Y_SHFT 0 -+#define IEP_YUV_COLOR_BAR_Y_MASK (0xff << IEP_YUV_COLOR_BAR_Y_SHFT) -+#define IEP_YUV_COLOR_BAR_U_SHFT 8 -+#define IEP_YUV_COLOR_BAR_U_MASK (0xff << IEP_YUV_COLOR_BAR_U_SHFT) -+#define IEP_YUV_COLOR_BAR_V_SHFT 16 -+#define IEP_YUV_COLOR_BAR_V_MASK (0xff << IEP_YUV_COLOR_BAR_V_SHFT) -+#define IEP_YUV_VIDEO_MODE_SHFT 24 -+#define IEP_YUV_VIDEO_MODE_MASK (3 << IEP_YUV_VIDEO_MODE_SHFT) -+ -+#define IEP_ENH_RGB_CNFG 0x04c /* RGB enhancement configuration */ -+#define IEP_ENH_RGB_C_COE 0x050 /* RGB color enhancement coefficient */ -+ -+#define IEP_RAW_CONFIG0 0x058 /* Raw configuration register0 */ -+#define IEP_RAW_CONFIG1 0x05c /* Raw configuration register1 */ -+#define IEP_RAW_VIR_IMG_WIDTH 0x060 /* Raw image virtual width */ -+#define IEP_RAW_IMG_SCL_FCT 0x064 /* Raw scaling factor */ -+#define IEP_RAW_SRC_IMG_SIZE 0x068 /* Raw src image width/height */ -+#define IEP_RAW_DST_IMG_SIZE 0x06c /* Raw src image width/height */ -+#define IEP_RAW_ENH_YUV_CNFG_0 0x070 /* Raw brightness,contrast,saturation adjustment */ -+#define IEP_RAW_ENH_YUV_CNFG_1 0x074 /* Raw hue configuration */ -+#define IEP_RAW_ENH_YUV_CNFG_2 0x078 /* Raw color bar configuration */ -+#define IEP_RAW_ENH_RGB_CNFG 0x07c /* Raw RGB enhancement configuration */ -+ -+#define IEP_SRC_ADDR_Y_RGB 0x080 /* Start addr. of src image 0 (Y/RGB) */ -+#define IEP_SRC_ADDR_CBCR 0x084 /* Start addr. of src image 0 (Cb/Cr) */ -+#define IEP_SRC_ADDR_CR 0x088 /* Start addr. of src image 0 (Cr) */ -+#define IEP_SRC_ADDR_Y1 0x08c /* Start addr. of src image 1 (Y) */ -+#define IEP_SRC_ADDR_CBCR1 0x090 /* Start addr. of src image 1 (Cb/Cr) */ -+#define IEP_SRC_ADDR_CR1 0x094 /* Start addr. of src image 1 (Cr) */ -+#define IEP_SRC_ADDR_Y_ITEMP 0x098 /* Start addr. of src image(Y int part) */ -+#define IEP_SRC_ADDR_CBCR_ITEMP 0x09c /* Start addr. of src image(CBCR int part) */ -+#define IEP_SRC_ADDR_CR_ITEMP 0x0a0 /* Start addr. of src image(CR int part) */ -+#define IEP_SRC_ADDR_Y_FTEMP 0x0a4 /* Start addr. of src image(Y frac part) */ -+#define IEP_SRC_ADDR_CBCR_FTEMP 0x0a8 /* Start addr. of src image(CBCR frac part) */ -+#define IEP_SRC_ADDR_CR_FTEMP 0x0ac /* Start addr. of src image(CR frac part) */ -+ -+#define IEP_DST_ADDR_Y_RGB 0x0b0 /* Start addr. of dst image 0 (Y/RGB) */ -+#define IEP_DST_ADDR_CBCR 0x0b4 /* Start addr. of dst image 0 (Cb/Cr) */ -+#define IEP_DST_ADDR_CR 0x0b8 /* Start addr. of dst image 0 (Cr) */ -+#define IEP_DST_ADDR_Y1 0x0bc /* Start addr. of dst image 1 (Y) */ -+#define IEP_DST_ADDR_CBCR1 0x0c0 /* Start addr. of dst image 1 (Cb/Cr) */ -+#define IEP_DST_ADDR_CR1 0x0c4 /* Start addr. of dst image 1 (Cr) */ -+#define IEP_DST_ADDR_Y_ITEMP 0x0c8 /* Start addr. of dst image(Y int part) */ -+#define IEP_DST_ADDR_CBCR_ITEMP 0x0cc /* Start addr. of dst image(CBCR int part)*/ -+#define IEP_DST_ADDR_CR_ITEMP 0x0d0 /* Start addr. of dst image(CR int part) */ -+#define IEP_DST_ADDR_Y_FTEMP 0x0d4 /* Start addr. of dst image(Y frac part) */ -+#define IEP_DST_ADDR_CBCR_FTEMP 0x0d8 /* Start addr. of dst image(CBCR frac part) */ -+#define IEP_DST_ADDR_CR_FTEMP 0x0dc /* Start addr. of dst image(CR frac part)*/ -+ -+#define IEP_DEIN_MTN_TAB0 0x0e0 /* Deinterlace motion table0 */ -+#define IEP_DEIN_MTN_TAB1 0x0e4 /* Deinterlace motion table1 */ -+#define IEP_DEIN_MTN_TAB2 0x0e8 /* Deinterlace motion table2 */ -+#define IEP_DEIN_MTN_TAB3 0x0ec /* Deinterlace motion table3 */ -+#define IEP_DEIN_MTN_TAB4 0x0f0 /* Deinterlace motion table4 */ -+#define IEP_DEIN_MTN_TAB5 0x0f4 /* Deinterlace motion table5 */ -+#define IEP_DEIN_MTN_TAB6 0x0f8 /* Deinterlace motion table6 */ -+#define IEP_DEIN_MTN_TAB7 0x0fc /* Deinterlace motion table7 */ -+ -+#define IEP_ENH_CG_TAB 0x100 /* Contrast and gamma enhancement table */ -+#define IEP_ENH_DDE_COE0 0x400 /* Denoise,detail and edge enhancement coefficient */ -+#define IEP_ENH_DDE_COE1 0x500 /* Denoise,detail and edge enhancement coefficient1 */ -+ -+#define IEP_INT_MASK (IEP_INT_FRAME_DONE) -+ -+/* IEP colorformats */ -+#define IEP_COLOR_FMT_XRGB 0U -+#define IEP_COLOR_FMT_RGB565 1U -+#define IEP_COLOR_FMT_YUV422 2U -+#define IEP_COLOR_FMT_YUV420 3U -+ -+/* IEP YUV color swaps */ -+#define IEP_YUV_SWP_SP_UV 0U -+#define IEP_YUV_SWP_SP_VU 1U -+#define IEP_YUV_SWP_P 2U -+ -+/* IEP XRGB color swaps */ -+#define XRGB_SWP_XRGB 0U -+#define XRGB_SWP_XBGR 1U -+#define XRGB_SWP_BGRX 2U -+ -+/* IEP RGB565 color swaps */ -+#define RGB565_SWP_RGB 0U -+#define RGB565_SWP_BGR 1U -+ -+#define FMT_IS_YUV(fmt) (fmt == IEP_COLOR_FMT_XRGB || fmt == IEP_COLOR_FMT_RGB565 ? 0 : 1) -+ -+#define IEP_IMG_SIZE(w, h) (((w - 1) & 0x1fff) << 0 | \ -+ ((h - 1) & 0x1fff) << 16) -+ -+#define IEP_VIR_WIDTH(src_w, dst_w) (((src_w / 4) & 0x1fff) << 0 | \ -+ ((dst_w / 4) & 0x1fff) << 16) -+ -+#define IEP_Y_STRIDE(w, h) (w * h) -+#define IEP_UV_STRIDE(w, h, fac) (w * h + w * h / fac) -+ -+#define IEP_SRC_FMT_SWP_MASK(f) (FMT_IS_YUV(f) ? IEP_SRC_YUV_SWP_MASK : IEP_SRC_RGB_SWP_MASK) -+#define IEP_DST_FMT_SWP_MASK(f) (FMT_IS_YUV(f) ? IEP_DST_YUV_SWP_MASK : IEP_DST_RGB_SWP_MASK) -+ -+#define IEP_SRC_FMT(f, swp) (f << IEP_SRC_FMT_SHFT | \ -+ (swp << (FMT_IS_YUV(f) ? IEP_SRC_YUV_SWP_SHFT : IEP_SRC_RGB_SWP_SHFT))) -+#define IEP_DST_FMT(f, swp) (f << IEP_DST_FMT_SHFT | \ -+ (swp << (FMT_IS_YUV(f) ? IEP_DST_YUV_SWP_SHFT : IEP_DST_RGB_SWP_SHFT))) -+ -+/* IEP DEINTERLACE MODES */ -+#define IEP_DEIN_MODE_YUV 0U -+#define IEP_DEIN_MODE_I4O2 1U -+#define IEP_DEIN_MODE_I4O1B 2U -+#define IEP_DEIN_MODE_I4O1T 3U -+#define IEP_DEIN_MODE_I2O1B 4U -+#define IEP_DEIN_MODE_I2O1T 5U -+#define IEP_DEIN_MODE_BYPASS 6U -+ -+#define IEP_DEIN_IN_FIELDS_2 2U -+#define IEP_DEIN_IN_FIELDS_4 4U -+ -+#define IEP_DEIN_OUT_FRAMES_1 1U -+#define IEP_DEIN_OUT_FRAMES_2 2U -+ -+/* values taken from BSP driver */ -+static const u32 default_dein_motion_tbl[][2] = { -+ { IEP_DEIN_MTN_TAB0, 0x40404040 }, -+ { IEP_DEIN_MTN_TAB1, 0x3c3e3f3f }, -+ { IEP_DEIN_MTN_TAB2, 0x3336393b }, -+ { IEP_DEIN_MTN_TAB3, 0x272a2d31 }, -+ { IEP_DEIN_MTN_TAB4, 0x181c2023 }, -+ { IEP_DEIN_MTN_TAB5, 0x0c0e1215 }, -+ { IEP_DEIN_MTN_TAB6, 0x03040609 }, -+ { IEP_DEIN_MTN_TAB7, 0x00000001 }, -+ -+}; -+ -+#define IEP_DEIN_IN_IMG0_Y(bff) (bff ? IEP_SRC_ADDR_Y_RGB : IEP_SRC_ADDR_Y1) -+#define IEP_DEIN_IN_IMG0_CBCR(bff) (bff ? IEP_SRC_ADDR_CBCR : IEP_SRC_ADDR_CBCR1) -+#define IEP_DEIN_IN_IMG0_CR(bff) (bff ? IEP_SRC_ADDR_CR : IEP_SRC_ADDR_CR1) -+#define IEP_DEIN_IN_IMG1_Y(bff) (IEP_DEIN_IN_IMG0_Y(!bff)) -+#define IEP_DEIN_IN_IMG1_CBCR(bff) (IEP_DEIN_IN_IMG0_CBCR(!bff)) -+#define IEP_DEIN_IN_IMG1_CR(bff) (IEP_DEIN_IN_IMG0_CR(!bff)) -+ -+#define IEP_DEIN_OUT_IMG0_Y(bff) (bff ? IEP_DST_ADDR_Y1 : IEP_DST_ADDR_Y_RGB) -+#define IEP_DEIN_OUT_IMG0_CBCR(bff) (bff ? IEP_DST_ADDR_CBCR1 : IEP_DST_ADDR_CBCR) -+#define IEP_DEIN_OUT_IMG0_CR(bff) (bff ? IEP_DST_ADDR_CR1 : IEP_DST_ADDR_CR) -+#define IEP_DEIN_OUT_IMG1_Y(bff) (IEP_DEIN_OUT_IMG0_Y(!bff)) -+#define IEP_DEIN_OUT_IMG1_CBCR(bff) (IEP_DEIN_OUT_IMG0_CBCR(!bff)) -+#define IEP_DEIN_OUT_IMG1_CR(bff) (IEP_DEIN_OUT_IMG0_CR(!bff)) -+ -+#define IEP_DEIN_MODE(m) (m << IEP_DEIN_MODE_SHFT) -+ -+#define IEP_DEIN_IN_MODE_FIELDS(m) ((m == IEP_DEIN_MODE_I4O1T || m == IEP_DEIN_MODE_I4O1B \ -+ || m == IEP_DEIN_MODE_I4O2) \ -+ ? IEP_DEIN_IN_FIELDS_4 : IEP_DEIN_IN_FIELDS_2) -+ -+#define IEP_DEIN_OUT_MODE_FRAMES(m) (m == IEP_DEIN_MODE_I4O2 \ -+ ? IEP_DEIN_OUT_FRAMES_2 : IEP_DEIN_OUT_FRAMES_1) -+ -+#define IEP_DEIN_OUT_MODE_1FRM_TOP_FIELD(m) (m == IEP_DEIN_MODE_I4O1T || IEP_DEIN_MODE_I2O1T \ -+ ? 1 : 0) -+ -+#define IEP_DEIN_EDGE_INTPOL_RADIUS(r) (r << IEP_DEIN_EDGE_INTPOL_RADIUS_SHFT) -+ -+#define IEP_DEIN_HIGH_FREQ(f) (f << IEP_DEIN_HIGH_FREQ_SHFT) -+ -+/* YUV Enhance video modes */ -+#define VIDEO_MODE_BLACK_SCREEN 0U -+#define VIDEO_MODE_BLUE_SCREEN 1U -+#define VIDEO_MODE_COLOR_BARS 2U -+#define VIDEO_MODE_NORMAL_VIDEO 3U -+ -+#define YUV_VIDEO_MODE(m) ((m << IEP_YUV_VIDEO_MODE_SHFT) & IEP_YUV_VIDEO_MODE_MASK) -+#define YUV_BRIGHTNESS(v) ((v << IEP_YUV_BRIGHTNESS_SHFT) & IEP_YUV_BRIGHTNESS_MASK) -+#define YUV_CONTRAST(v) ((v << IEP_YUV_CONTRAST_SHFT) & IEP_YUV_CONTRAST_MASK) -+#define YUV_SATURATION(v) ((v << IEP_YUV_SATURATION_SHFT) & IEP_YUV_SATURATION_MASK) -+#define YUV_COS_HUE(v) ((v << IEP_YUV_COS_HUE_SHFT) & IEP_YUV_COS_HUE_MASK) -+#define YUV_SIN_HUE(v) ((v << IEP_YUV_SIN_HUE_SHFT) & IEP_YUV_SIN_HUE_MASK) -+ -+#endif -diff --git a/drivers/media/platform/rockchip/iep/iep.c b/drivers/media/platform/rockchip/iep/iep.c -new file mode 100644 -index 000000000000..93954e6c4c4d ---- /dev/null -+++ b/drivers/media/platform/rockchip/iep/iep.c -@@ -0,0 +1,1121 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Rockchip Image Enhancement Processor (IEP) driver -+ * -+ * Copyright (C) 2020 Alex Bee -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "iep-regs.h" -+#include "iep.h" -+ -+static struct iep_fmt formats[] = { -+ { -+ .fourcc = V4L2_PIX_FMT_NV12, -+ .color_swap = IEP_YUV_SWP_SP_UV, -+ .hw_format = IEP_COLOR_FMT_YUV420, -+ .depth = 12, -+ .uv_factor = 4, -+ }, -+ -+ { -+ .fourcc = V4L2_PIX_FMT_NV21, -+ .color_swap = IEP_YUV_SWP_SP_VU, -+ .hw_format = IEP_COLOR_FMT_YUV420, -+ .depth = 12, -+ .uv_factor = 4, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_NV16, -+ .color_swap = IEP_YUV_SWP_SP_UV, -+ .hw_format = IEP_COLOR_FMT_YUV422, -+ .depth = 16, -+ .uv_factor = 2, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_NV61, -+ .color_swap = IEP_YUV_SWP_SP_VU, -+ .hw_format = IEP_COLOR_FMT_YUV422, -+ .depth = 16, -+ .uv_factor = 2, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_YUV420, -+ .color_swap = IEP_YUV_SWP_P, -+ .hw_format = IEP_COLOR_FMT_YUV420, -+ .depth = 12, -+ .uv_factor = 4, -+ }, -+ { -+ .fourcc = V4L2_PIX_FMT_YUV422P, -+ .color_swap = IEP_YUV_SWP_P, -+ .hw_format = IEP_COLOR_FMT_YUV422, -+ .depth = 16, -+ .uv_factor = 2, -+ }, -+}; -+ -+static struct iep_fmt *iep_fmt_find(struct v4l2_pix_format *pix_fmt) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(formats); i++) { -+ if (formats[i].fourcc == pix_fmt->pixelformat) -+ return &formats[i]; -+ } -+ -+ return NULL; -+} -+ -+static bool iep_check_pix_format(u32 pixelformat) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(formats); i++) -+ if (formats[i].fourcc == pixelformat) -+ return true; -+ -+ return false; -+} -+ -+static struct vb2_v4l2_buffer *iep_m2m_next_src_buf(struct iep_ctx *ctx) -+{ -+ struct vb2_v4l2_buffer *src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); -+ -+ /* applcication has set a sequence: take it as start point */ -+ if (ctx->src_sequence == 0 && src_buf->sequence > 0) -+ ctx->src_sequence = src_buf->sequence; -+ -+ src_buf->sequence = ctx->src_sequence++; -+ -+ return src_buf; -+} -+ -+static struct vb2_v4l2_buffer *iep_m2m_next_dst_buf(struct iep_ctx *ctx) -+{ -+ struct vb2_v4l2_buffer *dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); -+ -+ /* applcication has set a sequence: take it as start point */ -+ if (ctx->dst_sequence == 0 && dst_buf->sequence > 0) -+ ctx->dst_sequence = dst_buf->sequence; -+ -+ dst_buf->sequence = ctx->dst_sequence++; -+ -+ return dst_buf; -+} -+ -+static void iep_m2m_dst_bufs_done(struct iep_ctx *ctx, enum vb2_buffer_state state) -+{ -+ if (ctx->dst0_buf) { -+ v4l2_m2m_buf_done(ctx->dst0_buf, state); -+ ctx->dst_buffs_done++; -+ ctx->dst0_buf = NULL; -+ } -+ -+ if (ctx->dst1_buf) { -+ v4l2_m2m_buf_done(ctx->dst1_buf, state); -+ ctx->dst_buffs_done++; -+ ctx->dst1_buf = NULL; -+ } -+} -+ -+static void iep_setup_formats(struct iep_ctx *ctx) -+{ -+ /* setup src dimensions */ -+ iep_write(ctx->iep, IEP_SRC_IMG_SIZE, -+ IEP_IMG_SIZE(ctx->src_fmt.pix.width, ctx->src_fmt.pix.height)); -+ -+ /* setup dst dimensions */ -+ iep_write(ctx->iep, IEP_DST_IMG_SIZE, -+ IEP_IMG_SIZE(ctx->dst_fmt.pix.width, ctx->dst_fmt.pix.height)); -+ -+ /* setup virtual width */ -+ iep_write(ctx->iep, IEP_VIR_IMG_WIDTH, -+ IEP_VIR_WIDTH(ctx->src_fmt.pix.width, ctx->dst_fmt.pix.width)); -+ -+ /* setup src format */ -+ iep_shadow_mod(ctx->iep, IEP_CONFIG1, IEP_RAW_CONFIG1, -+ IEP_SRC_FMT_MASK | IEP_SRC_FMT_SWP_MASK(ctx->src_fmt.hw_fmt->hw_format), -+ IEP_SRC_FMT(ctx->src_fmt.hw_fmt->hw_format, -+ ctx->src_fmt.hw_fmt->color_swap)); -+ /* setup dst format */ -+ iep_shadow_mod(ctx->iep, IEP_CONFIG1, IEP_RAW_CONFIG1, -+ IEP_DST_FMT_MASK | IEP_DST_FMT_SWP_MASK(ctx->dst_fmt.hw_fmt->hw_format), -+ IEP_DST_FMT(ctx->dst_fmt.hw_fmt->hw_format, -+ ctx->dst_fmt.hw_fmt->color_swap)); -+ -+ ctx->fmt_changed = false; -+} -+ -+static void iep_dein_init(struct rockchip_iep *iep) -+{ -+ unsigned int i; -+ -+ /* values taken from BSP driver */ -+ iep_shadow_mod(iep, IEP_CONFIG0, IEP_RAW_CONFIG0, -+ (IEP_DEIN_EDGE_INTPOL_SMTH_EN | -+ IEP_DEIN_EDGE_INTPOL_RADIUS_MASK | -+ IEP_DEIN_HIGH_FREQ_EN | -+ IEP_DEIN_HIGH_FREQ_MASK), -+ (IEP_DEIN_EDGE_INTPOL_SMTH_EN | -+ IEP_DEIN_EDGE_INTPOL_RADIUS(3) | -+ IEP_DEIN_HIGH_FREQ_EN | -+ IEP_DEIN_HIGH_FREQ(64))); -+ -+ for (i = 0; i < ARRAY_SIZE(default_dein_motion_tbl); i++) -+ iep_write(iep, default_dein_motion_tbl[i][0], -+ default_dein_motion_tbl[i][1]); -+} -+ -+static void iep_init(struct rockchip_iep *iep) -+{ -+ iep_write(iep, IEP_CONFIG0, -+ IEP_DEIN_MODE(IEP_DEIN_MODE_BYPASS) // | -+ //IEP_YUV_ENHNC_EN -+ ); -+ -+ /* TODO: B/S/C/H works -+ * only in 1-frame-out modes -+ iep_write(iep, IEP_ENH_YUV_CNFG_0, -+ YUV_BRIGHTNESS(0) | -+ YUV_CONTRAST(128) | -+ YUV_SATURATION(128)); -+ -+ iep_write(iep, IEP_ENH_YUV_CNFG_1, -+ YUV_COS_HUE(255) | -+ YUV_SIN_HUE(255)); -+ -+ iep_write(iep, IEP_ENH_YUV_CNFG_2, -+ YUV_VIDEO_MODE(VIDEO_MODE_NORMAL_VIDEO)); -+ -+ */ -+ -+ /* reset frame counter */ -+ iep_write(iep, IEP_FRM_CNT, 0); -+} -+ -+static void iep_device_run(void *priv) -+{ -+ struct iep_ctx *ctx = priv; -+ struct rockchip_iep *iep = ctx->iep; -+ struct vb2_v4l2_buffer *src, *dst; -+ unsigned int dein_mode; -+ dma_addr_t addr; -+ -+ if (ctx->fmt_changed) -+ iep_setup_formats(ctx); -+ -+ if (ctx->prev_src_buf) -+ dein_mode = IEP_DEIN_MODE_I4O2; -+ else -+ dein_mode = ctx->field_bff ? IEP_DEIN_MODE_I2O1B : IEP_DEIN_MODE_I2O1T; -+ -+ iep_shadow_mod(iep, IEP_CONFIG0, IEP_RAW_CONFIG0, -+ IEP_DEIN_MODE_MASK, IEP_DEIN_MODE(dein_mode)); -+ -+ /* sync RAW_xxx registers with actual used */ -+ iep_write(iep, IEP_CONFIG_DONE, 1); -+ -+ /* setup src buff(s)/addresses */ -+ src = iep_m2m_next_src_buf(ctx); -+ addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG0_Y(ctx->field_bff), addr); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG0_CBCR(ctx->field_bff), -+ addr + ctx->src_fmt.y_stride); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG0_CR(ctx->field_bff), -+ addr + ctx->src_fmt.uv_stride); -+ -+ if (IEP_DEIN_IN_MODE_FIELDS(dein_mode) == IEP_DEIN_IN_FIELDS_4) -+ addr = vb2_dma_contig_plane_dma_addr(&ctx->prev_src_buf->vb2_buf, 0); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG1_Y(ctx->field_bff), addr); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG1_CBCR(ctx->field_bff), -+ addr + ctx->src_fmt.y_stride); -+ -+ iep_write(iep, IEP_DEIN_IN_IMG1_CR(ctx->field_bff), -+ addr + ctx->src_fmt.uv_stride); -+ -+ /* setup dst buff(s)/addresses */ -+ dst = iep_m2m_next_dst_buf(ctx); -+ addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0); -+ -+ if (IEP_DEIN_OUT_MODE_FRAMES(dein_mode) == IEP_DEIN_OUT_FRAMES_2) { -+ v4l2_m2m_buf_copy_metadata(ctx->prev_src_buf, dst, true); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG0_Y(ctx->field_bff), addr); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG0_CBCR(ctx->field_bff), -+ addr + ctx->dst_fmt.y_stride); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG0_CR(ctx->field_bff), -+ addr + ctx->dst_fmt.uv_stride); -+ -+ ctx->dst0_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); -+ -+ dst = iep_m2m_next_dst_buf(ctx); -+ addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0); -+ } -+ -+ v4l2_m2m_buf_copy_metadata(src, dst, true); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG1_Y(ctx->field_bff), addr); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG1_CBCR(ctx->field_bff), -+ addr + ctx->dst_fmt.y_stride); -+ -+ iep_write(iep, IEP_DEIN_OUT_IMG1_CR(ctx->field_bff), -+ addr + ctx->dst_fmt.uv_stride); -+ -+ ctx->dst1_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); -+ -+ iep_mod(ctx->iep, IEP_INT, IEP_INT_FRAME_DONE_EN, -+ IEP_INT_FRAME_DONE_EN); -+ -+ /* start HW */ -+ iep_write(iep, IEP_FRM_START, 1); -+} -+ -+static int iep_job_ready(void *priv) -+{ -+ struct iep_ctx *ctx = priv; -+ -+ return v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2 && -+ v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1; -+} -+ -+static void iep_job_abort(void *priv) -+{ -+ struct iep_ctx *ctx = priv; -+ -+ /* Will cancel the transaction in the next interrupt handler */ -+ ctx->job_abort = true; -+} -+ -+static const struct v4l2_m2m_ops iep_m2m_ops = { -+ .device_run = iep_device_run, -+ .job_ready = iep_job_ready, -+ .job_abort = iep_job_abort, -+}; -+ -+static int iep_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, -+ unsigned int *nplanes, unsigned int sizes[], -+ struct device *alloc_devs[]) -+{ -+ struct iep_ctx *ctx = vb2_get_drv_priv(vq); -+ struct v4l2_pix_format *pix_fmt; -+ -+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) -+ pix_fmt = &ctx->src_fmt.pix; -+ else -+ pix_fmt = &ctx->dst_fmt.pix; -+ -+ if (*nplanes) { -+ if (sizes[0] < pix_fmt->sizeimage) -+ return -EINVAL; -+ } else { -+ sizes[0] = pix_fmt->sizeimage; -+ *nplanes = 1; -+ } -+ -+ return 0; -+} -+ -+static int iep_buf_prepare(struct vb2_buffer *vb) -+{ -+ struct vb2_queue *vq = vb->vb2_queue; -+ struct iep_ctx *ctx = vb2_get_drv_priv(vq); -+ struct v4l2_pix_format *pix_fmt; -+ -+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) -+ pix_fmt = &ctx->src_fmt.pix; -+ else -+ pix_fmt = &ctx->dst_fmt.pix; -+ -+ if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) -+ return -EINVAL; -+ -+ /* set bytesused for capture buffers */ -+ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) -+ vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); -+ -+ return 0; -+} -+ -+static void iep_buf_queue(struct vb2_buffer *vb) -+{ -+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); -+ struct iep_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); -+ -+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -+} -+ -+static void iep_queue_cleanup(struct vb2_queue *vq, u32 state) -+{ -+ struct iep_ctx *ctx = vb2_get_drv_priv(vq); -+ struct vb2_v4l2_buffer *vbuf; -+ -+ do { -+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) -+ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); -+ else -+ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); -+ -+ if (vbuf) -+ v4l2_m2m_buf_done(vbuf, state); -+ } while (vbuf); -+ -+ if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->prev_src_buf) -+ v4l2_m2m_buf_done(ctx->prev_src_buf, state); -+ else -+ iep_m2m_dst_bufs_done(ctx, state); -+} -+ -+static int iep_start_streaming(struct vb2_queue *vq, unsigned int count) -+{ -+ struct iep_ctx *ctx = vb2_get_drv_priv(vq); -+ struct device *dev = ctx->iep->dev; -+ int ret; -+ -+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) { -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) { -+ dev_err(dev, "Failed to enable module\n"); -+ goto err_runtime_get; -+ } -+ -+ ctx->field_order_bff = -+ ctx->src_fmt.pix.field == V4L2_FIELD_INTERLACED_BT; -+ ctx->field_bff = ctx->field_order_bff; -+ -+ ctx->src_sequence = 0; -+ ctx->dst_sequence = 0; -+ -+ ctx->prev_src_buf = NULL; -+ -+ ctx->dst0_buf = NULL; -+ ctx->dst1_buf = NULL; -+ ctx->dst_buffs_done = 0; -+ -+ ctx->job_abort = false; -+ -+ iep_init(ctx->iep); -+ //if (ctx->src_fmt.pix.field != ctx->src_fmt.pix.field) -+ iep_dein_init(ctx->iep); -+ } -+ -+ return 0; -+ -+err_runtime_get: -+ iep_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); -+ -+ return ret; -+} -+ -+static void iep_stop_streaming(struct vb2_queue *vq) -+{ -+ struct iep_ctx *ctx = vb2_get_drv_priv(vq); -+ -+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) { -+ pm_runtime_mark_last_busy(ctx->iep->dev); -+ pm_runtime_put_autosuspend(ctx->iep->dev); -+ } -+ -+ iep_queue_cleanup(vq, VB2_BUF_STATE_ERROR); -+} -+ -+static const struct vb2_ops iep_qops = { -+ .queue_setup = iep_queue_setup, -+ .buf_prepare = iep_buf_prepare, -+ .buf_queue = iep_buf_queue, -+ .start_streaming = iep_start_streaming, -+ .stop_streaming = iep_stop_streaming, -+ .wait_prepare = vb2_ops_wait_prepare, -+ .wait_finish = vb2_ops_wait_finish, -+}; -+ -+static int iep_queue_init(void *priv, struct vb2_queue *src_vq, -+ struct vb2_queue *dst_vq) -+{ -+ struct iep_ctx *ctx = priv; -+ int ret; -+ -+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ src_vq->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES | -+ DMA_ATTR_NO_KERNEL_MAPPING; -+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF; -+ src_vq->drv_priv = ctx; -+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); -+ src_vq->min_buffers_needed = 1; -+ src_vq->ops = &iep_qops; -+ src_vq->mem_ops = &vb2_dma_contig_memops; -+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; -+ src_vq->lock = &ctx->iep->mutex; -+ src_vq->dev = ctx->iep->v4l2_dev.dev; -+ -+ ret = vb2_queue_init(src_vq); -+ if (ret) -+ return ret; -+ -+ dst_vq->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES | -+ DMA_ATTR_NO_KERNEL_MAPPING; -+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; -+ dst_vq->drv_priv = ctx; -+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); -+ dst_vq->min_buffers_needed = 2; -+ dst_vq->ops = &iep_qops; -+ dst_vq->mem_ops = &vb2_dma_contig_memops; -+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; -+ dst_vq->lock = &ctx->iep->mutex; -+ dst_vq->dev = ctx->iep->v4l2_dev.dev; -+ -+ ret = vb2_queue_init(dst_vq); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static void iep_prepare_format(struct v4l2_pix_format *pix_fmt) -+{ -+ unsigned int height = pix_fmt->height; -+ unsigned int width = pix_fmt->width; -+ unsigned int sizeimage, bytesperline; -+ -+ struct iep_fmt *hw_fmt = iep_fmt_find(pix_fmt); -+ -+ if (!hw_fmt) { -+ hw_fmt = &formats[0]; -+ pix_fmt->pixelformat = hw_fmt->fourcc; -+ } -+ -+ width = ALIGN(clamp(width, IEP_MIN_WIDTH, -+ IEP_MAX_WIDTH), 16); -+ height = ALIGN(clamp(height, IEP_MIN_HEIGHT, -+ IEP_MAX_HEIGHT), 16); -+ -+ bytesperline = FMT_IS_YUV(hw_fmt->hw_format) -+ ? width : (width * hw_fmt->depth) >> 3; -+ -+ sizeimage = height * (width * hw_fmt->depth) >> 3; -+ -+ pix_fmt->width = width; -+ pix_fmt->height = height; -+ pix_fmt->bytesperline = bytesperline; -+ pix_fmt->sizeimage = sizeimage; -+} -+ -+static int iep_open(struct file *file) -+{ -+ struct rockchip_iep *iep = video_drvdata(file); -+ struct iep_ctx *ctx = NULL; -+ -+ int ret; -+ -+ if (mutex_lock_interruptible(&iep->mutex)) -+ return -ERESTARTSYS; -+ -+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -+ if (!ctx) { -+ mutex_unlock(&iep->mutex); -+ return -ENOMEM; -+ } -+ -+ /* default output format */ -+ ctx->src_fmt.pix.pixelformat = formats[0].fourcc; -+ ctx->src_fmt.pix.field = V4L2_FIELD_INTERLACED; -+ ctx->src_fmt.pix.width = IEP_DEFAULT_WIDTH; -+ ctx->src_fmt.pix.height = IEP_DEFAULT_HEIGHT; -+ iep_prepare_format(&ctx->src_fmt.pix); -+ ctx->src_fmt.hw_fmt = &formats[0]; -+ ctx->dst_fmt.y_stride = IEP_Y_STRIDE(ctx->src_fmt.pix.width, ctx->src_fmt.pix.height); -+ ctx->dst_fmt.uv_stride = IEP_UV_STRIDE(ctx->src_fmt.pix.width, ctx->src_fmt.pix.height, -+ ctx->src_fmt.hw_fmt->uv_factor); -+ -+ /* default capture format */ -+ ctx->dst_fmt.pix.pixelformat = formats[0].fourcc; -+ ctx->dst_fmt.pix.field = V4L2_FIELD_NONE; -+ ctx->dst_fmt.pix.width = IEP_DEFAULT_WIDTH; -+ ctx->dst_fmt.pix.height = IEP_DEFAULT_HEIGHT; -+ iep_prepare_format(&ctx->dst_fmt.pix); -+ ctx->dst_fmt.hw_fmt = &formats[0]; -+ ctx->dst_fmt.y_stride = IEP_Y_STRIDE(ctx->dst_fmt.pix.width, ctx->dst_fmt.pix.height); -+ ctx->dst_fmt.uv_stride = IEP_UV_STRIDE(ctx->dst_fmt.pix.width, ctx->dst_fmt.pix.height, -+ ctx->dst_fmt.hw_fmt->uv_factor); -+ /* ensure fmts are written to HW */ -+ ctx->fmt_changed = true; -+ -+ v4l2_fh_init(&ctx->fh, video_devdata(file)); -+ file->private_data = &ctx->fh; -+ ctx->iep = iep; -+ -+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(iep->m2m_dev, ctx, -+ &iep_queue_init); -+ -+ if (IS_ERR(ctx->fh.m2m_ctx)) { -+ ret = PTR_ERR(ctx->fh.m2m_ctx); -+ goto err_free; -+ } -+ -+ v4l2_fh_add(&ctx->fh); -+ -+ mutex_unlock(&iep->mutex); -+ -+ return 0; -+ -+err_free: -+ kfree(ctx); -+ mutex_unlock(&iep->mutex); -+ -+ return ret; -+} -+ -+static int iep_release(struct file *file) -+{ -+ struct rockchip_iep *iep = video_drvdata(file); -+ struct iep_ctx *ctx = container_of(file->private_data, -+ struct iep_ctx, fh); -+ -+ mutex_lock(&iep->mutex); -+ -+ v4l2_fh_del(&ctx->fh); -+ v4l2_fh_exit(&ctx->fh); -+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); -+ kfree(ctx); -+ -+ mutex_unlock(&iep->mutex); -+ return 0; -+} -+ -+static const struct v4l2_file_operations iep_fops = { -+ .owner = THIS_MODULE, -+ .open = iep_open, -+ .release = iep_release, -+ .poll = v4l2_m2m_fop_poll, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = v4l2_m2m_fop_mmap, -+}; -+ -+static int iep_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ strscpy(cap->driver, IEP_NAME, sizeof(cap->driver)); -+ strscpy(cap->card, IEP_NAME, sizeof(cap->card)); -+ snprintf(cap->bus_info, sizeof(cap->bus_info), -+ "platform:%s", IEP_NAME); -+ -+ return 0; -+} -+ -+static int iep_enum_fmt(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ struct iep_fmt *fmt; -+ -+ if (f->index < ARRAY_SIZE(formats)) { -+ fmt = &formats[f->index]; -+ f->pixelformat = fmt->fourcc; -+ -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static int iep_enum_framesizes(struct file *file, void *priv, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index != 0) -+ return -EINVAL; -+ -+ if (!iep_check_pix_format(fsize->pixel_format)) -+ return -EINVAL; -+ -+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; -+ -+ fsize->stepwise.min_width = IEP_MIN_WIDTH; -+ fsize->stepwise.max_width = IEP_MAX_WIDTH; -+ fsize->stepwise.step_width = 16; -+ -+ fsize->stepwise.min_height = IEP_MIN_HEIGHT; -+ fsize->stepwise.max_height = IEP_MAX_HEIGHT; -+ fsize->stepwise.step_height = 16; -+ -+ return 0; -+} -+ -+static inline struct iep_ctx *iep_file2ctx(struct file *file) -+{ -+ return container_of(file->private_data, struct iep_ctx, fh); -+} -+ -+static int iep_g_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct iep_ctx *ctx = iep_file2ctx(file); -+ -+ f->fmt.pix = ctx->dst_fmt.pix; -+ -+ return 0; -+} -+ -+static int iep_g_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct iep_ctx *ctx = iep_file2ctx(file); -+ -+ f->fmt.pix = ctx->src_fmt.pix; -+ -+ return 0; -+} -+ -+static int iep_try_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ f->fmt.pix.field = V4L2_FIELD_NONE; -+ iep_prepare_format(&f->fmt.pix); -+ -+ return 0; -+} -+ -+static int iep_try_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB && -+ f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT && -+ f->fmt.pix.field != V4L2_FIELD_INTERLACED) -+ f->fmt.pix.field = V4L2_FIELD_INTERLACED; -+ -+ iep_prepare_format(&f->fmt.pix); -+ -+ return 0; -+} -+ -+static int iep_s_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct iep_ctx *ctx = iep_file2ctx(file); -+ struct vb2_queue *vq; -+ -+ int ret; -+ -+ ret = iep_try_fmt_vid_out(file, priv, f); -+ if (ret) -+ return ret; -+ -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); -+ if (vb2_is_busy(vq)) -+ return -EBUSY; -+ -+ ctx->src_fmt.pix = f->fmt.pix; -+ ctx->src_fmt.hw_fmt = iep_fmt_find(&f->fmt.pix); -+ ctx->src_fmt.y_stride = IEP_Y_STRIDE(f->fmt.pix.width, f->fmt.pix.height); -+ ctx->src_fmt.uv_stride = IEP_UV_STRIDE(f->fmt.pix.width, f->fmt.pix.height, -+ ctx->src_fmt.hw_fmt->uv_factor); -+ -+ /* Propagate colorspace information to capture. */ -+ ctx->dst_fmt.pix.colorspace = f->fmt.pix.colorspace; -+ ctx->dst_fmt.pix.xfer_func = f->fmt.pix.xfer_func; -+ ctx->dst_fmt.pix.ycbcr_enc = f->fmt.pix.ycbcr_enc; -+ ctx->dst_fmt.pix.quantization = f->fmt.pix.quantization; -+ -+ /* scaling is not supported */ -+ ctx->dst_fmt.pix.width = f->fmt.pix.width; -+ ctx->dst_fmt.pix.height = f->fmt.pix.height; -+ ctx->dst_fmt.y_stride = IEP_Y_STRIDE(f->fmt.pix.width, f->fmt.pix.height); -+ ctx->dst_fmt.uv_stride = IEP_UV_STRIDE(f->fmt.pix.width, f->fmt.pix.height, -+ ctx->dst_fmt.hw_fmt->uv_factor); -+ -+ ctx->fmt_changed = true; -+ -+ return 0; -+} -+ -+static int iep_s_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct iep_ctx *ctx = iep_file2ctx(file); -+ struct vb2_queue *vq; -+ int ret; -+ -+ ret = iep_try_fmt_vid_cap(file, priv, f); -+ if (ret) -+ return ret; -+ -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); -+ if (vb2_is_busy(vq)) -+ return -EBUSY; -+ -+ /* scaling is not supported */ -+ f->fmt.pix.width = ctx->src_fmt.pix.width; -+ f->fmt.pix.height = ctx->src_fmt.pix.height; -+ -+ ctx->dst_fmt.pix = f->fmt.pix; -+ ctx->dst_fmt.hw_fmt = iep_fmt_find(&f->fmt.pix); -+ -+ ctx->dst_fmt.y_stride = IEP_Y_STRIDE(f->fmt.pix.width, f->fmt.pix.height); -+ ctx->dst_fmt.uv_stride = IEP_UV_STRIDE(f->fmt.pix.width, f->fmt.pix.height, -+ ctx->dst_fmt.hw_fmt->uv_factor); -+ -+ ctx->fmt_changed = true; -+ -+ return 0; -+} -+ -+static const struct v4l2_ioctl_ops iep_ioctl_ops = { -+ .vidioc_querycap = iep_querycap, -+ -+ .vidioc_enum_framesizes = iep_enum_framesizes, -+ -+ .vidioc_enum_fmt_vid_cap = iep_enum_fmt, -+ .vidioc_g_fmt_vid_cap = iep_g_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = iep_try_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = iep_s_fmt_vid_cap, -+ -+ .vidioc_enum_fmt_vid_out = iep_enum_fmt, -+ .vidioc_g_fmt_vid_out = iep_g_fmt_vid_out, -+ .vidioc_try_fmt_vid_out = iep_try_fmt_vid_out, -+ .vidioc_s_fmt_vid_out = iep_s_fmt_vid_out, -+ -+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, -+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, -+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, -+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, -+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, -+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, -+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, -+ -+ .vidioc_streamon = v4l2_m2m_ioctl_streamon, -+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, -+}; -+ -+static const struct video_device iep_video_device = { -+ .name = IEP_NAME, -+ .vfl_dir = VFL_DIR_M2M, -+ .fops = &iep_fops, -+ .ioctl_ops = &iep_ioctl_ops, -+ .minor = -1, -+ .release = video_device_release_empty, -+ .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, -+}; -+ -+static int iep_parse_dt(struct rockchip_iep *iep) -+{ -+ int ret = 0; -+ -+ iep->resets = devm_reset_control_array_get(iep->dev, false, true); -+ if (IS_ERR(iep->resets)) { -+ dev_err(iep->dev, "getting resets failed %ld\n", PTR_ERR(iep->resets)); -+ return PTR_ERR(iep->resets); -+ } -+ -+ iep->axi_clk = devm_clk_get(iep->dev, "axi"); -+ if (IS_ERR(iep->axi_clk)) { -+ dev_err(iep->dev, "failed to get aclk clock\n"); -+ return PTR_ERR(iep->axi_clk); -+ } -+ -+ iep->ahb_clk = devm_clk_get(iep->dev, "ahb"); -+ if (IS_ERR(iep->ahb_clk)) { -+ dev_err(iep->dev, "failed to get hclk clock\n"); -+ return PTR_ERR(iep->ahb_clk); -+ } -+ -+ ret = clk_set_rate(iep->axi_clk, 300000000); -+ -+ if (ret) -+ dev_err(iep->dev, "failed to set axi clock rate to 300 MHz\n"); -+ -+ return ret; -+} -+ -+static irqreturn_t iep_isr(int irq, void *prv) -+{ -+ struct rockchip_iep *iep = prv; -+ struct iep_ctx *ctx; -+ u32 val; -+ enum vb2_buffer_state state = VB2_BUF_STATE_DONE; -+ -+ ctx = v4l2_m2m_get_curr_priv(iep->m2m_dev); -+ if (!ctx) { -+ v4l2_err(&iep->v4l2_dev, -+ "Instance released before the end of transaction\n"); -+ return IRQ_NONE; -+ } -+ -+ /* -+ * The irq is shared with the iommu. If the runtime-pm state of the -+ * iep-device is disabled or the interrupt status doesn't match the -+ * expeceted mask the irq has been targeted to the iommu. -+ */ -+ -+ if (!pm_runtime_active(iep->dev) || -+ !(iep_read(iep, IEP_INT) & IEP_INT_MASK)) -+ return IRQ_NONE; -+ -+ /* disable interrupt - will be re-enabled at next iep_device_run */ -+ iep_mod(ctx->iep, IEP_INT, -+ IEP_INT_FRAME_DONE_EN, 0); -+ -+ iep_mod(iep, IEP_INT, IEP_INT_FRAME_DONE_CLR, -+ IEP_INT_FRAME_DONE_CLR); -+ -+ /* wait for all status regs to show "idle" */ -+ val = readl_poll_timeout(iep->regs + IEP_STATUS, val, -+ (val == 0), 100, IEP_TIMEOUT); -+ -+ if (val) { -+ dev_err(iep->dev, -+ "Failed to wait for job to finish: status: %u\n", val); -+ state = VB2_BUF_STATE_ERROR; -+ ctx->job_abort = true; -+ } -+ -+ iep_m2m_dst_bufs_done(ctx, state); -+ -+ ctx->field_bff = (ctx->dst_buffs_done % 2 == 0) -+ ? ctx->field_order_bff : !ctx->field_order_bff; -+ -+ if (ctx->dst_buffs_done == 2 || ctx->job_abort) { -+ if (ctx->prev_src_buf) -+ v4l2_m2m_buf_done(ctx->prev_src_buf, state); -+ -+ /* current src buff will be next prev */ -+ ctx->prev_src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); -+ -+ v4l2_m2m_job_finish(ctx->iep->m2m_dev, ctx->fh.m2m_ctx); -+ ctx->dst_buffs_done = 0; -+ -+ } else { -+ iep_device_run(ctx); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int iep_probe(struct platform_device *pdev) -+{ -+ struct rockchip_iep *iep; -+ struct video_device *vfd; -+ struct resource *res; -+ int ret = 0; -+ int irq; -+ -+ if (!pdev->dev.of_node) -+ return -ENODEV; -+ -+ iep = devm_kzalloc(&pdev->dev, sizeof(*iep), GFP_KERNEL); -+ if (!iep) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, iep); -+ iep->dev = &pdev->dev; -+ iep->vfd = iep_video_device; -+ -+ ret = iep_parse_dt(iep); -+ if (ret) -+ dev_err(&pdev->dev, "Unable to parse OF data\n"); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ iep->regs = devm_ioremap_resource(iep->dev, res); -+ if (IS_ERR(iep->regs)) { -+ ret = PTR_ERR(iep->regs); -+ goto err_put_clk; -+ } -+ -+ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not set DMA coherent mask.\n"); -+ goto err_put_clk; -+ } -+ -+ vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ ret = irq; -+ goto err_put_clk; -+ } -+ -+ /* IRQ is shared with IOMMU */ -+ ret = devm_request_irq(iep->dev, irq, iep_isr, IRQF_SHARED, -+ dev_name(iep->dev), iep); -+ if (ret < 0) { -+ dev_err(iep->dev, "failed to request irq\n"); -+ goto err_put_clk; -+ } -+ -+ mutex_init(&iep->mutex); -+ -+ ret = v4l2_device_register(&pdev->dev, &iep->v4l2_dev); -+ if (ret) { -+ dev_err(iep->dev, "Failed to register V4L2 device\n"); -+ -+ return ret; -+ } -+ -+ vfd = &iep->vfd; -+ vfd->lock = &iep->mutex; -+ vfd->v4l2_dev = &iep->v4l2_dev; -+ -+ snprintf(vfd->name, sizeof(vfd->name), "%s", -+ iep_video_device.name); -+ -+ video_set_drvdata(vfd, iep); -+ -+ ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); -+ if (ret) { -+ v4l2_err(&iep->v4l2_dev, "Failed to register video device\n"); -+ -+ goto err_v4l2; -+ } -+ -+ v4l2_info(&iep->v4l2_dev, -+ "Device %s registered as /dev/video%d\n", vfd->name, vfd->num); -+ -+ iep->m2m_dev = v4l2_m2m_init(&iep_m2m_ops); -+ if (IS_ERR(iep->m2m_dev)) { -+ v4l2_err(&iep->v4l2_dev, -+ "Failed to initialize V4L2 M2M device\n"); -+ ret = PTR_ERR(iep->m2m_dev); -+ -+ goto err_video; -+ } -+ -+ /* -+ * needs to be done here, doing it any later, i.e. after -+ * the clocks are enabled, will make the device no more -+ * working (HW bug?) -+ */ -+ reset_control_assert(iep->resets); -+ udelay(1); -+ reset_control_deassert(iep->resets); -+ udelay(1); -+ -+ pm_runtime_set_autosuspend_delay(iep->dev, 100); -+ pm_runtime_use_autosuspend(iep->dev); -+ pm_runtime_enable(iep->dev); -+ -+ return ret; -+ -+err_video: -+ video_unregister_device(&iep->vfd); -+err_v4l2: -+ v4l2_device_unregister(&iep->v4l2_dev); -+err_put_clk: -+ pm_runtime_dont_use_autosuspend(iep->dev); -+ pm_runtime_disable(iep->dev); -+ -+return ret; -+} -+ -+static int iep_remove(struct platform_device *pdev) -+{ -+ struct rockchip_iep *iep = platform_get_drvdata(pdev); -+ -+ pm_runtime_dont_use_autosuspend(iep->dev); -+ pm_runtime_disable(iep->dev); -+ -+ v4l2_m2m_release(iep->m2m_dev); -+ video_unregister_device(&iep->vfd); -+ v4l2_device_unregister(&iep->v4l2_dev); -+ -+ return 0; -+} -+ -+static int __maybe_unused iep_runtime_suspend(struct device *dev) -+{ -+ struct rockchip_iep *iep = dev_get_drvdata(dev); -+ -+ dev_info(iep->dev, "%s\n", __func__); -+ -+ clk_disable_unprepare(iep->ahb_clk); -+ clk_disable_unprepare(iep->axi_clk); -+ -+ return 0; -+} -+ -+static int __maybe_unused iep_runtime_resume(struct device *dev) -+{ -+ struct rockchip_iep *iep; -+ int ret = 0; -+ -+ iep = dev_get_drvdata(dev); -+ -+ dev_info(iep->dev, "%s\n", __func__); -+ -+ ret = clk_prepare_enable(iep->axi_clk); -+ if (ret) { -+ dev_err(iep->dev, "Cannot enable axi clock: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(iep->ahb_clk); -+ if (ret) { -+ dev_err(iep->dev, "Cannot enable ahb clock: %d\n", ret); -+ goto err_disable_axi_clk; -+ } -+ -+ return ret; -+ -+err_disable_axi_clk: -+ clk_disable_unprepare(iep->axi_clk); -+ return ret; -+} -+ -+static const struct dev_pm_ops iep_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -+ pm_runtime_force_resume) -+ SET_RUNTIME_PM_OPS(iep_runtime_suspend, -+ iep_runtime_resume, NULL) -+}; -+ -+static const struct of_device_id rockchip_iep_match[] = { -+ { -+ .compatible = "rockchip,rk3228-iep", -+ }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, rockchip_iep_match); -+ -+static struct platform_driver iep_pdrv = { -+ .probe = iep_probe, -+ .remove = iep_remove, -+ .driver = { -+ .name = IEP_NAME, -+ .pm = &iep_pm_ops, -+ .of_match_table = rockchip_iep_match, -+ }, -+}; -+ -+module_platform_driver(iep_pdrv); -+ -+MODULE_AUTHOR("Alex Bee "); -+MODULE_DESCRIPTION("Rockchip Image Enhancement Processor"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/media/platform/rockchip/iep/iep.h b/drivers/media/platform/rockchip/iep/iep.h -new file mode 100644 -index 000000000000..6f525f23627b ---- /dev/null -+++ b/drivers/media/platform/rockchip/iep/iep.h -@@ -0,0 +1,114 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Rockchip Image Enhancement Processor (IEP) driver -+ * -+ * Copyright (C) 2020 Alex Bee -+ * -+ */ -+#ifndef __IEP_H__ -+#define __IEP_H__ -+ -+#include -+#include -+#include -+#include -+ -+#define IEP_NAME "rockchip-iep" -+ -+/* Hardware limits */ -+#define IEP_MIN_WIDTH 320U -+#define IEP_MAX_WIDTH 1920U -+ -+#define IEP_MIN_HEIGHT 240U -+#define IEP_MAX_HEIGHT 1088U -+ -+/* Hardware defaults */ -+#define IEP_DEFAULT_WIDTH 320U -+#define IEP_DEFAULT_HEIGHT 240U -+ -+//ns -+#define IEP_TIMEOUT 250000 -+ -+struct iep_fmt { -+ u32 fourcc; -+ u8 depth; -+ u8 uv_factor; -+ u8 color_swap; -+ u8 hw_format; -+}; -+ -+struct iep_frm_fmt { -+ struct iep_fmt *hw_fmt; -+ struct v4l2_pix_format pix; -+ -+ unsigned int y_stride; -+ unsigned int uv_stride; -+}; -+ -+struct iep_ctx { -+ struct v4l2_fh fh; -+ struct rockchip_iep *iep; -+ -+ struct iep_frm_fmt src_fmt; -+ struct iep_frm_fmt dst_fmt; -+ -+ struct vb2_v4l2_buffer *prev_src_buf; -+ struct vb2_v4l2_buffer *dst0_buf; -+ struct vb2_v4l2_buffer *dst1_buf; -+ -+ u32 dst_sequence; -+ u32 src_sequence; -+ -+ /* bff = bottom field first */ -+ bool field_order_bff; -+ bool field_bff; -+ -+ unsigned int dst_buffs_done; -+ -+ bool fmt_changed; -+ bool job_abort; -+}; -+ -+struct rockchip_iep { -+ struct v4l2_device v4l2_dev; -+ struct v4l2_m2m_dev *m2m_dev; -+ struct video_device vfd; -+ -+ struct device *dev; -+ -+ void __iomem *regs; -+ -+ struct clk *axi_clk; -+ struct clk *ahb_clk; -+ -+ struct reset_control *resets; -+ -+ /* vfd lock */ -+ struct mutex mutex; -+}; -+ -+static inline void iep_write(struct rockchip_iep *iep, u32 reg, u32 value) -+{ -+ writel(value, iep->regs + reg); -+}; -+ -+static inline u32 iep_read(struct rockchip_iep *iep, u32 reg) -+{ -+ return readl(iep->regs + reg); -+}; -+ -+static inline void iep_shadow_mod(struct rockchip_iep *iep, u32 reg, -+ u32 shadow_reg, u32 mask, u32 val) -+{ -+ u32 temp = iep_read(iep, shadow_reg) & ~(mask); -+ -+ temp |= val & mask; -+ iep_write(iep, reg, temp); -+}; -+ -+static inline void iep_mod(struct rockchip_iep *iep, u32 reg, u32 mask, u32 val) -+{ -+ iep_shadow_mod(iep, reg, reg, mask, val); -+}; -+ -+#endif - -From e9d4e43dc5a6fbcdff3be92e4ec40c7bb787a897 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 11 Oct 2020 14:48:44 +0200 -Subject: [PATCH] ARM: dts: rockchip: Add IEP node for RK322x - -Signed-off-by: Alex Bee ---- - arch/arm/boot/dts/rk322x.dtsi | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index de5727e0bc94..a2012a44421d 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -781,6 +781,21 @@ rga: rga@20060000 { - power-domains = <&power RK3228_PD_VIO>; - }; - -+ iep: iep@20070000 { -+ compatible = "rockchip,rk3228-iep"; -+ reg = <0x20070000 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_IEP_A>, -+ <&cru SRST_IEP_H>; -+ reset-names = "axi", "ahb"; -+ power-domains = <&power RK3228_PD_VIO>; -+ iommus = <&iep_mmu>; -+ }; -+ - iep_mmu: iommu@20070800 { - compatible = "rockchip,iommu"; - reg = <0x20070800 0x100>; -@@ -788,8 +803,8 @@ iep_mmu: iommu@20070800 { - interrupt-names = "iep_mmu"; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ #iommu-cells = <0>; -+ power-domains = <&power RK3228_PD_VIO>; - }; - - hdmi: hdmi@200a0000 { - -From e01ddeae4d23380545603195f72054a604ef45f4 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 20:22:38 +0200 -Subject: [PATCH] ARM64: dts: rockchip: Add IEP node for RK3328 - -while at that also add the iep mmu and powerdomain nodes - -Signed-off-by: Alex Bee ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 38 ++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 9a7a5c1adaa8..9fce8036df9b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -336,6 +336,12 @@ pd_vpu@RK3328_PD_VPU { - reg = ; - clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; - }; -+ pd_vio@RK3328_PD_VIO { -+ reg = ; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ pm_qos = <&qos_vio>; -+ }; - }; - - reboot-mode { -@@ -740,6 +746,33 @@ vop_mmu: iommu@ff373f00 { - status = "disabled"; - }; - -+ iep: iep@ff3a0000 { -+ compatible = "rockchip,rk3328-iep", "rockchip,rk3228-iep"; -+ reg = <0x0 0xff3a0000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_IEP_A>, -+ <&cru SRST_IEP_H>; -+ reset-names = "axi", "ahb"; -+ power-domains = <&power RK3328_PD_VIO>; -+ iommus = <&iep_mmu>; -+ }; -+ -+ iep_mmu: iommu@ff3a0800 { -+ compatible = "rockchip,iommu"; -+ reg = <0x0 0xff3a0800 0x0 0x40>; -+ interrupts = ; -+ interrupt-names = "iep_mmu"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "aclk", "iface"; -+ power-domains = <&power RK3328_PD_VIO>; -+ #iommu-cells = <0>; -+ }; -+ - hdmi: hdmi@ff3c0000 { - compatible = "rockchip,rk3328-dw-hdmi"; - reg = <0x0 0xff3c0000 0x0 0x20000>; -@@ -1046,6 +1079,11 @@ sdmmc_ext: dwmmc@ff5f0000 { - status = "disabled"; - }; - -+ qos_vio: qos@ff760080 { -+ compatible = "syscon"; -+ reg = <0x0 0xff760080 0x0 0x20>; -+ }; -+ - gic: interrupt-controller@ff811000 { - compatible = "arm,gic-400"; - #interrupt-cells = <3>; - -From d2753e5742ac64bd8969b69ad74b1eb95f61e885 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 20:43:12 +0200 -Subject: [PATCH] ARM64: dts: rockchip: Add IEP node for RK3399 - -Signed-off-by: Alex Bee ---- - arch/arm64/boot/dts/rockchip/rk3399.dtsi | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 81b4b8714e3f..910cc877e23f 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -1302,6 +1302,21 @@ vdec_mmu: iommu@ff660480 { - #iommu-cells = <0>; - }; - -+ iep: iep@ff670000 { -+ compatible = "rockchip,rk3399-iep", "rockchip,rk3228-iep"; -+ reg = <0x0 0xff670000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_A_IEP>, -+ <&cru SRST_H_IEP>; -+ reset-names = "axi", "ahb"; -+ power-domains = <&power RK3399_PD_IEP>; -+ iommus = <&iep_mmu>; -+ }; -+ - iep_mmu: iommu@ff670800 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff670800 0x0 0x40>; -@@ -1309,8 +1324,8 @@ iep_mmu: iommu@ff670800 { - interrupt-names = "iep_mmu"; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; -+ power-domains = <&power RK3399_PD_IEP>; - #iommu-cells = <0>; -- status = "disabled"; - }; - - rga: rga@ff680000 { - -From ce22eb2d667873d807131360f33980e5c7459f00 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 20:51:04 +0200 -Subject: [PATCH] ARM64: dts: rockchip: Add IEP node for RK3368 - -Signed-off-by: Alex Bee ---- - arch/arm64/boot/dts/rockchip/rk3368.dtsi | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi -index 3746f23dc3df..9403135881e8 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi -@@ -714,6 +714,20 @@ i2s_8ch: i2s-8ch@ff898000 { - status = "disabled"; - }; - -+ iep: iep@ff900000 { -+ compatible = "rockchip,rk3368-iep", "rockchip,rk3228-iep"; -+ reg = <0x0 0xff900000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_IEP_AXI>, -+ <&cru SRST_IEP_AHB>; -+ reset-names = "axi", "ahb"; -+ iommus = <&iep_mmu>; -+ }; -+ - iep_mmu: iommu@ff900800 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff900800 0x0 0x100>; -@@ -722,7 +736,6 @@ iep_mmu: iommu@ff900800 { - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; -- status = "disabled"; - }; - - isp_mmu: iommu@ff914000 { - -From 8a9cf089ef1310522371ada40d1aa6ff6ba41da5 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 14 Oct 2020 20:53:56 +0200 -Subject: [PATCH] ARM: dts: rockchip: Add IEP node for RK3288 - -Signed-off-by: Alex Bee ---- - arch/arm/boot/dts/rk3288.dtsi | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index 9757976d6e8a..d7aa05d7dee7 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -1002,6 +1002,21 @@ crypto: cypto-controller@ff8a0000 { - status = "okay"; - }; - -+ iep: iep@ff90000 { -+ compatible = "rockchip,rk3288-iep", "rockchip,rk3228-iep"; -+ reg = <0x0 0xff900000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "iep"; -+ clocks = <&cru ACLK_IEP>, -+ <&cru HCLK_IEP>; -+ clock-names = "axi", "ahb"; -+ resets = <&cru SRST_IEP_AXI>, -+ <&cru SRST_IEP_AHB>; -+ reset-names = "axi", "ahb"; -+ power-domains = <&power RK3288_PD_VIO>; -+ iommus = <&iep_mmu>; -+ }; -+ - iep_mmu: iommu@ff900800 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff900800 0x0 0x40>; -@@ -1009,8 +1024,8 @@ iep_mmu: iommu@ff900800 { - interrupt-names = "iep_mmu"; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; -+ power-domains = <&power RK3288_PD_VIO>; - #iommu-cells = <0>; -- status = "disabled"; - }; - - isp_mmu: iommu@ff914000 { diff --git a/patch/kernel/archive/rk322x-5.12/01-linux-1001-drm-wip.patch b/patch/kernel/archive/rk322x-5.12/01-linux-1001-drm-wip.patch deleted file mode 100644 index 957f36ad6..000000000 --- a/patch/kernel/archive/rk322x-5.12/01-linux-1001-drm-wip.patch +++ /dev/null @@ -1,4704 +0,0 @@ -From 0af28d066edbb4297d5140ff4c93db7b0bc0b182 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 3 May 2020 16:51:31 +0000 -Subject: [PATCH] drm/rockchip: vop: filter modes outside 0.5% pixel clock - tolerance - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +++++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index c80f7d9fd13f..6cbdb4672a4b 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1142,6 +1142,38 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) - spin_unlock_irqrestore(&vop->irq_lock, flags); - } - -+/* -+ * The VESA DMT standard specifies a 0.5% pixel clock frequency tolerance. -+ * The CVT spec reuses that tolerance in its examples. -+ */ -+#define CLOCK_TOLERANCE_PER_MILLE 5 -+ -+static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode) -+{ -+ struct vop *vop = to_vop(crtc); -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); -+ long rounded_rate; -+ long lowest, highest; -+ -+ if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) -+ return MODE_OK; -+ -+ rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); -+ if (rounded_rate < 0) -+ return MODE_NOCLOCK; -+ -+ lowest = mode->clock * (1000 - CLOCK_TOLERANCE_PER_MILLE); -+ if (rounded_rate < lowest) -+ return MODE_CLOCK_LOW; -+ -+ highest = mode->clock * (1000 + CLOCK_TOLERANCE_PER_MILLE); -+ if (rounded_rate > highest) -+ return MODE_CLOCK_HIGH; -+ -+ return MODE_OK; -+} -+ - static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -@@ -1512,6 +1544,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, - } - - static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { -+ .mode_valid = vop_crtc_mode_valid, - .mode_fixup = vop_crtc_mode_fixup, - .atomic_check = vop_crtc_atomic_check, - .atomic_begin = vop_crtc_atomic_begin, - -From 35e601dd9730b541bde93ec5cd5320b2c14a84fa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 11:46:16 +0000 -Subject: [PATCH] WIP: drm/rockchip: vop: max_output - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 ++++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 +++++++ - 3 files changed, 18 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 6cbdb4672a4b..106b38ea12df 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1152,6 +1152,7 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) - { - struct vop *vop = to_vop(crtc); -+ const struct vop_rect *max_output = &vop->data->max_output; - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); - long rounded_rate; - long lowest, highest; -@@ -1171,6 +1172,10 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - if (rounded_rate > highest) - return MODE_CLOCK_HIGH; - -+ if (max_output->width && max_output->height) -+ return drm_mode_validate_size(mode, max_output->width, -+ max_output->height); -+ - return MODE_OK; - } - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 4a2099cb582e..1516231bbf93 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -185,6 +185,11 @@ struct vop_win_data { - enum drm_plane_type type; - }; - -+struct vop_rect { -+ int width; -+ int height; -+}; -+ - struct vop_data { - uint32_t version; - const struct vop_intr *intr; -@@ -197,6 +202,7 @@ struct vop_data { - const struct vop_win_data *win; - unsigned int win_size; - unsigned int lut_size; -+ struct vop_rect max_output; - - #define VOP_FEATURE_OUTPUT_RGB10 BIT(0) - #define VOP_FEATURE_INTERNAL_RGB BIT(1) -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 80053d91a301..57c36e9207c1 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -682,6 +682,7 @@ static const struct vop_intr rk3288_vop_intr = { - static const struct vop_data rk3288_vop = { - .version = VOP_VERSION(3, 1), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 3840, 2160 }, - .intr = &rk3288_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -782,6 +783,7 @@ static const struct vop_misc rk3368_misc = { - - static const struct vop_data rk3368_vop = { - .version = VOP_VERSION(3, 2), -+ .max_output = { 4096, 2160 }, - .intr = &rk3368_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -803,6 +805,7 @@ static const struct vop_intr rk3366_vop_intr = { - - static const struct vop_data rk3366_vop = { - .version = VOP_VERSION(3, 4), -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -909,6 +912,7 @@ static const struct vop_afbc rk3399_vop_afbc = { - static const struct vop_data rk3399_vop_big = { - .version = VOP_VERSION(3, 5), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -935,6 +939,7 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { - - static const struct vop_data rk3399_vop_lit = { - .version = VOP_VERSION(3, 6), -+ .max_output = { 2560, 1600 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -955,6 +960,7 @@ static const struct vop_win_data rk3228_vop_win_data[] = { - static const struct vop_data rk3228_vop = { - .version = VOP_VERSION(3, 7), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3366_vop_intr, - .common = &rk3288_common, - .modeset = &rk3288_modeset, -@@ -1026,6 +1032,7 @@ static const struct vop_win_data rk3328_vop_win_data[] = { - static const struct vop_data rk3328_vop = { - .version = VOP_VERSION(3, 8), - .feature = VOP_FEATURE_OUTPUT_RGB10, -+ .max_output = { 4096, 2160 }, - .intr = &rk3328_vop_intr, - .common = &rk3328_common, - .modeset = &rk3328_modeset, - -From 61b85ebc7d075446c5f8a57607eb1fc87b16e2a8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:49 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: allow high tmds bit rates - -Prepare support for High TMDS Bit Rates used by HDMI2.0 display modes. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 23de359a1dec..cdf953850873 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -317,6 +317,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, - { - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - -+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); -+ - return phy_power_on(hdmi->phy); - } - - -From a1675f5032286c3f2e939a7392361fc15099c0b7 Mon Sep 17 00:00:00 2001 -From: Yakir Yang -Date: Mon, 11 Jul 2016 19:05:39 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI - -Dut to the high HDMI signal voltage driver, Mickey have meet -a serious RF/EMI problem, so we decided to reduce HDMI signal -voltage to a proper value. - -The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed) - ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43 - tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35 - -1. We decided to reduce voltage value to lower, but VSwing still -keep high, RF/EMI have been improved but still failed. - ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 - tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 - -2. We try to keep voltage value and vswing both lower, then RF/EMI -test all passed ;) - ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 - tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 -When we back to run HDMI different test and single-end test, we see -different test passed, but signle-end test failed. The oscilloscope -show that simgle-end clock's VL value is 1.78v (which remind LowLimit -should not lower then 2.6v). - -3. That's to say there are some different between PHY document and -measure value. And according to experiment 2 results, we need to -higher clock voltage and lower data voltage, then we can keep RF/EMI -satisfied and single-end & differen test passed. - ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47 - tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39 - -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cdf953850873..4652c0e0dcd6 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -181,7 +181,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { - static const struct dw_hdmi_phy_config rockchip_phy_config[] = { - /*pixelclk symbol term vlev*/ - { 74250000, 0x8009, 0x0004, 0x0272}, -- { 148500000, 0x802b, 0x0004, 0x028d}, -+ { 165000000, 0x802b, 0x0004, 0x0209}, - { 297000000, 0x8039, 0x0005, 0x028d}, - { ~0UL, 0x0000, 0x0000, 0x0000} - }; - -From 15a5f1ae8e0f570e81affb35b9b4aa4c0f485614 Mon Sep 17 00:00:00 2001 -From: Nickey Yang -Date: Mon, 13 Feb 2017 15:40:29 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: add phy_config for 594Mhz pixel clock - -Add phy_config for 594Mhz pixel clock used for 4K@60hz - -Signed-off-by: Nickey Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 4652c0e0dcd6..10c3dc521cbd 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -183,6 +183,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { - { 74250000, 0x8009, 0x0004, 0x0272}, - { 165000000, 0x802b, 0x0004, 0x0209}, - { 297000000, 0x8039, 0x0005, 0x028d}, -+ { 594000000, 0x8039, 0x0000, 0x019d}, - { ~0UL, 0x0000, 0x0000, 0x0000} - }; - - -From 43ac4790ecf27cf8db51e68298c541224af046a6 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Mon, 11 Jul 2016 19:05:36 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always - -Jitter was improved by lowering the MPLL bandwidth to account for high -frequency noise in the rk3288 PLL. In each case MPLL bandwidth was -lowered only enough to get us a comfortable margin. We believe that -lowering the bandwidth like this is safe given sufficient testing. - -Signed-off-by: Douglas Anderson -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++-------------- - 1 file changed, 2 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 10c3dc521cbd..cc7675638e4f 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -160,20 +160,8 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { - /* pixelclk bpp8 bpp10 bpp12 */ - { -- 40000000, { 0x0018, 0x0018, 0x0018 }, -- }, { -- 65000000, { 0x0028, 0x0028, 0x0028 }, -- }, { -- 66000000, { 0x0038, 0x0038, 0x0038 }, -- }, { -- 74250000, { 0x0028, 0x0038, 0x0038 }, -- }, { -- 83500000, { 0x0028, 0x0038, 0x0038 }, -- }, { -- 146250000, { 0x0038, 0x0038, 0x0038 }, -- }, { -- 148500000, { 0x0000, 0x0038, 0x0038 }, -- }, { -+ 600000000, { 0x0000, 0x0000, 0x0000 }, -+ }, { - ~0UL, { 0x0000, 0x0000, 0x0000}, - } - }; - -From 7604ef86c3d010fbfa61cf030b055b3860a53682 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Mon, 11 Jul 2016 19:05:42 +0800 -Subject: [PATCH] drm/rockchip: dw_hdmi: Use auto-generated tables - -The previous tables for mpll_cfg and curr_ctrl were created using the -20-pages of example settings provided by the PHY vendor. Those -example settings weren't particularly dense, so there were places -where we were guessing what the settings would be for 10-bit and -12-bit (not that we use those anyway). It was also always a lot of -extra work every time we wanted to add a new clock rate since we had -to cross-reference several tables. - -In I've gone through the work to figure -out how to generate this table automatically. Let's now use the -automatically generated table and then we'll never need to look at it -again. - -We only support 8-bit mode right now and only support a small number -of clock rates and and I've verified that the only 8-bit rate that was -affected was 148.5. That mode appears to have been wrong in the old -table. - -Signed-off-by: Douglas Anderson -Signed-off-by: Yakir Yang -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++++++++++--------- - 1 file changed, 69 insertions(+), 61 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cc7675638e4f..c4c158106ca4 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -79,80 +79,88 @@ struct rockchip_hdmi { - - static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - { -- 27000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ 30666000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2153, 0x0000 }, -+ { 0x40f3, 0x0000 }, - }, -- }, { -- 36000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ }, { -+ 36800000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2153, 0x0000 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 40000000, { -- { 0x00b3, 0x0000}, -- { 0x2153, 0x0000}, -- { 0x40f3, 0x0000} -+ }, { -+ 46000000, { -+ { 0x00b3, 0x0000 }, -+ { 0x2142, 0x0001 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 54000000, { -- { 0x0072, 0x0001}, -- { 0x2142, 0x0001}, -- { 0x40a2, 0x0001}, -+ }, { -+ 61333000, { -+ { 0x0072, 0x0001 }, -+ { 0x2142, 0x0001 }, -+ { 0x40a2, 0x0001 }, - }, -- }, { -- 65000000, { -- { 0x0072, 0x0001}, -- { 0x2142, 0x0001}, -- { 0x40a2, 0x0001}, -+ }, { -+ 73600000, { -+ { 0x0072, 0x0001 }, -+ { 0x2142, 0x0001 }, -+ { 0x4061, 0x0002 }, - }, -- }, { -- 66000000, { -- { 0x013e, 0x0003}, -- { 0x217e, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 92000000, { -+ { 0x0072, 0x0001 }, -+ { 0x2145, 0x0002 }, -+ { 0x4061, 0x0002 }, -+ }, -+ }, { -+ 122666000, { -+ { 0x0051, 0x0002 }, -+ { 0x2145, 0x0002 }, -+ { 0x4061, 0x0002 }, - }, -- }, { -- 74250000, { -- { 0x0072, 0x0001}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 147200000, { -+ { 0x0051, 0x0002 }, -+ { 0x2145, 0x0002 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 83500000, { -- { 0x0072, 0x0001}, -+ }, { -+ 184000000, { -+ { 0x0051, 0x0002 }, -+ { 0x214c, 0x0003 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 108000000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 226666000, { -+ { 0x0040, 0x0003 }, -+ { 0x214c, 0x0003 }, -+ { 0x4064, 0x0003 }, - }, -- }, { -- 106500000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 272000000, { -+ { 0x0040, 0x0003 }, -+ { 0x214c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -- 146250000, { -- { 0x0051, 0x0002}, -- { 0x2145, 0x0002}, -- { 0x4061, 0x0002} -+ }, { -+ 340000000, { -+ { 0x0040, 0x0003 }, -+ { 0x3b4c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -- 148500000, { -- { 0x0051, 0x0003}, -- { 0x214c, 0x0003}, -- { 0x4064, 0x0003} -+ }, { -+ 600000000, { -+ { 0x1a40, 0x0003 }, -+ { 0x3b4c, 0x0003 }, -+ { 0x5a64, 0x0003 }, - }, -- }, { -+ }, { - ~0UL, { -- { 0x00a0, 0x000a }, -- { 0x2001, 0x000f }, -- { 0x4002, 0x000f }, -+ { 0x0000, 0x0000 }, -+ { 0x0000, 0x0000 }, -+ { 0x0000, 0x0000 }, - }, - } - }; - -From 119aca9dc20be1639fe8146237d2821695a2bc6b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:52 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: limit tmds to 340mhz - -RK3228/RK3328 does not provide a stable hdmi signal at TMDS rates -above 371.25MHz (340MHz pixel clock). - -Limit the pixel clock rate to 340MHz to provide a stable signal. -Also limit the pixel clock to the display reported max tmds clock. - -This also enables use of pixel clocks up to 340MHz on RK3288/RK3399. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++------------ - 1 file changed, 4 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index c4c158106ca4..b62d8f4fc9a8 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -221,19 +221,11 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *info, - const struct drm_display_mode *mode) - { -- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; -- int pclk = mode->clock * 1000; -- bool valid = false; -- int i; -- -- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { -- if (pclk == mpll_cfg[i].mpixelclock) { -- valid = true; -- break; -- } -- } -+ if (mode->clock > 340000 || -+ (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) -+ return MODE_CLOCK_HIGH; - -- return (valid) ? MODE_OK : MODE_BAD; -+ return MODE_OK; - } - - static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - -From 9f31d6e1e2951eeaa979e1f9eb4b04cb64a4daf8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 3 May 2020 22:36:23 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: limit resolution to 3840x2160 - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index b62d8f4fc9a8..6f7641fbe6cc 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -225,7 +225,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) - return MODE_CLOCK_HIGH; - -- return MODE_OK; -+ return drm_mode_validate_size(mode, 3840, 2160); - } - - static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - -From bea1222407f1eb9d6af776d98eae5bd0f3544134 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:52 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: remove unused plat_data on - rk3228/rk3328 - -mpll_cfg/cur_ctr/phy_config is not used when phy_force_vendor is true, -lets remove them. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 6f7641fbe6cc..cc20a83fa9b8 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -396,9 +396,6 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { - .mode_valid = dw_hdmi_rockchip_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3228_chip_data, - .phy_ops = &rk3228_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", -@@ -433,9 +430,6 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .mode_valid = dw_hdmi_rockchip_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3328_chip_data, - .phy_ops = &rk3328_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", - -From 0bd355e25df8c93481ea6995bec7f452da97d5bf Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 8 Jan 2020 21:07:50 +0000 -Subject: [PATCH] clk: rockchip: set parent rate for DCLK_VOP clock on rk3228 - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3228.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 2ac006e99c03..1f9176a5cc07 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -393,7 +393,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), - DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, - RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), -- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, -+ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), - - FACTOR(0, "xin12m", "xin24m", 0, 1, 2), - -From 957c41ed6b5a182b12880b6f16f6e17d034bf483 Mon Sep 17 00:00:00 2001 -From: Nickey Yang -Date: Mon, 17 Jul 2017 16:35:34 +0800 -Subject: [PATCH] HACK: clk: rockchip: rk3288: dedicate npll for vopb and hdmi - use - -MINIARM: set npll be used for hdmi only - -Signed-off-by: Nickey Yang -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288.dtsi | 2 ++ - drivers/clk/rockchip/clk-rk3288.c | 4 ++-- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index 68d5a58cfe88..a376dea3bb1b 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -1046,6 +1046,8 @@ vopb: vop@ff930000 { - resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; - reset-names = "axi", "ahb", "dclk"; - iommus = <&vopb_mmu>; -+ assigned-clocks = <&cru DCLK_VOP0>; -+ assigned-clock-parents = <&cru PLL_NPLL>; - status = "disabled"; - - vopb_out: port { -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index 15c8f1dcba9a..460b19d65ef3 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -234,7 +234,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { - [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), - RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), - [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), -- RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), -+ RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), - }; - - static struct clk_div_table div_hclk_cpu_t[] = { -@@ -444,7 +444,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { - RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, - RK3288_CLKGATE_CON(3), 4, GFLAGS), - -- COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, -+ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, - RK3288_CLKGATE_CON(3), 1, GFLAGS), - COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, - -From 0f7295f13d592ba60dee79a0cc23302ed2febffa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 4 Aug 2018 14:51:14 +0200 -Subject: [PATCH] HACK: clk: rockchip: rk3288: use npll table to to improve - HDMI compatibility - -Based on https://github.com/TinkerBoard/debian_kernel/commit/3d90870530b8a2901681f7b7fa598ee7381e49f3 - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3288.c | 23 ++++++++++++++++++++++- - 1 file changed, 22 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index 460b19d65ef3..b973c6b0315b 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -124,6 +124,27 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { - { /* sentinel */ }, - }; - -+static struct rockchip_pll_rate_table rk3288_npll_rates[] = { -+ RK3066_PLL_RATE_NB(594000000, 1, 99, 4, 32), -+ RK3066_PLL_RATE_NB(585000000, 6, 585, 4, 32), -+ RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), -+ RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), -+ RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), -+ RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), -+ RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), -+ RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), -+ RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), -+ RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), -+ RK3066_PLL_RATE(148352000, 13, 1125, 14), -+ RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), -+ RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), -+ RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), -+ RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), -+ RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), -+ RK3066_PLL_RATE(74176000, 26, 1125, 14), -+ { /* sentinel */ }, -+}; -+ - #define RK3288_DIV_ACLK_CORE_M0_MASK 0xf - #define RK3288_DIV_ACLK_CORE_M0_SHIFT 0 - #define RK3288_DIV_ACLK_CORE_MP_MASK 0xf -@@ -234,7 +255,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { - [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), - RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), - [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), -- RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), -+ RK3288_MODE_CON, 14, 9, 0, rk3288_npll_rates), - }; - - static struct clk_div_table div_hclk_cpu_t[] = { - -From e9d9694635e5cd9a84779e045c670239fc255606 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 28 Oct 2018 21:43:01 +0100 -Subject: [PATCH] HACK: clk: rockchip: rk3288: add more npll clocks - -Fixes 2560x1440@60Hz, 1600x1200@60Hz, 1920x1200@60Hz, 1680x1050@60Hz and 1440x900@60Hz modes on my monitor - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3288.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index b973c6b0315b..9192b89c2550 100644 ---- a/drivers/clk/rockchip/clk-rk3288.c -+++ b/drivers/clk/rockchip/clk-rk3288.c -@@ -130,18 +130,34 @@ static struct rockchip_pll_rate_table rk3288_npll_rates[] = { - RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), - RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), - RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), -+ RK3066_PLL_RATE(348500000, 8, 697, 6), - RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), - RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), - RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), - RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), -+ RK3066_PLL_RATE(241500000, 2, 161, 8), -+ RK3066_PLL_RATE(162000000, 1, 81, 12), -+ RK3066_PLL_RATE(154000000, 6, 539, 14), - RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), - RK3066_PLL_RATE(148352000, 13, 1125, 14), - RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), -+ RK3066_PLL_RATE(121750000, 6, 487, 16), -+ RK3066_PLL_RATE(119000000, 3, 238, 16), - RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), - RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), -+ RK3066_PLL_RATE(101000000, 3, 202, 16), -+ RK3066_PLL_RATE(88750000, 6, 355, 16), - RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), -+ RK3066_PLL_RATE(83500000, 3, 167, 16), -+ RK3066_PLL_RATE(79500000, 1, 53, 16), - RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), - RK3066_PLL_RATE(74176000, 26, 1125, 14), -+ RK3066_PLL_RATE(72000000, 1, 48, 16), -+ RK3066_PLL_RATE(71000000, 3, 142, 16), -+ RK3066_PLL_RATE(68250000, 2, 91, 16), -+ RK3066_PLL_RATE(65000000, 3, 130, 16), -+ RK3066_PLL_RATE(40000000, 3, 80, 16), -+ RK3066_PLL_RATE(33750000, 2, 45, 16), - { /* sentinel */ }, - }; - - -From 2e18be0e366e9afcfe7dcdb69c3c90cce472bfa0 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 25 May 2020 20:36:45 +0000 -Subject: [PATCH] HACK: clk: rockchip: rk3399: dedicate vpll for vopb and hdmi - use - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3399.c | 32 +++++++++++++++++++++++++------ - 1 file changed, 26 insertions(+), 6 deletions(-) - -diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c -index 3682d5675cf7..0934145c09ad 100644 ---- a/drivers/clk/rockchip/clk-rk3399.c -+++ b/drivers/clk/rockchip/clk-rk3399.c -@@ -111,6 +111,25 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { - { /* sentinel */ }, - }; - -+static struct rockchip_pll_rate_table rk3399_vpll_rates[] = { -+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ -+ RK3036_PLL_RATE( 594000000, 1, 123, 5, 1, 0, 12582912), /* vco = 2970000000 */ -+ RK3036_PLL_RATE( 593406592, 1, 123, 5, 1, 0, 10508804), /* vco = 2967032965 */ -+ RK3036_PLL_RATE( 297000000, 1, 123, 5, 2, 0, 12582912), /* vco = 2970000000 */ -+ RK3036_PLL_RATE( 296703296, 1, 123, 5, 2, 0, 10508807), /* vco = 2967032970 */ -+ RK3036_PLL_RATE( 148500000, 1, 129, 7, 3, 0, 15728640), /* vco = 3118500000 */ -+ RK3036_PLL_RATE( 148351648, 1, 123, 5, 4, 0, 10508800), /* vco = 2967032960 */ -+ RK3036_PLL_RATE( 106500000, 1, 124, 7, 4, 0, 4194304), /* vco = 2982000000 */ -+ RK3036_PLL_RATE( 74250000, 1, 129, 7, 6, 0, 15728640), /* vco = 3118500000 */ -+ RK3036_PLL_RATE( 74175824, 1, 129, 7, 6, 0, 13550823), /* vco = 3115384608 */ -+ RK3036_PLL_RATE( 65000000, 1, 113, 7, 6, 0, 12582912), /* vco = 2730000000 */ -+ RK3036_PLL_RATE( 59340659, 1, 121, 7, 7, 0, 2581098), /* vco = 2907692291 */ -+ RK3036_PLL_RATE( 54000000, 1, 110, 7, 7, 0, 4194304), /* vco = 2646000000 */ -+ RK3036_PLL_RATE( 27000000, 1, 55, 7, 7, 0, 2097152), /* vco = 1323000000 */ -+ RK3036_PLL_RATE( 26973026, 1, 55, 7, 7, 0, 1173232), /* vco = 1321678323 */ -+ { /* sentinel */ }, -+}; -+ - /* CRU parents */ - PNAME(mux_pll_p) = { "xin24m", "xin32k" }; - -@@ -129,7 +148,7 @@ PNAME(mux_ddrclk_p) = { "clk_ddrc_lpll_src", - PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", - "gpll_aclk_cci_src", - "npll_aclk_cci_src", -- "vpll_aclk_cci_src" }; -+ "prevent:vpll" }; - PNAME(mux_cci_trace_p) = { "cpll_cci_trace", - "gpll_cci_trace" }; - PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", -@@ -156,9 +175,10 @@ PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", - "ppll", "upll", "xin24m" }; - - PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; --PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", -+ -+PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "prevent:vpll", "cpll", "gpll", - "npll" }; --PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", -+PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "prevent:vpll", "cpll", "gpll", - "xin24m" }; - - PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", -@@ -235,7 +255,7 @@ static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { - [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), - RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), - [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), -- RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), -+ RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_vpll_rates), - }; - - static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { -@@ -285,7 +305,7 @@ static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = - RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); - - static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = -- MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, -+ MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); - - static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = -@@ -1166,7 +1186,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { - GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, - RK3399_CLKGATE_CON(28), 0, GFLAGS), - -- COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, -+ COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, - RK3399_CLKGATE_CON(10), 12, GFLAGS), - - -From b2d23eae37a78a425144a21eb8bfbedc03edc754 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 19 Jul 2020 16:35:11 +0000 -Subject: [PATCH] HACK: dts: rockchip: do not use vopl for hdmi - ---- - arch/arm/boot/dts/rk3288.dtsi | 9 --------- - arch/arm64/boot/dts/rockchip/rk3399.dtsi | 9 --------- - 2 files changed, 18 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index a376dea3bb1b..9757976d6e8a 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -1104,11 +1104,6 @@ vopl_out: port { - #address-cells = <1>; - #size-cells = <0>; - -- vopl_out_hdmi: endpoint@0 { -- reg = <0>; -- remote-endpoint = <&hdmi_in_vopl>; -- }; -- - vopl_out_edp: endpoint@1 { - reg = <1>; - remote-endpoint = <&edp_in_vopl>; -@@ -1249,10 +1244,6 @@ hdmi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_hdmi>; - }; -- hdmi_in_vopl: endpoint@1 { -- reg = <1>; -- remote-endpoint = <&vopl_out_hdmi>; -- }; - }; - }; - }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index f5dee5f447bb..3e44bf8eac5c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -1640,11 +1640,6 @@ vopl_out_edp: endpoint@1 { - remote-endpoint = <&edp_in_vopl>; - }; - -- vopl_out_hdmi: endpoint@2 { -- reg = <2>; -- remote-endpoint = <&hdmi_in_vopl>; -- }; -- - vopl_out_mipi1: endpoint@3 { - reg = <3>; - remote-endpoint = <&mipi1_in_vopl>; -@@ -1816,10 +1811,6 @@ hdmi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_hdmi>; - }; -- hdmi_in_vopl: endpoint@1 { -- reg = <1>; -- remote-endpoint = <&vopl_out_hdmi>; -- }; - }; - }; - }; - -From c94f4e569387f6874b2c96a3db684751529fb6b6 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 12:33:01 +0000 -Subject: [PATCH] Revert "fixup! WIP: drm/rockchip: vop: max_output" - -This reverts commit c69612ca6820500cd1a0a3e4f8eb8c6f7b971cda. ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 106b38ea12df..138f449924f8 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1184,8 +1184,19 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *adjusted_mode) - { - struct vop *vop = to_vop(crtc); -+ const struct vop_rect *max_output = &vop->data->max_output; - unsigned long rate; - -+ if (max_output->width && max_output->height) { -+ enum drm_mode_status status; -+ -+ status = drm_mode_validate_size(adjusted_mode, -+ max_output->width, -+ max_output->height); -+ if (status != MODE_OK) -+ return false; -+ } -+ - /* - * Clock craziness. - * - -From 8af324175e002a9ee48be8618dce51ffc348a409 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 15 Jul 2020 15:24:47 +0000 -Subject: [PATCH] drm/rockchip: vop: fix crtc duplicate state - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 138f449924f8..0a25de483515 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1578,7 +1578,11 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) - { - struct rockchip_crtc_state *rockchip_state; - -- rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); -+ if (WARN_ON(!crtc->state)) -+ return NULL; -+ -+ rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state), -+ sizeof(*rockchip_state), GFP_KERNEL); - if (!rockchip_state) - return NULL; - - -From cf2f0b3497dd7094b96d0f61d71e07927aae3e0c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 15:15:50 +0000 -Subject: [PATCH] WIP: drm/rockchip: vop: filter interlaced modes - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 0a25de483515..5ab1412173a7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1160,6 +1160,9 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, - if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) - return MODE_OK; - -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return MODE_NO_INTERLACE; -+ - rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); - if (rounded_rate < 0) - return MODE_NOCLOCK; - -From 1400714403b22c227d281c8fc5a3c07cc6312740 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: add bridge and switch to - drm_bridge_funcs - -Switch the dw-hdmi driver to drm_bridge_funcs by implementing -a new local bridge, connecting it to the dw-hdmi bridge. - -Also enable bridge format negotiation by implementing -atomic_get_input_bus_fmts and support for 8-bit RGB 4:4:4. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 138 ++++++++++++++------ - 1 file changed, 95 insertions(+), 43 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index cc20a83fa9b8..745fd1c13cef 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -68,6 +68,7 @@ struct rockchip_hdmi { - struct device *dev; - struct regmap *regmap; - struct drm_encoder encoder; -+ struct drm_bridge bridge; - const struct rockchip_hdmi_chip_data *chip_data; - struct clk *vpll_clk; - struct clk *grf_clk; -@@ -228,30 +229,20 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - return drm_mode_validate_size(mode, 3840, 2160); - } - --static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) -+static void -+dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode, -+ const struct drm_display_mode *adjusted_mode) - { --} -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - --static bool --dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, -- const struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) --{ -- return true; -+ clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } - --static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, -- struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) -+static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - { -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -- -- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); --} -- --static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) --{ -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 val; - int ret; - -@@ -279,10 +270,21 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) - ret ? "LIT" : "BIG"); - } - -+static bool is_rgb(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int --dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) -+dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - -@@ -292,12 +294,38 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, - return 0; - } - --static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { -- .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, -- .mode_set = dw_hdmi_rockchip_encoder_mode_set, -- .enable = dw_hdmi_rockchip_encoder_enable, -- .disable = dw_hdmi_rockchip_encoder_disable, -- .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, -+static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmt; -+ -+ *num_input_fmts = 0; -+ -+ if (!is_rgb(output_fmt)) -+ return NULL; -+ -+ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -+ if (!input_fmt) -+ return NULL; -+ -+ *num_input_fmts = 1; -+ *input_fmt = output_fmt; -+ -+ return input_fmt; -+} -+ -+static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { -+ .mode_set = dw_hdmi_rockchip_bridge_mode_set, -+ .enable = dw_hdmi_rockchip_bridge_enable, -+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, -+ .atomic_get_input_bus_fmts = dw_hdmi_rockchip_get_input_bus_fmts, -+ .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, -+ .atomic_reset = drm_atomic_helper_bridge_reset, - }; - - static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, -@@ -476,6 +504,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - struct dw_hdmi_plat_data *plat_data; - const struct of_device_id *match; - struct drm_device *drm = data; -+ struct drm_bridge *next_bridge; - struct drm_encoder *encoder; - struct rockchip_hdmi *hdmi; - int ret; -@@ -516,8 +545,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { -- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", -- ret); -+ DRM_DEV_ERROR(hdmi->dev, "Failed to enable vpll: %d\n", ret); - return ret; - } - -@@ -525,27 +553,51 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->phy)) { - ret = PTR_ERR(hdmi->phy); - if (ret != -EPROBE_DEFER) -- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); -- return ret; -+ DRM_DEV_ERROR(hdmi->dev, "Failed to get phy: %d\n", ret); -+ goto err_disable_clk; - } - -- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); -- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, "Failed to init encoder: %d\n", ret); -+ goto err_disable_clk; -+ } - -- platform_set_drvdata(pdev, hdmi); -+ hdmi->bridge.funcs = &dw_hdmi_rockchip_bridge_funcs; -+ drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); - -- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); -+ platform_set_drvdata(pdev, hdmi); - -- /* -- * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), -- * which would have called the encoder cleanup. Do it manually. -- */ -+ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); - if (IS_ERR(hdmi->hdmi)) { - ret = PTR_ERR(hdmi->hdmi); -- drm_encoder_cleanup(encoder); -- clk_disable_unprepare(hdmi->vpll_clk); -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(hdmi->dev, "Failed to init dw-hdmi bridge: %d\n", ret); -+ goto err_encoder_cleanup; -+ } -+ -+ next_bridge = of_drm_find_bridge(pdev->dev.of_node); -+ if (!next_bridge) { -+ ret = -EPROBE_DEFER; -+ goto err_dw_hdmi_remove; -+ } -+ -+ ret = drm_bridge_attach(encoder, next_bridge, &hdmi->bridge, 0); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(hdmi->dev, "Failed to attach dw-hdmi bridge: %d\n", ret); -+ goto err_dw_hdmi_remove; - } - -+ return 0; -+ -+err_dw_hdmi_remove: -+ dw_hdmi_remove(hdmi->hdmi); -+err_encoder_cleanup: -+ drm_encoder_cleanup(encoder); -+err_disable_clk: -+ clk_disable_unprepare(hdmi->vpll_clk); -+ - return ret; - } - -@@ -554,7 +606,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, - { - struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - -- dw_hdmi_unbind(hdmi->hdmi); -+ dw_hdmi_remove(hdmi->hdmi); - clk_disable_unprepare(hdmi->vpll_clk); - } - - -From ea791312a81f11f719a019e30c7736e7ab314739 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 18:00:44 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: add mtmdsclock parameter to phy - configure ops - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 ++++++---- - drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- - include/drm/bridge/dw_hdmi.h | 3 ++- - 3 files changed, 10 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 0c79a9ba48bb..50199329ad6f 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -137,7 +137,8 @@ struct dw_hdmi_phy_data { - bool has_svsret; - int (*configure)(struct dw_hdmi *hdmi, - const struct dw_hdmi_plat_data *pdata, -- unsigned long mpixelclock); -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock); - }; - - struct dw_hdmi { -@@ -1441,7 +1442,8 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) - */ - static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_plat_data *pdata, -- unsigned long mpixelclock) -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock) - { - const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; - const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; -@@ -1516,9 +1518,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, - - /* Write to the PHY as configured by the platform */ - if (pdata->configure_phy) -- ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); -+ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock, mtmdsclock); - else -- ret = phy->configure(hdmi, pdata, mpixelclock); -+ ret = phy->configure(hdmi, pdata, mpixelclock, mtmdsclock); - if (ret) { - dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", - mpixelclock); -diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -index 7b8ec8310699..539d86131fd4 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -+++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -@@ -53,7 +53,8 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, - } - - static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, -- unsigned long mpixelclock) -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock) - { - const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; - -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index ea34ca146b82..4f61ede6486d 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -152,7 +152,8 @@ struct dw_hdmi_plat_data { - const struct dw_hdmi_curr_ctrl *cur_ctr; - const struct dw_hdmi_phy_config *phy_config; - int (*configure_phy)(struct dw_hdmi *hdmi, void *data, -- unsigned long mpixelclock); -+ unsigned long mpixelclock, -+ unsigned long mtmdsclock); - }; - - struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, - -From 0ea5bddefeeecd75d9dbee409ad8a8fddff6d378 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 21:34:48 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: support configuring phy for deep color - -Q: Should we rename dw_hdmi_curr_ctrl and dw_hdmi_phy_config mpixelclock to mtmdsclock ? - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 50199329ad6f..2581789178c7 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1448,6 +1448,7 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; - const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; - const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; -+ int depth; - - /* TOFIX Will need 420 specific PHY configuration tables */ - -@@ -1457,11 +1458,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - break; - - for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) -- if (mpixelclock <= curr_ctrl->mpixelclock) -+ if (mtmdsclock <= curr_ctrl->mpixelclock) - break; - - for (; phy_config->mpixelclock != ~0UL; phy_config++) -- if (mpixelclock <= phy_config->mpixelclock) -+ if (mtmdsclock <= phy_config->mpixelclock) - break; - - if (mpll_config->mpixelclock == ~0UL || -@@ -1469,11 +1470,17 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - phy_config->mpixelclock == ~0UL) - return -EINVAL; - -- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, -+ depth = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); -+ if (depth > 8 && mpixelclock != mtmdsclock) -+ depth = fls(depth - 8) - 1; -+ else -+ depth = 0; -+ -+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, - HDMI_3D_TX_PHY_CPCE_CTRL); -- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, -+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, - HDMI_3D_TX_PHY_GMPCTRL); -- dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], -+ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], - HDMI_3D_TX_PHY_CURRCTRL); - - dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); - -From 153e20ab5fd968cb5aff1e0cd7191d1ca1a6744e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 20 Jul 2020 22:25:15 +0000 -Subject: [PATCH] drm/bridge: dw-hdmi: add mpll_cfg_420 for ycbcr420 mode - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- - include/drm/bridge/dw_hdmi.h | 1 + - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 2581789178c7..6d319b95b992 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1450,7 +1450,9 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, - const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; - int depth; - -- /* TOFIX Will need 420 specific PHY configuration tables */ -+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) && -+ pdata->mpll_cfg_420) -+ mpll_config = pdata->mpll_cfg_420; - - /* PLL/MPLL Cfg - always match on final entry */ - for (; mpll_config->mpixelclock != ~0UL; mpll_config++) -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 4f61ede6486d..0ebe01835d2a 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -149,6 +149,7 @@ struct dw_hdmi_plat_data { - - /* Synopsys PHY support */ - const struct dw_hdmi_mpll_config *mpll_cfg; -+ const struct dw_hdmi_mpll_config *mpll_cfg_420; - const struct dw_hdmi_curr_ctrl *cur_ctr; - const struct dw_hdmi_phy_config *phy_config; - int (*configure_phy)(struct dw_hdmi *hdmi, void *data, - -From 21174838c2d39a88ea46dbf64ced1ac133f32e7c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 15 Jul 2020 09:49:21 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: mode_valid: allow 420 clock rate - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 745fd1c13cef..9784111ea746 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -222,8 +222,15 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *info, - const struct drm_display_mode *mode) - { -- if (mode->clock > 340000 || -- (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) -+ struct dw_hdmi_plat_data *pdata = (struct dw_hdmi_plat_data *)data; -+ int clock = mode->clock; -+ -+ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > 340000 || -+ (info->max_tmds_clock && clock > info->max_tmds_clock)) - return MODE_CLOCK_HIGH; - - return drm_mode_validate_size(mode, 3840, 2160); -@@ -524,6 +531,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - - hdmi->dev = &pdev->dev; - hdmi->chip_data = plat_data->phy_data; -+ plat_data->priv_data = plat_data; - plat_data->phy_data = hdmi; - encoder = &hdmi->encoder; - - -From fbf69694a8f832cfa942f16a4bd8a630aa8f0f3f Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: limit mode and bus format to - max_tmds_clock - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 120 ++++++++++++++-------- - 1 file changed, 76 insertions(+), 44 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 6d319b95b992..c2425d7fc465 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1859,6 +1859,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, - HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); - } - -+static unsigned int -+hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) -+{ -+ int color_depth = hdmi_bus_fmt_color_depth(bus_format); -+ unsigned int tmdsclock = pixelclock; -+ -+ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) -+ tmdsclock = (u64)pixelclock * color_depth / 8; -+ -+ if (hdmi_bus_fmt_is_yuv420(bus_format)) -+ tmdsclock /= 2; -+ -+ return tmdsclock; -+} -+ - static void hdmi_av_composer(struct dw_hdmi *hdmi, - const struct drm_display_info *display, - const struct drm_display_mode *mode) -@@ -1870,29 +1885,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - unsigned int vdisplay, hdisplay; - - vmode->mpixelclock = mode->clock * 1000; -+ vmode->mtmdsclock = -+ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, -+ vmode->mpixelclock); - - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); -- -- vmode->mtmdsclock = vmode->mpixelclock; -- -- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -- switch (hdmi_bus_fmt_color_depth( -- hdmi->hdmi_data.enc_out_bus_format)) { -- case 16: -- vmode->mtmdsclock = vmode->mpixelclock * 2; -- break; -- case 12: -- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; -- break; -- case 10: -- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; -- break; -- } -- } -- -- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -- vmode->mtmdsclock /= 2; -- - dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); - - /* Set up HDMI_FC_INVIDCONF */ -@@ -2544,8 +2541,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) - * - MEDIA_BUS_FMT_RGB888_1X24, - */ - --/* Can return a maximum of 11 possible output formats for a mode/connector */ --#define MAX_OUTPUT_SEL_FORMATS 11 -+/* Can return a maximum of 15 possible output formats for a mode/connector */ -+#define MAX_OUTPUT_SEL_FORMATS 15 -+ -+static bool is_tmds_allowed(struct drm_display_info *info, -+ struct drm_display_mode *mode, -+ u32 bus_format) -+{ -+ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ -+ if (max_tmds_clock >= tmdsclock) -+ return true; -+ -+ return false; -+} - - static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -2557,8 +2567,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_display_info *info = &conn->display_info; - struct drm_display_mode *mode = &crtc_state->mode; - u8 max_bpc = conn_state->max_requested_bpc; -- bool is_hdmi2_sink = info->hdmi.scdc.supported || -- (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); - u32 *output_fmts; - unsigned int i = 0; - -@@ -2581,29 +2589,33 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - * If the current mode enforces 4:2:0, force the output but format - * to 4:2:0 and do not add the YUV422/444/RGB formats - */ -- if (conn->ycbcr_420_allowed && -- (drm_mode_is_420_only(info, mode) || -- (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { -+ if (conn->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) { - - /* Order bus formats from 16bit to 8bit if supported */ - if (max_bpc >= 16 && info->bpc == 16 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; - - if (max_bpc >= 12 && info->bpc >= 12 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; - - if (max_bpc >= 10 && info->bpc >= 10 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; - - /* Default 8bit fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; - - *num_output_fmts = i; - -- return output_fmts; -+ if (drm_mode_is_420_only(info, mode)) -+ return output_fmts; - } - - /* -@@ -2612,40 +2624,51 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - */ - - if (max_bpc >= 16 && info->bpc == 16) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; - } - - if (max_bpc >= 12 && info->bpc >= 12) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; - } - - if (max_bpc >= 10 && info->bpc >= 10) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; - } - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; - - /* Default 8bit RGB fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB888_1X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; - - *num_output_fmts = i; - -@@ -2825,11 +2848,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - struct dw_hdmi *hdmi = bridge->driver_private; - const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; - enum drm_mode_status mode_status = MODE_OK; -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ int clock = mode->clock; - - /* We don't support double-clocked modes */ - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_BAD; - -+ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > max_tmds_clock) -+ return MODE_CLOCK_HIGH; -+ - if (pdata->mode_valid) - mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, - mode); - -From 6e9f31fe455b92a19f12c4bae9c9f4b00efde58e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] WIP: drm/rockchip: dw_hdmi: add 10-bit rgb bus format - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 + - 2 files changed, 43 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 9784111ea746..ddff1582b271 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -77,6 +77,7 @@ struct rockchip_hdmi { - }; - - #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) -+#define to_crtc_state(x) container_of(x, struct drm_crtc_state, x) - - static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - { -@@ -242,6 +243,11 @@ dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *adjusted_mode) - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_crtc_state *crtc_state = to_crtc_state(adjusted_mode); -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, s->bus_width); - - clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } -@@ -280,6 +286,7 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - static bool is_rgb(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_RGB888_1X24: - return true; - default: -@@ -287,6 +294,16 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_10bit(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int - dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -294,9 +311,24 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ struct drm_atomic_state *state = bridge_state->base.state; -+ struct drm_crtc_state *old_crtc_state; -+ struct rockchip_crtc_state *old_state; -+ u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ s->output_bpc = 10; -+ s->bus_format = format; -+ s->bus_width = is_10bit(format) ? 10 : 8; -+ -+ old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -+ if (old_crtc_state && !crtc_state->mode_changed) { -+ old_state = to_rockchip_crtc_state(old_crtc_state); -+ if (s->bus_format != old_state->bus_format || -+ s->bus_width != old_state->bus_width) -+ crtc_state->mode_changed = true; -+ } - - return 0; - } -@@ -308,10 +340,19 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - u32 output_fmt, - unsigned int *num_input_fmts) - { -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 *input_fmt; -+ bool has_10bit = true; - - *num_input_fmts = 0; - -+ if (drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder)) -+ has_10bit = false; -+ -+ if (!has_10bit && is_10bit(output_fmt)) -+ return NULL; -+ - if (!is_rgb(output_fmt)) - return NULL; - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -index e33c2dcd0d4b..03944e08b6c7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -@@ -31,6 +31,8 @@ struct rockchip_crtc_state { - int output_bpc; - int output_flags; - bool enable_afbc; -+ u32 bus_format; -+ int bus_width; - }; - #define to_rockchip_crtc_state(s) \ - container_of(s, struct rockchip_crtc_state, base) - -From 83871fb221f71065f78cff3c8019f8684481a155 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:42:44 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: add content type connector property - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index c2425d7fc465..f86b8fa40ab6 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1646,6 +1646,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, - const struct drm_connector *connector, - const struct drm_display_mode *mode) - { -+ const struct drm_connector_state *conn_state = connector->state; - struct hdmi_avi_infoframe frame; - u8 val; - -@@ -1703,6 +1704,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - } - -+ drm_hdmi_avi_infoframe_content_type(&frame, conn_state); -+ - /* - * The Designware IP uses a different byte format from standard - * AVI info frames, though generally the bits are in the correct -@@ -2431,7 +2434,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, - if (!crtc) - return 0; - -- if (!hdr_metadata_equal(old_state, new_state)) { -+ if (!hdr_metadata_equal(old_state, new_state) || -+ old_state->content_type != new_state->content_type) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); -@@ -2499,6 +2503,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) - - drm_connector_attach_max_bpc_property(connector, 8, 16); - -+ drm_connector_attach_content_type_property(connector); -+ - if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.hdr_output_metadata_property, 0); - -From 553cc49748b8f0d074735f18cd45f050fca567e7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv444 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 30 ++++++++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 ++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 14 ++++++++++ - 4 files changed, 78 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index ddff1582b271..eea8e1491204 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -62,6 +62,7 @@ struct rockchip_hdmi_chip_data { - int lcdsel_grf_reg; - u32 lcdsel_big; - u32 lcdsel_lit; -+ bool ycbcr_444_allowed; - }; - - struct rockchip_hdmi { -@@ -294,10 +295,22 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_yuv444(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { - case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_YUV10_1X30: - return true; - default: - return false; -@@ -314,12 +327,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_atomic_state *state = bridge_state->base.state; - struct drm_crtc_state *old_crtc_state; - struct rockchip_crtc_state *old_state; -+ struct drm_bridge *next_bridge; -+ struct drm_bridge_state *next_bridge_state; - u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; - s->output_bpc = 10; - s->bus_format = format; -+ -+ next_bridge = drm_bridge_get_next_bridge(bridge); -+ if (next_bridge) { -+ next_bridge_state = drm_atomic_get_new_bridge_state(state, -+ next_bridge); -+ format = next_bridge_state->output_bus_cfg.format; -+ } -+ - s->bus_width = is_10bit(format) ? 10 : 8; - - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -@@ -353,7 +376,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (!has_10bit && is_10bit(output_fmt)) - return NULL; - -- if (!is_rgb(output_fmt)) -+ if (is_yuv444(output_fmt)) { -+ if (!hdmi->chip_data->ycbcr_444_allowed) -+ return NULL; -+ } else if (!is_rgb(output_fmt)) - return NULL; - - input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -@@ -502,6 +528,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { - - static struct rockchip_hdmi_chip_data rk3328_chip_data = { - .lcdsel_grf_reg = -1, -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { -@@ -517,6 +544,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { - .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, - .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), - .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 5ab1412173a7..a17bd4e90ba7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -310,6 +310,17 @@ static int vop_convert_afbc_format(uint32_t format) - return -EINVAL; - } - -+static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, - uint32_t dst, bool is_horizontal, - int vsu_mode, int *vskiplines) -@@ -1329,6 +1340,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - u16 vact_end = vact_st + vdisplay; - uint32_t pin_pol, val; - int dither_bpc = s->output_bpc ? s->output_bpc : 10; -+ bool yuv_output = is_yuv_output(s->bus_format); - int ret; - - if (old_state && old_state->self_refresh_active) { -@@ -1402,6 +1414,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -+ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); - else -@@ -1417,6 +1431,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, overlay_mode, yuv_output); -+ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); -+ -+ /* -+ * Background color is 10bit depth if vop version >= 3.5 -+ */ -+ if (!yuv_output) -+ val = 0; -+ else if (VOP_MAJOR(vop_data->version) == 3 && -+ VOP_MINOR(vop_data->version) >= 5) -+ val = 0x20010200; -+ else -+ val = 0x801080; -+ VOP_REG_SET(vop, common, dsp_background, val); -+ - VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); - val = hact_st << 16; - val |= hact_end; -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 1516231bbf93..b820ad3fa091 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -92,10 +92,16 @@ struct vop_common { - struct vop_reg mmu_en; - struct vop_reg out_mode; - struct vop_reg standby; -+ -+ struct vop_reg overlay_mode; -+ struct vop_reg dsp_data_swap; -+ struct vop_reg dsp_out_yuv; -+ struct vop_reg dsp_background; - }; - - struct vop_misc { - struct vop_reg global_regdone_en; -+ struct vop_reg win_channel[4]; - }; - - struct vop_intr { -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 57c36e9207c1..800b9341dd42 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -644,6 +644,11 @@ static const struct vop_common rk3288_common = { - .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), - }; - - /* -@@ -996,6 +1001,10 @@ static const struct vop_output rk3328_output = { - - static const struct vop_misc rk3328_misc = { - .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), -+ -+ .win_channel[0] = VOP_REG(RK3328_WIN0_CTRL2, 0xff, 0), -+ .win_channel[1] = VOP_REG(RK3328_WIN1_CTRL2, 0xff, 0), -+ .win_channel[2] = VOP_REG(RK3328_WIN2_CTRL2, 0xff, 0), - }; - - static const struct vop_common rk3328_common = { -@@ -1008,6 +1017,11 @@ static const struct vop_common rk3328_common = { - .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), - }; - - static const struct vop_intr rk3328_vop_intr = { - -From 6127108151898a2c69fb50749d7e647ac35cf8aa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv420 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 +++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 10 +++++---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ - 4 files changed, 48 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index eea8e1491204..c25ebe31b98d 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -306,9 +306,21 @@ static bool is_yuv444(u32 format) - } - } - -+static bool is_yuv420(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: - case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_YUV10_1X30: - return true; -@@ -345,6 +357,11 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - - s->bus_width = is_10bit(format) ? 10 : 8; - -+ if (is_yuv420(format)) { -+ s->output_mode = ROCKCHIP_OUT_MODE_YUV420; -+ s->bus_width /= 2; -+ } -+ - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); - if (old_crtc_state && !crtc_state->mode_changed) { - old_state = to_rockchip_crtc_state(old_crtc_state); -@@ -365,6 +382,7 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = conn_state->connector; - u32 *input_fmt; - bool has_10bit = true; - -@@ -379,6 +397,9 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (is_yuv444(output_fmt)) { - if (!hdmi->chip_data->ycbcr_444_allowed) - return NULL; -+ } else if (is_yuv420(output_fmt)) { -+ if (!connector->ycbcr_420_allowed) -+ return NULL; - } else if (!is_rgb(output_fmt)) - return NULL; - -@@ -538,6 +559,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .phy_name = "inno_dw_hdmi_phy2", - .phy_force_vendor = true, - .use_drm_infoframe = true, -+ .ycbcr_420_allowed = true, - }; - - static struct rockchip_hdmi_chip_data rk3399_chip_data = { -@@ -554,6 +576,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { - .phy_config = rockchip_phy_config, - .phy_data = &rk3399_chip_data, - .use_drm_infoframe = true, -+ .ycbcr_420_allowed = true, - }; - - static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index a17bd4e90ba7..5ea8031eb0f7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -311,6 +311,19 @@ static int vop_convert_afbc_format(uint32_t format) - } - - static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool has_uv_swapped(uint32_t bus_format) - { - switch (bus_format) { - case MEDIA_BUS_FMT_YUV8_1X24: -@@ -1414,7 +1427,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -- VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ VOP_REG_SET(vop, common, dsp_data_swap, has_uv_swapped(s->bus_format) ? 2 : 0); - - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); -@@ -1431,6 +1444,9 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, dclk_ddr, -+ s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); -+ - VOP_REG_SET(vop, common, overlay_mode, yuv_output); - VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index b820ad3fa091..8e6e999e5163 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -94,6 +94,7 @@ struct vop_common { - struct vop_reg standby; - - struct vop_reg overlay_mode; -+ struct vop_reg dclk_ddr; - struct vop_reg dsp_data_swap; - struct vop_reg dsp_out_yuv; - struct vop_reg dsp_background; -@@ -257,11 +258,12 @@ struct vop_data { - /* - * display output interface supported by rockchip lcdc - */ --#define ROCKCHIP_OUT_MODE_P888 0 --#define ROCKCHIP_OUT_MODE_P666 1 --#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_P888 0 -+#define ROCKCHIP_OUT_MODE_P666 1 -+#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_YUV420 14 - /* for use special outface */ --#define ROCKCHIP_OUT_MODE_AAAA 15 -+#define ROCKCHIP_OUT_MODE_AAAA 15 - - /* output flags */ - #define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 800b9341dd42..dd4546f9f410 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -646,6 +646,7 @@ static const struct vop_common rk3288_common = { - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3288_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), -@@ -1019,6 +1020,7 @@ static const struct vop_common rk3328_common = { - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), - -From c70da56116a103e5f6bd154b7819217410a9c4f7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 7 Jun 2020 20:25:25 +0000 -Subject: [PATCH] drm: drm_fourcc: add NV20 and NV30 YUV formats - -DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled -variant of NV15, a 10-bit 2-plane YUV format that has no padding between -components. Instead, luminance and chrominance samples are grouped into 4s -so that each group is packed into an integer number of bytes: - -YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes - -The '20' and '30' suffix refers to the optimum effective bits per pixel -which is achieved when the total number of luminance samples is a multiple -of 4. - -V2: Added NV30 format - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/drm_fourcc.c | 8 ++++++++ - include/uapi/drm/drm_fourcc.h | 2 ++ - 2 files changed, 10 insertions(+) - -diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c -index 722c7ebe4e88..2daf8a304b53 100644 ---- a/drivers/gpu/drm/drm_fourcc.c -+++ b/drivers/gpu/drm/drm_fourcc.c -@@ -278,6 +278,14 @@ const struct drm_format_info *__drm_format_info(u32 format) - .num_planes = 2, .char_per_block = { 5, 5, 0 }, - .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, - .vsub = 2, .is_yuv = true }, -+ { .format = DRM_FORMAT_NV20, .depth = 0, -+ .num_planes = 2, .char_per_block = { 5, 5, 0 }, -+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, -+ .vsub = 1, .is_yuv = true }, -+ { .format = DRM_FORMAT_NV30, .depth = 0, -+ .num_planes = 2, .char_per_block = { 5, 5, 0 }, -+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1, -+ .vsub = 1, .is_yuv = true }, - { .format = DRM_FORMAT_Q410, .depth = 0, - .num_planes = 3, .char_per_block = { 2, 2, 2 }, - .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, -diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h -index 82f327801267..d8e6159213dc 100644 ---- a/include/uapi/drm/drm_fourcc.h -+++ b/include/uapi/drm/drm_fourcc.h -@@ -242,6 +242,8 @@ extern "C" { - * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian - */ - #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ -+#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ -+#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */ - - /* - * 2 plane YCbCr MSB aligned - -From b41c8312d8bcd440bc42a799dd09b4acd9d4eca2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 7 Jun 2020 20:25:26 +0000 -Subject: [PATCH] drm: rockchip: add NV15, NV20 and NV30 support - -Add support for displaying 10-bit 4:2:0 and 4:2:2 formats produced by the -Rockchip Video Decoder on RK322X, RK3288, RK3328, RK3368 and RK3399. -Also add support for 10-bit 4:4:4 format while at it. - -V2: Added NV30 support - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++-- - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 32 +++++++++++++++++---- - 3 files changed, 54 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 5ea8031eb0f7..413534cf1a93 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -261,6 +261,18 @@ static bool has_rb_swapped(uint32_t format) - } - } - -+static bool is_fmt_10(uint32_t format) -+{ -+ switch (format) { -+ case DRM_FORMAT_NV15: -+ case DRM_FORMAT_NV20: -+ case DRM_FORMAT_NV30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static enum vop_data_format vop_convert_format(uint32_t format) - { - switch (format) { -@@ -276,10 +288,13 @@ static enum vop_data_format vop_convert_format(uint32_t format) - case DRM_FORMAT_BGR565: - return VOP_FMT_RGB565; - case DRM_FORMAT_NV12: -+ case DRM_FORMAT_NV15: - return VOP_FMT_YUV420SP; - case DRM_FORMAT_NV16: -+ case DRM_FORMAT_NV20: - return VOP_FMT_YUV422SP; - case DRM_FORMAT_NV24: -+ case DRM_FORMAT_NV30: - return VOP_FMT_YUV444SP; - default: - DRM_ERROR("unsupported format[%08x]\n", format); -@@ -946,7 +961,12 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; - dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); - -- offset = (src->x1 >> 16) * fb->format->cpp[0]; -+ if (fb->format->block_w[0]) -+ offset = (src->x1 >> 16) * fb->format->char_per_block[0] / -+ fb->format->block_w[0]; -+ else -+ offset = (src->x1 >> 16) * fb->format->cpp[0]; -+ - offset += (src->y1 >> 16) * fb->pitches[0]; - dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; - -@@ -972,6 +992,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - } - - VOP_WIN_SET(vop, win, format, format); -+ VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); - VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); - VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); -@@ -988,7 +1009,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - uv_obj = fb->obj[1]; - rk_uv_obj = to_rockchip_obj(uv_obj); - -- offset = (src->x1 >> 16) * bpp / hsub; -+ if (fb->format->block_w[1]) -+ offset = (src->x1 >> 16) * bpp / -+ fb->format->block_w[1] / hsub; -+ else -+ offset = (src->x1 >> 16) * bpp / hsub; - offset += (src->y1 >> 16) * fb->pitches[1] / vsub; - - dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 8e6e999e5163..9f50e0e00127 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -161,6 +161,7 @@ struct vop_win_phy { - struct vop_reg enable; - struct vop_reg gate; - struct vop_reg format; -+ struct vop_reg fmt_10; - struct vop_reg rb_swap; - struct vop_reg act_info; - struct vop_reg dsp_info; -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index dd4546f9f410..7d5191421ddf 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -50,6 +50,23 @@ static const uint32_t formats_win_full[] = { - DRM_FORMAT_NV24, - }; - -+static const uint32_t formats_win_full_10[] = { -+ DRM_FORMAT_XRGB8888, -+ DRM_FORMAT_ARGB8888, -+ DRM_FORMAT_XBGR8888, -+ DRM_FORMAT_ABGR8888, -+ DRM_FORMAT_RGB888, -+ DRM_FORMAT_BGR888, -+ DRM_FORMAT_RGB565, -+ DRM_FORMAT_BGR565, -+ DRM_FORMAT_NV12, -+ DRM_FORMAT_NV16, -+ DRM_FORMAT_NV24, -+ DRM_FORMAT_NV15, -+ DRM_FORMAT_NV20, -+ DRM_FORMAT_NV30, -+}; -+ - static const uint64_t format_modifiers_win_full[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID, -@@ -579,11 +596,12 @@ static const struct vop_scl_regs rk3288_win_full_scl = { - - static const struct vop_win_phy rk3288_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), - .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -@@ -720,11 +738,12 @@ static const struct vop_intr rk3368_vop_intr = { - - static const struct vop_win_phy rk3368_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), - .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21), - .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22), -@@ -871,11 +890,12 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { - - static const struct vop_win_phy rk3399_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full, -- .nformats = ARRAY_SIZE(formats_win_full), -+ .data_formats = formats_win_full_10, -+ .nformats = ARRAY_SIZE(formats_win_full_10), - .format_modifiers = format_modifiers_win_full_afbc, - .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), - .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), - .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), - .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), - -From 478dd53361097d99541d777ce0f7fec7a79b7fa8 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 21:11:08 +0200 -Subject: [PATCH] !fixup drm/rockchip: rk3368's vop does not support 10-bit - formats - ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 7d5191421ddf..20c3e6248ec7 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -738,8 +738,8 @@ static const struct vop_intr rk3368_vop_intr = { - - static const struct vop_win_phy rk3368_win01_data = { - .scl = &rk3288_win_full_scl, -- .data_formats = formats_win_full_10, -- .nformats = ARRAY_SIZE(formats_win_full_10), -+ .data_formats = formats_win_full, -+ .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), - .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), - -From 1f05ca5dfe7bd1553d32be9f450614b545be0912 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 23:20:34 +0200 -Subject: [PATCH] drm/rockchip: enable ycbcr_420_allowed and ycbcr_444_allowed - for RK3228 - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index c25ebe31b98d..5562326e4bce 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -515,6 +515,7 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { - - static struct rockchip_hdmi_chip_data rk3228_chip_data = { - .lcdsel_grf_reg = -1, -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { -@@ -523,6 +524,7 @@ static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { - .phy_ops = &rk3228_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", - .phy_force_vendor = true, -+ .ycbcr_420_allowed = true, - }; - - static struct rockchip_hdmi_chip_data rk3288_chip_data = { - -From 4273e39fec795fe18f83414655d30b0b9c5420d9 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:28 +0200 -Subject: [PATCH] drm: rockchip: add scaling for RK3036 win1 - -Add the registers needed to make scaling work on RK3036's win1. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 20c3e6248ec7..93a00b6ac295 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -94,15 +94,20 @@ static const uint64_t format_modifiers_win_lite[] = { - DRM_FORMAT_MOD_INVALID, - }; - --static const struct vop_scl_regs rk3036_win_scl = { -+static const struct vop_scl_regs rk3036_win0_scl = { - .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), - .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), - .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), - .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), - }; - -+static const struct vop_scl_regs rk3036_win1_scl = { -+ .scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0), -+ .scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16), -+}; -+ - static const struct vop_win_phy rk3036_win0_data = { -- .scl = &rk3036_win_scl, -+ .scl = &rk3036_win0_scl, - .data_formats = formats_win_full, - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, -@@ -119,6 +124,7 @@ static const struct vop_win_phy rk3036_win0_data = { - }; - - static const struct vop_win_phy rk3036_win1_data = { -+ .scl = &rk3036_win1_scl, - .data_formats = formats_win_lite, - .nformats = ARRAY_SIZE(formats_win_lite), - .format_modifiers = format_modifiers_win_lite, - -From a05d484d84e54a59c7846d2b409dda1e7355e3de Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:29 +0200 -Subject: [PATCH] drm: rockchip: add missing registers for RK3188 - -Add dither_up, dsp_lut_en and data_blank registers to enable their -respective functionality for RK3188's VOP. -While at that also fix .dsp_blank register which is (only) set though -BIT24 (same as RK3066) - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 93a00b6ac295..f8a898c5bb62 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -528,7 +528,10 @@ static const struct vop_common rk3188_common = { - .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27), - .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), - .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), -- .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), -+ .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24), -+ .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), -+ .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), -+ .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), - }; - - static const struct vop_win_data rk3188_vop_win_data[] = { - -From 6dd7876510c6a23e6d6b1243c730d73e6acb1137 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:44:12 +0200 -Subject: [PATCH] drm: rockchip: add missing registers for RK3066 - -Add dither_up, dsp_lut_en and data_blank registers to enable their -respective functionality for RK3066's VOP. -While at that also fix .rb_swap and .format registers for all windows, -which have to be set though RK3066_SYS_CTRL1. Also remove .scl from -win1: Scaling is only supported on the primary plane. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index f8a898c5bb62..77f8b49a4d17 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -372,8 +372,8 @@ static const struct vop_win_phy rk3066_win0_data = { - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19), - .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), -@@ -384,13 +384,12 @@ static const struct vop_win_phy rk3066_win0_data = { - }; - - static const struct vop_win_phy rk3066_win1_data = { -- .scl = &rk3066_win_scl, - .data_formats = formats_win_full, - .nformats = ARRAY_SIZE(formats_win_full), - .format_modifiers = format_modifiers_win_full, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23), - .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), - .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), -@@ -405,8 +404,8 @@ static const struct vop_win_phy rk3066_win2_data = { - .nformats = ARRAY_SIZE(formats_win_lite), - .format_modifiers = format_modifiers_win_lite, - .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), -- .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), -- .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), -+ .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10), -+ .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27), - .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), - .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), -@@ -431,6 +430,9 @@ static const struct vop_common rk3066_common = { - .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11), - .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10), - .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), -+ .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), -+ .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), -+ .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), - }; - - static const struct vop_win_data rk3066_vop_win_data[] = { - -From 08b0db205ddef2853dd75c0691d7d6d6f94c611b Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:30 +0200 -Subject: [PATCH] drm: rockchip: add alpha support for RK3036, RK3066, RK3126 - and RK3188 - -With commit 2aae8ed1f390 -("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") alpha -support was introduced for PX30's VOP. -RK3036, RK3066, RK3126 and RK3188 VOPs support alpha blending in the -same manner. -With the exception of RK3066 all of them support pre-multiplied alpha. - -Lets add these registers to make this work for those VOPs as well. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 21 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 77f8b49a4d17..27a04c5bc2fd 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -121,6 +121,9 @@ static const struct vop_win_phy rk3036_win0_data = { - .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_phy rk3036_win1_data = { -@@ -136,6 +139,9 @@ static const struct vop_win_phy rk3036_win1_data = { - .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_data rk3036_vop_win_data[] = { -@@ -202,6 +208,9 @@ static const struct vop_win_phy rk3126_win1_data = { - .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_data rk3126_vop_win_data[] = { -@@ -381,6 +390,8 @@ static const struct vop_win_phy rk3066_win0_data = { - .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0), - }; - - static const struct vop_win_phy rk3066_win1_data = { -@@ -397,6 +408,8 @@ static const struct vop_win_phy rk3066_win1_data = { - .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0), - .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1), - }; - - static const struct vop_win_phy rk3066_win2_data = { -@@ -410,6 +423,8 @@ static const struct vop_win_phy rk3066_win2_data = { - .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0), -+ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23), -+ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2), - }; - - static const struct vop_modeset rk3066_modeset = { -@@ -495,6 +510,9 @@ static const struct vop_win_phy rk3188_win0_data = { - .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), - .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), -+ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18), -+ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0), -+ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_win_phy rk3188_win1_data = { -@@ -509,6 +527,9 @@ static const struct vop_win_phy rk3188_win1_data = { - .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), - .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), - .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), -+ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19), -+ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1), -+ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), - }; - - static const struct vop_modeset rk3188_modeset = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -index 6e9fa5815d4d..0b3cd65ba5c1 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h -@@ -955,6 +955,7 @@ - #define RK3188_DSP_CTRL0 0x04 - #define RK3188_DSP_CTRL1 0x08 - #define RK3188_INT_STATUS 0x10 -+#define RK3188_ALPHA_CTRL 0x14 - #define RK3188_WIN0_YRGB_MST0 0x20 - #define RK3188_WIN0_CBR_MST0 0x24 - #define RK3188_WIN0_YRGB_MST1 0x28 - -From 9fb777928ddfedc0412fa79b320814c06b7195cf Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:13:31 +0200 -Subject: [PATCH] drm: rockchip: set alpha_en to 0 if it is not used - -alpha_en should be set to 0 if it is not used, i.e. to disable alpha -blending if it was enabled before and should be disabled now. - -Fixes: 2aae8ed1f390 ("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 413534cf1a93..9b1cc0f413fc 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1062,6 +1062,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - VOP_WIN_SET(vop, win, alpha_en, 1); - } else { - VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); -+ VOP_WIN_SET(vop, win, alpha_en, 0); - } - - VOP_WIN_SET(vop, win, enable, 1); - -From 9be348c6cade7e709be7347d336c7638bf603b46 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sat, 15 Aug 2020 23:38:05 +0200 -Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3188 - ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 27a04c5bc2fd..b47f036d4a2c 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -555,6 +555,7 @@ static const struct vop_common rk3188_common = { - .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), - .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), - .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), -+ .dsp_data_swap = VOP_REG(RK3188_DSP_CTRL1, 0x1f, 26), - }; - - static const struct vop_win_data rk3188_vop_win_data[] = { - -From 195b202dbc5abe9c65e029826a7f3e2a2d71067a Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 22 Jul 2020 20:22:02 +0200 -Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3066 - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index b47f036d4a2c..ae4a27704ad6 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -448,6 +448,7 @@ static const struct vop_common rk3066_common = { - .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), - .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), - .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), -+ .dsp_data_swap = VOP_REG(RK3066_DSP_CTRL1, 0x1f, 26), - }; - - static const struct vop_win_data rk3066_vop_win_data[] = { - -From 526739e44d5b0936db93bb92d2a98835723502c3 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 16 Aug 2020 00:55:19 +0200 -Subject: [PATCH] drm/rockchip: inno hdmi - add audio support - add required - aclk - fix video timing - fix phy pre-emphasis - ---- - .../display/rockchip/inno_hdmi-rockchip.txt | 6 +- - arch/arm/boot/dts/rk3036.dtsi | 24 +- - drivers/gpu/drm/rockchip/inno_hdmi.c | 266 +++++++++++++++++- - drivers/gpu/drm/rockchip/inno_hdmi.h | 2 + - 4 files changed, 279 insertions(+), 19 deletions(-) - -diff --git a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -index cec21714f0e0..b022c931e186 100644 ---- a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -+++ b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt -@@ -7,7 +7,7 @@ Required properties: - - reg: - Physical base address and length of the controller's registers. - - clocks, clock-names: -- Phandle to hdmi controller clock, name should be "pclk" -+ Phandle to hdmi controller clock, name should be "aclk" and "pclk". - - interrupts: - HDMI interrupt number - - ports: -@@ -21,8 +21,8 @@ hdmi: hdmi@20034000 { - compatible = "rockchip,rk3036-inno-hdmi"; - reg = <0x20034000 0x4000>; - interrupts = ; -- clocks = <&cru PCLK_HDMI>; -- clock-names = "pclk"; -+ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; -+ clock-names = "aclk", "pclk"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_ctl>; - -diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi -index d7668a437c70..a86e1dc7fb5b 100644 ---- a/arch/arm/boot/dts/rk3036.dtsi -+++ b/arch/arm/boot/dts/rk3036.dtsi -@@ -397,11 +397,14 @@ hdmi: hdmi@20034000 { - compatible = "rockchip,rk3036-inno-hdmi"; - reg = <0x20034000 0x4000>; - interrupts = ; -- clocks = <&cru PCLK_HDMI>; -- clock-names = "pclk"; -+ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; -+ clock-names = "aclk", "pclk"; - rockchip,grf = <&grf>; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_ctl>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - status = "disabled"; - - hdmi_in: port { -@@ -414,6 +417,23 @@ hdmi_in_vop: endpoint@0 { - }; - }; - -+ hdmi_sound: hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "HDMI"; -+ status = "disabled"; -+ -+ simple-audio-card,dai-link { -+ format = "i2s"; -+ mclk-fs = <256>; -+ cpu { -+ sound-dai = <&i2s>; -+ }; -+ codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ }; -+ - timer: timer@20044000 { - compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer"; - reg = <0x20044000 0x20>; -diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c -index 7afdc54eb3ec..7e93208609a0 100644 ---- a/drivers/gpu/drm/rockchip/inno_hdmi.c -+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -21,6 +22,8 @@ - #include - #include - -+#include -+ - #include "rockchip_drm_drv.h" - #include "rockchip_drm_vop.h" - -@@ -28,6 +31,12 @@ - - #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x) - -+struct audio_info { -+ int sample_rate; -+ int channels; -+ int sample_width; -+}; -+ - struct hdmi_data_info { - int vic; - bool sink_is_hdmi; -@@ -52,8 +61,10 @@ struct inno_hdmi { - struct drm_device *drm_dev; - - int irq; -+ struct clk *aclk; - struct clk *pclk; - void __iomem *regs; -+ struct regmap *regmap; - - struct drm_connector connector; - struct drm_encoder encoder; -@@ -63,6 +74,9 @@ struct inno_hdmi { - - unsigned int tmds_rate; - -+ struct platform_device *audio_pdev; -+ bool audio_enable; -+ - struct hdmi_data_info hdmi_data; - struct drm_display_mode previous_mode; - }; -@@ -189,11 +203,17 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) - - static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) - { -+ -+ u8 value; -+ - switch (mode) { - case NORMAL: - inno_hdmi_sys_power(hdmi, false); -- -- hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); -+ if (hdmi->tmds_rate > 140000000) -+ value = 0x6f; -+ else -+ value = 0x3f; -+ hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, value); - hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); - - hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); -@@ -301,6 +321,21 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, - return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0); - } - -+static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi, -+ struct audio_info *audio) -+{ -+ struct hdmi_audio_infoframe *faudio; -+ union hdmi_infoframe frame; -+ int rc; -+ -+ rc = hdmi_audio_infoframe_init(&frame.audio); -+ faudio = (struct hdmi_audio_infoframe *)&frame; -+ -+ faudio->channels = audio->channels; -+ -+ return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AAI, 0, 0, 0); -+} -+ - static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) - { - struct hdmi_data_info *data = &hdmi->hdmi_data; -@@ -383,6 +418,11 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - { - int value; - -+ value = BIT(20) | BIT(21); -+ value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; -+ value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; -+ regmap_write(hdmi->regmap, 0x148, value); -+ - /* Set detail external video timing polarity and interlace mode */ - value = v_EXTERANL_VIDEO(1); - value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? -@@ -402,7 +442,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF); - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); - -- value = mode->hsync_start - mode->hdisplay; -+ value = mode->htotal - mode->hsync_start; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF); - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); - -@@ -417,7 +457,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, - value = mode->vtotal - mode->vdisplay; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF); - -- value = mode->vsync_start - mode->vdisplay; -+ value = mode->vtotal - mode->vsync_start; - hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF); - - value = mode->vsync_end - mode->vsync_start; -@@ -473,8 +513,9 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, - inno_hdmi_i2c_init(hdmi); - - /* Unmute video and audio output */ -- hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, -- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0)); -+ if (hdmi->audio_enable) -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0)); - - return 0; - } -@@ -521,6 +562,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, - - s->output_mode = ROCKCHIP_OUT_MODE_P888; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ s->bus_format = MEDIA_BUS_FMT_RGB888_1X24; - - return 0; - } -@@ -597,6 +639,175 @@ static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { - .mode_valid = inno_hdmi_connector_mode_valid, - }; - -+int inno_hdmi_audio_config_set(struct inno_hdmi *hdmi, struct audio_info *audio) -+{ -+ int rate, N, channel; -+ -+ if (audio->channels < 3) -+ channel = I2S_CHANNEL_1_2; -+ else if (audio->channels < 5) -+ channel = I2S_CHANNEL_3_4; -+ else if (audio->channels < 7) -+ channel = I2S_CHANNEL_5_6; -+ else -+ channel = I2S_CHANNEL_7_8; -+ -+ switch (audio->sample_rate) { -+ case 32000: -+ rate = AUDIO_32K; -+ N = N_32K; -+ break; -+ case 44100: -+ rate = AUDIO_441K; -+ N = N_441K; -+ break; -+ case 48000: -+ rate = AUDIO_48K; -+ N = N_48K; -+ break; -+ case 88200: -+ rate = AUDIO_882K; -+ N = N_882K; -+ break; -+ case 96000: -+ rate = AUDIO_96K; -+ N = N_96K; -+ break; -+ case 176400: -+ rate = AUDIO_1764K; -+ N = N_1764K; -+ break; -+ case 192000: -+ rate = AUDIO_192K; -+ N = N_192K; -+ break; -+ default: -+ dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", -+ __func__, audio->sample_rate); -+ return -ENOENT; -+ } -+ -+ /* set_audio source I2S */ -+ hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); -+ hdmi_writeb(hdmi, AUDIO_SAMPLE_RATE, rate); -+ hdmi_writeb(hdmi, AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | -+ v_I2S_CHANNEL(channel)); -+ -+ hdmi_writeb(hdmi, AUDIO_I2S_MAP, 0x00); -+ hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, 0); -+ -+ /* Set N value */ -+ hdmi_writeb(hdmi, AUDIO_N_H, (N >> 16) & 0x0F); -+ hdmi_writeb(hdmi, AUDIO_N_M, (N >> 8) & 0xFF); -+ hdmi_writeb(hdmi, AUDIO_N_L, N & 0xFF); -+ -+ /*Set hdmi nlpcm mode to support hdmi bitstream*/ -+ hdmi_writeb(hdmi, HDMI_AUDIO_CHANNEL_STATUS, v_AUDIO_STATUS_NLPCM(0)); -+ -+ return inno_hdmi_config_audio_aai(hdmi, audio); -+} -+ -+static int inno_hdmi_audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ struct audio_info audio = { -+ .sample_width = params->sample_width, -+ .sample_rate = params->sample_rate, -+ .channels = params->channels, -+ }; -+ -+ if (!hdmi->hdmi_data.sink_has_audio) { -+ dev_err(hdmi->dev, "Sink do not support audio!\n"); -+ return -ENODEV; -+ } -+ -+ if (!hdmi->encoder.crtc) -+ return -ENODEV; -+ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ break; -+ default: -+ dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt); -+ return -EINVAL; -+ } -+ -+ return inno_hdmi_audio_config_set(hdmi, &audio); -+} -+ -+static void inno_hdmi_audio_shutdown(struct device *dev, void *data) -+{ -+ /* do nothing */ -+} -+ -+static int inno_hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ -+ if (!hdmi->hdmi_data.sink_has_audio) { -+ dev_err(hdmi->dev, "Sink do not support audio!\n"); -+ return -ENODEV; -+ } -+ -+ hdmi->audio_enable = !mute; -+ -+ if (mute) -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, -+ v_AUDIO_MUTE(1) | v_AUDIO_PD(1)); -+ else -+ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, -+ v_AUDIO_MUTE(0) | v_AUDIO_PD(0)); -+ -+ return 0; -+} -+ -+static int inno_hdmi_audio_get_eld(struct device *dev, void *data, -+ uint8_t *buf, size_t len) -+{ -+ struct inno_hdmi *hdmi = dev_get_drvdata(dev); -+ struct drm_mode_config *config = &hdmi->encoder.dev->mode_config; -+ struct drm_connector *connector; -+ int ret = -ENODEV; -+ -+ mutex_lock(&config->mutex); -+ list_for_each_entry(connector, &config->connector_list, head) { -+ if (&hdmi->encoder == connector->encoder) { -+ memcpy(buf, connector->eld, -+ min(sizeof(connector->eld), len)); -+ ret = 0; -+ } -+ } -+ mutex_unlock(&config->mutex); -+ -+ return ret; -+} -+ -+static const struct hdmi_codec_ops audio_codec_ops = { -+ .hw_params = inno_hdmi_audio_hw_params, -+ .audio_shutdown = inno_hdmi_audio_shutdown, -+ //.digital_mute = inno_hdmi_audio_digital_mute, -+ .get_eld = inno_hdmi_audio_get_eld, -+}; -+ -+static int inno_hdmi_audio_codec_init(struct inno_hdmi *hdmi, -+ struct device *dev) -+{ -+ struct hdmi_codec_pdata codec_data = { -+ .i2s = 1, -+ .ops = &audio_codec_ops, -+ .max_i2s_channels = 8, -+ }; -+ -+ hdmi->audio_enable = false; -+ hdmi->audio_pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE, -+ &codec_data, sizeof(codec_data)); -+ -+ return PTR_ERR_OR_ZERO(hdmi->audio_pdev); -+} -+ - static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) - { - struct drm_encoder *encoder = &hdmi->encoder; -@@ -627,6 +838,8 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) - - drm_connector_attach_encoder(&hdmi->connector, encoder); - -+ inno_hdmi_audio_codec_init(hdmi, dev); -+ - return 0; - } - -@@ -826,23 +1039,44 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->regs)) - return PTR_ERR(hdmi->regs); - -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ hdmi->aclk = devm_clk_get(hdmi->dev, "aclk"); -+ if (IS_ERR(hdmi->aclk)) { -+ dev_err(hdmi->dev, "Unable to get HDMI aclk clk\n"); -+ return PTR_ERR(hdmi->aclk); -+ } -+ - hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); - if (IS_ERR(hdmi->pclk)) { - DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); - return PTR_ERR(hdmi->pclk); - } - -+ ret = clk_prepare_enable(hdmi->aclk); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, -+ "Cannot enable HDMI aclk clock: %d\n", ret); -+ return ret; -+ } -+ -+ - ret = clk_prepare_enable(hdmi->pclk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Cannot enable HDMI pclk clock: %d\n", ret); -- return ret; -+ goto err_disable_aclk; - } - -- irq = platform_get_irq(pdev, 0); -- if (irq < 0) { -- ret = irq; -- goto err_disable_clk; -+ hdmi->regmap = -+ syscon_regmap_lookup_by_phandle(hdmi->dev->of_node, -+ "rockchip,grf"); -+ if (IS_ERR(hdmi->regmap)) { -+ dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); -+ ret = PTR_ERR(hdmi->regmap); -+ goto err_disable_aclk; - } - - inno_hdmi_reset(hdmi); -@@ -851,7 +1085,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - if (IS_ERR(hdmi->ddc)) { - ret = PTR_ERR(hdmi->ddc); - hdmi->ddc = NULL; -- goto err_disable_clk; -+ goto err_disable_pclk; - } - - /* -@@ -884,9 +1118,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, - hdmi->encoder.funcs->destroy(&hdmi->encoder); - err_put_adapter: - i2c_put_adapter(hdmi->ddc); --err_disable_clk: -+err_disable_pclk: - clk_disable_unprepare(hdmi->pclk); -- return ret; -+err_disable_aclk: -+ clk_disable_unprepare(hdmi->aclk); -+ -+return ret; - } - - static void inno_hdmi_unbind(struct device *dev, struct device *master, -@@ -899,6 +1136,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, - - i2c_put_adapter(hdmi->ddc); - clk_disable_unprepare(hdmi->pclk); -+ clk_disable_unprepare(hdmi->aclk); - } - - static const struct component_ops inno_hdmi_ops = { -diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h -index 93245b55f967..b722afc4e41f 100644 ---- a/drivers/gpu/drm/rockchip/inno_hdmi.h -+++ b/drivers/gpu/drm/rockchip/inno_hdmi.h -@@ -96,11 +96,13 @@ enum { - #define HDMI_AV_MUTE 0x05 - #define m_AVMUTE_CLEAR (1 << 7) - #define m_AVMUTE_ENABLE (1 << 6) -+#define m_AUDIO_PD (1 << 2) - #define m_AUDIO_MUTE (1 << 1) - #define m_VIDEO_BLACK (1 << 0) - #define v_AVMUTE_CLEAR(n) (n << 7) - #define v_AVMUTE_ENABLE(n) (n << 6) - #define v_AUDIO_MUTE(n) (n << 1) -+#define v_AUDIO_PD(n) (n << 2) - #define v_VIDEO_MUTE(n) (n << 0) - - #define HDMI_VIDEO_TIMING_CTL 0x08 - -From a8d962000848a237f8e8f0de8395d4e7df2a7197 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Sun, 16 Aug 2020 23:40:24 +0200 -Subject: [PATCH] WIP: ARM: dts: rockchip add vpll clock to RK322Xs hdmi node - ---- - arch/arm/boot/dts/rk322x.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 4bc631881c05..f98a945c68d3 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -766,8 +766,8 @@ hdmi: hdmi@200a0000 { - interrupts = ; - assigned-clocks = <&cru SCLK_HDMI_PHY>; - assigned-clock-parents = <&hdmi_phy>; -- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>; -- clock-names = "isfr", "iahb", "cec"; -+ clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>; -+ clock-names = "isfr", "iahb", "vpll", "cec"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>; - resets = <&cru SRST_HDMI_P>; - -From 30c781872a7b883b18193fa5aed75c312b06f4ab Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 18 Nov 2017 11:09:39 +0100 -Subject: [PATCH] rockchip: vop: force skip lines if image too big - ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 9b1cc0f413fc..a34ff7593e1f 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -932,6 +932,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - int format; - int is_yuv = fb->format->is_yuv; - int i; -+ int skiplines = 0; - - /* - * can't update plane when vop is disabled. -@@ -950,8 +951,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - obj = fb->obj[0]; - rk_obj = to_rockchip_obj(obj); - -+ /* -+ * Force skip lines when image is yuv and 3840 width, -+ * fixes a "jumping" green lines issue on RK3328. -+ */ - actual_w = drm_rect_width(src) >> 16; -- actual_h = drm_rect_height(src) >> 16; -+ if (actual_w == 3840 && is_yuv) -+ skiplines = 1; -+ actual_h = drm_rect_height(src) >> (16 + skiplines); - act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); - - dsp_info = (drm_rect_height(dest) - 1) << 16; -@@ -993,7 +1000,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - - VOP_WIN_SET(vop, win, format, format); - VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); -- VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); -+ VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4 >> skiplines)); - VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); - VOP_WIN_SET(vop, win, y_mir_en, -@@ -1017,7 +1024,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - offset += (src->y1 >> 16) * fb->pitches[1] / vsub; - - dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; -- VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); -+ VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4 >> skiplines)); - VOP_WIN_SET(vop, win, uv_mst, dma_addr); - - for (i = 0; i < NUM_YUV2YUV_COEFFICIENTS; i++) { - -From b26ffb40570c456d0f84a3fa7886e2120c0397c2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 26 May 2020 13:48:12 +0200 -Subject: [PATCH] drm: bridge: it66121: add IT66121FN variant - ---- - drivers/gpu/drm/bridge/ite-it66121.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 7e1a90319a6a..68f7e50fdddd 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -242,6 +242,11 @@ static const struct it66121_conf it66121_conf_simple = { - .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, - }; - -+static const struct it66121_conf it66121fn_conf_simple = { -+ .input_mode_reg = IT66121_INPUT_MODE_RGB, -+ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, -+}; -+ - static void it66121_hw_reset(struct it66121_ctx *ctx) - { - gpiod_set_value(ctx->gpio_reset, 1); -@@ -970,6 +975,9 @@ static const struct of_device_id it66121_dt_match[] = { - { .compatible = "ite,it66121", - .data = &it66121_conf_simple, - }, -+ { .compatible = "ite,it66121fn", -+ .data = &it66121fn_conf_simple, -+ }, - { }, - }; - MODULE_DEVICE_TABLE(of, it66121_dt_match); - -From a52fbdfbb0bccb1202beb25b58bdc29517c178d2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 23:15:45 +0200 -Subject: [PATCH] HACK: drm/rockchip: return false in ... if no platform device - is found - -This check will perfectly fail for bridges which are connected via i2c -and are therefore no platform devices. -TODO: look for a smarter solution - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -index b7654f5e4225..44ec8003e2a4 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c -@@ -274,7 +274,7 @@ int rockchip_drm_endpoint_is_subdriver(struct device_node *ep) - pdev = of_find_device_by_node(node); - of_node_put(node); - if (!pdev) -- return -ENODEV; -+ return false; - - /* - * All rockchip subdrivers have probed at this point, so - -From 1fca49c650ba0441613da75e43323afb5525c8de Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 14:22:32 +0200 -Subject: [PATCH] drm/bridge: it66121 fix regmap config - -registers 0x00~0x2f don't need/must not have a selector -also: fix regmap range ---- - drivers/gpu/drm/bridge/ite-it66121.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 68f7e50fdddd..90f0881818d6 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -218,21 +218,21 @@ struct it66121_ctx { - - static const struct regmap_range_cfg it66121_regmap_banks[] = { - { -- .name = "it66121", -- .range_min = 0x00, -- .range_max = 0x1FF, -+ .name = "it66121-banks", -+ .range_min = 0x30, -+ .range_max = 0x1bf, - .selector_reg = IT66121_CLK_BANK_REG, - .selector_mask = 0x1, - .selector_shift = 0, -- .window_start = 0x00, -- .window_len = 0x130, -+ .window_start = 0x30, -+ .window_len = 0xcf, - }, - }; - - static const struct regmap_config it66121_regmap_config = { - .val_bits = 8, - .reg_bits = 8, -- .max_register = 0x1FF, -+ .max_register = 0x1bf, - .ranges = it66121_regmap_banks, - .num_ranges = ARRAY_SIZE(it66121_regmap_banks), - }; - -From 525f46ff24e5db028d341d04d1aede0cfc672c39 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 17:29:54 +0200 -Subject: [PATCH] drm/bridge: it66121 add detection message - ---- - drivers/gpu/drm/bridge/ite-it66121.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 90f0881818d6..650dd2f063cc 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -936,8 +936,11 @@ static int it66121_probe(struct i2c_client *client, - ids[2] != IT66121_DEVICE_ID0 || - ((ids[3] & IT66121_DEVICE_MASK) != IT66121_DEVICE_ID1)) { - ite66121_power_off(ctx); -+ DRM_INFO("HDMITX it66121 could not be indentified.\n"); - return -ENODEV; -- } -+ } else -+ DRM_INFO("HDMITX it66121 rev %d succsessfully indentified.\n", -+ ids[3] >> 4); - - ctx->bridge.funcs = &it66121_bridge_funcs; - ctx->bridge.of_node = dev->of_node; - -From ff31ba7e3c18672f7fa3ac17f9399301cc55cacb Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:28:21 +0200 -Subject: [PATCH] drm/bridge it66121 add AFE_XP_PLL_CTRL settings - -Add IT66121_AFE_XP_PLL_CTRL settings, it's unknown what they actualy -mean, since there is no documentation about it. Values have been taken -from vendor driver and it helps stablize signal at 1080p modes. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 650dd2f063cc..bc6ca85e5ee1 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -72,6 +72,10 @@ - #define IT66121_AFE_XP_EC1_REG 0x68 - #define IT66121_AFE_XP_EC1_LOWCLK BIT(4) - -+#define IT66121_AFE_XP_PLL_CTRL 0x6a -+#define IT66121_AFE_XP_PLL_HIGH_CLK_MASK (BIT(4) | BIT(5) | \ -+ BIT(6)) -+ - #define IT66121_SW_RST_REG 0x04 - #define IT66121_SW_RST_REF BIT(5) - #define IT66121_SW_RST_AREF BIT(4) -@@ -325,6 +329,13 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_AFE_XP_EC1_LOWCLK, 0x80); - if (ret) - return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_PLL_CTRL, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK); -+ if (ret) -+ return ret; -+ - } else { - ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, - IT66121_AFE_XP_GAINBIT | -@@ -346,6 +357,13 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_AFE_XP_EC1_LOWCLK); - if (ret) - return ret; -+ -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_PLL_CTRL, -+ IT66121_AFE_XP_PLL_HIGH_CLK_MASK, -+ ~(IT66121_AFE_XP_PLL_HIGH_CLK_MASK) & 0xff); -+ if (ret) -+ return ret; - } - - /* Clear reset flags */ - -From 2a962b60c92993e1a1c82e74a403b33641d1cfbd Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Wed, 19 Aug 2020 19:02:02 +0200 -Subject: [PATCH] drm/bridge it66121 fire_afe if IT66121_SYS_STATUS_VID_STABLE - -There is an interrupt if video is stable - we should fire afe after that -arrived. - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 101 ++++++++++++++++++++++----- - 1 file changed, 83 insertions(+), 18 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index bc6ca85e5ee1..81d1f53d50f5 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -95,12 +95,30 @@ - #define IT66121_HDCP_EN1P1FEAT BIT(1) - - #define IT66121_INT_STATUS1_REG 0x06 --#define IT66121_INT_STATUS1_AUD_OVF BIT(7) --#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) --#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) --#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) --#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) --#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) -+#define IT66121_INT_STATUS1_AUD_OVF BIT(7) -+#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) -+#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) -+#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) -+#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) -+#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) -+ -+#define IT66121_INT_STATUS2_REG 0x07 -+#define IT66121_INT_STATUS2_PKT_3D BIT(7) -+#define IT66121_INT_STATUS2_VID_UNSTABLE BIT(6) -+#define IT66121_INT_STATUS2_PKT_ACP BIT(5) -+#define IT66121_INT_STATUS2_PKT_NULL BIT(4) -+#define IT66121_INT_STATUS2_PKT_GEN BIT(3) -+#define IT66121_INT_STATUS2_CHK_KSV_LIST BIT(2) -+#define IT66121_INT_STATUS2_AUTH_DONE BIT(1) -+#define IT66121_INT_STATUS2_AUTH_FAIL BIT(0) -+ -+#define IT66121_INT_STATUS3_REG 0x08 -+#define IT66121_INT_STATUS3_AUD_CTS BIT(6) -+#define IT66121_INT_STATUS3_VSYNC BIT(5) -+#define IT66121_INT_STATUS3_VID_STABLE BIT(4) -+#define IT66121_INT_STATUS2_PKT_MPEG BIT(3) -+#define IT66121_INT_STATUS3_PKT_AUD BIT(1) -+#define IT66121_INT_STATUS3_PKT_AVI BIT(0) - - #define IT66121_DDC_HEADER_REG 0x11 - #define IT66121_DDC_HEADER_HDCP 0x74 -@@ -132,16 +150,43 @@ - #define IT66121_INT_MASK1_RX_SENS BIT(1) - #define IT66121_INT_MASK1_HPD BIT(0) - -+#define IT66121_INT_MASK2_REG 0x0a -+#define IT66121_INT_MASK2_PKT_AVI BIT(7) -+#define IT66121_INT_MASK2_VID_UNSTABLE BIT(6) -+#define IT66121_INT_MASK2_PKT_ACP BIT(5) -+#define IT66121_INT_MASK2_PKT_NULL BIT(4) -+#define IT66121_INT_MASK2_PKT_GEN BIT(3) -+#define IT66121_INT_MASK2_CHK_KSV_LIST BIT(2) -+#define IT66121_INT_MASK2_AUTH_DONE BIT(1) -+#define IT66121_INT_MASK2_AUTH_FAIL BIT(0) -+ -+#define IT66121_INT_MASK3_REG 0x0b -+#define IT66121_INT_MASK3_PKT_3D BIT(6) -+#define IT66121_INT_MASK3_AUD_CTS BIT(5) -+#define IT66121_INT_MASK3_VSYNC BIT(4) -+#define IT66121_INT_MASK3_VID_STABLE BIT(3) -+#define IT66121_INT_MASK3_PKT_MPEG BIT(2) -+#define IT66121_INT_MASK3_PKT_AUD BIT(0) -+ - #define IT66121_INT_CLR1_REG 0x0C --#define IT66121_INT_CLR1_PKTACP BIT(7) --#define IT66121_INT_CLR1_PKTNULL BIT(6) --#define IT66121_INT_CLR1_PKTGEN BIT(5) --#define IT66121_INT_CLR1_KSVLISTCHK BIT(4) --#define IT66121_INT_CLR1_AUTHDONE BIT(3) --#define IT66121_INT_CLR1_AUTHFAIL BIT(2) -+#define IT66121_INT_CLR1_PKT_ACP BIT(7) -+#define IT66121_INT_CLR1_PKT_NULL BIT(6) -+#define IT66121_INT_CLR1_PKT_GEN BIT(5) -+#define IT66121_INT_CLR1_CHK_KSV_LIST BIT(4) -+#define IT66121_INT_CLR1_AUTH_DONE BIT(3) -+#define IT66121_INT_CLR1_AUTH_FAIL BIT(2) - #define IT66121_INT_CLR1_RX_SENS BIT(1) - #define IT66121_INT_CLR1_HPD BIT(0) - -+#define IT66121_INT_CLR2_REG 0x0d -+#define IT66121_INT_CLR2_VSYNC BIT(7) -+#define IT66121_INT_CLR2_VID_STABLE BIT(6) -+#define IT66121_INT_CLR2_PKT_MPEG BIT(5) -+#define IT66121_INT_CLR2_PKT_AUD BIT(3) -+#define IT66121_INT_CLR2_PKT_AVI BIT(2) -+#define IT66121_INT_CLR2_PKT_3D BIT(1) -+#define IT66121_INT_CLR2_VID_UNSTABLE BIT(0) -+ - #define IT66121_AV_MUTE_REG 0xC1 - #define IT66121_AV_MUTE_ON BIT(0) - #define IT66121_AV_MUTE_BLUESCR BIT(1) -@@ -371,10 +416,9 @@ static int it66121_configure_afe(struct it66121_ctx *ctx, - IT66121_SW_RST_REF | IT66121_SW_RST_VID, - ~(IT66121_SW_RST_REF | IT66121_SW_RST_VID) & - 0xFF); -- if (ret) -- return ret; - -- return it66121_fire_afe(ctx); -+ return ret; -+ - } - - static inline int it66121_wait_ddc_ready(struct it66121_ctx *ctx) -@@ -711,6 +755,12 @@ static int it66121_bridge_attach(struct drm_bridge *bridge, - return ret; - - /* Start interrupts */ -+ ret = regmap_write_bits(ctx->regmap, IT66121_INT_MASK3_REG, -+ IT66121_INT_MASK3_VID_STABLE, -+ ~(IT66121_INT_MASK3_VID_STABLE) & 0xff); -+ if (ret) -+ return ret; -+ - return regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, - IT66121_INT_MASK1_DDC_NOACK | - IT66121_INT_MASK1_HPD | -@@ -847,18 +897,18 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = { - static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - { - int ret; -- unsigned int val; -+ unsigned int val, sys_status; - struct it66121_ctx *ctx = dev_id; - struct device *dev = ctx->dev; - bool event = false; - - mutex_lock(&ctx->lock); - -- ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val); -+ ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &sys_status); - if (ret) - goto unlock; - -- if (val & IT66121_SYS_STATUS_ACTIVE_IRQ) { -+ if (sys_status & IT66121_SYS_STATUS_ACTIVE_IRQ) { - ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); - if (ret) { - dev_err(dev, "Cannot read STATUS1_REG %d\n", ret); -@@ -882,6 +932,21 @@ static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - } - } - -+ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS3_REG, &val); -+ if (ret) { -+ dev_err(dev, "Cannot read STATUS3_REG %d\n", ret); -+ } else if (val) { -+ if (val & IT66121_INT_STATUS3_VID_STABLE) { -+ if (sys_status & IT66121_SYS_STATUS_VID_STABLE) -+ it66121_fire_afe(ctx); -+ -+ regmap_write_bits(ctx->regmap, -+ IT66121_INT_CLR2_REG, -+ IT66121_INT_CLR2_VID_STABLE, -+ IT66121_INT_CLR2_VID_STABLE); -+ } -+ } -+ - regmap_write_bits(ctx->regmap, IT66121_SYS_STATUS_REG, - IT66121_SYS_STATUS_CLEAR_IRQ, - IT66121_SYS_STATUS_CLEAR_IRQ); - -From 2ec0caed703ceb5aad46c162c1f3fde4789fd635 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:44:12 +0200 -Subject: [PATCH] drm/bridge it66121: add I2S sound support - -Add sound support for it66121 - todos: - - TODOs - - refactor some huge functions - - smarter error handling (whole driver) - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/Kconfig | 1 + - drivers/gpu/drm/bridge/ite-it66121.c | 685 +++++++++++++++++++++++++++ - 2 files changed, 686 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig -index 6fe281070602..fd026f7cb4ba 100644 ---- a/drivers/gpu/drm/bridge/Kconfig -+++ b/drivers/gpu/drm/bridge/Kconfig -@@ -64,6 +64,7 @@ config DRM_LONTIUM_LT9611 - config DRM_ITE_IT66121 - tristate "ITE IT66121 HDMI bridge" - depends on OF -+ select SND_SOC_HDMI_CODEC if SND_SOC - select DRM_KMS_HELPER - select REGMAP_I2C - help -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 81d1f53d50f5..98f3d68fe01f 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* -+ * Copyright (C) 2020 Alex Bee - * Copyright (C) 2020 BayLibre, SAS - * Author: Phong LE - * Copyright (C) 2018-2019, Artem Mygaiev -@@ -26,6 +27,9 @@ - #include - #include - -+#include -+#include -+ - #define IT66121_MASTER_SEL_REG 0x10 - #define IT66121_MASTER_SEL_HOST BIT(0) - -@@ -245,11 +249,149 @@ - #define IT66121_EDID_FIFO_SIZE 32 - #define IT66121_AFE_CLK_HIGH 80000 - -+#define IT66121_AUD_CLK_CTRL_REG 0x58 -+#define IT66121_AUD_AUT_IP_CLK BIT(0) -+#define IT66121_AUD_AUT_OVR_SMPL_CLK BIT(4) -+#define IT66121_AUD_EXT_MCLK_128FS (0 << 2) -+#define IT66121_AUD_EXT_MCLK_256FS BIT(2) -+#define IT66121_AUD_EXT_MCLK_512FS (2 << 2) -+#define IT66121_AUD_EXT_MCLK_1024FS (3 << 2) -+ -+#define IT66121_AUD_INFO_REG_SZ 5 -+#define IT66121_AUD_INFO_DB1_REG 0x168 -+#define IT66121_AUD_INFO_DB2_REG 0x169 -+#define IT66121_AUD_INFO_DB3_REG 0x16a -+#define IT66121_AUD_INFO_DB4_REG 0x16b -+#define IT66121_AUD_INFO_DB5_REG 0x16c -+#define IT66121_AUD_INFO_CSUM_REG 0x16d -+ -+#define IT66121_AUD_INFO_PKT_REG 0xce -+#define IT66121_AUD_INFO_PKT_ON BIT(0) -+#define IT66121_AUD_INFO_PKT_RPT BIT(1) -+ -+#define IT66121_AUD_PKT_N1_REG 0x133 -+#define IT66121_AUD_PKT_N2_REG 0x134 -+#define IT66121_AUD_PKT_N3_REG 0x135 -+ -+#define IT66121_AUD_PKT_CTS_MODE_REG 0xc5 -+#define IT66121_AUD_PKT_CTS_MODE_USER BIT(1) -+#define IT66121_AUD_PKT_CTS_MODE_AUTO_VAL 0 -+#define IT66121_AUD_PKT_CTS1_REG 0x130 -+#define IT66121_AUD_PKT_CTS2_REG 0x131 -+#define IT66121_AUD_PKT_CTS3_REG 0x132 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS1_REG 0x135 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS2_REG 0x136 -+#define IT66121_AUD_PKT_AUTO_CNT_CTS3_REG 0x137 -+ -+#define IT66121_AUD_CHST_MODE_REG 0x191 -+#define IT66121_AUD_CHST_MODE_NLPCM BIT(1) -+#define IT66121_AUD_CHST_CAT_REG 0x192 -+#define IT66121_AUD_CHST_SRCNUM_REG 0x193 -+#define IT66121_AUD_CHST_CHTNUM_REG 0x194 -+#define IT66121_AUD_CHST_CA_FS_REG 0x198 -+#define IT66121_AUD_CHST_OFS_WL_REG 0x199 -+ -+#define IT66121_AUD_CTRL0_REG 0xe0 -+#define IT66121_AUD_SWL_16BIT (0 << 6) -+#define IT66121_AUD_SWL_18BIT BIT(6) -+#define IT66121_AUD_SWL_20BIT (2 << 6) -+#define IT66121_AUD_SWL_24BIT (3 << 6) -+#define IT66121_AUD_SWL_MASK IT66121_AUD_SWL_24BIT -+#define IT66121_AUD_SPDIFTC BIT(5) -+#define IT66121_AUD_SPDIF BIT(4) -+#define IT66121_AUD_I2S (0 << 4) -+#define IT66121_AUD_TYPE_MASK IT66121_AUD_SPDIF -+#define IT66121_AUD_EN_I2S3 BIT(3) -+#define IT66121_AUD_EN_I2S2 BIT(2) -+#define IT66121_AUD_EN_I2S1 BIT(1) -+#define IT66121_AUD_EN_I2S0 BIT(0) -+#define IT66121_AUD_EN_I2S_MASK 0x0f -+#define IT66121_AUD_EN_SPDIF 1 -+ -+#define IT66121_AUD_CTRL1_REG 0xe1 -+#define IT66121_AUD_FMT_STD_I2S (0 << 0) -+#define IT66121_AUD_FMT_32BIT_I2S BIT(0) -+#define IT66121_AUD_FMT_LEFT_JUSTIFY (0 << 1) -+#define IT66121_AUD_FMT_RIGHT_JUSTIFY BIT(1) -+#define IT66121_AUD_FMT_DELAY_1T_TO_WS (0 << 2) -+#define IT66121_AUD_FMT_NO_DELAY_TO_WS BIT(2) -+#define IT66121_AUD_FMT_WS0_LEFT (0 << 3) -+#define IT66121_AUD_FMT_WS0_RIGHT BIT(3) -+#define IT66121_AUD_FMT_MSB_SHIFT_FIRST (0 << 4) -+#define IT66121_AUD_FMT_LSB_SHIFT_FIRST BIT(4) -+#define IT66121_AUD_FMT_RISE_EDGE_SAMPLE_WS (0 << 5) -+#define IT66121_AUD_FMT_FALL_EDGE_SAMPLE_WS BIT(5) -+#define IT66121_AUD_FMT_FULLPKT BIT(6) -+ -+#define IT66121_AUD_FIFOMAP_REG 0xe2 -+#define IT66121_AUD_FIFO3_SEL 6 -+#define IT66121_AUD_FIFO2_SEL 4 -+#define IT66121_AUD_FIFO1_SEL 2 -+#define IT66121_AUD_FIFO0_SEL 0 -+#define IT66121_AUD_FIFO_SELSRC3 3 -+#define IT66121_AUD_FIFO_SELSRC2 2 -+#define IT66121_AUD_FIFO_SELSRC1 1 -+#define IT66121_AUD_FIFO_SELSRC0 0 -+#define IT66121_AUD_FIFOMAP_DEFAULT (IT66121_AUD_FIFO_SELSRC0 \ -+ << IT66121_AUD_FIFO0_SEL | \ -+ IT66121_AUD_FIFO_SELSRC1 \ -+ << IT66121_AUD_FIFO1_SEL | \ -+ IT66121_AUD_FIFO_SELSRC2 \ -+ << IT66121_AUD_FIFO2_SEL | \ -+ IT66121_AUD_FIFO_SELSRC3 \ -+ << IT66121_AUD_FIFO3_SEL) -+ -+#define IT66121_AUD_CTRL3_REG 0xe3 -+#define IT66121_AUD_MULCH BIT(7) -+#define IT66121_AUD_ZERO_CTS BIT(6) -+#define IT66121_AUD_CHSTSEL BIT(4) -+#define IT66121_AUD_S3RLCHG BIT(3) -+#define IT66121_AUD_S2RLCHG BIT(2) -+#define IT66121_AUD_S1RLCHG BIT(1) -+#define IT66121_AUD_S0RLCHG BIT(0) -+#define IT66121_AUD_SRLCHG_MASK 0x0f -+#define IT66121_AUD_SRLCHG_DEFAULT ((~IT66121_AUD_S0RLCHG & \ -+ ~IT66121_AUD_S1RLCHG & \ -+ ~IT66121_AUD_S2RLCHG & \ -+ ~IT66121_AUD_S3RLCHG) & \ -+ IT66121_AUD_SRLCHG_MASK) -+ -+#define IT66121_AUD_SRC_VALID_FLAT_REG 0xe4 -+#define IT66121_AUD_SPXFLAT_SRC3 BIT(7) -+#define IT66121_AUD_SPXFLAT_SRC2 BIT(6) -+#define IT66121_AUD_SPXFLAT_SRC1 BIT(5) -+#define IT66121_AUD_SPXFLAT_SRC0 BIT(4) -+#define IT66121_AUD_SPXFLAT_MASK 0xf0 -+#define IT66121_AUD_SPXFLAT_SRC_ALL (IT66121_AUD_SPXFLAT_SRC0 | \ -+ IT66121_AUD_SPXFLAT_SRC1 | \ -+ IT66121_AUD_SPXFLAT_SRC2 | \ -+ IT66121_AUD_SPXFLAT_SRC3) -+#define IT66121_AUD_ERR2FLAT BIT(3) -+#define IT66121_AUD_S3VALID BIT(2) -+#define IT66121_AUD_S2VALID BIT(1) -+#define IT66121_AUD_S1VALID BIT(0) -+ -+#define IT66121_AUD_HDAUDIO_REG 0xe5 -+#define IT66121_AUD_HBR BIT(3) -+#define IT66121_AUD_DSD BIT(1) -+ - struct it66121_conf { - unsigned int input_mode_reg; - unsigned int input_conversion_reg; - }; - -+struct it66121_audio { -+ struct platform_device *pdev; -+ unsigned int sources; -+ unsigned int n; -+ unsigned int cts; -+ unsigned int format; -+ unsigned int sample_wl; -+ bool is_hbr; -+ struct hdmi_audio_infoframe audio_infoframe; -+ struct snd_aes_iec958 aes_iec958; -+}; -+ - struct it66121_ctx { - struct regmap *regmap; - struct drm_bridge bridge; -@@ -260,6 +402,8 @@ struct it66121_ctx { - struct regulator_bulk_data supplies[3]; - bool dual_edge; - const struct it66121_conf *conf; -+ bool sink_has_audio; -+ struct it66121_audio audio; - struct mutex lock; /* Protects fields below and device registers */ - struct edid *edid; - struct hdmi_avi_infoframe hdmi_avi_infoframe; -@@ -610,6 +754,7 @@ static int it66121_connector_get_modes(struct drm_connector *connector) - } - - num_modes = drm_add_edid_modes(connector, ctx->edid); -+ ctx->sink_has_audio = drm_detect_monitor_audio(ctx->edid); - - unlock: - mutex_unlock(&ctx->lock); -@@ -894,6 +1039,536 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = { - .mode_set = it66121_bridge_mode_set, - }; - -+/* Audio related functions */ -+ -+static int it66121_audio_reset_fifo(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD, -+ IT66121_SW_RST_AUD); -+ if (ret) -+ return ret; -+ -+ usleep_range(2000, 4000); -+ -+ return regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD, -+ ~(IT66121_SW_RST_AUD) & 0xff); -+} -+ -+static int it66121_audio_set_infoframe(struct it66121_ctx *ctx) -+{ -+ int i, ret; -+ u8 infoframe_buf[HDMI_INFOFRAME_SIZE(AUDIO)]; -+ -+ const u16 audioinfo_reg[IT66121_AUD_INFO_REG_SZ] = { -+ IT66121_AUD_INFO_DB1_REG, -+ IT66121_AUD_INFO_DB2_REG, -+ IT66121_AUD_INFO_DB3_REG, -+ IT66121_AUD_INFO_DB4_REG, -+ IT66121_AUD_INFO_DB5_REG -+ }; -+ -+ ret = hdmi_audio_infoframe_pack(&ctx->audio.audio_infoframe, infoframe_buf, -+ sizeof(infoframe_buf)); -+ if (ret < 0) { -+ dev_err(ctx->dev, "%s: failed to pack audio infoframe: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ for (i = 0; i < IT66121_AUD_INFO_REG_SZ; i++) { -+ ret = regmap_write(ctx->regmap, audioinfo_reg[i], -+ infoframe_buf[i + HDMI_INFOFRAME_HEADER_SIZE]); -+ if (ret) -+ return ret; -+ } -+ -+ /* -+ * TODO: linux defines 10 bytes; currently only 5 are filled -+ * if that ever changes checksum will differ since -+ * it66121 takes max 5 bytes -> calc checksum here???? -+ */ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_INFO_CSUM_REG, infoframe_buf[3]); -+ -+ if (ret) -+ return ret; -+ -+ return regmap_write(ctx->regmap, IT66121_AUD_INFO_PKT_REG, -+ IT66121_AUD_INFO_PKT_ON | IT66121_AUD_INFO_PKT_RPT); -+} -+ -+static int it66121_audio_set_cts_n(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N1_REG, -+ ctx->audio.n & 0xff); -+ if (ret) -+ return ret; -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N2_REG, -+ (ctx->audio.n >> 8) & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N3_REG, -+ (ctx->audio.n >> 16) & 0xf); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS1_REG, -+ ctx->audio.cts & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS2_REG, -+ (ctx->audio.cts >> 8) & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS3_REG, -+ (ctx->audio.cts >> 16) & 0xf); -+ if (ret) -+ return ret; -+ -+ /* -+ * magic values ("password") have to be written to -+ * f8 register to enable writing to IT66121_AUD_PKT_CTS_MODE_REG -+ */ -+ -+ ret = regmap_write(ctx->regmap, 0xf8, 0xc3); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, 0xf8, 0xa5); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, -+ IT66121_AUD_PKT_CTS_MODE_REG, -+ IT66121_AUD_PKT_CTS_MODE_USER, -+ ctx->audio.cts == IT66121_AUD_PKT_CTS_MODE_AUTO_VAL -+ ? ~IT66121_AUD_PKT_CTS_MODE_USER & 0xff -+ : IT66121_AUD_PKT_CTS_MODE_USER); -+ if (ret) -+ return ret; -+ -+ /* -+ * disabling write to IT66121_AUD_PKT_CTS_MODE_REG -+ * again by overwriting perviously set "password" -+ */ -+ return regmap_write(ctx->regmap, 0xf8, 0xff); -+} -+ -+static int it66121_audio_set_channel_status(struct it66121_ctx *ctx) -+{ -+ int ret; -+ unsigned int val; -+ -+ /* TODO: check: always use NLPCM - would to cover LPCM also?*/ -+ val = IT66121_AUD_CHST_MODE_NLPCM; -+ val |= ctx->audio.aes_iec958.status[0] & IEC958_AES0_CON_NOT_COPYRIGHT -+ ? BIT(3) -+ : (0 << 3); -+ val |= (ctx->audio.aes_iec958.status[0] & IEC958_AES0_CON_EMPHASIS) << 4; -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_MODE_REG, -+ val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CAT_REG, -+ ctx->audio.aes_iec958.status[1]); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_SRCNUM_REG, -+ ctx->audio.aes_iec958.status[2] & -+ IEC958_AES2_CON_SOURCE); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CHTNUM_REG, -+ ((ctx->audio.aes_iec958.status[2] & -+ IEC958_AES2_CON_CHANNEL) >> 4)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_CA_FS_REG, -+ (ctx->audio.aes_iec958.status[3] & -+ IEC958_AES3_CON_CLOCK) << 2 | -+ (ctx->audio.aes_iec958.status[3] & -+ IEC958_AES3_CON_FS)); -+ if (ret) -+ return ret; -+ -+ return regmap_write(ctx->regmap, -+ IT66121_AUD_CHST_OFS_WL_REG, -+ ctx->audio.aes_iec958.status[4]); -+} -+ -+static int it66121_audio_mute(struct it66121_ctx *ctx, bool enable) -+{ -+ return regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, -+ IT66121_AUD_EN_I2S_MASK, -+ enable ? 0x0 : ctx->audio.sources); -+} -+ -+static int it66121_audio_set_controls(struct it66121_ctx *ctx) -+{ -+ int ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, -+ IT66121_AUD_TYPE_MASK | IT66121_AUD_SWL_MASK, -+ IT66121_AUD_I2S | ctx->audio.sample_wl); -+ -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL1_REG, -+ ctx->audio.format); -+ if (ret) -+ return ret; -+ -+ /* default fifo mapping: fifo0 => source0, fifo1 => source1, ... */ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_FIFOMAP_REG, -+ IT66121_AUD_FIFOMAP_DEFAULT); -+ if (ret) -+ return ret; -+ -+ /* Do not swap R/L for any source */ -+ ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL3_REG, -+ IT66121_AUD_SRLCHG_MASK, -+ IT66121_AUD_SRLCHG_DEFAULT); -+ if (ret) -+ return ret; -+ -+ /* "unflat" all sources */ -+ ret = regmap_write_bits(ctx->regmap, -+ IT66121_AUD_SRC_VALID_FLAT_REG, -+ IT66121_AUD_SPXFLAT_MASK, -+ ~IT66121_AUD_SPXFLAT_SRC_ALL & 0xff); -+ if (ret) -+ return ret; -+ -+ /* TODO: check if we really support HBR audio yet */ -+ return regmap_write_bits(ctx->regmap, IT66121_AUD_HDAUDIO_REG, -+ IT66121_AUD_HBR, -+ ctx->audio.is_hbr -+ ? IT66121_AUD_HBR -+ : ~IT66121_AUD_HBR & 0xff); -+} -+ -+static int it66121_audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ int ret; -+ unsigned int sources = 0; -+ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ if (!ctx->sink_has_audio) { -+ dev_err(ctx->dev, "%s: sink has no audio", __func__); -+ return -EINVAL; -+ } -+ -+ /* for now i2s only */ -+ if (daifmt->bit_clk_master | daifmt->frame_clk_master) { -+ dev_err(ctx->dev, -+ "%s: only clk_master and frame_clk_master formats are supported\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ /* TODO: move all these switches in functions ? */ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ ctx->audio.format = IT66121_AUD_FMT_32BIT_I2S; -+ break; -+ case HDMI_RIGHT_J: -+ ctx->audio.format = IT66121_AUD_FMT_RIGHT_JUSTIFY; -+ break; -+ case HDMI_LEFT_J: -+ ctx->audio.format = IT66121_AUD_FMT_LEFT_JUSTIFY; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported daiformat: %u\n", -+ __func__, daifmt->fmt); -+ return -EINVAL; -+ } -+ -+ switch (params->channels) { -+ case 7 ... 8: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S3; -+ sources++; -+ fallthrough; -+ case 5 ... 6: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S2; -+ sources++; -+ fallthrough; -+ case 3 ... 4: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S1; -+ sources++; -+ fallthrough; -+ case 1 ... 2: -+ ctx->audio.sources |= IT66121_AUD_EN_I2S0; -+ sources++; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported channel count: %d\n", -+ __func__, params->channels); -+ return -EINVAL; -+ } -+ -+ switch (params->sample_width) { -+ case 16: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_16BIT; -+ break; -+ case 18: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_18BIT; -+ break; -+ case 20: -+ ctx->audio.sample_wl = IT66121_AUD_SWL_20BIT; -+ break; -+ case 24: -+ case 32: -+ /* assume 24 bit wordlength for 32 bit width */ -+ ctx->audio.sample_wl = IT66121_AUD_SWL_24BIT; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported sample width: %d\n", -+ __func__, params->channels); -+ return -EINVAL; -+ } -+ -+ switch (params->sample_rate) { -+ case 32000: -+ case 48000: -+ case 96000: -+ case 192000: -+ ctx->audio.n = 128 * params->sample_rate / 1000; -+ ctx->audio.is_hbr = false; -+ break; -+ case 44100: -+ case 88200: -+ case 176400: -+ ctx->audio.n = 128 * params->sample_rate / 900; -+ ctx->audio.is_hbr = false; -+ break; -+ case 768000: -+ ctx->audio.n = 24576; -+ ctx->audio.is_hbr = true; -+ break; -+ default: -+ dev_err(ctx->dev, "%s: unsupported sample_rate: %d\n", -+ __func__, params->sample_rate); -+ return -EINVAL; -+ } -+ -+ /* not all bits are correctly filled in snd_aes_iec958 - fill them here */ -+ if ((params->iec.status[2] & IEC958_AES2_CON_SOURCE) == IEC958_AES2_CON_SOURCE_UNSPEC) -+ params->iec.status[2] |= sources; -+ -+ if ((params->iec.status[2] & IEC958_AES2_CON_CHANNEL) == IEC958_AES2_CON_CHANNEL_UNSPEC) -+ params->iec.status[2] |= params->channels << 4; -+ -+ /* OFs is 1-complement of Fs */ -+ if ((params->iec.status[4] & IEC958_AES4_CON_ORIGFS) == IEC958_AES4_CON_ORIGFS_NOTID && -+ (params->iec.status[3] & IEC958_AES3_CON_FS) != IEC958_AES3_CON_FS_NOTID) -+ params->iec.status[4] |= (~(params->iec.status[3] & IEC958_AES3_CON_FS) & 0xf) << 4; -+ -+ ctx->audio.format |= IT66121_AUD_FMT_FULLPKT; -+ ctx->audio.cts = IT66121_AUD_PKT_CTS_MODE_AUTO_VAL; -+ ctx->audio.audio_infoframe = params->cea; -+ ctx->audio.aes_iec958 = params->iec; -+ -+ ret = it66121_audio_reset_fifo(ctx); -+ if (ret) -+ return ret; -+ -+ ret = it66121_audio_set_infoframe(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to assemble/enable audio infoframe: %d\n", -+ __func__, ret); -+ /* TODO: Really fail here? */ -+ return ret; -+ } -+ -+ ret = it66121_audio_set_cts_n(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write cts/n values: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ ret = it66121_audio_set_channel_status(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write channel_status %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ ret = it66121_audio_set_controls(ctx); -+ if (ret) { -+ dev_err(ctx->dev, -+ "%s: failed to write audio controls %d\n", -+ __func__, ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static void it66121_audio_shutdown(struct device *dev, void *data) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); -+ -+ regmap_write(ctx->regmap, IT66121_AUD_CLK_CTRL_REG, 0x0); -+ -+ regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, -+ IT66121_INT_MASK1_AUD_OVF, -+ IT66121_INT_MASK1_AUD_OVF); -+ -+ regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, -+ IT66121_CLK_BANK_PWROFF_ACLK, -+ IT66121_CLK_BANK_PWROFF_ACLK); -+ -+ regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ ~(IT66121_SW_RST_AUD | IT66121_SW_RST_AREF) & 0xff); -+} -+ -+static int it66121_audio_startup(struct device *dev, void *data) -+{ -+ int ret; -+ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); -+ if (ret) -+ return ret; -+ /* TODO: check how to determine Fs at runtime -> only for spdif???*/ -+ ret = regmap_write(ctx->regmap, IT66121_AUD_CLK_CTRL_REG, -+ IT66121_AUD_AUT_OVR_SMPL_CLK | -+ IT66121_AUD_EXT_MCLK_256FS); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, -+ IT66121_CLK_BANK_PWROFF_ACLK, -+ ~IT66121_CLK_BANK_PWROFF_ACLK & 0xff); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, -+ IT66121_INT_MASK1_AUD_OVF, -+ ~IT66121_INT_MASK1_AUD_OVF & 0xff); -+ if (ret) -+ return ret; -+ -+ return regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, -+ IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, -+ ~(IT66121_SW_RST_AUD | IT66121_SW_RST_AREF) & 0xff); -+} -+ -+int it66121_audio_mute_stream(struct device *dev, void *data, bool enable, -+ int direction) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ return it66121_audio_mute(ctx, enable); -+} -+ -+static int it66121_audio_get_dai_id(struct snd_soc_component *component, -+ struct device_node *endpoint) -+{ -+ struct of_endpoint of_ep; -+ int ret; -+ -+ ret = of_graph_parse_endpoint(endpoint, &of_ep); -+ if (ret < 0) -+ return ret; -+ -+ /* -+ * HDMI sound should be located as reg = <2> -+ * Then, it is sound port 0 -+ */ -+ if (of_ep.port == 2) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int it66121_audio_get_eld(struct device *dev, void *data, -+ u8 *buf, size_t len) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ memcpy(buf, ctx->connector.eld, -+ min(sizeof(ctx->connector.eld), len)); -+ -+ return 0; -+} -+ -+static const struct hdmi_codec_ops it66121_audio_codec_ops = { -+ .audio_shutdown = it66121_audio_shutdown, -+ .audio_startup = it66121_audio_startup, -+ .mute_stream = it66121_audio_mute_stream, -+ .no_capture_mute = 1, -+ .hw_params = it66121_audio_hw_params, -+ .get_eld = it66121_audio_get_eld, -+ .get_dai_id = it66121_audio_get_dai_id, -+}; -+ -+static const struct hdmi_codec_pdata codec_data = { -+ .ops = &it66121_audio_codec_ops, -+ .i2s = 1, /* Only i2s support for now. */ -+ .spdif = 0, -+ .max_i2s_channels = 8, -+}; -+ -+static int it66121_audio_codec_init(struct it66121_ctx *it66121, -+ struct device *dev) -+{ -+ struct it66121_ctx *ctx = dev_get_drvdata(dev); -+ -+ ctx->audio.pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, -+ &codec_data, sizeof(codec_data)); -+ -+ if (IS_ERR(ctx->audio.pdev)) -+ return PTR_ERR(ctx->audio.pdev); -+ -+ DRM_INFO("%s has been bound to to HDMITX it66121\n", -+ HDMI_CODEC_DRV_NAME); -+ -+ return 0; -+} -+ -+static void it66121_audio_codec_exit(struct it66121_ctx *ctx) -+{ -+ if (ctx->audio.pdev) { -+ platform_device_unregister(ctx->audio.pdev); -+ ctx->audio.pdev = NULL; -+ } -+} -+ - static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - { - int ret; -@@ -930,6 +1605,8 @@ static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) - } - event = true; - } -+ if (val & IT66121_INT_STATUS1_AUD_OVF) -+ it66121_audio_reset_fifo(ctx); - } - - ret = regmap_read(ctx->regmap, IT66121_INT_STATUS3_REG, &val); -@@ -1042,6 +1719,12 @@ static int it66121_probe(struct i2c_client *client, - - drm_bridge_add(&ctx->bridge); - -+ ret = it66121_audio_codec_init(ctx, dev); -+ if (ret) { -+ dev_err(dev, "Failed to initialize audio codec %d\n", ret); -+ return ret; -+ } -+ - return 0; - } - -@@ -1049,6 +1732,7 @@ static int it66121_remove(struct i2c_client *client) - { - struct it66121_ctx *ctx = i2c_get_clientdata(client); - -+ it66121_audio_codec_exit(ctx); - ite66121_power_off(ctx); - drm_bridge_remove(&ctx->bridge); - kfree(ctx->edid); -@@ -1086,6 +1770,7 @@ static struct i2c_driver it66121_driver = { - - module_i2c_driver(it66121_driver); - -+MODULE_AUTHOR("Alex Bee"); - MODULE_AUTHOR("Phong LE"); - MODULE_DESCRIPTION("IT66121 HDMI transmitter driver"); - MODULE_LICENSE("GPL v2"); - -From a6545c717b35bb1e53f8df75093e7582d1b75635 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Tue, 18 Aug 2020 22:46:01 +0200 -Subject: [PATCH] drm/bridge: it66121: increase reset time - -Signed-off-by: Alex Bee ---- - drivers/gpu/drm/bridge/ite-it66121.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 98f3d68fe01f..a01d2e46bb0c 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -443,7 +443,7 @@ static const struct it66121_conf it66121fn_conf_simple = { - static void it66121_hw_reset(struct it66121_ctx *ctx) - { - gpiod_set_value(ctx->gpio_reset, 1); -- msleep(20); -+ msleep(50); - gpiod_set_value(ctx->gpio_reset, 0); - } -