Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/media/platform/qcom/iris/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 30 kB image not shown  

Quelle  iris_hfi_gen2_command.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */


#include <linux/bitfield.h>

#include "iris_hfi_gen2.h"
#include "iris_hfi_gen2_packet.h"

#define UNSPECIFIED_COLOR_FORMAT 5
#define NUM_SYS_INIT_PACKETS 8

#define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \
 NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32)))

#define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \
 sizeof(struct iris_hfi_packet) + sizeof(u32))

#define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \
 sizeof(struct iris_hfi_packet))

static int iris_hfi_gen2_sys_init(struct iris_core *core)
{
 struct iris_hfi_header *hdr;
 int ret;

 hdr = kzalloc(SYS_INIT_PKT_SIZE, GFP_KERNEL);
 if (!hdr)
  return -ENOMEM;

 iris_hfi_gen2_packet_sys_init(core, hdr);
 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);

 kfree(hdr);

 return ret;
}

static int iris_hfi_gen2_sys_image_version(struct iris_core *core)
{
 struct iris_hfi_header *hdr;
 int ret;

 hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL);
 if (!hdr)
  return -ENOMEM;

 iris_hfi_gen2_packet_image_version(core, hdr);
 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);

 kfree(hdr);

 return ret;
}

static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core)
{
 struct iris_hfi_header *hdr;
 int ret;

 hdr = kzalloc(SYS_IFPC_PKT_SIZE, GFP_KERNEL);
 if (!hdr)
  return -ENOMEM;

 iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr);
 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);

 kfree(hdr);

 return ret;
}

static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core)
{
 struct iris_hfi_header *hdr;
 int ret;

 hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL);
 if (!hdr)
  return -ENOMEM;

 iris_hfi_gen2_packet_sys_pc_prep(core, hdr);
 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);

 kfree(hdr);

 return ret;
}

static u32 iris_hfi_gen2_get_port(u32 plane)
{
 switch (plane) {
 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
  return HFI_PORT_BITSTREAM;
 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
  return HFI_PORT_RAW;
 default:
  return HFI_PORT_NONE;
 }
}

static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type)
{
 switch (buffer_type) {
 case BUF_INPUT:
 case BUF_BIN:
 case BUF_COMV:
 case BUF_NON_COMV:
 case BUF_LINE:
  return HFI_PORT_BITSTREAM;
 case BUF_OUTPUT:
 case BUF_DPB:
  return HFI_PORT_RAW;
 case BUF_PERSIST:
 default:
  return HFI_PORT_NONE;
 }
}

static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet_type, u32 flag,
           u32 plane, u32 payload_type, void *payload,
           u32 payload_size)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

 iris_hfi_gen2_packet_session_property(inst,
           packet_type,
           flag,
           plane,
           payload_type,
           payload,
           payload_size);

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
  inst->fmt_src->fmt.pix_mp.height;

 inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_BITSTREAM_RESOLUTION,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &resolution,
        sizeof(u32));
}

static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst)
{
 u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height);
 u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width);
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 left_offset = inst->crop.left;
 u32 top_offset = inst->crop.top;
 u32 payload[2];

 payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset;
 payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset;
 inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0];
 inst_hfi_gen2->src_subcr_params.crop_offsets[1] = payload[1];

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_CROP_OFFSETS,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_64_PACKED,
        &payload,
        sizeof(u64));
}

static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 bitdepth = BIT_DEPTH_8;

 inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &bitdepth,
        sizeof(u32));
}

static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 coded_frames = 0;

 if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE)
  coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG;
 inst_hfi_gen2->src_subcr_params.coded_frames = coded_frames;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_CODED_FRAMES,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &coded_frames,
        sizeof(u32));
}

static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 min_output = inst->buffers[BUF_OUTPUT].min_count;

 inst_hfi_gen2->src_subcr_params.fw_min_count = min_output;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &min_output,
        sizeof(u32));
}

static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 poc = 0;

 inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_PIC_ORDER_CNT_TYPE,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &poc,
        sizeof(u32));
}

static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp;
 u32 video_signal_type_present_flag = 0, color_info;
 u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED;
 u32 video_format = UNSPECIFIED_COLOR_FORMAT;
 u32 full_range = V4L2_QUANTIZATION_DEFAULT;
 u32 transfer_char = HFI_TRANSFER_RESERVED;
 u32 colour_description_present_flag = 0;
 u32 primaries = HFI_PRIMARIES_RESERVED;

 if (pixmp->colorspace != V4L2_COLORSPACE_DEFAULT ||
     pixmp->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT ||
     pixmp->xfer_func != V4L2_XFER_FUNC_DEFAULT) {
  colour_description_present_flag = 1;
  video_signal_type_present_flag = 1;
  primaries = iris_hfi_gen2_get_color_primaries(pixmp->colorspace);
  matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp->ycbcr_enc);
  transfer_char = iris_hfi_gen2_get_transfer_char(pixmp->xfer_func);
 }

 if (pixmp->quantization != V4L2_QUANTIZATION_DEFAULT) {
  video_signal_type_present_flag = 1;
  full_range = pixmp->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0;
 }

 color_info = iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries,
        colour_description_present_flag, full_range,
        video_format, video_signal_type_present_flag);

 inst_hfi_gen2->src_subcr_params.color_info = color_info;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_SIGNAL_COLOR_INFO,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_32_PACKED,
        &color_info,
        sizeof(u32));
}

static int iris_hfi_gen2_set_profile(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 profile = 0;

 switch (inst->codec) {
 case V4L2_PIX_FMT_HEVC:
  profile = inst->fw_caps[PROFILE_HEVC].value;
  break;
 case V4L2_PIX_FMT_VP9:
  profile = inst->fw_caps[PROFILE_VP9].value;
  break;
 case V4L2_PIX_FMT_H264:
  profile = inst->fw_caps[PROFILE_H264].value;
  break;
 }

 inst_hfi_gen2->src_subcr_params.profile = profile;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_PROFILE,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32_ENUM,
        &profile,
        sizeof(u32));
}

static int iris_hfi_gen2_set_level(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 level = 0;

 switch (inst->codec) {
 case V4L2_PIX_FMT_HEVC:
  level = inst->fw_caps[LEVEL_HEVC].value;
  break;
 case V4L2_PIX_FMT_VP9:
  level = inst->fw_caps[LEVEL_VP9].value;
  break;
 case V4L2_PIX_FMT_H264:
  level = inst->fw_caps[LEVEL_H264].value;
  break;
 }

 inst_hfi_gen2->src_subcr_params.level = level;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_LEVEL,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32_ENUM,
        &level,
        sizeof(u32));
}

static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst)
{
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 u32 hfi_colorformat, pixelformat;

 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
 hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_COLOR_FORMAT,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32,
        &hfi_colorformat,
        sizeof(u32));
}

static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst)
{
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
 u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height;
 u32 stride_y = inst->fmt_dst->fmt.pix_mp.width;
 u32 scanline_uv = scanline_y / 2;
 u32 stride_uv = stride_y;
 u32 payload[2];

 if (pixelformat != V4L2_PIX_FMT_NV12)
  return 0;

 payload[0] = stride_y << 16 | scanline_y;
 payload[1] = stride_uv << 16 | scanline_uv;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_LINEAR_STRIDE_SCANLINE,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U64,
        &payload,
        sizeof(u64));
}

static int iris_hfi_gen2_set_tier(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 u32 tier = inst->fw_caps[TIER].value;

 inst_hfi_gen2->src_subcr_params.tier = tier;

 return iris_hfi_gen2_session_set_property(inst,
        HFI_PROP_TIER,
        HFI_HOST_FLAGS_NONE,
        port,
        HFI_PAYLOAD_U32_ENUM,
        &tier,
        sizeof(u32));
}

static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane)
{
 struct iris_core *core = inst->core;
 u32 config_params_size = 0, i, j;
 const u32 *config_params = NULL;
 int ret;

 static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = {
  {HFI_PROP_BITSTREAM_RESOLUTION,       iris_hfi_gen2_set_bitstream_resolution   },
  {HFI_PROP_CROP_OFFSETS,               iris_hfi_gen2_set_crop_offsets           },
  {HFI_PROP_CODED_FRAMES,               iris_hfi_gen2_set_coded_frames           },
  {HFI_PROP_LUMA_CHROMA_BIT_DEPTH,      iris_hfi_gen2_set_bit_depth              },
  {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count       },
  {HFI_PROP_PIC_ORDER_CNT_TYPE,         iris_hfi_gen2_set_picture_order_count    },
  {HFI_PROP_SIGNAL_COLOR_INFO,          iris_hfi_gen2_set_colorspace             },
  {HFI_PROP_PROFILE,                    iris_hfi_gen2_set_profile                },
  {HFI_PROP_LEVEL,                      iris_hfi_gen2_set_level                  },
  {HFI_PROP_COLOR_FORMAT,               iris_hfi_gen2_set_colorformat            },
  {HFI_PROP_LINEAR_STRIDE_SCANLINE,     iris_hfi_gen2_set_linear_stride_scanline },
  {HFI_PROP_TIER,                       iris_hfi_gen2_set_tier                   },
 };

 if (V4L2_TYPE_IS_OUTPUT(plane)) {
  switch (inst->codec) {
  case V4L2_PIX_FMT_H264:
   config_params = core->iris_platform_data->input_config_params_default;
   config_params_size =
    core->iris_platform_data->input_config_params_default_size;
   break;
  case V4L2_PIX_FMT_HEVC:
   config_params = core->iris_platform_data->input_config_params_hevc;
   config_params_size =
    core->iris_platform_data->input_config_params_hevc_size;
   break;
  case V4L2_PIX_FMT_VP9:
   config_params = core->iris_platform_data->input_config_params_vp9;
   config_params_size =
    core->iris_platform_data->input_config_params_vp9_size;
   break;
  }
 } else {
  config_params = core->iris_platform_data->output_config_params;
  config_params_size = core->iris_platform_data->output_config_params_size;
 }

 if (!config_params || !config_params_size)
  return -EINVAL;

 for (i = 0; i < config_params_size; i++) {
  for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
   if (prop_type_handle_arr[j].type == config_params[i]) {
    ret = prop_type_handle_arr[j].handle(inst);
    if (ret)
     return ret;
    break;
   }
  }
 }

 return 0;
}

static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 codec = 0;

 switch (inst->codec) {
 case V4L2_PIX_FMT_H264:
  codec = HFI_CODEC_DECODE_AVC;
  break;
 case V4L2_PIX_FMT_HEVC:
  codec = HFI_CODEC_DECODE_HEVC;
  break;
 case V4L2_PIX_FMT_VP9:
  codec = HFI_CODEC_DECODE_VP9;
  break;
 }

 iris_hfi_gen2_packet_session_property(inst,
           HFI_PROP_CODEC,
           HFI_HOST_FLAGS_NONE,
           HFI_PORT_NONE,
           HFI_PAYLOAD_U32_ENUM,
           &codec,
           sizeof(u32));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_set_default_header(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 default_header = false;

 iris_hfi_gen2_packet_session_property(inst,
           HFI_PROP_DEC_DEFAULT_HEADER,
           HFI_HOST_FLAGS_NONE,
           HFI_PORT_BITSTREAM,
           HFI_PAYLOAD_U32,
           &default_header,
           sizeof(u32));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_open(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 int ret;

 if (inst->state != IRIS_INST_DEINIT)
  return -EALREADY;

 inst_hfi_gen2->ipsc_properties_set = false;
 inst_hfi_gen2->opsc_properties_set = false;

 inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL);
 if (!inst_hfi_gen2->packet)
  return -ENOMEM;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_OPEN,
          HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED,
          HFI_PORT_NONE,
          0,
          HFI_PAYLOAD_U32,
          &inst->session_id,
          sizeof(u32));

 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
           inst_hfi_gen2->packet->size);
 if (ret)
  goto fail_free_packet;

 ret = iris_hfi_gen2_session_set_codec(inst);
 if (ret)
  goto fail_free_packet;

 ret = iris_hfi_gen2_session_set_default_header(inst);
 if (ret)
  goto fail_free_packet;

 return 0;

fail_free_packet:
 kfree(inst_hfi_gen2->packet);
 inst_hfi_gen2->packet = NULL;

 return ret;
}

static int iris_hfi_gen2_session_close(struct iris_inst *inst)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 int ret;

 if (!inst_hfi_gen2->packet)
  return -EINVAL;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_CLOSE,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED |
          HFI_HOST_FLAGS_NON_DISCARDABLE),
          HFI_PORT_NONE,
          inst->session_id,
          HFI_PAYLOAD_NONE,
          NULL,
          0);

 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
           inst_hfi_gen2->packet->size);

 kfree(inst_hfi_gen2->packet);
 inst_hfi_gen2->packet = NULL;

 return ret;
}

static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst,
      u32 cmd, u32 plane, u32 payload_type,
      void *payload, u32 payload_size)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

 iris_hfi_gen2_packet_session_command(inst,
          cmd,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          payload_type,
          payload,
          payload_size);

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 struct hfi_subscription_params subsc_params;
 u32 prop_type, payload_size, payload_type;
 struct iris_core *core = inst->core;
 const u32 *change_param = NULL;
 u32 change_param_size = 0;
 u32 payload[32] = {0};
 u32 hfi_port = 0, i;
 int ret;

 if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) ||
     (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) {
  dev_err(core->dev, "invalid plane\n");
  return 0;
 }

 switch (inst->codec) {
 case V4L2_PIX_FMT_H264:
  change_param = core->iris_platform_data->input_config_params_default;
  change_param_size =
   core->iris_platform_data->input_config_params_default_size;
  break;
 case V4L2_PIX_FMT_HEVC:
  change_param = core->iris_platform_data->input_config_params_hevc;
  change_param_size =
   core->iris_platform_data->input_config_params_hevc_size;
  break;
 case V4L2_PIX_FMT_VP9:
  change_param = core->iris_platform_data->input_config_params_vp9;
  change_param_size =
   core->iris_platform_data->input_config_params_vp9_size;
  break;
 }

 payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;

 for (i = 0; i < change_param_size; i++)
  payload[i + 1] = change_param[i];

 ret = iris_hfi_gen2_session_subscribe_mode(inst,
         HFI_CMD_SUBSCRIBE_MODE,
         plane,
         HFI_PAYLOAD_U32_ARRAY,
         &payload[0],
         ((change_param_size + 1) * sizeof(u32)));
 if (ret)
  return ret;

 if (V4L2_TYPE_IS_OUTPUT(plane)) {
  inst_hfi_gen2->ipsc_properties_set = true;
 } else {
  hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
  memcpy(&inst_hfi_gen2->dst_subcr_params,
         &inst_hfi_gen2->src_subcr_params,
         sizeof(inst_hfi_gen2->src_subcr_params));
  subsc_params = inst_hfi_gen2->dst_subcr_params;
  for (i = 0; i < change_param_size; i++) {
   payload[0] = 0;
   payload[1] = 0;
   payload_size = 0;
   payload_type = 0;
   prop_type = change_param[i];
   switch (prop_type) {
   case HFI_PROP_BITSTREAM_RESOLUTION:
    payload[0] = subsc_params.bitstream_resolution;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_CROP_OFFSETS:
    payload[0] = subsc_params.crop_offsets[0];
    payload[1] = subsc_params.crop_offsets[1];
    payload_size = sizeof(u64);
    payload_type = HFI_PAYLOAD_64_PACKED;
    break;
   case HFI_PROP_CODED_FRAMES:
    payload[0] = subsc_params.coded_frames;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_LUMA_CHROMA_BIT_DEPTH:
    payload[0] = subsc_params.bit_depth;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
    payload[0] = subsc_params.fw_min_count;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_PIC_ORDER_CNT_TYPE:
    payload[0] = subsc_params.pic_order_cnt;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_SIGNAL_COLOR_INFO:
    payload[0] = subsc_params.color_info;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_PROFILE:
    payload[0] = subsc_params.profile;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_LEVEL:
    payload[0] = subsc_params.level;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   case HFI_PROP_TIER:
    payload[0] = subsc_params.tier;
    payload_size = sizeof(u32);
    payload_type = HFI_PAYLOAD_U32;
    break;
   default:
    prop_type = 0;
    ret = -EINVAL;
    break;
   }
   if (prop_type) {
    ret = iris_hfi_gen2_session_set_property(inst,
          prop_type,
          HFI_HOST_FLAGS_NONE,
          hfi_port,
          payload_type,
          &payload,
          payload_size);
    if (ret)
     return ret;
   }
  }
  inst_hfi_gen2->opsc_properties_set = true;
 }

 return 0;
}

static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane)
{
 struct iris_core *core = inst->core;
 u32 subscribe_prop_size = 0, i;
 const u32 *subcribe_prop = NULL;
 u32 payload[32] = {0};

 payload[0] = HFI_MODE_PROPERTY;

 if (V4L2_TYPE_IS_OUTPUT(plane)) {
  subscribe_prop_size = core->iris_platform_data->dec_input_prop_size;
  subcribe_prop = core->iris_platform_data->dec_input_prop;
 } else {
  switch (inst->codec) {
  case V4L2_PIX_FMT_H264:
   subcribe_prop = core->iris_platform_data->dec_output_prop_avc;
   subscribe_prop_size =
    core->iris_platform_data->dec_output_prop_avc_size;
   break;
  case V4L2_PIX_FMT_HEVC:
   subcribe_prop = core->iris_platform_data->dec_output_prop_hevc;
   subscribe_prop_size =
    core->iris_platform_data->dec_output_prop_hevc_size;
   break;
  case V4L2_PIX_FMT_VP9:
   subcribe_prop = core->iris_platform_data->dec_output_prop_vp9;
   subscribe_prop_size =
    core->iris_platform_data->dec_output_prop_vp9_size;
   break;
  }
 }

 for (i = 0; i < subscribe_prop_size; i++)
  payload[i + 1] = subcribe_prop[i];

 return iris_hfi_gen2_session_subscribe_mode(inst,
          HFI_CMD_SUBSCRIBE_MODE,
          plane,
          HFI_PAYLOAD_U32_ARRAY,
          &payload[0],
          (subscribe_prop_size + 1) * sizeof(u32));
}

static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 int ret = 0;

 ret = iris_hfi_gen2_subscribe_change_param(inst, plane);
 if (ret)
  return ret;

 ret = iris_hfi_gen2_subscribe_property(inst, plane);
 if (ret)
  return ret;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_START,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_NONE,
          NULL,
          0);

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 int ret = 0;

 reinit_completion(&inst->completion);

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_STOP,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED |
          HFI_HOST_FLAGS_NON_DISCARDABLE),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_NONE,
          NULL,
          0);

 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
           inst_hfi_gen2->packet->size);
 if (ret)
  return ret;

 return iris_wait_for_session_response(inst, false);
}

static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_PAUSE,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_NONE,
          NULL,
          0);

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 payload = HFI_CMD_SETTINGS_CHANGE;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_RESUME,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_U32,
          &payload,
          sizeof(u32));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 u32 payload = HFI_CMD_DRAIN;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_RESUME,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_U32,
          &payload,
          sizeof(u32));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

 if (!V4L2_TYPE_IS_OUTPUT(plane))
  return 0;

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_DRAIN,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED |
          HFI_HOST_FLAGS_NON_DISCARDABLE),
          iris_hfi_gen2_get_port(plane),
          inst->session_id,
          HFI_PAYLOAD_NONE,
          NULL,
          0);

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
{
 switch (buffer_type) {
 case BUF_INPUT:
  return HFI_BUFFER_BITSTREAM;
 case BUF_OUTPUT:
  return HFI_BUFFER_RAW;
 case BUF_BIN:
  return HFI_BUFFER_BIN;
 case BUF_COMV:
  return HFI_BUFFER_COMV;
 case BUF_NON_COMV:
  return HFI_BUFFER_NON_COMV;
 case BUF_LINE:
  return HFI_BUFFER_LINE;
 case BUF_DPB:
  return HFI_BUFFER_DPB;
 case BUF_PERSIST:
  return HFI_BUFFER_PERSIST;
 default:
  return 0;
 }
}

static int iris_set_num_comv(struct iris_inst *inst)
{
 struct platform_inst_caps *caps;
 struct iris_core *core = inst->core;
 u32 num_comv;

 caps = core->iris_platform_data->inst_caps;
 num_comv = caps->num_comv;

 return core->hfi_ops->session_set_property(inst,
         HFI_PROP_COMV_BUFFER_COUNT,
         HFI_HOST_FLAGS_NONE,
         HFI_PORT_BITSTREAM,
         HFI_PAYLOAD_U32,
         &num_comv, sizeof(u32));
}

static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf)
{
 memset(buf, 0, sizeof(*buf));
 buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type);
 buf->index = buffer->index;
 buf->base_address = buffer->device_addr;
 buf->addr_offset = 0;
 buf->buffer_size = buffer->buffer_size;

 if (buffer->type == BUF_INPUT)
  buf->buffer_size = ALIGN(buffer->buffer_size, 256);
 buf->data_offset = buffer->data_offset;
 buf->data_size = buffer->data_size;
 if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
  buf->flags |= HFI_BUF_HOST_FLAG_RELEASE;
 buf->flags |= HFI_BUF_HOST_FLAGS_CB_NON_SECURE;
 buf->timestamp = buffer->timestamp;
}

static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buffer)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 struct iris_hfi_buffer hfi_buffer;
 u32 port;
 int ret;

 iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
 if (buffer->type == BUF_COMV) {
  ret = iris_set_num_comv(inst);
  if (ret)
   return ret;
 }

 port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);
 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_BUFFER,
          HFI_HOST_FLAGS_INTR_REQUIRED,
          port,
          inst->session_id,
          HFI_PAYLOAD_STRUCTURE,
          &hfi_buffer,
          sizeof(hfi_buffer));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct iris_buffer *buffer)
{
 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
 struct iris_hfi_buffer hfi_buffer;
 u32 port;

 iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
 hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE;
 port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);

 iris_hfi_gen2_packet_session_command(inst,
          HFI_CMD_BUFFER,
          (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
          HFI_HOST_FLAGS_INTR_REQUIRED),
          port,
          inst->session_id,
          HFI_PAYLOAD_STRUCTURE,
          &hfi_buffer,
          sizeof(hfi_buffer));

 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
     inst_hfi_gen2->packet->size);
}

static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
 .sys_init = iris_hfi_gen2_sys_init,
 .sys_image_version = iris_hfi_gen2_sys_image_version,
 .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse,
 .sys_pc_prep = iris_hfi_gen2_sys_pc_prep,
 .session_open = iris_hfi_gen2_session_open,
 .session_set_config_params = iris_hfi_gen2_session_set_config_params,
 .session_set_property = iris_hfi_gen2_session_set_property,
 .session_start = iris_hfi_gen2_session_start,
 .session_queue_buf = iris_hfi_gen2_session_queue_buffer,
 .session_release_buf = iris_hfi_gen2_session_release_buffer,
 .session_pause = iris_hfi_gen2_session_pause,
 .session_resume_drc = iris_hfi_gen2_session_resume_drc,
 .session_stop = iris_hfi_gen2_session_stop,
 .session_drain = iris_hfi_gen2_session_drain,
 .session_resume_drain = iris_hfi_gen2_session_resume_drain,
 .session_close = iris_hfi_gen2_session_close,
};

void iris_hfi_gen2_command_ops_init(struct iris_core *core)
{
 core->hfi_ops = &iris_hfi_gen2_command_ops;
}

struct iris_inst *iris_hfi_gen2_get_instance(void)
{
 return kzalloc(sizeof(struct iris_inst_hfi_gen2), GFP_KERNEL);
}

Messung V0.5
C=100 H=94 G=96

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.