From patchwork Wed Aug 18 14:10:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sidraya Jayagond X-Patchwork-Id: 499240 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00942C4320A for ; Wed, 18 Aug 2021 14:12:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E1331610A7 for ; Wed, 18 Aug 2021 14:12:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238961AbhHRONI (ORCPT ); Wed, 18 Aug 2021 10:13:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46496 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239177AbhHROM7 (ORCPT ); Wed, 18 Aug 2021 10:12:59 -0400 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6B41C06129D for ; Wed, 18 Aug 2021 07:12:16 -0700 (PDT) Received: by mail-pf1-x42b.google.com with SMTP id j187so2258312pfg.4 for ; Wed, 18 Aug 2021 07:12:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pathpartnertech.com; s=google; h=mime-version:from:to:cc:subject:date:message-id:in-reply-to :references; bh=m++M81VE6OdBHGBRaES4X5rl8RRew/F1aidWQUBA3Dg=; b=XgUwth7g1HxRLL5bt6/ntSyf8x0/qNqatr1NwLtR5RO4qkBAag3GhX7VWYokMNmsLI d4DiI5PTnfwdhDK1mjHttmel4foqT/jj7H/M8rIsqL6pLl70PBX2kKwO0DYeLS4XO8qB ABQGon+dN9G1J+0aB2/Xyp9kG2VBOHPP1zwnYRBnQ8/lR66MoLKvSwv2VxebMttsw1w7 zxQPWKqTtU+4yowHeaC4+Bx+c3jXMVFVzsAOEJnFlX/neEcRHt5ZPKyzCqhicDv0pgHF FgHLAcosXUUgDrEy1MJasp53n0YSZQ8v+7PrHUw5aCAmB4JkwX067izvq7gyquD9ieM+ 63mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :in-reply-to:references; bh=m++M81VE6OdBHGBRaES4X5rl8RRew/F1aidWQUBA3Dg=; b=EgQm/vUqGjkVI7VkIeon5s1VmBAhFiVTmlZTM5KIwJC5VI6/w+wqp8PbSo4hBe5t+t 3EyOf6zj83pOgg2CnMZpIXl7kDFZRsH5VGtw3BvnfEL3+FfsKYtvwHMq6sMkdwwJREoa 6NEtrjVtfj/0s4/vqjhPhrasu2XF7kS0xKnpnlAumehwAvHldw/haRSGJL7VUzQUiNc6 9B6Imo0M7HN5hLbOcaDiqUu1wGpsH753UCkB5gCJH5E0bYhuRDTBet51OeRAflCSKc57 FGLS2ynk1nlqza66A3TKkHSIih1N3M+4izuFMLR+0vrSe/8PK9QZZri63+sZzEQpGCmj DzWw== MIME-Version: 1.0 X-Gm-Message-State: AOAM531Wv0hCT08rIuaEqXgNhyiJ+/tn3BvVc13iS+XddifHDR/0Zn9B 214GQE4yxP1QRh/tweqCval/S9OZdA5Lw3bVApCCSBH+qCtVrdFbTuCjdkwGaL44P3oD4xVfRP9 kdycGEFjjFas4LVaZ X-Google-Smtp-Source: ABdhPJzVod3IDoBobK2yD1TioSpwBm4BGtTVLyNIdws93umdsJPE5YKQacPp712ygVgHeZqd7UV9IA== X-Received: by 2002:a63:510a:: with SMTP id f10mr9154852pgb.249.1629295935997; Wed, 18 Aug 2021 07:12:15 -0700 (PDT) Received: from localhost.localdomain ([49.207.214.181]) by smtp.gmail.com with ESMTPSA id e8sm8084343pgg.31.2021.08.18.07.12.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Aug 2021 07:12:15 -0700 (PDT) From: sidraya.bj@pathpartnertech.com To: gregkh@linuxfoundation.org, linux-staging@lists.linux.dev, linux-kernel@vger.kernel.org Cc: prashanth.ka@pathpartnertech.com, praneeth@ti.com, mchehab@kernel.org, linux-media@vger.kernel.org, praveen.ap@pathpartnertech.com, Sidraya Subject: [PATCH 07/30] v4l: vxd-dec: Add vxd core module Date: Wed, 18 Aug 2021 19:40:14 +0530 Message-Id: <20210818141037.19990-8-sidraya.bj@pathpartnertech.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210818141037.19990-1-sidraya.bj@pathpartnertech.com> References: <20210818141037.19990-1-sidraya.bj@pathpartnertech.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Sidraya This patch prepares the picture commands for the firmware it includes reconstructed and alternate picture commands. Signed-off-by: Amit Makani Signed-off-by: Sidraya --- MAINTAINERS | 2 + drivers/staging/media/vxd/decoder/vxd_int.c | 1137 +++++++++++++++++++ drivers/staging/media/vxd/decoder/vxd_int.h | 128 +++ 3 files changed, 1267 insertions(+) create mode 100644 drivers/staging/media/vxd/decoder/vxd_int.c create mode 100644 drivers/staging/media/vxd/decoder/vxd_int.h diff --git a/MAINTAINERS b/MAINTAINERS index 2327ea12caa6..7b21ebfc61d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19548,6 +19548,8 @@ F: drivers/staging/media/vxd/decoder/img_dec_common.h F: drivers/staging/media/vxd/decoder/vxd_core.c F: drivers/staging/media/vxd/decoder/vxd_dec.c F: drivers/staging/media/vxd/decoder/vxd_dec.h +F: drivers/staging/media/vxd/decoder/vxd_int.c +F: drivers/staging/media/vxd/decoder/vxd_int.h F: drivers/staging/media/vxd/decoder/vxd_pvdec.c F: drivers/staging/media/vxd/decoder/vxd_pvdec_priv.h F: drivers/staging/media/vxd/decoder/vxd_pvdec_regs.h diff --git a/drivers/staging/media/vxd/decoder/vxd_int.c b/drivers/staging/media/vxd/decoder/vxd_int.c new file mode 100644 index 000000000000..c75aef6deed1 --- /dev/null +++ b/drivers/staging/media/vxd/decoder/vxd_int.c @@ -0,0 +1,1137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * VXD DEC Common low level core interface component + * + * Copyright (c) Imagination Technologies Ltd. + * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/ + * + * Authors: + * Amit Makani + * + * Re-written for upstreamimg + * Sidraya Jayagond + * Prashanth Kumar Amai + */ + +#include +#include +#include +#include +#include + +#include "bspp.h" +#include "fw_interface.h" +#include "h264fw_data.h" +#include "img_errors.h" +#include "img_dec_common.h" +#include "img_pvdec_core_regs.h" +#include "img_pvdec_pixel_regs.h" +#include "img_pvdec_test_regs.h" +#include "img_vdec_fw_msg.h" +#include "img_video_bus4_mmu_regs.h" +#include "img_msvdx_core_regs.h" +#include "img_msvdx_cmds.h" +#include "reg_io2.h" +#include "scaler_setup.h" +#include "vdecdd_defs.h" +#include "vdecdd_utils.h" +#include "vdecfw_shared.h" +#include "vdec_defs.h" +#include "vxd_ext.h" +#include "vxd_int.h" +#include "vxd_props.h" + +#define MSVDX_CACHE_REF_OFFSET_V100 (72L) +#define MSVDX_CACHE_ROW_OFFSET_V100 (4L) + +#define MSVDX_CACHE_REF_OFFSET_V550 (144L) +#define MSVDX_CACHE_ROW_OFFSET_V550 (8L) + +#define GET_BITS(v, lb, n) (((v) >> (lb)) & ((1 << (n)) - 1)) +#define IS_PVDEC_PIPELINE(std) ((std) == VDEC_STD_HEVC ? 1 : 0) + +static int amsvdx_codecmode[VDEC_STD_MAX] = { + /* Invalid */ + -1, + /* MPEG2 */ + 3, + /* MPEG4 */ + 4, + /* H263 */ + 4, + /* H264 */ + 1, + /* VC1 */ + 2, + /* AVS */ + 5, + /* RealVideo (8) */ + 8, + /* JPEG */ + 0, + /* On2 VP6 */ + 10, + /* On2 VP8 */ + 11, + /* Invalid */ +#ifdef HAS_VP9 + /* On2 VP9 */ + 13, +#endif + /* Sorenson */ + 4, + /* HEVC */ + 12, +}; + +struct msvdx_scaler_coeff_cmds { + unsigned int acmd_horizluma_coeff[VDECFW_NUM_SCALE_COEFFS]; + unsigned int acmd_vertluma_coeff[VDECFW_NUM_SCALE_COEFFS]; + unsigned int acmd_horizchroma_coeff[VDECFW_NUM_SCALE_COEFFS]; + unsigned int acmd_vertchroma_coeff[VDECFW_NUM_SCALE_COEFFS]; +}; + +static struct vxd_vidstd_props astd_props[] = { + { VDEC_STD_MPEG2, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_MPEG4, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_H263, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_H264, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0x10000, 8, + 8, PIXEL_FORMAT_420 }, + { VDEC_STD_VC1, CORE_REVISION(7, 0, 0), 80, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_AVS, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_REAL, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_JPEG, CORE_REVISION(7, 0, 0), 64, 16, 32768, 32768, 0, 8, 8, + PIXEL_FORMAT_444 }, + { VDEC_STD_VP6, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_VP8, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8, + PIXEL_FORMAT_420 }, + { VDEC_STD_SORENSON, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, + 8, PIXEL_FORMAT_420 }, + { VDEC_STD_HEVC, CORE_REVISION(7, 0, 0), 64, 16, 8192, 8192, 0, 8, 8, + PIXEL_FORMAT_420 }, +}; + +enum vdec_msvdx_async_mode { + VDEC_MSVDX_ASYNC_NORMAL, + VDEC_MSVDX_ASYNC_VDMC, + VDEC_MSVDX_ASYNC_VDEB, + VDEC_MSVDX_ASYNC_FORCE32BITS = 0x7FFFFFFFU +}; + +/* MSVDX row strides for video buffers. */ +static const unsigned int amsvdx_64byte_row_stride[] = { + 384, 768, 1280, 1920, 512, 1024, 2048, 4096 +}; + +/* MSVDX row strides for jpeg buffers. */ +static const unsigned int amsvdx_jpeg_row_stride[] = { + 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768 +}; + +/* VXD Core major revision. */ +static unsigned int maj_rev; +/* VXD Core minor revision. */ +static unsigned int min_rev; +/* VXD Core maintenance revision. */ +static unsigned int maint_rev; + +static int get_stride_code(enum vdec_vid_std vidstd, unsigned int row_stride) +{ + unsigned int i; + + if (vidstd == VDEC_STD_JPEG) { + for (i = 0; i < (sizeof(amsvdx_jpeg_row_stride) / + sizeof(amsvdx_jpeg_row_stride[0])); i++) { + if (amsvdx_jpeg_row_stride[i] == row_stride) + return i; + } + } else { + for (i = 0; i < (sizeof(amsvdx_64byte_row_stride) / + sizeof(amsvdx_64byte_row_stride[0])); i++) { + if (amsvdx_64byte_row_stride[i] == row_stride) + return i; + } + } + + return -1; +} + +/* Obtains the hardware defined video profile. */ +static unsigned int vxd_getprofile(enum vdec_vid_std vidstd, unsigned int std_profile) +{ + unsigned int profile = 0; + + switch (vidstd) { + case VDEC_STD_H264: + switch (std_profile) { + case H264_PROFILE_BASELINE: + profile = 0; + break; + + /* + * Extended may be attempted as Baseline or + * Main depending on the constraint_set_flags + */ + case H264_PROFILE_EXTENDED: + case H264_PROFILE_MAIN: + profile = 1; + break; + + case H264_PROFILE_HIGH: + case H264_PROFILE_HIGH444: + case H264_PROFILE_HIGH422: + case H264_PROFILE_HIGH10: + case H264_PROFILE_CAVLC444: + case H264_PROFILE_MVC_HIGH: + case H264_PROFILE_MVC_STEREO: + profile = 2; + break; + default: + profile = 2; + break; + } + break; + + default: + profile = 0; + break; + } + + return profile; +} + +static int vxd_getcoreproperties(struct vxd_coreprops *coreprops, + unsigned int corerev, + unsigned int pvdec_coreid, unsigned int mmu_config0, + unsigned int mmu_config1, unsigned int *pixel_pipecfg, + unsigned int *pixel_misccfg, unsigned int max_framecfg) +{ + unsigned int group_id; + unsigned int core_id; + unsigned int core_config; + unsigned int extended_address_range; + unsigned char group_size = 0; + unsigned char pipe_minus1 = 0; + unsigned int max_h264_hw_chromaformat = 0; + unsigned int max_hevc_hw_chromaformat = 0; + unsigned int max_bitdepth_luma = 0; + unsigned int i; + + struct pvdec_core_rev core_rev; + + if (!coreprops || !pixel_pipecfg || !pixel_misccfg) + return IMG_ERROR_INVALID_PARAMETERS; + + /* PVDEC Core Revision Information */ + core_rev.maj_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV, + CR_PVDEC_MAJOR_REV); + core_rev.min_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV, + CR_PVDEC_MINOR_REV); + core_rev.maint_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV, + CR_PVDEC_MAINT_REV); + + /* core id */ + group_id = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE, CR_PVDEC_CORE_ID, CR_GROUP_ID); + core_id = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE, CR_PVDEC_CORE_ID, CR_CORE_ID); + + /* Ensure that the core is IMG Video Decoder (PVDEC). */ + if (group_id != 3 || core_id != 3) + return IMG_ERROR_DEVICE_NOT_FOUND; + + core_config = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE, + CR_PVDEC_CORE_ID, CR_PVDEC_CORE_CONFIG); + + memset(coreprops, 0, sizeof(*(coreprops))); + + /* Construct core version name. */ + snprintf(coreprops->aversion, VER_STR_LEN, "%d.%d.%d", + core_rev.maj_rev, core_rev.min_rev, core_rev.maint_rev); + + coreprops->mmu_support_stride_per_context = + REGIO_READ_FIELD(mmu_config1, IMG_VIDEO_BUS4_MMU, + MMU_CONFIG1, + SUPPORT_STRIDE_PER_CONTEXT) == 1 ? 1 : 0; + + coreprops->mmu_support_secure = REGIO_READ_FIELD(mmu_config1, IMG_VIDEO_BUS4_MMU, + MMU_CONFIG1, SUPPORT_SECURE) == 1 ? 1 : 0; + + extended_address_range = REGIO_READ_FIELD(mmu_config0, IMG_VIDEO_BUS4_MMU, + MMU_CONFIG0, EXTENDED_ADDR_RANGE); + + switch (extended_address_range) { + case 0: + coreprops->mmu_type = MMU_TYPE_32BIT; + break; + case 4: + coreprops->mmu_type = MMU_TYPE_36BIT; + break; + case 8: + coreprops->mmu_type = MMU_TYPE_40BIT; + break; + default: + return IMG_ERROR_NOT_SUPPORTED; + } + + group_size += REGIO_READ_FIELD(mmu_config0, IMG_VIDEO_BUS4_MMU, + MMU_CONFIG0, GROUP_OVERRIDE_SIZE); + + coreprops->num_entropy_pipes = core_config & 0xF; + coreprops->num_pixel_pipes = core_config >> 4 & 0xF; +#ifdef DEBUG_DECODER_DRIVER + pr_info("PVDEC revision %08x detected, id %08x.\n", corerev, core_id); + pr_info("Found %d entropy pipe(s), %d pixel pipe(s), %d group size", + coreprops->num_entropy_pipes, coreprops->num_pixel_pipes, + group_size); +#endif + + /* Set global rev info variables used by macros */ + maj_rev = core_rev.maj_rev; + min_rev = core_rev.min_rev; + maint_rev = core_rev.maint_rev; + + /* Default settings */ + for (i = 0; i < ARRAY_SIZE(astd_props); i++) { + struct vxd_vidstd_props *pvidstd_props = + &coreprops->vidstd_props[astd_props[i].vidstd]; + /* + * Update video standard properties if the core is beyond + * specified version and the properties are for newer cores + * than the previous. + */ + if (FROM_REV(MAJOR_REVISION((int)astd_props[i].core_rev), + MINOR_REVISION((int)astd_props[i].core_rev), + MAINT_REVISION((int)astd_props[i].core_rev), int) && + astd_props[i].core_rev >= pvidstd_props->core_rev) { + *pvidstd_props = astd_props[i]; + + if (pvidstd_props->vidstd != VDEC_STD_JPEG && + (FROM_REV(8, 0, 0, int)) && (pvidstd_props->vidstd == + VDEC_STD_HEVC ? 1 : 0)) { + /* + * override default values with values + * specified in HW (register does not + * exist in previous cores) + */ + pvidstd_props->max_width = + 2 << REGIO_READ_FIELD(max_framecfg, + PVDEC_PIXEL, + CR_MAX_FRAME_CONFIG, + CR_PVDEC_HOR_MSB); + + pvidstd_props->max_height = + 2 << REGIO_READ_FIELD(max_framecfg, + PVDEC_PIXEL, + CR_MAX_FRAME_CONFIG, + CR_PVDEC_VER_MSB); + } else if (pvidstd_props->vidstd != VDEC_STD_JPEG && + (FROM_REV(8, 0, 0, int))) { + pvidstd_props->max_width = + 2 << REGIO_READ_FIELD(max_framecfg, + PVDEC_PIXEL, + CR_MAX_FRAME_CONFIG, + CR_MSVDX_HOR_MSB); + + pvidstd_props->max_height = + 2 << REGIO_READ_FIELD(max_framecfg, + PVDEC_PIXEL, + CR_MAX_FRAME_CONFIG, + CR_MSVDX_VER_MSB); + } + } + } + + /* Populate the core properties. */ + if (GET_BITS(core_config, 11, 1)) + coreprops->hd_support = 1; + + for (pipe_minus1 = 0; pipe_minus1 < coreprops->num_pixel_pipes; + pipe_minus1++) { + unsigned int current_bitdepth = + GET_BITS(pixel_misccfg[pipe_minus1], 4, 3) + 8; + unsigned int current_h264_hw_chromaformat = + GET_BITS(pixel_misccfg[pipe_minus1], 0, 2); + unsigned int current_hevc_hw_chromaformat = + GET_BITS(pixel_misccfg[pipe_minus1], 2, 2); +#ifdef DEBUG_DECODER_DRIVER + pr_info("cur_bitdepth: %d cur_h264_hw_chromaformat: %d", + current_bitdepth, current_h264_hw_chromaformat); + pr_info("cur_hevc_hw_chromaformat: %d pipe_minus1: %d\n", + current_hevc_hw_chromaformat, pipe_minus1); +#endif + + if (GET_BITS(pixel_misccfg[pipe_minus1], 8, 1)) + coreprops->rotation_support[pipe_minus1] = 1; + + if (GET_BITS(pixel_misccfg[pipe_minus1], 9, 1)) + coreprops->scaling_support[pipe_minus1] = 1; + + coreprops->num_streams[pipe_minus1] = + GET_BITS(pixel_misccfg[pipe_minus1], 12, 2) + 1; + + /* Video standards. */ + coreprops->mpeg2[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 0, 1) ? 1 : 0; + coreprops->mpeg4[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 1, 1) ? 1 : 0; + coreprops->h264[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 2, 1) ? 1 : 0; + coreprops->vc1[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 3, 1) ? 1 : 0; + coreprops->jpeg[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 5, 1) ? 1 : 0; + coreprops->avs[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 7, 1) ? 1 : 0; + coreprops->real[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 8, 1) ? 1 : 0; + coreprops->vp6[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 9, 1) ? 1 : 0; + coreprops->vp8[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 10, 1) ? 1 : 0; + coreprops->hevc[pipe_minus1] = + GET_BITS(pixel_pipecfg[pipe_minus1], 22, 1) ? 1 : 0; + + max_bitdepth_luma = (max_bitdepth_luma > current_bitdepth ? + max_bitdepth_luma : current_bitdepth); + max_h264_hw_chromaformat = (max_h264_hw_chromaformat > + current_h264_hw_chromaformat ? max_h264_hw_chromaformat + : current_h264_hw_chromaformat); + max_hevc_hw_chromaformat = (max_hevc_hw_chromaformat > + current_hevc_hw_chromaformat ? max_hevc_hw_chromaformat + : current_hevc_hw_chromaformat); + } + + /* Override default bit-depth with value signalled explicitly by core. */ + coreprops->vidstd_props[0].max_luma_bitdepth = max_bitdepth_luma; + coreprops->vidstd_props[0].max_chroma_bitdepth = + coreprops->vidstd_props[0].max_luma_bitdepth; + + for (i = 1; i < VDEC_STD_MAX; i++) { + coreprops->vidstd_props[i].max_luma_bitdepth = + coreprops->vidstd_props[0].max_luma_bitdepth; + coreprops->vidstd_props[i].max_chroma_bitdepth = + coreprops->vidstd_props[0].max_chroma_bitdepth; + } + + switch (max_h264_hw_chromaformat) { + case 1: + coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format = + PIXEL_FORMAT_420; + break; + + case 2: + coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format = + PIXEL_FORMAT_422; + break; + + case 3: + coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format = + PIXEL_FORMAT_444; + break; + + default: + break; + } + + switch (max_hevc_hw_chromaformat) { + case 1: + coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format = + PIXEL_FORMAT_420; + break; + + case 2: + coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format = + PIXEL_FORMAT_422; + break; + + case 3: + coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format = + PIXEL_FORMAT_444; + break; + + default: + break; + } + + return 0; +} + +static unsigned char vxd_is_supported_byatleast_onepipe(const unsigned char *features, + unsigned int num_pipes) +{ + unsigned int i; + + VDEC_ASSERT(features); + VDEC_ASSERT(num_pipes <= VDEC_MAX_PIXEL_PIPES); + + for (i = 0; i < num_pipes; i++) { + if (features[i]) + return 1; + } + + return 0; +} + +void vxd_set_reconpictcmds(const struct vdecdd_str_unit *str_unit, + const struct vdec_str_configdata *str_configdata, + const struct vdec_str_opconfig *output_config, + const struct vxd_coreprops *coreprops, + const struct vxd_buffers *buffers, + unsigned int *pict_cmds) +{ + struct pixel_pixinfo *pixel_info; + unsigned int row_stride_code; + unsigned char benable_auxline_buf = 1; + + unsigned int coded_height; + unsigned int coded_width; + unsigned int disp_height; + unsigned int disp_width; + unsigned int profile; + unsigned char plane; + unsigned int y_stride; + unsigned int uv_stride; + unsigned int v_stride; + unsigned int cache_ref_offset; + unsigned int cache_row_offset; + + if (str_configdata->vid_std == VDEC_STD_JPEG) { + disp_height = 0; + disp_width = 0; + coded_height = 0; + coded_width = 0; + } else { + coded_height = ALIGN(str_unit->pict_hdr_info->coded_frame_size.height, + (str_unit->pict_hdr_info->field) ? + 2 * VDEC_MB_DIMENSION : VDEC_MB_DIMENSION); + /* Hardware field is coded size - 1 */ + coded_height -= 1; + + coded_width = ALIGN(str_unit->pict_hdr_info->coded_frame_size.width, + VDEC_MB_DIMENSION); + /* Hardware field is coded size - 1 */ + coded_width -= 1; + + disp_height = str_unit->pict_hdr_info->disp_info.enc_disp_region.height + + str_unit->pict_hdr_info->disp_info.enc_disp_region.left_offset - 1; + disp_width = str_unit->pict_hdr_info->disp_info.enc_disp_region.width + + str_unit->pict_hdr_info->disp_info.enc_disp_region.top_offset - 1; + } + /* + * Display picture size (DISPLAY_PICTURE) + * The display to be written is not the actual video size to be + * displayed but a number that has to differ from the coded pixel size + * by less than 1MB (coded_size-display_size <= 0x0F). Because H264 can + * have a different display size, we need to check and write + * the coded_size again in the display_size register if this condition + * is not fulfilled. + */ + if (str_configdata->vid_std != VDEC_STD_VC1 && ((coded_height - disp_height) > 0x0F)) { + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE], + MSVDX_CMDS, DISPLAY_PICTURE_SIZE, + DISPLAY_PICTURE_HEIGHT, + coded_height, unsigned int); + } else { + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE], + MSVDX_CMDS, DISPLAY_PICTURE_SIZE, + DISPLAY_PICTURE_HEIGHT, + disp_height, unsigned int); + } + + if (((coded_width - disp_width) > 0x0F)) { + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE], + MSVDX_CMDS, DISPLAY_PICTURE_SIZE, + DISPLAY_PICTURE_WIDTH, + coded_width, unsigned int); + } else { + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE], + MSVDX_CMDS, DISPLAY_PICTURE_SIZE, + DISPLAY_PICTURE_WIDTH, + disp_width, unsigned int); + } + + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_CODED_PICTURE], + MSVDX_CMDS, CODED_PICTURE_SIZE, + CODED_PICTURE_HEIGHT, + coded_height, unsigned int); + REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_CODED_PICTURE], + MSVDX_CMDS, CODED_PICTURE_SIZE, + CODED_PICTURE_WIDTH, + coded_width, unsigned int); + + /* + * For standards where dpb_diff != 1 and chroma format != 420 + * cache_ref_offset has to be calculated in the F/W. + */ + if (str_configdata->vid_std != VDEC_STD_HEVC && str_configdata->vid_std != VDEC_STD_H264) { + unsigned int log2_size, cache_size, luma_size; + unsigned char is_hevc_supported, is_hevc444_supported = 0; + + is_hevc_supported = + vxd_is_supported_byatleast_onepipe(coreprops->hevc, + coreprops->num_pixel_pipes); + + if (is_hevc_supported) { + is_hevc444_supported = + coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format == + PIXEL_FORMAT_444 ? 1 : 0; + } + + log2_size = 9 + (is_hevc_supported ? 1 : 0) + (is_hevc444_supported ? 1 : 0); + cache_size = 3 << log2_size; + luma_size = (cache_size * 2) / 3; + cache_ref_offset = (luma_size * 15) / 32; + cache_ref_offset = (cache_ref_offset + 7) & (~7); + cache_row_offset = 0x0C; + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION], + MSVDX_CMDS, MC_CACHE_CONFIGURATION, + CONFIG_REF_CHROMA_ADJUST, 1, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION], + MSVDX_CMDS, MC_CACHE_CONFIGURATION, + CONFIG_REF_OFFSET, cache_ref_offset, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION], + MSVDX_CMDS, MC_CACHE_CONFIGURATION, + CONFIG_ROW_OFFSET, cache_row_offset, + unsigned int, unsigned int); + } + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, + amsvdx_codecmode[str_configdata->vid_std], + unsigned int, unsigned int); + + profile = str_unit->seq_hdr_info->com_sequ_hdr_info.codec_profile; + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, + vxd_getprofile(str_configdata->vid_std, profile), + unsigned int, unsigned int); + + plane = str_unit->seq_hdr_info->com_sequ_hdr_info.separate_chroma_planes; + pixel_info = &str_unit->seq_hdr_info->com_sequ_hdr_info.pixel_info; + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, plane ? + 0 : pixel_info->chroma_fmt, unsigned int, int); + + if (str_configdata->vid_std != VDEC_STD_JPEG) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], + MSVDX_CMDS, EXT_OP_MODE, CHROMA_FORMAT_IDC, plane ? + 0 : pixel_get_hw_chroma_format_idc + (pixel_info->chroma_fmt_idc), + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], + MSVDX_CMDS, EXT_OP_MODE, MEMORY_PACKING, + output_config->pixel_info.mem_pkg == + PIXEL_BIT10_MP ? 1 : 0, unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], + MSVDX_CMDS, EXT_OP_MODE, BIT_DEPTH_LUMA_MINUS8, + pixel_info->bitdepth_y - 8, + unsigned int, unsigned int); + + if (pixel_info->chroma_fmt_idc == PIXEL_FORMAT_MONO) { + /* + * For monochrome streams use the same bit depth for + * chroma and luma. + */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], + MSVDX_CMDS, EXT_OP_MODE, + BIT_DEPTH_CHROMA_MINUS8, + pixel_info->bitdepth_y - 8, + unsigned int, unsigned int); + } else { + /* + * For normal streams use the appropriate bit depth for chroma. + */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], MSVDX_CMDS, + EXT_OP_MODE, BIT_DEPTH_CHROMA_MINUS8, + pixel_info->bitdepth_c - 8, + unsigned int, unsigned int); + } + } else { + pict_cmds[VDECFW_CMD_EXT_OP_MODE] = 0; + } + + if (str_configdata->vid_std != VDEC_STD_JPEG) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], MSVDX_CMDS, + OPERATING_MODE, CHROMA_INTERLEAVED, + PIXEL_GET_HW_CHROMA_INTERLEAVED + (output_config->pixel_info.chroma_interleave), + unsigned int, int); + } + + if (str_configdata->vid_std == VDEC_STD_JPEG) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, + VDEC_MSVDX_ASYNC_VDMC, + unsigned int, unsigned int); + } + + if (str_configdata->vid_std == VDEC_STD_H264) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], MSVDX_CMDS, + OPERATING_MODE, ASYNC_MODE, + str_unit->pict_hdr_info->discontinuous_mbs ? + VDEC_MSVDX_ASYNC_VDMC : VDEC_MSVDX_ASYNC_NORMAL, + unsigned int, int); + } + + y_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_Y].stride; + uv_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_UV].stride; + v_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_V].stride; + + if (((y_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) && + ((uv_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) && + ((v_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0)) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, + USE_EXT_ROW_STRIDE, 1, unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXTENDED_ROW_STRIDE], + MSVDX_CMDS, EXTENDED_ROW_STRIDE, + EXT_ROW_STRIDE, y_stride >> 6, unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE], + MSVDX_CMDS, CHROMA_ROW_STRIDE, + CHROMA_ROW_STRIDE, uv_stride >> 6, unsigned int, unsigned int); + } else { + row_stride_code = get_stride_code(str_configdata->vid_std, y_stride); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, + row_stride_code & 0x7, unsigned int, unsigned int); + + if (str_configdata->vid_std == VDEC_STD_JPEG) { + /* + * Use the unused chroma interleaved flag + * to hold MSB of row stride code + */ + IMG_ASSERT(row_stride_code < 16); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], + MSVDX_CMDS, OPERATING_MODE, + CHROMA_INTERLEAVED, + row_stride_code >> 3, unsigned int, unsigned int); + } else { + IMG_ASSERT(row_stride_code < 8); + } + } + pict_cmds[VDECFW_CMD_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) + + buffers->recon_pict->rend_info.plane_info[0].offset; + + pict_cmds[VDECFW_CMD_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) + + buffers->recon_pict->rend_info.plane_info[1].offset; + + pict_cmds[VDECFW_CMD_CHROMA2_RECONSTRUCTED_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) + + buffers->recon_pict->rend_info.plane_info[2].offset; + + pict_cmds[VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS] = 0; + pict_cmds[VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS] = 0; + +#ifdef ERROR_CONCEALMENT + /* update error concealment frame info if available */ + if (buffers->err_pict_bufinfo) { + pict_cmds[VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(buffers->err_pict_bufinfo) + + buffers->recon_pict->rend_info.plane_info[0].offset; + + pict_cmds[VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(buffers->err_pict_bufinfo) + + buffers->recon_pict->rend_info.plane_info[1].offset; + } +#endif + + pict_cmds[VDECFW_CMD_INTRA_BUFFER_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(buffers->intra_bufinfo); + pict_cmds[VDECFW_CMD_INTRA_BUFFER_PLANE_SIZE] = + buffers->intra_bufsize_per_pipe / 3; + pict_cmds[VDECFW_CMD_INTRA_BUFFER_SIZE_PER_PIPE] = + buffers->intra_bufsize_per_pipe; + pict_cmds[VDECFW_CMD_AUX_LINE_BUFFER_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(buffers->auxline_bufinfo); + pict_cmds[VDECFW_CMD_AUX_LINE_BUFFER_SIZE_PER_PIPE] = + buffers->auxline_bufsize_per_pipe; + + /* + * for pvdec we need to set this registers even if we don't + * use alternative output + */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_CHROMA_MINUS8, + output_config->pixel_info.bitdepth_c - 8, unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_LUMA_MINUS8, + output_config->pixel_info.bitdepth_y - 8, unsigned int, unsigned int); + + /* + * this is causing corruption in RV40 and VC1 streams with + * scaling/rotation enabled on Coral, so setting to 0 + */ + benable_auxline_buf = benable_auxline_buf && + (str_configdata->vid_std != VDEC_STD_REAL) && + (str_configdata->vid_std != VDEC_STD_VC1); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + USE_AUX_LINE_BUF, benable_auxline_buf ? 1 : 0, unsigned int, int); +} + +void vxd_set_altpictcmds(const struct vdecdd_str_unit *str_unit, + const struct vdec_str_configdata *str_configdata, + const struct vdec_str_opconfig *output_config, + const struct vxd_coreprops *coreprops, + const struct vxd_buffers *buffers, + unsigned int *pict_cmds) +{ + unsigned int row_stride_code; + unsigned int y_stride; + unsigned int uv_stride; + unsigned int v_stride; + + y_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_Y].stride; + uv_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_UV].stride; + v_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_V].stride; + + if (((y_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) && + ((uv_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) && + ((v_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0)) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + USE_EXT_ROT_ROW_STRIDE, 1, unsigned int, int); + + /* 64-byte (min) aligned luma stride value. */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, + ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + EXT_ROT_ROW_STRIDE, y_stride >> 6, + unsigned int, unsigned int); + + /* 64-byte (min) aligned chroma stride value. */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE], + MSVDX_CMDS, CHROMA_ROW_STRIDE, + ALT_CHROMA_ROW_STRIDE, uv_stride >> 6, + unsigned int, unsigned int); + } else { + /* + * Obtain the code for buffer stride + * (must be less than 8, i.e. not JPEG strides) + */ + row_stride_code = + get_stride_code(str_configdata->vid_std, y_stride); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, + ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + ROTATION_ROW_STRIDE, row_stride_code & 0x7, + unsigned int, unsigned int); + } + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + SCALE_INPUT_SIZE_SEL, + ((output_config->pixel_info.chroma_fmt_idc != + str_unit->seq_hdr_info->com_sequ_hdr_info.pixel_info.chroma_fmt_idc)) ? + 1 : 0, unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, + PACKED_422_OUTPUT, + (output_config->pixel_info.chroma_fmt_idc == + PIXEL_FORMAT_422 && + output_config->pixel_info.num_planes == 1) ? 1 : 0, + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_OUTPUT_FORMAT, + str_unit->seq_hdr_info->com_sequ_hdr_info.separate_chroma_planes ? + 0 : pixel_get_hw_chroma_format_idc + (output_config->pixel_info.chroma_fmt_idc), + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_CHROMA_MINUS8, + output_config->pixel_info.bitdepth_c - 8, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_LUMA_MINUS8, + output_config->pixel_info.bitdepth_y - 8, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_MEMORY_PACKING, + (output_config->pixel_info.mem_pkg == + PIXEL_BIT10_MP) ? 1 : 0, unsigned int, int); + + pict_cmds[VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) + + buffers->alt_pict->rend_info.plane_info[0].offset; + + pict_cmds[VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) + + buffers->alt_pict->rend_info.plane_info[1].offset; + + pict_cmds[VDECFW_CMD_CHROMA2_ALTERNATIVE_PICTURE_BASE_ADDRESS] = + (unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) + + buffers->alt_pict->rend_info.plane_info[2].offset; +} + +int vxd_getscalercmds(const struct scaler_config *scaler_config, + const struct scaler_pitch *pitch, + const struct scaler_filter *filter, + const struct pixel_pixinfo *out_loop_pixel_info, + struct scaler_params *params, + unsigned int *pict_cmds) +{ + const struct vxd_coreprops *coreprops = scaler_config->coreprops; + /* + * Indirectly detect decoder core type (if HEVC is supported, it has + * to be PVDEC core) and decide if to force luma re-sampling. + */ + unsigned char bforce_luma_resampling = coreprops->hevc[0]; + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_OUTPUT_FORMAT, + scaler_config->bseparate_chroma_planes ? 0 : + pixel_get_hw_chroma_format_idc(out_loop_pixel_info->chroma_fmt_idc), + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + SCALE_CHROMA_RESAMP_ONLY, bforce_luma_resampling ? 0 : + (pitch->horiz_luma == FIXED(1, HIGHP)) && + (pitch->vert_luma == FIXED(1, HIGHP)), unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_MEMORY_PACKING, + pixel_get_hw_memory_packing(out_loop_pixel_info->mem_pkg), + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_LUMA_MINUS8, + out_loop_pixel_info->bitdepth_y - 8, + unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + ALT_BIT_DEPTH_CHROMA_MINUS8, + out_loop_pixel_info->bitdepth_c - 8, + unsigned int, unsigned int); + + /* Scale luma bifilter is always 0 for now */ + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + SCALE_LUMA_BIFILTER_HORIZ, + 0, unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + SCALE_LUMA_BIFILTER_VERT, + 0, unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + SCALE_CHROMA_BIFILTER_HORIZ, + filter->bhoriz_bilinear ? 1 : 0, + unsigned int, int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL], + MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, + SCALE_CHROMA_BIFILTER_VERT, + filter->bvert_bilinear ? 1 : 0, unsigned int, int); + + /* for cores 7.x.x and more, precision 3.13 */ + params->fixed_point_shift = 13; + + /* Calculate the fixed-point versions for use by the hardware. */ + params->vert_pitch = (int)((pitch->vert_luma + + (1 << (HIGHP - params->fixed_point_shift - 1))) >> + (HIGHP - params->fixed_point_shift)); + params->vert_startpos = params->vert_pitch >> 1; + params->vert_pitch_chroma = (int)((pitch->vert_chroma + + (1 << (HIGHP - params->fixed_point_shift - 1))) >> + (HIGHP - params->fixed_point_shift)); + params->vert_startpos_chroma = params->vert_pitch_chroma >> 1; + params->horz_pitch = (int)(pitch->horiz_luma >> + (HIGHP - params->fixed_point_shift)); + params->horz_startpos = params->horz_pitch >> 1; + params->horz_pitch_chroma = (int)(pitch->horiz_chroma >> + (HIGHP - params->fixed_point_shift)); + params->horz_startpos_chroma = params->horz_pitch_chroma >> 1; + +#ifdef HAS_HEVC + if (scaler_config->vidstd == VDEC_STD_HEVC) { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE, + PVDEC_SCALE_DISPLAY_WIDTH, + scaler_config->recon_width - 1, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE, + PVDEC_SCALE_DISPLAY_HEIGHT, + scaler_config->recon_height - 1, + unsigned int, unsigned int); + } else { + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, SCALED_DISPLAY_SIZE, + SCALE_DISPLAY_WIDTH, + scaler_config->recon_width - 1, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, SCALED_DISPLAY_SIZE, + SCALE_DISPLAY_HEIGHT, + scaler_config->recon_height - 1, + unsigned int, unsigned int); + } +#else + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, SCALED_DISPLAY_SIZE, + SCALE_DISPLAY_WIDTH, + scaler_config->recon_width - 1, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE], + MSVDX_CMDS, SCALED_DISPLAY_SIZE, SCALE_DISPLAY_HEIGHT, + scaler_config->recon_height - 1, + unsigned int, unsigned int); +#endif + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE], + MSVDX_CMDS, SCALE_OUTPUT_SIZE, + SCALE_OUTPUT_WIDTH_MIN1, + scaler_config->scale_width - 1, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE], + MSVDX_CMDS, SCALE_OUTPUT_SIZE, + SCALE_OUTPUT_HEIGHT_MIN1, + scaler_config->scale_height - 1, + unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL], + MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL, + HORIZONTAL_SCALE_PITCH, params->horz_pitch, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL], + MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL, + HORIZONTAL_INITIAL_POS, params->horz_startpos, + unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_HORIZONTAL_CHROMA], + MSVDX_CMDS, SCALE_HORIZONTAL_CHROMA, + CHROMA_HORIZONTAL_PITCH, params->horz_pitch_chroma, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_HORIZONTAL_CHROMA], + MSVDX_CMDS, SCALE_HORIZONTAL_CHROMA, + CHROMA_HORIZONTAL_INITIAL, + params->horz_startpos_chroma, + unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL], + MSVDX_CMDS, VERTICAL_SCALE_CONTROL, + VERTICAL_SCALE_PITCH, params->vert_pitch, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL], + MSVDX_CMDS, VERTICAL_SCALE_CONTROL, + VERTICAL_INITIAL_POS, params->vert_startpos, + unsigned int, unsigned int); + + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_VERTICAL_CHROMA], + MSVDX_CMDS, SCALE_VERTICAL_CHROMA, + CHROMA_VERTICAL_PITCH, params->vert_pitch_chroma, + unsigned int, unsigned int); + REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_VERTICAL_CHROMA], + MSVDX_CMDS, SCALE_VERTICAL_CHROMA, + CHROMA_VERTICAL_INITIAL, + params->vert_startpos_chroma, + unsigned int, unsigned int); + return 0; +} + +unsigned int vxd_get_codedpicsize(unsigned short width_min1, unsigned short height_min1) +{ + unsigned int reg = 0; + + REGIO_WRITE_FIELD_LITE(reg, MSVDX_CMDS, CODED_PICTURE_SIZE, + CODED_PICTURE_WIDTH, width_min1, + unsigned short); + REGIO_WRITE_FIELD_LITE(reg, MSVDX_CMDS, CODED_PICTURE_SIZE, + CODED_PICTURE_HEIGHT, height_min1, + unsigned short); + + return reg; +} + +unsigned char vxd_get_codedmode(enum vdec_vid_std vidstd) +{ + return (unsigned char)amsvdx_codecmode[vidstd]; +} + +void vxd_get_coreproperties(void *hndl_coreproperties, + struct vxd_coreprops *vxd_coreprops) +{ + struct vxd_core_props *props = + (struct vxd_core_props *)hndl_coreproperties; + + vxd_getcoreproperties(vxd_coreprops, props->core_rev, + props->pvdec_core_id, + props->mmu_config0, + props->mmu_config1, + props->pixel_pipe_cfg, + props->pixel_misc_cfg, + props->pixel_max_frame_cfg); +} + +int vxd_get_pictattrs(unsigned int flags, struct vxd_pict_attrs *pict_attrs) +{ + if (flags & (VXD_FW_MSG_FLAG_DWR | VXD_FW_MSG_FLAG_FATAL)) + pict_attrs->dwrfired = 1; + if (flags & VXD_FW_MSG_FLAG_MMU_FAULT) + pict_attrs->mmufault = 1; + if (flags & VXD_FW_MSG_FLAG_DEV_ERR) + pict_attrs->deverror = 1; + + return 0; +} + +int vxd_get_msgerrattr(unsigned int flags, enum vxd_msg_attr *msg_attr) +{ + if ((flags & ~VXD_FW_MSG_FLAG_CANCELED)) + *msg_attr = VXD_MSG_ATTR_FATAL; + else if ((flags & VXD_FW_MSG_FLAG_CANCELED)) + *msg_attr = VXD_MSG_ATTR_CANCELED; + else + *msg_attr = VXD_MSG_ATTR_NONE; + + return 0; +} + +int vxd_set_msgflag(enum vxd_msg_flag input_flag, unsigned int *flags) +{ + switch (input_flag) { + case VXD_MSG_FLAG_DROP: + *flags |= VXD_FW_MSG_FLAG_DROP; + break; + case VXD_MSG_FLAG_EXCL: + *flags |= VXD_FW_MSG_FLAG_EXCL; + break; + default: + return IMG_ERROR_FATAL; + } + + return 0; +} diff --git a/drivers/staging/media/vxd/decoder/vxd_int.h b/drivers/staging/media/vxd/decoder/vxd_int.h new file mode 100644 index 000000000000..a294e0d6044f --- /dev/null +++ b/drivers/staging/media/vxd/decoder/vxd_int.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * VXD DEC Common low level core interface component + * + * Copyright (c) Imagination Technologies Ltd. + * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/ + * + * Authors: + * Amit Makani + * + * Re-written for upstreamimg + * Sidraya Jayagond + * Prashanth Kumar Amai + */ +#ifndef _VXD_INT_H +#define _VXD_INT_H + +#include "fw_interface.h" +#include "scaler_setup.h" +#include "vdecdd_defs.h" +#include "vdecfw_shared.h" +#include "vdec_defs.h" +#include "vxd_ext.h" +#include "vxd_props.h" + +/* + * Size of buffer used for batching messages + */ +#define BATCH_MSG_BUFFER_SIZE (8 * 4096) + +#define INTRA_BUF_SIZE (1024 * 32) +#define AUX_LINE_BUFFER_SIZE (512 * 1024) + +#define MAX_PICTURE_WIDTH (4096) +#define MAX_PICTURE_HEIGHT (4096) + +/* + * this macro returns the host address of device buffer. + */ +#define GET_HOST_ADDR(buf) ((buf)->dev_virt) + +#define GET_HOST_ADDR_OFFSET(buf, offset) (((buf)->dev_virt) + (offset)) + +/* + * The extended stride alignment for VXD. + */ +#define VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT (64) + +struct vxd_buffers { + struct vdecdd_ddpict_buf *recon_pict; + struct vdecdd_ddpict_buf *alt_pict; + struct vidio_ddbufinfo *intra_bufinfo; + struct vidio_ddbufinfo *auxline_bufinfo; + struct vidio_ddbufinfo *err_pict_bufinfo; + unsigned int intra_bufsize_per_pipe; + unsigned int auxline_bufsize_per_pipe; + struct vidio_ddbufinfo *msb_bufinfo; + unsigned char btwopass; +}; + +struct pvdec_core_rev { + unsigned int maj_rev; + unsigned int min_rev; + unsigned int maint_rev; + unsigned int int_rev; +}; + +/* + * this has all that it needs to translate a Stream Unit for a picture + * into a transaction. + */ +void vxd_set_altpictcmds(const struct vdecdd_str_unit *str_unit, + const struct vdec_str_configdata *str_configdata, + const struct vdec_str_opconfig *output_config, + const struct vxd_coreprops *coreprops, + const struct vxd_buffers *buffers, + unsigned int *pict_cmds); + +/* + * this has all that it needs to translate a Stream Unit for + * a picture into a transaction. + */ +void vxd_set_reconpictcmds(const struct vdecdd_str_unit *str_unit, + const struct vdec_str_configdata *str_configdata, + const struct vdec_str_opconfig *output_config, + const struct vxd_coreprops *coreprops, + const struct vxd_buffers *buffers, + unsigned int *pict_cmds); + +int vxd_getscalercmds(const struct scaler_config *scaler_config, + const struct scaler_pitch *pitch, + const struct scaler_filter *filter, + const struct pixel_pixinfo *out_loop_pixel_info, + struct scaler_params *params, + unsigned int *pict_cmds); + +/* + * this creates value of MSVDX_CMDS_CODED_PICTURE_SIZE register. + */ +unsigned int vxd_get_codedpicsize(unsigned short width_min1, unsigned short height_min1); + +/* + * return HW codec mode based on video standard. + */ +unsigned char vxd_get_codedmode(enum vdec_vid_std vidstd); + +/* + * translates core properties to the form of the struct vxd_coreprops struct. + */ +void vxd_get_coreproperties(void *hndl_coreproperties, + struct vxd_coreprops *vxd_coreprops); + +/* + * translates picture attributes to the form of the VXD_sPictAttrs struct. + */ +int vxd_get_pictattrs(unsigned int flags, struct vxd_pict_attrs *pict_attrs); + +/* + * translates message attributes to the form of the VXD_eMsgAttr struct. + */ +int vxd_get_msgerrattr(unsigned int flags, enum vxd_msg_attr *msg_attr); + +/* + * sets a message flag. + */ +int vxd_set_msgflag(enum vxd_msg_flag input_flag, unsigned int *flags); + +#endif /* _VXD_INT_H */