/*
 * Copyright (C) 2018 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    Xiang Haihao <haihao.xiang@intel.com>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>

#include "intel_batchbuffer.h"
#include "i965_defines.h"
#include "i965_structs.h"
#include "i965_drv_video.h"
#include "i965_encoder.h"
#include "i965_encoder_utils.h"
#include "intel_media.h"
#include "i965_encoder_common.h"
#include "gen10_vdenc_common.h"
#include "gen10_hcp_common.h"
#include "gen10_huc_common.h"
#include "gen10_vdenc_vp9.h"

static const uint32_t gen10_vdenc_vp9_dys[][4] = {
#include "shaders/brc/cnl/vp9_dys.g10b"
};

static struct i965_kernel vdenc_vp9_kernels_dys[1] = {
	{
		"dys",
		0,
		gen10_vdenc_vp9_dys,
		sizeof(gen10_vdenc_vp9_dys),
		NULL
	},
};

static const uint32_t gen10_vdenc_vp9_streamin[][4] = {
#include "shaders/brc/cnl/vp9_vdenc_hme_vp9_streamin.g10b"
};

static struct i965_kernel vdenc_vp9_kernels_streamin[1] = {
	{
		"streamin",
		0,
		gen10_vdenc_vp9_streamin,
		sizeof(gen10_vdenc_vp9_streamin),
		NULL
	},
};

static const uint32_t vdenc_vp9_huc_prob_dmem_data[320] = {
	0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
	0x00000004, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x01000000, 0x0000ff00, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001,
	0x00540049, 0x00000060, 0x00000072, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x02b80078, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

static const uint8_t vdenc_vp9_key_frame_default_probs[2048] = {
	0x64, 0x42, 0x14, 0x98, 0x0f, 0x65, 0x03, 0x88, 0x25, 0x05, 0x34, 0x0d, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xc3, 0x1d, 0xb7, 0x54, 0x31, 0x88, 0x08, 0x2a, 0x47, 0x1f, 0x6b, 0xa9, 0x23, 0x63, 0x9f, 0x11,
	0x52, 0x8c, 0x08, 0x42, 0x72, 0x02, 0x2c, 0x4c, 0x01, 0x13, 0x20, 0x28, 0x84, 0xc9, 0x1d, 0x72,
	0xbb, 0x0d, 0x5b, 0x9d, 0x07, 0x4b, 0x7f, 0x03, 0x3a, 0x5f, 0x01, 0x1c, 0x2f, 0x45, 0x8e, 0xdd,
	0x2a, 0x7a, 0xc9, 0x0f, 0x5b, 0x9f, 0x06, 0x43, 0x79, 0x01, 0x2a, 0x4d, 0x01, 0x11, 0x1f, 0x66,
	0x94, 0xe4, 0x43, 0x75, 0xcc, 0x11, 0x52, 0x9a, 0x06, 0x3b, 0x72, 0x02, 0x27, 0x4b, 0x01, 0x0f,
	0x1d, 0x9c, 0x39, 0xe9, 0x77, 0x39, 0xd4, 0x3a, 0x30, 0xa3, 0x1d, 0x28, 0x7c, 0x0c, 0x1e, 0x51,
	0x03, 0x0c, 0x1f, 0xbf, 0x6b, 0xe2, 0x7c, 0x75, 0xcc, 0x19, 0x63, 0x9b, 0x1d, 0x94, 0xd2, 0x25,
	0x7e, 0xc2, 0x08, 0x5d, 0x9d, 0x02, 0x44, 0x76, 0x01, 0x27, 0x45, 0x01, 0x11, 0x21, 0x29, 0x97,
	0xd5, 0x1b, 0x7b, 0xc1, 0x03, 0x52, 0x90, 0x01, 0x3a, 0x69, 0x01, 0x20, 0x3c, 0x01, 0x0d, 0x1a,
	0x3b, 0x9f, 0xdc, 0x17, 0x7e, 0xc6, 0x04, 0x58, 0x97, 0x01, 0x42, 0x72, 0x01, 0x26, 0x47, 0x01,
	0x12, 0x22, 0x72, 0x88, 0xe8, 0x33, 0x72, 0xcf, 0x0b, 0x53, 0x9b, 0x03, 0x38, 0x69, 0x01, 0x21,
	0x41, 0x01, 0x11, 0x22, 0x95, 0x41, 0xea, 0x79, 0x39, 0xd7, 0x3d, 0x31, 0xa6, 0x1c, 0x24, 0x72,
	0x0c, 0x19, 0x4c, 0x03, 0x10, 0x2a, 0xd6, 0x31, 0xdc, 0x84, 0x3f, 0xbc, 0x2a, 0x41, 0x89, 0x55,
	0x89, 0xdd, 0x68, 0x83, 0xd8, 0x31, 0x6f, 0xc0, 0x15, 0x57, 0x9b, 0x02, 0x31, 0x57, 0x01, 0x10,
	0x1c, 0x59, 0xa3, 0xe6, 0x5a, 0x89, 0xdc, 0x1d, 0x64, 0xb7, 0x0a, 0x46, 0x87, 0x02, 0x2a, 0x51,
	0x01, 0x11, 0x21, 0x6c, 0xa7, 0xed, 0x37, 0x85, 0xde, 0x0f, 0x61, 0xb3, 0x04, 0x48, 0x87, 0x01,
	0x2d, 0x55, 0x01, 0x13, 0x26, 0x7c, 0x92, 0xf0, 0x42, 0x7c, 0xe0, 0x11, 0x58, 0xaf, 0x04, 0x3a,
	0x7a, 0x01, 0x24, 0x4b, 0x01, 0x12, 0x25, 0x8d, 0x4f, 0xf1, 0x7e, 0x46, 0xe3, 0x42, 0x3a, 0xb6,
	0x1e, 0x2c, 0x88, 0x0c, 0x22, 0x60, 0x02, 0x14, 0x2f, 0xe5, 0x63, 0xf9, 0x8f, 0x6f, 0xeb, 0x2e,
	0x6d, 0xc0, 0x52, 0x9e, 0xec, 0x5e, 0x92, 0xe0, 0x19, 0x75, 0xbf, 0x09, 0x57, 0x95, 0x03, 0x38,
	0x63, 0x01, 0x21, 0x39, 0x53, 0xa7, 0xed, 0x44, 0x91, 0xde, 0x0a, 0x67, 0xb1, 0x02, 0x48, 0x83,
	0x01, 0x29, 0x4f, 0x01, 0x14, 0x27, 0x63, 0xa7, 0xef, 0x2f, 0x8d, 0xe0, 0x0a, 0x68, 0xb2, 0x02,
	0x49, 0x85, 0x01, 0x2c, 0x55, 0x01, 0x16, 0x2f, 0x7f, 0x91, 0xf3, 0x47, 0x81, 0xe4, 0x11, 0x5d,
	0xb1, 0x03, 0x3d, 0x7c, 0x01, 0x29, 0x54, 0x01, 0x15, 0x34, 0x9d, 0x4e, 0xf4, 0x8c, 0x48, 0xe7,
	0x45, 0x3a, 0xb8, 0x1f, 0x2c, 0x89, 0x0e, 0x26, 0x69, 0x08, 0x17, 0x3d, 0x7d, 0x22, 0xbb, 0x34,
	0x29, 0x85, 0x06, 0x1f, 0x38, 0x25, 0x6d, 0x99, 0x33, 0x66, 0x93, 0x17, 0x57, 0x80, 0x08, 0x43,
	0x65, 0x01, 0x29, 0x3f, 0x01, 0x13, 0x1d, 0x1f, 0x9a, 0xb9, 0x11, 0x7f, 0xaf, 0x06, 0x60, 0x91,
	0x02, 0x49, 0x72, 0x01, 0x33, 0x52, 0x01, 0x1c, 0x2d, 0x17, 0xa3, 0xc8, 0x0a, 0x83, 0xb9, 0x02,
	0x5d, 0x94, 0x01, 0x43, 0x6f, 0x01, 0x29, 0x45, 0x01, 0x0e, 0x18, 0x1d, 0xb0, 0xd9, 0x0c, 0x91,
	0xc9, 0x03, 0x65, 0x9c, 0x01, 0x45, 0x6f, 0x01, 0x27, 0x3f, 0x01, 0x0e, 0x17, 0x39, 0xc0, 0xe9,
	0x19, 0x9a, 0xd7, 0x06, 0x6d, 0xa7, 0x03, 0x4e, 0x76, 0x01, 0x30, 0x45, 0x01, 0x15, 0x1d, 0xca,
	0x69, 0xf5, 0x6c, 0x6a, 0xd8, 0x12, 0x5a, 0x90, 0x21, 0xac, 0xdb, 0x40, 0x95, 0xce, 0x0e, 0x75,
	0xb1, 0x05, 0x5a, 0x8d, 0x02, 0x3d, 0x5f, 0x01, 0x25, 0x39, 0x21, 0xb3, 0xdc, 0x0b, 0x8c, 0xc6,
	0x01, 0x59, 0x94, 0x01, 0x3c, 0x68, 0x01, 0x21, 0x39, 0x01, 0x0c, 0x15, 0x1e, 0xb5, 0xdd, 0x08,
	0x8d, 0xc6, 0x01, 0x57, 0x91, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x14, 0x20, 0xba,
	0xe0, 0x07, 0x8e, 0xc6, 0x01, 0x56, 0x8f, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x16,
	0x39, 0xc0, 0xe3, 0x14, 0x8f, 0xcc, 0x03, 0x60, 0x9a, 0x01, 0x44, 0x70, 0x01, 0x2a, 0x45, 0x01,
	0x13, 0x20, 0xd4, 0x23, 0xd7, 0x71, 0x2f, 0xa9, 0x1d, 0x30, 0x69, 0x4a, 0x81, 0xcb, 0x6a, 0x78,
	0xcb, 0x31, 0x6b, 0xb2, 0x13, 0x54, 0x90, 0x04, 0x32, 0x54, 0x01, 0x0f, 0x19, 0x47, 0xac, 0xd9,
	0x2c, 0x8d, 0xd1, 0x0f, 0x66, 0xad, 0x06, 0x4c, 0x85, 0x02, 0x33, 0x59, 0x01, 0x18, 0x2a, 0x40,
	0xb9, 0xe7, 0x1f, 0x94, 0xd8, 0x08, 0x67, 0xaf, 0x03, 0x4a, 0x83, 0x01, 0x2e, 0x51, 0x01, 0x12,
	0x1e, 0x41, 0xc4, 0xeb, 0x19, 0x9d, 0xdd, 0x05, 0x69, 0xae, 0x01, 0x43, 0x78, 0x01, 0x26, 0x45,
	0x01, 0x0f, 0x1e, 0x41, 0xcc, 0xee, 0x1e, 0x9c, 0xe0, 0x07, 0x6b, 0xb1, 0x02, 0x46, 0x7c, 0x01,
	0x2a, 0x49, 0x01, 0x12, 0x22, 0xe1, 0x56, 0xfb, 0x90, 0x68, 0xeb, 0x2a, 0x63, 0xb5, 0x55, 0xaf,
	0xef, 0x70, 0xa5, 0xe5, 0x1d, 0x88, 0xc8, 0x0c, 0x67, 0xa2, 0x06, 0x4d, 0x7b, 0x02, 0x35, 0x54,
	0x4b, 0xb7, 0xef, 0x1e, 0x9b, 0xdd, 0x03, 0x6a, 0xab, 0x01, 0x4a, 0x80, 0x01, 0x2c, 0x4c, 0x01,
	0x11, 0x1c, 0x49, 0xb9, 0xf0, 0x1b, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x4b, 0x7f, 0x01, 0x2a,
	0x49, 0x01, 0x11, 0x1d, 0x3e, 0xbe, 0xee, 0x15, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x48, 0x7a,
	0x01, 0x28, 0x47, 0x01, 0x12, 0x20, 0x3d, 0xc7, 0xf0, 0x1b, 0xa1, 0xe2, 0x04, 0x71, 0xb4, 0x01,
	0x4c, 0x81, 0x01, 0x2e, 0x50, 0x01, 0x17, 0x29, 0x07, 0x1b, 0x99, 0x05, 0x1e, 0x5f, 0x01, 0x10,
	0x1e, 0x32, 0x4b, 0x7f, 0x39, 0x4b, 0x7c, 0x1b, 0x43, 0x6c, 0x0a, 0x36, 0x56, 0x01, 0x21, 0x34,
	0x01, 0x0c, 0x12, 0x2b, 0x7d, 0x97, 0x1a, 0x6c, 0x94, 0x07, 0x53, 0x7a, 0x02, 0x3b, 0x59, 0x01,
	0x26, 0x3c, 0x01, 0x11, 0x1b, 0x17, 0x90, 0xa3, 0x0d, 0x70, 0x9a, 0x02, 0x4b, 0x75, 0x01, 0x32,
	0x51, 0x01, 0x1f, 0x33, 0x01, 0x0e, 0x17, 0x12, 0xa2, 0xb9, 0x06, 0x7b, 0xab, 0x01, 0x4e, 0x7d,
	0x01, 0x33, 0x56, 0x01, 0x1f, 0x36, 0x01, 0x0e, 0x17, 0x0f, 0xc7, 0xe3, 0x03, 0x96, 0xcc, 0x01,
	0x5b, 0x92, 0x01, 0x37, 0x5f, 0x01, 0x1e, 0x35, 0x01, 0x0b, 0x14, 0x13, 0x37, 0xf0, 0x13, 0x3b,
	0xc4, 0x03, 0x34, 0x69, 0x29, 0xa6, 0xcf, 0x68, 0x99, 0xc7, 0x1f, 0x7b, 0xb5, 0x0e, 0x65, 0x98,
	0x05, 0x48, 0x6a, 0x01, 0x24, 0x34, 0x23, 0xb0, 0xd3, 0x0c, 0x83, 0xbe, 0x02, 0x58, 0x90, 0x01,
	0x3c, 0x65, 0x01, 0x24, 0x3c, 0x01, 0x10, 0x1c, 0x1c, 0xb7, 0xd5, 0x08, 0x86, 0xbf, 0x01, 0x56,
	0x8e, 0x01, 0x38, 0x60, 0x01, 0x1e, 0x35, 0x01, 0x0c, 0x14, 0x14, 0xbe, 0xd7, 0x04, 0x87, 0xc0,
	0x01, 0x54, 0x8b, 0x01, 0x35, 0x5b, 0x01, 0x1c, 0x31, 0x01, 0x0b, 0x14, 0x0d, 0xc4, 0xd8, 0x02,
	0x89, 0xc0, 0x01, 0x56, 0x8f, 0x01, 0x39, 0x63, 0x01, 0x20, 0x38, 0x01, 0x0d, 0x18, 0xd3, 0x1d,
	0xd9, 0x60, 0x2f, 0x9c, 0x16, 0x2b, 0x57, 0x4e, 0x78, 0xc1, 0x6f, 0x74, 0xba, 0x2e, 0x66, 0xa4,
	0x0f, 0x50, 0x80, 0x02, 0x31, 0x4c, 0x01, 0x12, 0x1c, 0x47, 0xa1, 0xcb, 0x2a, 0x84, 0xc0, 0x0a,
	0x62, 0x96, 0x03, 0x45, 0x6d, 0x01, 0x2c, 0x46, 0x01, 0x12, 0x1d, 0x39, 0xba, 0xd3, 0x1e, 0x8c,
	0xc4, 0x04, 0x5d, 0x92, 0x01, 0x3e, 0x66, 0x01, 0x26, 0x41, 0x01, 0x10, 0x1b, 0x2f, 0xc7, 0xd9,
	0x0e, 0x91, 0xc4, 0x01, 0x58, 0x8e, 0x01, 0x39, 0x62, 0x01, 0x24, 0x3e, 0x01, 0x0f, 0x1a, 0x1a,
	0xdb, 0xe5, 0x05, 0x9b, 0xcf, 0x01, 0x5e, 0x97, 0x01, 0x3c, 0x68, 0x01, 0x24, 0x3e, 0x01, 0x10,
	0x1c, 0xe9, 0x1d, 0xf8, 0x92, 0x2f, 0xdc, 0x2b, 0x34, 0x8c, 0x64, 0xa3, 0xe8, 0xb3, 0xa1, 0xde,
	0x3f, 0x8e, 0xcc, 0x25, 0x71, 0xae, 0x1a, 0x59, 0x89, 0x12, 0x44, 0x61, 0x55, 0xb5, 0xe6, 0x20,
	0x92, 0xd1, 0x07, 0x64, 0xa4, 0x03, 0x47, 0x79, 0x01, 0x2d, 0x4d, 0x01, 0x12, 0x1e, 0x41, 0xbb,
	0xe6, 0x14, 0x94, 0xcf, 0x02, 0x61, 0x9f, 0x01, 0x44, 0x74, 0x01, 0x28, 0x46, 0x01, 0x0e, 0x1d,
	0x28, 0xc2, 0xe3, 0x08, 0x93, 0xcc, 0x01, 0x5e, 0x9b, 0x01, 0x41, 0x70, 0x01, 0x27, 0x42, 0x01,
	0x0e, 0x1a, 0x10, 0xd0, 0xe4, 0x03, 0x97, 0xcf, 0x01, 0x62, 0xa0, 0x01, 0x43, 0x75, 0x01, 0x29,
	0x4a, 0x01, 0x11, 0x1f, 0x11, 0x26, 0x8c, 0x07, 0x22, 0x50, 0x01, 0x11, 0x1d, 0x25, 0x4b, 0x80,
	0x29, 0x4c, 0x80, 0x1a, 0x42, 0x74, 0x0c, 0x34, 0x5e, 0x02, 0x20, 0x37, 0x01, 0x0a, 0x10, 0x32,
	0x7f, 0x9a, 0x25, 0x6d, 0x98, 0x10, 0x52, 0x79, 0x05, 0x3b, 0x55, 0x01, 0x23, 0x36, 0x01, 0x0d,
	0x14, 0x28, 0x8e, 0xa7, 0x11, 0x6e, 0x9d, 0x02, 0x47, 0x70, 0x01, 0x2c, 0x48, 0x01, 0x1b, 0x2d,
	0x01, 0x0b, 0x11, 0x1e, 0xaf, 0xbc, 0x09, 0x7c, 0xa9, 0x01, 0x4a, 0x74, 0x01, 0x30, 0x4e, 0x01,
	0x1e, 0x31, 0x01, 0x0b, 0x12, 0x0a, 0xde, 0xdf, 0x02, 0x96, 0xc2, 0x01, 0x53, 0x80, 0x01, 0x30,
	0x4f, 0x01, 0x1b, 0x2d, 0x01, 0x0b, 0x11, 0x24, 0x29, 0xeb, 0x1d, 0x24, 0xc1, 0x0a, 0x1b, 0x6f,
	0x55, 0xa5, 0xde, 0xb1, 0xa2, 0xd7, 0x6e, 0x87, 0xc3, 0x39, 0x71, 0xa8, 0x17, 0x53, 0x78, 0x0a,
	0x31, 0x3d, 0x55, 0xbe, 0xdf, 0x24, 0x8b, 0xc8, 0x05, 0x5a, 0x92, 0x01, 0x3c, 0x67, 0x01, 0x26,
	0x41, 0x01, 0x12, 0x1e, 0x48, 0xca, 0xdf, 0x17, 0x8d, 0xc7, 0x02, 0x56, 0x8c, 0x01, 0x38, 0x61,
	0x01, 0x24, 0x3d, 0x01, 0x10, 0x1b, 0x37, 0xda, 0xe1, 0x0d, 0x91, 0xc8, 0x01, 0x56, 0x8d, 0x01,
	0x39, 0x63, 0x01, 0x23, 0x3d, 0x01, 0x0d, 0x16, 0x0f, 0xeb, 0xd4, 0x01, 0x84, 0xb8, 0x01, 0x54,
	0x8b, 0x01, 0x39, 0x61, 0x01, 0x22, 0x38, 0x01, 0x0e, 0x17, 0xb5, 0x15, 0xc9, 0x3d, 0x25, 0x7b,
	0x0a, 0x26, 0x47, 0x2f, 0x6a, 0xac, 0x5f, 0x68, 0xad, 0x2a, 0x5d, 0x9f, 0x12, 0x4d, 0x83, 0x04,
	0x32, 0x51, 0x01, 0x11, 0x17, 0x3e, 0x93, 0xc7, 0x2c, 0x82, 0xbd, 0x1c, 0x66, 0x9a, 0x12, 0x4b,
	0x73, 0x02, 0x2c, 0x41, 0x01, 0x0c, 0x13, 0x37, 0x99, 0xd2, 0x18, 0x82, 0xc2, 0x03, 0x5d, 0x92,
	0x01, 0x3d, 0x61, 0x01, 0x1f, 0x32, 0x01, 0x0a, 0x10, 0x31, 0xba, 0xdf, 0x11, 0x94, 0xcc, 0x01,
	0x60, 0x8e, 0x01, 0x35, 0x53, 0x01, 0x1a, 0x2c, 0x01, 0x0b, 0x11, 0x0d, 0xd9, 0xd4, 0x02, 0x88,
	0xb4, 0x01, 0x4e, 0x7c, 0x01, 0x32, 0x53, 0x01, 0x1d, 0x31, 0x01, 0x0e, 0x17, 0xc5, 0x0d, 0xf7,
	0x52, 0x11, 0xde, 0x19, 0x11, 0xa2, 0x7e, 0xba, 0xf7, 0xea, 0xbf, 0xf3, 0xb0, 0xb1, 0xea, 0x68,
	0x9e, 0xdc, 0x42, 0x80, 0xba, 0x37, 0x5a, 0x89, 0x6f, 0xc5, 0xf2, 0x2e, 0x9e, 0xdb, 0x09, 0x68,
	0xab, 0x02, 0x41, 0x7d, 0x01, 0x2c, 0x50, 0x01, 0x11, 0x5b, 0x68, 0xd0, 0xf5, 0x27, 0xa8, 0xe0,
	0x03, 0x6d, 0xa2, 0x01, 0x4f, 0x7c, 0x01, 0x32, 0x66, 0x01, 0x2b, 0x66, 0x54, 0xdc, 0xf6, 0x1f,
	0xb1, 0xe7, 0x02, 0x73, 0xb4, 0x01, 0x4f, 0x86, 0x01, 0x37, 0x4d, 0x01, 0x3c, 0x4f, 0x2b, 0xf3,
	0xf0, 0x08, 0xb4, 0xd9, 0x01, 0x73, 0xa6, 0x01, 0x54, 0x79, 0x01, 0x33, 0x43, 0x01, 0x10, 0x06,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xc0, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x61, 0x5e, 0x5d,
	0x18, 0x63, 0x55, 0x77, 0x2c, 0x3e, 0x3b, 0x43, 0x95, 0x35, 0x35, 0x5e, 0x14, 0x30, 0x53, 0x35,
	0x18, 0x34, 0x12, 0x12, 0x96, 0x28, 0x27, 0x4e, 0x0c, 0x1a, 0x43, 0x21, 0x0b, 0x18, 0x07, 0x05,
	0xae, 0x23, 0x31, 0x44, 0x0b, 0x1b, 0x39, 0x0f, 0x09, 0x0c, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x90, 0x0b, 0x36, 0x9d, 0xc3, 0x82, 0x2e, 0x3a, 0x6c, 0x76, 0x0f, 0x7b, 0x94, 0x83, 0x65, 0x2c,
	0x5d, 0x83, 0x71, 0x0c, 0x17, 0xbc, 0xe2, 0x8e, 0x1a, 0x20, 0x7d, 0x78, 0x0b, 0x32, 0x7b, 0xa3,
	0x87, 0x40, 0x4d, 0x67, 0x71, 0x09, 0x24, 0x9b, 0x6f, 0x9d, 0x20, 0x2c, 0xa1, 0x74, 0x09, 0x37,
	0xb0, 0x4c, 0x60, 0x25, 0x3d, 0x95, 0x73, 0x09, 0x1c, 0x8d, 0xa1, 0xa7, 0x15, 0x19, 0xc1, 0x78,
	0x0c, 0x20, 0x91, 0xc3, 0x8e, 0x20, 0x26, 0x56, 0x74, 0x0c, 0x40, 0x78, 0x8c, 0x7d, 0x31, 0x73,
	0x79, 0x66, 0x13, 0x42, 0xa2, 0xb6, 0x7a, 0x23, 0x3b, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t vdenc_vp9_inter_default_probs[2048] = {
	0x64, 0x42, 0x14, 0x98, 0x0f, 0x65, 0x03, 0x88, 0x25, 0x05, 0x34, 0x0d, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xc3, 0x1d, 0xb7, 0x54, 0x31, 0x88, 0x08, 0x2a, 0x47, 0x1f, 0x6b, 0xa9, 0x23, 0x63, 0x9f, 0x11,
	0x52, 0x8c, 0x08, 0x42, 0x72, 0x02, 0x2c, 0x4c, 0x01, 0x13, 0x20, 0x28, 0x84, 0xc9, 0x1d, 0x72,
	0xbb, 0x0d, 0x5b, 0x9d, 0x07, 0x4b, 0x7f, 0x03, 0x3a, 0x5f, 0x01, 0x1c, 0x2f, 0x45, 0x8e, 0xdd,
	0x2a, 0x7a, 0xc9, 0x0f, 0x5b, 0x9f, 0x06, 0x43, 0x79, 0x01, 0x2a, 0x4d, 0x01, 0x11, 0x1f, 0x66,
	0x94, 0xe4, 0x43, 0x75, 0xcc, 0x11, 0x52, 0x9a, 0x06, 0x3b, 0x72, 0x02, 0x27, 0x4b, 0x01, 0x0f,
	0x1d, 0x9c, 0x39, 0xe9, 0x77, 0x39, 0xd4, 0x3a, 0x30, 0xa3, 0x1d, 0x28, 0x7c, 0x0c, 0x1e, 0x51,
	0x03, 0x0c, 0x1f, 0xbf, 0x6b, 0xe2, 0x7c, 0x75, 0xcc, 0x19, 0x63, 0x9b, 0x1d, 0x94, 0xd2, 0x25,
	0x7e, 0xc2, 0x08, 0x5d, 0x9d, 0x02, 0x44, 0x76, 0x01, 0x27, 0x45, 0x01, 0x11, 0x21, 0x29, 0x97,
	0xd5, 0x1b, 0x7b, 0xc1, 0x03, 0x52, 0x90, 0x01, 0x3a, 0x69, 0x01, 0x20, 0x3c, 0x01, 0x0d, 0x1a,
	0x3b, 0x9f, 0xdc, 0x17, 0x7e, 0xc6, 0x04, 0x58, 0x97, 0x01, 0x42, 0x72, 0x01, 0x26, 0x47, 0x01,
	0x12, 0x22, 0x72, 0x88, 0xe8, 0x33, 0x72, 0xcf, 0x0b, 0x53, 0x9b, 0x03, 0x38, 0x69, 0x01, 0x21,
	0x41, 0x01, 0x11, 0x22, 0x95, 0x41, 0xea, 0x79, 0x39, 0xd7, 0x3d, 0x31, 0xa6, 0x1c, 0x24, 0x72,
	0x0c, 0x19, 0x4c, 0x03, 0x10, 0x2a, 0xd6, 0x31, 0xdc, 0x84, 0x3f, 0xbc, 0x2a, 0x41, 0x89, 0x55,
	0x89, 0xdd, 0x68, 0x83, 0xd8, 0x31, 0x6f, 0xc0, 0x15, 0x57, 0x9b, 0x02, 0x31, 0x57, 0x01, 0x10,
	0x1c, 0x59, 0xa3, 0xe6, 0x5a, 0x89, 0xdc, 0x1d, 0x64, 0xb7, 0x0a, 0x46, 0x87, 0x02, 0x2a, 0x51,
	0x01, 0x11, 0x21, 0x6c, 0xa7, 0xed, 0x37, 0x85, 0xde, 0x0f, 0x61, 0xb3, 0x04, 0x48, 0x87, 0x01,
	0x2d, 0x55, 0x01, 0x13, 0x26, 0x7c, 0x92, 0xf0, 0x42, 0x7c, 0xe0, 0x11, 0x58, 0xaf, 0x04, 0x3a,
	0x7a, 0x01, 0x24, 0x4b, 0x01, 0x12, 0x25, 0x8d, 0x4f, 0xf1, 0x7e, 0x46, 0xe3, 0x42, 0x3a, 0xb6,
	0x1e, 0x2c, 0x88, 0x0c, 0x22, 0x60, 0x02, 0x14, 0x2f, 0xe5, 0x63, 0xf9, 0x8f, 0x6f, 0xeb, 0x2e,
	0x6d, 0xc0, 0x52, 0x9e, 0xec, 0x5e, 0x92, 0xe0, 0x19, 0x75, 0xbf, 0x09, 0x57, 0x95, 0x03, 0x38,
	0x63, 0x01, 0x21, 0x39, 0x53, 0xa7, 0xed, 0x44, 0x91, 0xde, 0x0a, 0x67, 0xb1, 0x02, 0x48, 0x83,
	0x01, 0x29, 0x4f, 0x01, 0x14, 0x27, 0x63, 0xa7, 0xef, 0x2f, 0x8d, 0xe0, 0x0a, 0x68, 0xb2, 0x02,
	0x49, 0x85, 0x01, 0x2c, 0x55, 0x01, 0x16, 0x2f, 0x7f, 0x91, 0xf3, 0x47, 0x81, 0xe4, 0x11, 0x5d,
	0xb1, 0x03, 0x3d, 0x7c, 0x01, 0x29, 0x54, 0x01, 0x15, 0x34, 0x9d, 0x4e, 0xf4, 0x8c, 0x48, 0xe7,
	0x45, 0x3a, 0xb8, 0x1f, 0x2c, 0x89, 0x0e, 0x26, 0x69, 0x08, 0x17, 0x3d, 0x7d, 0x22, 0xbb, 0x34,
	0x29, 0x85, 0x06, 0x1f, 0x38, 0x25, 0x6d, 0x99, 0x33, 0x66, 0x93, 0x17, 0x57, 0x80, 0x08, 0x43,
	0x65, 0x01, 0x29, 0x3f, 0x01, 0x13, 0x1d, 0x1f, 0x9a, 0xb9, 0x11, 0x7f, 0xaf, 0x06, 0x60, 0x91,
	0x02, 0x49, 0x72, 0x01, 0x33, 0x52, 0x01, 0x1c, 0x2d, 0x17, 0xa3, 0xc8, 0x0a, 0x83, 0xb9, 0x02,
	0x5d, 0x94, 0x01, 0x43, 0x6f, 0x01, 0x29, 0x45, 0x01, 0x0e, 0x18, 0x1d, 0xb0, 0xd9, 0x0c, 0x91,
	0xc9, 0x03, 0x65, 0x9c, 0x01, 0x45, 0x6f, 0x01, 0x27, 0x3f, 0x01, 0x0e, 0x17, 0x39, 0xc0, 0xe9,
	0x19, 0x9a, 0xd7, 0x06, 0x6d, 0xa7, 0x03, 0x4e, 0x76, 0x01, 0x30, 0x45, 0x01, 0x15, 0x1d, 0xca,
	0x69, 0xf5, 0x6c, 0x6a, 0xd8, 0x12, 0x5a, 0x90, 0x21, 0xac, 0xdb, 0x40, 0x95, 0xce, 0x0e, 0x75,
	0xb1, 0x05, 0x5a, 0x8d, 0x02, 0x3d, 0x5f, 0x01, 0x25, 0x39, 0x21, 0xb3, 0xdc, 0x0b, 0x8c, 0xc6,
	0x01, 0x59, 0x94, 0x01, 0x3c, 0x68, 0x01, 0x21, 0x39, 0x01, 0x0c, 0x15, 0x1e, 0xb5, 0xdd, 0x08,
	0x8d, 0xc6, 0x01, 0x57, 0x91, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x14, 0x20, 0xba,
	0xe0, 0x07, 0x8e, 0xc6, 0x01, 0x56, 0x8f, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x16,
	0x39, 0xc0, 0xe3, 0x14, 0x8f, 0xcc, 0x03, 0x60, 0x9a, 0x01, 0x44, 0x70, 0x01, 0x2a, 0x45, 0x01,
	0x13, 0x20, 0xd4, 0x23, 0xd7, 0x71, 0x2f, 0xa9, 0x1d, 0x30, 0x69, 0x4a, 0x81, 0xcb, 0x6a, 0x78,
	0xcb, 0x31, 0x6b, 0xb2, 0x13, 0x54, 0x90, 0x04, 0x32, 0x54, 0x01, 0x0f, 0x19, 0x47, 0xac, 0xd9,
	0x2c, 0x8d, 0xd1, 0x0f, 0x66, 0xad, 0x06, 0x4c, 0x85, 0x02, 0x33, 0x59, 0x01, 0x18, 0x2a, 0x40,
	0xb9, 0xe7, 0x1f, 0x94, 0xd8, 0x08, 0x67, 0xaf, 0x03, 0x4a, 0x83, 0x01, 0x2e, 0x51, 0x01, 0x12,
	0x1e, 0x41, 0xc4, 0xeb, 0x19, 0x9d, 0xdd, 0x05, 0x69, 0xae, 0x01, 0x43, 0x78, 0x01, 0x26, 0x45,
	0x01, 0x0f, 0x1e, 0x41, 0xcc, 0xee, 0x1e, 0x9c, 0xe0, 0x07, 0x6b, 0xb1, 0x02, 0x46, 0x7c, 0x01,
	0x2a, 0x49, 0x01, 0x12, 0x22, 0xe1, 0x56, 0xfb, 0x90, 0x68, 0xeb, 0x2a, 0x63, 0xb5, 0x55, 0xaf,
	0xef, 0x70, 0xa5, 0xe5, 0x1d, 0x88, 0xc8, 0x0c, 0x67, 0xa2, 0x06, 0x4d, 0x7b, 0x02, 0x35, 0x54,
	0x4b, 0xb7, 0xef, 0x1e, 0x9b, 0xdd, 0x03, 0x6a, 0xab, 0x01, 0x4a, 0x80, 0x01, 0x2c, 0x4c, 0x01,
	0x11, 0x1c, 0x49, 0xb9, 0xf0, 0x1b, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x4b, 0x7f, 0x01, 0x2a,
	0x49, 0x01, 0x11, 0x1d, 0x3e, 0xbe, 0xee, 0x15, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x48, 0x7a,
	0x01, 0x28, 0x47, 0x01, 0x12, 0x20, 0x3d, 0xc7, 0xf0, 0x1b, 0xa1, 0xe2, 0x04, 0x71, 0xb4, 0x01,
	0x4c, 0x81, 0x01, 0x2e, 0x50, 0x01, 0x17, 0x29, 0x07, 0x1b, 0x99, 0x05, 0x1e, 0x5f, 0x01, 0x10,
	0x1e, 0x32, 0x4b, 0x7f, 0x39, 0x4b, 0x7c, 0x1b, 0x43, 0x6c, 0x0a, 0x36, 0x56, 0x01, 0x21, 0x34,
	0x01, 0x0c, 0x12, 0x2b, 0x7d, 0x97, 0x1a, 0x6c, 0x94, 0x07, 0x53, 0x7a, 0x02, 0x3b, 0x59, 0x01,
	0x26, 0x3c, 0x01, 0x11, 0x1b, 0x17, 0x90, 0xa3, 0x0d, 0x70, 0x9a, 0x02, 0x4b, 0x75, 0x01, 0x32,
	0x51, 0x01, 0x1f, 0x33, 0x01, 0x0e, 0x17, 0x12, 0xa2, 0xb9, 0x06, 0x7b, 0xab, 0x01, 0x4e, 0x7d,
	0x01, 0x33, 0x56, 0x01, 0x1f, 0x36, 0x01, 0x0e, 0x17, 0x0f, 0xc7, 0xe3, 0x03, 0x96, 0xcc, 0x01,
	0x5b, 0x92, 0x01, 0x37, 0x5f, 0x01, 0x1e, 0x35, 0x01, 0x0b, 0x14, 0x13, 0x37, 0xf0, 0x13, 0x3b,
	0xc4, 0x03, 0x34, 0x69, 0x29, 0xa6, 0xcf, 0x68, 0x99, 0xc7, 0x1f, 0x7b, 0xb5, 0x0e, 0x65, 0x98,
	0x05, 0x48, 0x6a, 0x01, 0x24, 0x34, 0x23, 0xb0, 0xd3, 0x0c, 0x83, 0xbe, 0x02, 0x58, 0x90, 0x01,
	0x3c, 0x65, 0x01, 0x24, 0x3c, 0x01, 0x10, 0x1c, 0x1c, 0xb7, 0xd5, 0x08, 0x86, 0xbf, 0x01, 0x56,
	0x8e, 0x01, 0x38, 0x60, 0x01, 0x1e, 0x35, 0x01, 0x0c, 0x14, 0x14, 0xbe, 0xd7, 0x04, 0x87, 0xc0,
	0x01, 0x54, 0x8b, 0x01, 0x35, 0x5b, 0x01, 0x1c, 0x31, 0x01, 0x0b, 0x14, 0x0d, 0xc4, 0xd8, 0x02,
	0x89, 0xc0, 0x01, 0x56, 0x8f, 0x01, 0x39, 0x63, 0x01, 0x20, 0x38, 0x01, 0x0d, 0x18, 0xd3, 0x1d,
	0xd9, 0x60, 0x2f, 0x9c, 0x16, 0x2b, 0x57, 0x4e, 0x78, 0xc1, 0x6f, 0x74, 0xba, 0x2e, 0x66, 0xa4,
	0x0f, 0x50, 0x80, 0x02, 0x31, 0x4c, 0x01, 0x12, 0x1c, 0x47, 0xa1, 0xcb, 0x2a, 0x84, 0xc0, 0x0a,
	0x62, 0x96, 0x03, 0x45, 0x6d, 0x01, 0x2c, 0x46, 0x01, 0x12, 0x1d, 0x39, 0xba, 0xd3, 0x1e, 0x8c,
	0xc4, 0x04, 0x5d, 0x92, 0x01, 0x3e, 0x66, 0x01, 0x26, 0x41, 0x01, 0x10, 0x1b, 0x2f, 0xc7, 0xd9,
	0x0e, 0x91, 0xc4, 0x01, 0x58, 0x8e, 0x01, 0x39, 0x62, 0x01, 0x24, 0x3e, 0x01, 0x0f, 0x1a, 0x1a,
	0xdb, 0xe5, 0x05, 0x9b, 0xcf, 0x01, 0x5e, 0x97, 0x01, 0x3c, 0x68, 0x01, 0x24, 0x3e, 0x01, 0x10,
	0x1c, 0xe9, 0x1d, 0xf8, 0x92, 0x2f, 0xdc, 0x2b, 0x34, 0x8c, 0x64, 0xa3, 0xe8, 0xb3, 0xa1, 0xde,
	0x3f, 0x8e, 0xcc, 0x25, 0x71, 0xae, 0x1a, 0x59, 0x89, 0x12, 0x44, 0x61, 0x55, 0xb5, 0xe6, 0x20,
	0x92, 0xd1, 0x07, 0x64, 0xa4, 0x03, 0x47, 0x79, 0x01, 0x2d, 0x4d, 0x01, 0x12, 0x1e, 0x41, 0xbb,
	0xe6, 0x14, 0x94, 0xcf, 0x02, 0x61, 0x9f, 0x01, 0x44, 0x74, 0x01, 0x28, 0x46, 0x01, 0x0e, 0x1d,
	0x28, 0xc2, 0xe3, 0x08, 0x93, 0xcc, 0x01, 0x5e, 0x9b, 0x01, 0x41, 0x70, 0x01, 0x27, 0x42, 0x01,
	0x0e, 0x1a, 0x10, 0xd0, 0xe4, 0x03, 0x97, 0xcf, 0x01, 0x62, 0xa0, 0x01, 0x43, 0x75, 0x01, 0x29,
	0x4a, 0x01, 0x11, 0x1f, 0x11, 0x26, 0x8c, 0x07, 0x22, 0x50, 0x01, 0x11, 0x1d, 0x25, 0x4b, 0x80,
	0x29, 0x4c, 0x80, 0x1a, 0x42, 0x74, 0x0c, 0x34, 0x5e, 0x02, 0x20, 0x37, 0x01, 0x0a, 0x10, 0x32,
	0x7f, 0x9a, 0x25, 0x6d, 0x98, 0x10, 0x52, 0x79, 0x05, 0x3b, 0x55, 0x01, 0x23, 0x36, 0x01, 0x0d,
	0x14, 0x28, 0x8e, 0xa7, 0x11, 0x6e, 0x9d, 0x02, 0x47, 0x70, 0x01, 0x2c, 0x48, 0x01, 0x1b, 0x2d,
	0x01, 0x0b, 0x11, 0x1e, 0xaf, 0xbc, 0x09, 0x7c, 0xa9, 0x01, 0x4a, 0x74, 0x01, 0x30, 0x4e, 0x01,
	0x1e, 0x31, 0x01, 0x0b, 0x12, 0x0a, 0xde, 0xdf, 0x02, 0x96, 0xc2, 0x01, 0x53, 0x80, 0x01, 0x30,
	0x4f, 0x01, 0x1b, 0x2d, 0x01, 0x0b, 0x11, 0x24, 0x29, 0xeb, 0x1d, 0x24, 0xc1, 0x0a, 0x1b, 0x6f,
	0x55, 0xa5, 0xde, 0xb1, 0xa2, 0xd7, 0x6e, 0x87, 0xc3, 0x39, 0x71, 0xa8, 0x17, 0x53, 0x78, 0x0a,
	0x31, 0x3d, 0x55, 0xbe, 0xdf, 0x24, 0x8b, 0xc8, 0x05, 0x5a, 0x92, 0x01, 0x3c, 0x67, 0x01, 0x26,
	0x41, 0x01, 0x12, 0x1e, 0x48, 0xca, 0xdf, 0x17, 0x8d, 0xc7, 0x02, 0x56, 0x8c, 0x01, 0x38, 0x61,
	0x01, 0x24, 0x3d, 0x01, 0x10, 0x1b, 0x37, 0xda, 0xe1, 0x0d, 0x91, 0xc8, 0x01, 0x56, 0x8d, 0x01,
	0x39, 0x63, 0x01, 0x23, 0x3d, 0x01, 0x0d, 0x16, 0x0f, 0xeb, 0xd4, 0x01, 0x84, 0xb8, 0x01, 0x54,
	0x8b, 0x01, 0x39, 0x61, 0x01, 0x22, 0x38, 0x01, 0x0e, 0x17, 0xb5, 0x15, 0xc9, 0x3d, 0x25, 0x7b,
	0x0a, 0x26, 0x47, 0x2f, 0x6a, 0xac, 0x5f, 0x68, 0xad, 0x2a, 0x5d, 0x9f, 0x12, 0x4d, 0x83, 0x04,
	0x32, 0x51, 0x01, 0x11, 0x17, 0x3e, 0x93, 0xc7, 0x2c, 0x82, 0xbd, 0x1c, 0x66, 0x9a, 0x12, 0x4b,
	0x73, 0x02, 0x2c, 0x41, 0x01, 0x0c, 0x13, 0x37, 0x99, 0xd2, 0x18, 0x82, 0xc2, 0x03, 0x5d, 0x92,
	0x01, 0x3d, 0x61, 0x01, 0x1f, 0x32, 0x01, 0x0a, 0x10, 0x31, 0xba, 0xdf, 0x11, 0x94, 0xcc, 0x01,
	0x60, 0x8e, 0x01, 0x35, 0x53, 0x01, 0x1a, 0x2c, 0x01, 0x0b, 0x11, 0x0d, 0xd9, 0xd4, 0x02, 0x88,
	0xb4, 0x01, 0x4e, 0x7c, 0x01, 0x32, 0x53, 0x01, 0x1d, 0x31, 0x01, 0x0e, 0x17, 0xc5, 0x0d, 0xf7,
	0x52, 0x11, 0xde, 0x19, 0x11, 0xa2, 0x7e, 0xba, 0xf7, 0xea, 0xbf, 0xf3, 0xb0, 0xb1, 0xea, 0x68,
	0x9e, 0xdc, 0x42, 0x80, 0xba, 0x37, 0x5a, 0x89, 0x6f, 0xc5, 0xf2, 0x2e, 0x9e, 0xdb, 0x09, 0x68,
	0xab, 0x02, 0x41, 0x7d, 0x01, 0x2c, 0x50, 0x01, 0x11, 0x5b, 0x68, 0xd0, 0xf5, 0x27, 0xa8, 0xe0,
	0x03, 0x6d, 0xa2, 0x01, 0x4f, 0x7c, 0x01, 0x32, 0x66, 0x01, 0x2b, 0x66, 0x54, 0xdc, 0xf6, 0x1f,
	0xb1, 0xe7, 0x02, 0x73, 0xb4, 0x01, 0x4f, 0x86, 0x01, 0x37, 0x4d, 0x01, 0x3c, 0x4f, 0x2b, 0xf3,
	0xf0, 0x08, 0xb4, 0xd9, 0x01, 0x73, 0xa6, 0x01, 0x54, 0x79, 0x01, 0x33, 0x43, 0x01, 0x10, 0x06,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xc0, 0x80, 0x40, 0x02, 0xad, 0x22, 0x07, 0x91, 0x55, 0x07, 0xa6, 0x3f, 0x07, 0x5e, 0x42, 0x08,
	0x40, 0x2e, 0x11, 0x51, 0x1f, 0x19, 0x1d, 0x1e, 0xeb, 0xa2, 0x24, 0xff, 0x22, 0x03, 0x95, 0x90,
	0x09, 0x66, 0xbb, 0xe1, 0xef, 0xb7, 0x77, 0x60, 0x29, 0x21, 0x10, 0x4d, 0x4a, 0x8e, 0x8e, 0xac,
	0xaa, 0xee, 0xf7, 0x32, 0x7e, 0x7b, 0xdd, 0xe2, 0x41, 0x20, 0x12, 0x90, 0xa2, 0xc2, 0x29, 0x33,
	0x62, 0x84, 0x44, 0x12, 0xa5, 0xd9, 0xc4, 0x2d, 0x28, 0x4e, 0xad, 0x50, 0x13, 0xb0, 0xf0, 0xc1,
	0x40, 0x23, 0x2e, 0xdd, 0x87, 0x26, 0xc2, 0xf8, 0x79, 0x60, 0x55, 0x1d, 0xc7, 0x7a, 0x8d, 0x93,
	0x3f, 0x9f, 0x94, 0x85, 0x76, 0x79, 0x68, 0x72, 0xae, 0x49, 0x57, 0x5c, 0x29, 0x53, 0x52, 0x63,
	0x32, 0x35, 0x27, 0x27, 0xb1, 0x3a, 0x3b, 0x44, 0x1a, 0x3f, 0x34, 0x4f, 0x19, 0x11, 0x0e, 0x0c,
	0xde, 0x22, 0x1e, 0x48, 0x10, 0x2c, 0x3a, 0x20, 0x0c, 0x0a, 0x07, 0x06, 0x20, 0x40, 0x60, 0x80,
	0xe0, 0x90, 0xc0, 0xa8, 0xc0, 0xb0, 0xc0, 0xc6, 0xc6, 0xf5, 0xd8, 0x88, 0x8c, 0x94, 0xa0, 0xb0,
	0xc0, 0xe0, 0xea, 0xea, 0xf0, 0x80, 0xd8, 0x80, 0xb0, 0xa0, 0xb0, 0xb0, 0xc0, 0xc6, 0xc6, 0xd0,
	0xd0, 0x88, 0x8c, 0x94, 0xa0, 0xb0, 0xc0, 0xe0, 0xea, 0xea, 0xf0, 0x80, 0x80, 0x40, 0x60, 0x70,
	0x40, 0x40, 0x60, 0x40, 0x80, 0x80, 0x40, 0x60, 0x70, 0x40, 0x40, 0x60, 0x40, 0xa0, 0x80, 0xa0,
	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x78, 0x07, 0x4c, 0xb0, 0xd0, 0x7e, 0x1c, 0x36, 0x67, 0x30, 0x0c, 0x9a, 0x9b, 0x8b, 0x5a, 0x22,
	0x75, 0x77, 0x43, 0x06, 0x19, 0xcc, 0xf3, 0x9e, 0x0d, 0x15, 0x60, 0x61, 0x05, 0x2c, 0x83, 0xb0,
	0x8b, 0x30, 0x44, 0x61, 0x53, 0x05, 0x2a, 0x9c, 0x6f, 0x98, 0x1a, 0x31, 0x98, 0x50, 0x05, 0x3a,
	0xb2, 0x4a, 0x53, 0x21, 0x3e, 0x91, 0x56, 0x05, 0x20, 0x9a, 0xc0, 0xa8, 0x0e, 0x16, 0xa3, 0x55,
	0x05, 0x20, 0x9c, 0xd8, 0x94, 0x13, 0x1d, 0x49, 0x4d, 0x07, 0x40, 0x74, 0x84, 0x7a, 0x25, 0x7e,
	0x78, 0x65, 0x15, 0x6b, 0xb5, 0xc0, 0x67, 0x13, 0x43, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint16_t
vdenc_vp9_quant_ac[256] = {
	4,       8,    9,   10,   11,   12,   13,   14,
	15,     16,   17,   18,   19,   20,   21,   22,
	23,     24,   25,   26,   27,   28,   29,   30,
	31,     32,   33,   34,   35,   36,   37,   38,
	39,     40,   41,   42,   43,   44,   45,   46,
	47,     48,   49,   50,   51,   52,   53,   54,
	55,     56,   57,   58,   59,   60,   61,   62,
	63,     64,   65,   66,   67,   68,   69,   70,
	71,     72,   73,   74,   75,   76,   77,   78,
	79,     80,   81,   82,   83,   84,   85,   86,
	87,     88,   89,   90,   91,   92,   93,   94,
	95,     96,   97,   98,   99,  100,  101,  102,
	104,   106,  108,  110,  112,  114,  116,  118,
	120,   122,  124,  126,  128,  130,  132,  134,
	136,   138,  140,  142,  144,  146,  148,  150,
	152,   155,  158,  161,  164,  167,  170,  173,
	176,   179,  182,  185,  188,  191,  194,  197,
	200,   203,  207,  211,  215,  219,  223,  227,
	231,   235,  239,  243,  247,  251,  255,  260,
	265,   270,  275,  280,  285,  290,  295,  300,
	305,   311,  317,  323,  329,  335,  341,  347,
	353,   359,  366,  373,  380,  387,  394,  401,
	408,   416,  424,  432,  440,  448,  456,  465,
	474,   483,  492,  501,  510,  520,  530,  540,
	550,   560,  571,  582,  593,  604,  615,  627,
	639,   651,  663,  676,  689,  702,  715,  729,
	743,   757,  771,  786,  801,  816,  832,  848,
	864,   881,  898,  915,  933,  951,  969,  988,
	1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
	1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
	1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
	1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
};

static const int8_t vdenc_vp9_huc_inst_rate_thresh_i[4] = {
	30, 50, 90, 115,
};

static const int8_t vdenc_vp9_huc_inst_rate_thresh_p[4] = {
	30, 50, 70, 120,
};

static const uint32_t vdenc_vp9_huc_brc_init_dmem_data[48] = {
	0x00000000, 0x00038400, 0x00030d40, 0x000c3500, 0x00061a80, 0x00061a80, 0x00000000, 0x0000001e,
	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x270f0020, 0x02800000, 0x00010168,
	0x000000ff, 0x0000000e, 0x00000073, 0x00000000, 0x00000000, 0x7846321e, 0x7846321e, 0x735a321e,
	0xe5dfd8d1, 0x2f29211b, 0xe5ddd7d1, 0x5e56463f, 0xeae3dad4, 0x2f281f16, 0x01007488, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

static const uint32_t vdenc_vp9_huc_brc_update_dmem_data[64] = {
	0x00061a80, 0x00000000, 0x0007a120, 0x000493e0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x0032000a, 0x00960064, 0x01680280, 0x02200000, 0x007802b8,
	0x00000000, 0x00000000, 0x00000000, 0x02032000, 0xb4785028, 0x67614b28, 0x0101a07d, 0x28010203,
	0x01030505, 0x00fefcfa, 0x04060402, 0x78503c1e, 0x00ffc88c, 0x503c1e04, 0xffc88c78, 0x28140200,
	0xc8a08246, 0x090800ff, 0x040c0b0a, 0x07060605, 0x06060504, 0x00650007, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

static const uint32_t vdenc_vp9_huc_brc_constant_data[2][416] = {
	{
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x0E0A0602, 0x06040212, 0x00000E0A, 0x00080402, 0x04020000, 0x000000FE, 0xFEFCFA02, 0xF8F60000,
		0xF200FEFC, 0xFEFCF8F4, 0xFCF6F2EE, 0x0A0402FE, 0x04021410, 0x00100C08, 0x0C080402, 0x02000000,
		0x0000FE04, 0xFEFC0200, 0xFA0000FE, 0x00FEFEFC, 0xFEFCFAF6, 0xF8F4F200, 0x0402FEFC, 0x0214100A,
		0x100C0804, 0x08040200, 0x0000000C, 0x00FE0402, 0xFC020000, 0x0000FEFE, 0xFEFEFCFA, 0xFCFAF600,
		0xF4F200FE, 0x00FEFCF8, 0x00000000, 0x14100C08, 0x00000000, 0x0E0A0600, 0x0000FE12, 0x08060000,
		0xFEFC0E0C, 0x02000000, 0xFA0A0604, 0x0000FEFC, 0x0A060200, 0x00FEFCF8, 0x06020000, 0xFCFAF60A,
		0x020000FE, 0xF8F40A06, 0x0000FEFC, 0xF40A0602, 0x00FEFCF8, 0x0A060200, 0x00000000, 0x0E0A0600,
		0x00000012, 0x0A060000, 0x00FE100C, 0x06000000, 0xFC100E0A, 0x000000FE, 0x0C0A0804, 0x00FEFCFA,
		0x08020000, 0xFEFCF80A, 0x02000000, 0xFCF80A08, 0x0000FEFE, 0xF80A0800, 0x00FEFCFA, 0x0A020000,
		0xFEFCF8F6, 0x02000000, 0x00000008, 0x0A060000, 0x0000120E, 0x06000000, 0xFE100C0A, 0x00000000,
		0x100E0A06, 0x0000FEFC, 0x0A080400, 0xFEFCFA0C, 0x02000000, 0xFCF80A08, 0x000000FE, 0xF80A0802,
		0x00FEFEFC, 0x0A080000, 0xFEFCFAF8, 0x02000000, 0xFCF8F60A, 0x000000FE, 0x00000802, 0x00000000,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
	},

	{
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
		0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
		0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
		0x0E0A0602, 0x06040212, 0x00000E0A, 0x00080402, 0x04020000, 0x000000FE, 0xFEFCFA02, 0xF8F60000,
		0xF200FEFC, 0xFEFCF8F4, 0xFCF6F2EE, 0x0A0402FE, 0x04021410, 0x00100C08, 0x0C080402, 0x02000000,
		0x0000FE04, 0xFEFC0200, 0xFA0000FE, 0x00FEFEFC, 0xFEFCFAF6, 0xF8F4F200, 0x0402FEFC, 0x0214100A,
		0x100C0804, 0x08040200, 0x0000000C, 0x00FE0402, 0xFC020000, 0x0000FEFE, 0xFEFEFCFA, 0xFCFAF600,
		0xF4F200FE, 0x00FEFCF8, 0x00000000, 0x14100C08, 0x00000000, 0x0E0A0600, 0x0000FE12, 0x08060000,
		0xFEFC0E0C, 0x02000000, 0xFA0A0604, 0x0000FEFC, 0x0A060200, 0x00FEFCF8, 0x06020000, 0xFCFAF60A,
		0x020000FE, 0xF8F40A06, 0x0000FEFC, 0xF40A0602, 0x00FEFCF8, 0x0A060200, 0x00000000, 0x0E0A0600,
		0x00000012, 0x0A060000, 0x00FE100C, 0x06000000, 0xFC100E0A, 0x000000FE, 0x0C0A0804, 0x00FEFCFA,
		0x08020000, 0xFEFCF80A, 0x02000000, 0xFCF80A08, 0x0000FEFE, 0xF80A0800, 0x00FEFCFA, 0x0A020000,
		0xFEFCF8F6, 0x02000000, 0x00000008, 0x0A060000, 0x0000120E, 0x06000000, 0xFE100C0A, 0x00000000,
		0x100E0A06, 0x0000FEFC, 0x0A080400, 0xFEFCFA0C, 0x02000000, 0xFCF80A08, 0x000000FE, 0xF80A0802,
		0x00FEFEFC, 0x0A080000, 0xFEFCFAF8, 0x02000000, 0xFCF8F60A, 0x000000FE, 0x00000802, 0x00000000,
		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
	}
};

static const double
vdenc_brc_dev_threshi0_fp_neg[4] = { 0.80, 0.60, 0.34, 0.2 };

static const double
vdenc_brc_dev_threshi0_fp_pos[4] = { 0.2, 0.4, 0.66, 0.9 };

static const double
vdenc_brc_dev_threshpb0_fp_neg[4] = { 0.90, 0.66, 0.46, 0.3 };

static const double
vdenc_brc_dev_threshpb0_fp_pos[4] = { 0.3, 0.46, 0.70, 0.90 };

static const double
vdenc_brc_dev_threshvbr0_neg[4] = { 0.90, 0.70, 0.50, 0.3 };

static const double
vdenc_brc_dev_threshvbr0_pos[4] = { 0.4, 0.5, 0.75, 0.90 };

#define OUT_BUFFER_2DW(batch, bo, is_target, delta)  do {               \
		if (bo) {                                                       \
			OUT_BCS_RELOC64(batch,                                      \
							bo,                                         \
							I915_GEM_DOMAIN_RENDER,                     \
							is_target ? I915_GEM_DOMAIN_RENDER : 0,     \
							delta);                                     \
		} else {                                                        \
			OUT_BCS_BATCH(batch, 0);                                    \
			OUT_BCS_BATCH(batch, 0);                                    \
		}                                                               \
	} while (0)

#define OUT_BUFFER_3DW(batch, bo, is_target, delta, attr)  do { \
		OUT_BUFFER_2DW(batch, bo, is_target, delta);            \
		OUT_BCS_BATCH(batch, i965->intel.mocs_state);           \
	} while (0)

#define ALLOC_VDENC_BUFFER_RESOURCE(buffer, bfsize, des) do {   \
		buffer.type = I965_GPE_RESOURCE_BUFFER;                 \
		buffer.width = bfsize;                                  \
		buffer.height = 1;                                      \
		buffer.pitch = buffer.width;                            \
		buffer.size = buffer.pitch;                             \
		buffer.tiling = I915_TILING_NONE;                       \
		i965_allocate_gpe_resource(i965->intel.bufmgr,          \
								   &buffer,                     \
								   bfsize,                      \
								   (des));                      \
	} while (0)

#define MAX_URB_SIZE                    4096 /* In register */

extern const unsigned int gen9_vp9_avs_coeffs[256];

static void
gen10_vdenc_vp9_init_media_object_walker_parameter(struct intel_encoder_context *encoder_context,
												   struct gpe_encoder_kernel_walker_parameter *kernel_walker_param,
												   struct gpe_media_object_walker_parameter *walker_param)
{
	memset(walker_param, 0, sizeof(*walker_param));

	walker_param->use_scoreboard = kernel_walker_param->use_scoreboard;

	walker_param->block_resolution.x = kernel_walker_param->resolution_x;
	walker_param->block_resolution.y = kernel_walker_param->resolution_y;

	walker_param->global_resolution.x = kernel_walker_param->resolution_x;
	walker_param->global_resolution.y = kernel_walker_param->resolution_y;

	walker_param->global_outer_loop_stride.x = kernel_walker_param->resolution_x;
	walker_param->global_outer_loop_stride.y = 0;

	walker_param->global_inner_loop_unit.x = 0;
	walker_param->global_inner_loop_unit.y = kernel_walker_param->resolution_y;

	walker_param->local_loop_exec_count = 0xFFFF;  //MAX VALUE
	walker_param->global_loop_exec_count = 0xFFFF;  //MAX VALUE

	if (kernel_walker_param->no_dependency) {
		walker_param->scoreboard_mask = 0;
		walker_param->use_scoreboard = 0;
		// Raster scan walking pattern
		walker_param->local_outer_loop_stride.x = 0;
		walker_param->local_outer_loop_stride.y = 1;
		walker_param->local_inner_loop_unit.x = 1;
		walker_param->local_inner_loop_unit.y = 0;
		walker_param->local_end.x = kernel_walker_param->resolution_x - 1;
		walker_param->local_end.y = 0;
	} else {
		walker_param->local_end.x = 0;
		walker_param->local_end.y = 0;

		if (kernel_walker_param->walker_degree == VP9_45Z_DEGREE) {
			// 45z degree
			walker_param->scoreboard_mask = 0x0F;

			walker_param->global_loop_exec_count = 0x3FF;
			walker_param->local_loop_exec_count = 0x3FF;

			walker_param->global_resolution.x = (unsigned int)(kernel_walker_param->resolution_x / 2.f) + 1;
			walker_param->global_resolution.y = 2 * kernel_walker_param->resolution_y;

			walker_param->global_start.x = 0;
			walker_param->global_start.y = 0;

			walker_param->global_outer_loop_stride.x = walker_param->global_resolution.x;
			walker_param->global_outer_loop_stride.y = 0;

			walker_param->global_inner_loop_unit.x = 0;
			walker_param->global_inner_loop_unit.y = walker_param->global_resolution.y;

			walker_param->block_resolution.x = walker_param->global_resolution.x;
			walker_param->block_resolution.y = walker_param->global_resolution.y;

			walker_param->local_start.x = 0;
			walker_param->local_start.y = 0;

			walker_param->local_outer_loop_stride.x = 1;
			walker_param->local_outer_loop_stride.y = 0;

			walker_param->local_inner_loop_unit.x = -1;
			walker_param->local_inner_loop_unit.y = 4;

			walker_param->middle_loop_extra_steps = 3;
			walker_param->mid_loop_unit_x = 0;
			walker_param->mid_loop_unit_y = 1;
		} else {
			// 26 degree
			walker_param->scoreboard_mask = 0x0F;
			walker_param->local_outer_loop_stride.x = 1;
			walker_param->local_outer_loop_stride.y = 0;
			walker_param->local_inner_loop_unit.x = -2;
			walker_param->local_inner_loop_unit.y = 1;
		}
	}
}

static void
gen10_vdenc_vp9_run_media_object_walker(VADriverContextP ctx,
										struct intel_encoder_context *encoder_context,
										struct i965_gpe_context *gpe_context,
										struct gpe_media_object_walker_parameter *param)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;

	intel_batchbuffer_start_atomic(batch, 0x1000);

	intel_batchbuffer_emit_mi_flush(batch);
	gpe->pipeline_setup(ctx, gpe_context, batch);
	gpe->media_object_walker(ctx, gpe_context, batch, param);
	gpe->media_state_flush(ctx, gpe_context, batch);
	gpe->pipeline_end(ctx, gpe_context, batch);

	intel_batchbuffer_end_atomic(batch);

	intel_batchbuffer_flush(batch);
}

static void
gen10_vdenc_vp9_gpe_context_vfe_scoreboard_init(struct i965_gpe_context *gpe_context, struct gen10_vdenc_vp9_kernel_scoreboard_parameters *scoreboard_params)
{
	gpe_context->vfe_desc5.scoreboard0.mask = scoreboard_params->mask;
	gpe_context->vfe_desc5.scoreboard0.type = scoreboard_params->type;
	gpe_context->vfe_desc5.scoreboard0.enable = scoreboard_params->enable;

	if (scoreboard_params->walk_pattern_flag) {
		gpe_context->vfe_desc5.scoreboard0.mask = 0x0F;
		gpe_context->vfe_desc5.scoreboard0.type = 1;

		gpe_context->vfe_desc6.scoreboard1.delta_x0 = 0;
		gpe_context->vfe_desc6.scoreboard1.delta_y0 = -1;

		gpe_context->vfe_desc6.scoreboard1.delta_x1 = 0;
		gpe_context->vfe_desc6.scoreboard1.delta_y1 = -2;

		gpe_context->vfe_desc6.scoreboard1.delta_x2 = -1;
		gpe_context->vfe_desc6.scoreboard1.delta_y2 = 3;

		gpe_context->vfe_desc6.scoreboard1.delta_x3 = -1;
		gpe_context->vfe_desc6.scoreboard1.delta_y3 = 1;
	} else {
		// Scoreboard 0
		gpe_context->vfe_desc6.scoreboard1.delta_x0 = -1;
		gpe_context->vfe_desc6.scoreboard1.delta_y0 = 0;

		// Scoreboard 1
		gpe_context->vfe_desc6.scoreboard1.delta_x1 = 0;
		gpe_context->vfe_desc6.scoreboard1.delta_y1 = -1;

		// Scoreboard 2
		gpe_context->vfe_desc6.scoreboard1.delta_x2 = 1;
		gpe_context->vfe_desc6.scoreboard1.delta_y2 = -1;

		// Scoreboard 3
		gpe_context->vfe_desc6.scoreboard1.delta_x3 = -1;
		gpe_context->vfe_desc6.scoreboard1.delta_y3 = -1;

		// Scoreboard 4
		gpe_context->vfe_desc7.scoreboard2.delta_x4 = -1;
		gpe_context->vfe_desc7.scoreboard2.delta_y4 = 1;

		// Scoreboard 5
		gpe_context->vfe_desc7.scoreboard2.delta_x5 = 0;
		gpe_context->vfe_desc7.scoreboard2.delta_y5 = -2;

		// Scoreboard 6
		gpe_context->vfe_desc7.scoreboard2.delta_x6 = 1;
		gpe_context->vfe_desc7.scoreboard2.delta_y6 = -2;

		// Scoreboard 7
		gpe_context->vfe_desc7.scoreboard2.delta_x6 = -1;
		gpe_context->vfe_desc7.scoreboard2.delta_y6 = -2;
	}
}

static void
gen10_vdenc_vp9_gpe_context_init_once(VADriverContextP ctx,
									  struct i965_gpe_context *gpe_context,
									  struct gen10_vdenc_vp9_kernel_parameters *kernel_params)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);

	gpe_context->curbe.length = kernel_params->curbe_size; // in bytes

	gpe_context->sampler.entry_size = 0;
	gpe_context->sampler.max_entries = 0;

	if (kernel_params->sampler_size) {
		gpe_context->sampler.entry_size = ALIGN(kernel_params->sampler_size, 64);
		gpe_context->sampler.max_entries = 1;
	}

	gpe_context->idrt.entry_size = ALIGN(sizeof(struct gen8_interface_descriptor_data), 64);
	gpe_context->idrt.max_entries = NUM_KERNELS_PER_GPE_CONTEXT;

	gpe_context->surface_state_binding_table.max_entries = MAX_VP9_VDENC_SURFACES;
	gpe_context->surface_state_binding_table.binding_table_offset = 0;
	gpe_context->surface_state_binding_table.surface_state_offset = gpe_context->surface_state_binding_table.binding_table_offset + ALIGN(MAX_VP9_VDENC_SURFACES * sizeof(unsigned int), 64);
	gpe_context->surface_state_binding_table.length = ALIGN(MAX_VP9_VDENC_SURFACES * sizeof(unsigned int), 64) + ALIGN(MAX_VP9_VDENC_SURFACES * SURFACE_STATE_PADDED_SIZE_GEN9, 64);

	if (i965->intel.eu_total > 0)
		gpe_context->vfe_state.max_num_threads = 6 * i965->intel.eu_total;
	else
		gpe_context->vfe_state.max_num_threads = 112;

	gpe_context->vfe_state.curbe_allocation_size = ALIGN(gpe_context->curbe.length, 32) >> 5; // in registers
	gpe_context->vfe_state.urb_entry_size = MAX(1, (ALIGN(kernel_params->inline_data_size, 32) +
													ALIGN(kernel_params->external_data_size, 32)) >> 5); // in registers
	gpe_context->vfe_state.num_urb_entries = (MAX_URB_SIZE -
											  gpe_context->vfe_state.curbe_allocation_size -
											  ((gpe_context->idrt.entry_size >> 5) *
											   gpe_context->idrt.max_entries)) / gpe_context->vfe_state.urb_entry_size;
	gpe_context->vfe_state.num_urb_entries = CLAMP(gpe_context->vfe_state.num_urb_entries, 1, 64);
	gpe_context->vfe_state.gpgpu_mode = 0;
}

static void
gen10_vdenc_vp9_dys_set_sampler_state(struct i965_gpe_context *gpe_context)
{
	struct gen9_sampler_8x8_avs *sampler_cmd;

	if (!gpe_context)
		return;

	dri_bo_map(gpe_context->sampler.bo, 1);

	if (!gpe_context->sampler.bo->virtual)
		return;

	sampler_cmd = (struct gen9_sampler_8x8_avs *)(gpe_context->sampler.bo->virtual + gpe_context->sampler.offset);
	memset(sampler_cmd, 0, sizeof(struct gen9_sampler_8x8_avs));

	sampler_cmd->dw0.r3c_coefficient = 15;
	sampler_cmd->dw0.r3x_coefficient = 6;
	sampler_cmd->dw0.strong_edge_threshold = 8;
	sampler_cmd->dw0.weak_edge_threshold = 1;
	sampler_cmd->dw0.gain_factor = 32;

	sampler_cmd->dw2.r5c_coefficient = 3;
	sampler_cmd->dw2.r5cx_coefficient = 8;
	sampler_cmd->dw2.r5x_coefficient = 9;
	sampler_cmd->dw2.strong_edge_weight = 6;
	sampler_cmd->dw2.regular_weight = 3;
	sampler_cmd->dw2.non_edge_weight = 2;
	sampler_cmd->dw2.global_noise_estimation = 255;

	sampler_cmd->dw3.enable_8tap_adaptive_filter = 0;
	sampler_cmd->dw3.cos_alpha = 79;
	sampler_cmd->dw3.sin_alpha = 101;

	sampler_cmd->dw5.diamond_du = 0;
	sampler_cmd->dw5.hs_margin = 3;
	sampler_cmd->dw5.diamond_alpha = 100;

	sampler_cmd->dw7.inv_margin_vyl = 3300;

	sampler_cmd->dw8.inv_margin_vyu = 1600;

	sampler_cmd->dw10.y_slope2 = 24;
	sampler_cmd->dw10.s0l = 1792;

	sampler_cmd->dw12.y_slope1 = 24;

	sampler_cmd->dw14.s0u = 256;

	sampler_cmd->dw15.s2u = 1792;
	sampler_cmd->dw15.s1u = 0;

	memcpy(sampler_cmd->coefficients, &gen9_vp9_avs_coeffs[0], 17 * sizeof(struct gen8_sampler_8x8_avs_coefficients));

	sampler_cmd->dw152.default_sharpness_level = 255;
	sampler_cmd->dw152.max_derivative_4_pixels = 7;
	sampler_cmd->dw152.max_derivative_8_pixels = 20;
	sampler_cmd->dw152.transition_area_with_4_pixels = 4;
	sampler_cmd->dw152.transition_area_with_8_pixels = 5;

	sampler_cmd->dw153.bypass_x_adaptive_filtering = 1;
	sampler_cmd->dw153.bypass_y_adaptive_filtering = 1;
	sampler_cmd->dw153.adaptive_filter_for_all_channel = 0;

	memcpy(sampler_cmd->extra_coefficients, &gen9_vp9_avs_coeffs[17 * 8], 15 * sizeof(struct gen8_sampler_8x8_avs_coefficients));

	dri_bo_unmap(gpe_context->sampler.bo);
}

static void
gen10_vdenc_vp9_dys_context_init(VADriverContextP ctx, struct gen10_vdenc_vp9_context *vdenc_context)
{
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	struct i965_gpe_context *gpe_context = NULL;
	struct gen10_vdenc_vp9_kernel_parameters kernel_params;
	struct gen10_vdenc_vp9_kernel_scoreboard_parameters scoreboard_params;

	kernel_params.curbe_size = sizeof(struct gen10_vdenc_vp9_dys_curbe_data);
	kernel_params.inline_data_size = 0;
	kernel_params.external_data_size = 0;
	kernel_params.sampler_size = sizeof(struct gen9_sampler_8x8_avs);

	memset(&scoreboard_params, 0, sizeof(scoreboard_params));
	scoreboard_params.mask = 0xFF;
	scoreboard_params.enable = vdenc_context->use_hw_scoreboard;
	scoreboard_params.type = vdenc_context->use_hw_non_stalling_scoreborad;
	scoreboard_params.walk_pattern_flag = 0;

	gpe_context = &vdenc_context->dys_context.gpe_context;
	gen10_vdenc_vp9_gpe_context_init_once(ctx, gpe_context, &kernel_params);
	gen10_vdenc_vp9_gpe_context_vfe_scoreboard_init(gpe_context, &scoreboard_params);
	gpe->load_kernels(ctx,
					  gpe_context,
					  &vdenc_vp9_kernels_dys[0],
					  1);
}

static void
gen10_vdenc_vp9_streamin_context_init(VADriverContextP ctx, struct gen10_vdenc_vp9_context *vdenc_context)
{
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	struct i965_gpe_context *gpe_context = NULL;
	struct gen10_vdenc_vp9_kernel_parameters kernel_params;
	struct gen10_vdenc_vp9_kernel_scoreboard_parameters scoreboard_params;

	kernel_params.curbe_size = sizeof(struct gen10_vdenc_vp9_streamin_curbe_data);
	kernel_params.inline_data_size = 0;
	kernel_params.external_data_size = 0;
	kernel_params.sampler_size = 0;

	memset(&scoreboard_params, 0, sizeof(scoreboard_params));
	scoreboard_params.mask = 0xFF;
	scoreboard_params.enable = vdenc_context->use_hw_scoreboard;
	scoreboard_params.type = vdenc_context->use_hw_non_stalling_scoreborad;
	scoreboard_params.walk_pattern_flag = 0;

	gpe_context = &vdenc_context->streamin_context.gpe_context;
	gen10_vdenc_vp9_gpe_context_init_once(ctx, gpe_context, &kernel_params);
	gen10_vdenc_vp9_gpe_context_vfe_scoreboard_init(gpe_context, &scoreboard_params);
	gpe->load_kernels(ctx,
					  gpe_context,
					  &vdenc_vp9_kernels_streamin[0],
					  1);
}

static Bool
gen10_vdenc_vp9_gpe_context_init(VADriverContextP ctx,
								 struct intel_encoder_context *encoder_context,
								 struct gen10_vdenc_vp9_context *vdenc_context)
{
	gen10_vdenc_vp9_dys_context_init(ctx, vdenc_context);
	gen10_vdenc_vp9_streamin_context_init(ctx, vdenc_context);

	return True;
}

static void
gen10_vdenc_vp9_kernel_context_destroy(struct gen10_vdenc_vp9_context *vdenc_context)
{
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;

	gpe->context_destroy(&vdenc_context->dys_context.gpe_context);
	gpe->context_destroy(&vdenc_context->streamin_context.gpe_context);
}

static VAStatus
gen10_vdenc_vp9_gpe_kernel_init(VADriverContextP ctx,
								struct encode_state *encode_state,
								struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_vdenc_vp9_dys_context *dys_context = &vdenc_context->dys_context;
	struct gen10_vdenc_vp9_streamin_context *streamin_context = &vdenc_context->streamin_context;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;

	/* DYS */
	gpe->context_init(ctx, &dys_context->gpe_context);
	gen10_vdenc_vp9_dys_set_sampler_state(&dys_context->gpe_context);

	gpe->context_init(ctx, &streamin_context->gpe_context);

	return VA_STATUS_SUCCESS;
}

static void
gen10_vdenc_vp9_dys_set_curbe_data(VADriverContextP ctx,
								   struct encode_state *encode_state,
								   struct i965_gpe_context *gpe_context,
								   struct intel_encoder_context *encoder_context,
								   struct gen10_vdenc_vp9_dys_curbe_parameters *curbe_param)
{
	struct gen10_vdenc_vp9_dys_curbe_data *curbe_cmd;

	curbe_cmd = i965_gpe_context_map_curbe(gpe_context);

	if (!curbe_cmd)
		return;

	memset(curbe_cmd, 0, sizeof(*curbe_cmd));

	curbe_cmd->dw0.input_frame_width = curbe_param->input_width;
	curbe_cmd->dw0.input_frame_height = curbe_param->input_height;

	curbe_cmd->dw1.output_frame_width = curbe_param->output_width;
	curbe_cmd->dw1.output_frame_height = curbe_param->output_height;

	curbe_cmd->dw2.delta_u = 1.0f / curbe_param->output_width;
	curbe_cmd->dw3.delta_v = 1.0f / curbe_param->output_height;

	curbe_cmd->dw16.input_frame_nv12_bti = VP9_BTI_DYS_INPUT_NV12;
	curbe_cmd->dw17.output_frame_y_bti = VP9_BTI_DYS_OUTPUT_Y;
	curbe_cmd->dw18.avs_sample_bti = 0;

	i965_gpe_context_unmap_curbe(gpe_context);
}

static VAStatus
gen10_vdenc_vp9_dys_surface(VADriverContextP ctx,
							struct encode_state *encode_state,
							struct i965_gpe_context *gpe_context,
							struct intel_encoder_context *encoder_context,
							struct gen10_vdenc_vp9_dys_surface_parameters *surface_param)
{

	if (surface_param->input_frame)
		i965_add_adv_gpe_surface(ctx,
								 gpe_context,
								 surface_param->input_frame,
								 VP9_BTI_DYS_INPUT_NV12);

	if (surface_param->output_frame) {
		i965_add_2d_gpe_surface(ctx,
								gpe_context,
								surface_param->output_frame,
								0,
								1,
								I965_SURFACEFORMAT_R8_UNORM,
								VP9_BTI_DYS_OUTPUT_Y);

		i965_add_2d_gpe_surface(ctx,
								gpe_context,
								surface_param->output_frame,
								1,
								1,
								I965_SURFACEFORMAT_R16_UINT,
								VP9_BTI_DYS_OUTPUT_UV);
	}

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_dys_kernel(VADriverContextP ctx,
						   struct encode_state *encode_state,
						   struct intel_encoder_context *encoder_context,
						   struct gen10_vdenc_vp9_dys_kernel_parameters *dys_kernel_param)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_gpe_context *gpe_context;
	struct gen10_vdenc_vp9_dys_curbe_parameters curbe_param;
	struct gen10_vdenc_vp9_dys_surface_parameters surface_param;
	struct gpe_media_object_walker_parameter media_object_walker_param;
	struct gpe_encoder_kernel_walker_parameter kernel_walker_param;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	unsigned int resolution_x, resolution_y;

	gpe_context = &vdenc_context->dys_context.gpe_context;
	gpe->reset_binding_table(ctx, gpe_context);

	memset(&curbe_param, 0, sizeof(curbe_param));
	curbe_param.input_width = dys_kernel_param->input_width;
	curbe_param.input_height = dys_kernel_param->input_height;
	curbe_param.output_width = dys_kernel_param->output_width;
	curbe_param.output_height = dys_kernel_param->output_height;
	gen10_vdenc_vp9_dys_set_curbe_data(ctx,
									   encode_state,
									   gpe_context,
									   encoder_context,
									   &curbe_param);

	// Add surface states
	memset(&surface_param, 0, sizeof(surface_param));
	surface_param.input_frame = dys_kernel_param->input_surface;
	surface_param.output_frame = dys_kernel_param->output_surface;
	surface_param.vert_line_stride = 0;
	surface_param.vert_line_stride_offset = 0;
	gen10_vdenc_vp9_dys_surface(ctx,
								encode_state,
								gpe_context,
								encoder_context,
								&surface_param);

	gpe->setup_interface_data(ctx, gpe_context);

	resolution_x = ALIGN(dys_kernel_param->output_width, 16) / 16;
	resolution_y = ALIGN(dys_kernel_param->output_height, 16) / 16;
	memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
	kernel_walker_param.resolution_x = resolution_x;
	kernel_walker_param.resolution_y = resolution_y;
	kernel_walker_param.no_dependency = 1;
	gen10_vdenc_vp9_init_media_object_walker_parameter(encoder_context, &kernel_walker_param, &media_object_walker_param);

	gen10_vdenc_vp9_run_media_object_walker(ctx,
											encoder_context,
											gpe_context,
											&media_object_walker_param);

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_dys_src_frame(VADriverContextP ctx,
							  struct encode_state *encode_state,
							  struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_vdenc_vp9_dys_kernel_parameters dys_kernel_param;
	struct object_surface *obj_surface, *input_surface, *output_surface;
	struct vdenc_vp9_surface *vdenc_vp9_surface;
	VAEncPictureParameterBufferVP9  *pic_param = vdenc_context->pic_param;

	if (!vdenc_context->dys_in_use)
		return VA_STATUS_SUCCESS;

	if ((pic_param->frame_width_src != pic_param->frame_width_dst) ||
		(pic_param->frame_height_src != pic_param->frame_height_dst)) {
		input_surface = encode_state->input_yuv_object;
		obj_surface = encode_state->reconstructed_object;
		vdenc_vp9_surface = (struct vdenc_vp9_surface *)(obj_surface->private_data);
		output_surface = vdenc_vp9_surface->dys_surface_obj;

		memset(&dys_kernel_param, 0, sizeof(dys_kernel_param));
		dys_kernel_param.input_width = pic_param->frame_width_src;
		dys_kernel_param.input_height = pic_param->frame_height_src;
		dys_kernel_param.input_surface = input_surface;
		dys_kernel_param.output_width = pic_param->frame_width_dst;
		dys_kernel_param.output_height = pic_param->frame_height_dst;
		dys_kernel_param.output_surface = output_surface;

		gen10_vdenc_vp9_dys_kernel(ctx,
								   encode_state,
								   encoder_context,
								   &dys_kernel_param);
	}

	return VA_STATUS_SUCCESS;
}

#if 0

static void
gen10_vdenc_vp9_streamin_set_curbe_data(VADriverContextP ctx,
										struct encode_state *encode_state,
										struct i965_gpe_context *gpe_context,
										struct intel_encoder_context *encoder_context,
										struct gen10_vdenc_vp9_streamin_curbe_parameters *curbe_param)
{
	struct gen10_vdenc_vp9_streamin_curbe_data *curbe_cmd;

	curbe_cmd = i965_gpe_context_map_curbe(gpe_context);

	if (!curbe_cmd)
		return;

	memset(curbe_cmd, 0, sizeof(*curbe_cmd));

	i965_gpe_context_unmap_curbe(gpe_context);
}

static VAStatus
gen10_vdenc_vp9_streamin_surface(VADriverContextP ctx,
								 struct encode_state *encode_state,
								 struct i965_gpe_context *gpe_context,
								 struct intel_encoder_context *encoder_context,
								 struct gen10_vdenc_vp9_streamin_surface_parameters *surface_param)
{

	if (surface_param->input_frame)
		i965_add_adv_gpe_surface(ctx,
								 gpe_context,
								 surface_param->input_frame,
								 VP9_BTI_DYS_INPUT_NV12);

	if (surface_param->output_frame) {
		i965_add_2d_gpe_surface(ctx,
								gpe_context,
								surface_param->output_frame,
								0,
								1,
								I965_SURFACEFORMAT_R8_UNORM,
								VP9_BTI_DYS_OUTPUT_Y);

		i965_add_2d_gpe_surface(ctx,
								gpe_context,
								surface_param->output_frame,
								1,
								1,
								I965_SURFACEFORMAT_R16_UINT,
								VP9_BTI_DYS_OUTPUT_UV);
	}

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_streamin_kernel(VADriverContextP ctx,
								struct encode_state *encode_state,
								struct intel_encoder_context *encoder_context,
								struct gen10_vdenc_vp9_streamin_kernel_parameters *streamin_kernel_param)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_gpe_context *gpe_context;
	struct gen10_vdenc_vp9_streamin_curbe_parameters curbe_param;
	struct gen10_vdenc_vp9_streamin_surface_parameters surface_param;
	struct gpe_media_object_walker_parameter media_object_walker_param;
	struct gpe_encoder_kernel_walker_parameter kernel_walker_param;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	unsigned int resolution_x, resolution_y;

	gpe_context = &vdenc_context->streamin_context.gpe_context;
	gpe->reset_binding_table(ctx, gpe_context);

	memset(&curbe_param, 0, sizeof(curbe_param));
	curbe_param.input_width = streamin_kernel_param->input_width;
	curbe_param.input_height = streamin_kernel_param->input_height;
	curbe_param.output_width = streamin_kernel_param->output_width;
	curbe_param.output_height = streamin_kernel_param->output_height;
	gen10_vdenc_vp9_streamin_set_curbe_data(ctx,
											encode_state,
											gpe_context,
											encoder_context,
											&curbe_param);

	// Add surface states
	memset(&surface_param, 0, sizeof(surface_param));
	surface_param.input_frame = streamin_kernel_param->input_surface;
	surface_param.output_frame = streamin_kernel_param->output_surface;
	surface_param.vert_line_stride = 0;
	surface_param.vert_line_stride_offset = 0;
	gen10_vdenc_vp9_streamin_surface(ctx,
									 encode_state,
									 gpe_context,
									 encoder_context,
									 &surface_param);

	gpe->setup_interface_data(ctx, gpe_context);

	resolution_x = ALIGN(streamin_kernel_param->output_width, 16) / 16;
	resolution_y = ALIGN(streamin_kernel_param->output_height, 16) / 16;
	memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
	kernel_walker_param.resolution_x = resolution_x;
	kernel_walker_param.resolution_y = resolution_y;
	kernel_walker_param.no_dependency = 1;
	gen10_vdenc_vp9_init_media_object_walker_parameter(encoder_context, &kernel_walker_param, &media_object_walker_param);

	gen10_vdenc_vp9_run_media_object_walker(ctx,
											encoder_context,
											gpe_context,
											&media_object_walker_param);

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_run_streamin(VADriverContextP ctx,
							 struct encode_state *encode_state,
							 struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_vdenc_vp9_streamin_kernel_parameters streamin_kernel_param;
	struct object_surface *obj_surface, *input_surface, *output_surface;
	struct vdenc_vp9_surface *vdenc_vp9_surface;
	VAEncPictureParameterBufferVP9  *pic_param = vdenc_context->pic_param;

	input_surface = encode_state->input_yuv_object;
	obj_surface = encode_state->reconstructed_object;
	vdenc_vp9_surface = (struct vdenc_vp9_surface *)(obj_surface->private_data);
	output_surface = vdenc_vp9_surface->dys_surface_obj;

	memset(&streamin_kernel_param, 0, sizeof(streamin_kernel_param));
	streamin_kernel_param.input_width = pic_param->frame_width_src;
	streamin_kernel_param.input_height = pic_param->frame_height_src;
	streamin_kernel_param.input_surface = input_surface;
	streamin_kernel_param.output_width = pic_param->frame_width_dst;
	streamin_kernel_param.output_height = pic_param->frame_height_dst;
	streamin_kernel_param.output_surface = output_surface;

	gen10_vdenc_vp9_streamin_kernel(ctx,
									encode_state,
									encoder_context,
									&streamin_kernel_param);
	return VA_STATUS_SUCCESS;
}

#endif

static uint32_t
intel_convert_sign_mag(int val, int sign_bit_pos)
{
	uint32_t ret_val = 0;

	if (val < 0) {
		val = -val;
		ret_val = ((1 << (sign_bit_pos - 1)) | (val & ((1 << (sign_bit_pos - 1)) - 1)));
	} else {
		ret_val = val & ((1 << (sign_bit_pos - 1)) - 1);
	}

	return ret_val;
}

static void
gen10_vdenc_vp9_update_brc_parameters(VADriverContextP ctx,
									  struct encode_state *encode_state,
									  struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;

	if (vdenc_context->internal_rate_mode != I965_BRC_CQP &&
		encoder_context->brc.need_reset) {
		/* So far, vdenc doesn't support temporal layer */
		vdenc_context->framerate = encoder_context->brc.framerate[0];

		vdenc_context->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
		vdenc_context->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;

		vdenc_context->max_bit_rate = encoder_context->brc.bits_per_second[0];
		vdenc_context->brc_need_reset = (vdenc_context->brc_initted && encoder_context->brc.need_reset);

		if (vdenc_context->internal_rate_mode == I965_BRC_CBR) {
			vdenc_context->min_bit_rate = vdenc_context->max_bit_rate;
			vdenc_context->target_bit_rate = vdenc_context->max_bit_rate;
		} else {
			assert(vdenc_context->internal_rate_mode == I965_BRC_VBR);
			vdenc_context->min_bit_rate = vdenc_context->max_bit_rate * (2 * encoder_context->brc.target_percentage[0] - 100) / 100;
			vdenc_context->target_bit_rate = vdenc_context->max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
		}
	}

	if (vdenc_context->internal_rate_mode == I965_BRC_CBR ||
		vdenc_context->internal_rate_mode == I965_BRC_VBR)
		vdenc_context->brc_enabled = 1;
	else
		vdenc_context->brc_enabled = 0;

	if (vdenc_context->brc_enabled &&
		(!vdenc_context->init_vbv_buffer_fullness_in_bit ||
		 !vdenc_context->vbv_buffer_size_in_bit ||
		 !vdenc_context->max_bit_rate ||
		 !vdenc_context->target_bit_rate ||
		 !vdenc_context->framerate.num ||
		 !vdenc_context->framerate.den))
		vdenc_context->brc_enabled = 0;

	if (!vdenc_context->brc_enabled) {
		vdenc_context->target_bit_rate = 0;
		vdenc_context->max_bit_rate = 0;
		vdenc_context->min_bit_rate = 0;
		vdenc_context->init_vbv_buffer_fullness_in_bit = 0;
		vdenc_context->vbv_buffer_size_in_bit = 0;
	}
}

static VAStatus
gen10_vdenc_vp9_update_parameters(VADriverContextP ctx,
								  VAProfile profile,
								  struct encode_state *encode_state,
								  struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct object_surface *obj_surface;
	VAEncPictureParameterBufferVP9 *pic_param = NULL;
	VAEncMiscParameterTypeVP9PerSegmantParam *seg_param = NULL;
	VAEncSequenceParameterBufferVP9 *seq_param = NULL;
	VDEncVP9Surface *vdenc_vp9_surface;

	vdenc_context->dys_multiple_pass_enbaled = 1;
	vdenc_context->tx_mode = TX_MODE_SELECT;
	vdenc_context->current_pass = 0;
	vdenc_context->num_passes = 1;

	if (vdenc_context->has_hme)
		vdenc_context->need_hme = (encoder_context->quality_level == 1);
	else
		vdenc_context->need_hme = 0;

	gen10_vdenc_vp9_update_brc_parameters(ctx, encode_state, encoder_context);

	if (vdenc_context->use_huc)
		vdenc_context->num_passes = 2;

	if (vdenc_context->brc_enabled) {
		vdenc_context->num_passes = VDENC_VP9_BRC_MAX_NUM_OF_PASSES;

		if (!vdenc_context->multiple_pass_brc_enabled)
			vdenc_context->num_passes--;
	}

	if (!encode_state->pic_param_ext ||
		!encode_state->pic_param_ext->buffer) {
		return VA_STATUS_ERROR_INVALID_PARAMETER;
	}

	pic_param = (VAEncPictureParameterBufferVP9 *)encode_state->pic_param_ext->buffer;

	if (!pic_param->pic_flags.bits.frame_type)
		vdenc_context->is_key_frame = 1;
	else
		vdenc_context->is_key_frame = 0;

	if (pic_param->pic_flags.bits.intra_only)
		vdenc_context->frame_intra_only = 1;
	else
		vdenc_context->frame_intra_only = 0;

	vdenc_context->is_8bit = (VAProfileVP9Profile0 == profile);
	vdenc_context->ref_frame_flag = VP9_REF_NONE;
	vdenc_context->num_ref_frames = 0;
	vdenc_context->pic_param = NULL;
	vdenc_context->segment_param = NULL;
	vdenc_context->seq_param = NULL;
	vdenc_context->last_ref_obj = NULL;
	vdenc_context->golden_ref_obj = NULL;
	vdenc_context->alt_ref_obj = NULL;
	i965_free_gpe_resource(&vdenc_context->mb_segment_map_buffer_res);

	if (vdenc_context->is_key_frame || vdenc_context->frame_intra_only) {
		/* this will be regarded as I-frame type */
		vdenc_context->vp9_frame_type = VP9_FRAME_I;
	} else {
		vdenc_context->vp9_frame_type = VP9_FRAME_P;
		vdenc_context->ref_frame_flag = (pic_param->ref_flags.bits.ref_frame_ctrl_l0 | pic_param->ref_flags.bits.ref_frame_ctrl_l1);

		/* Last */
		obj_surface = SURFACE(pic_param->reference_frames[pic_param->ref_flags.bits.ref_last_idx]);

		if (!obj_surface ||
			!obj_surface->bo ||
			!obj_surface->private_data) {
			vdenc_context->ref_frame_flag &= ~(VP9_REF_LAST);
			obj_surface = NULL;
		}

		vdenc_context->last_ref_obj = obj_surface;

		/* Golden */
		obj_surface = SURFACE(pic_param->reference_frames[pic_param->ref_flags.bits.ref_gf_idx]);

		if (!obj_surface ||
			!obj_surface->bo ||
			!obj_surface->private_data) {
			vdenc_context->ref_frame_flag &= ~(VP9_REF_GOLDEN);
			obj_surface = NULL;
		}

		vdenc_context->golden_ref_obj = obj_surface;

		/* Alt */
		obj_surface = SURFACE(pic_param->reference_frames[pic_param->ref_flags.bits.ref_arf_idx]);

		if (!obj_surface ||
			!obj_surface->bo ||
			!obj_surface->private_data) {
			vdenc_context->ref_frame_flag &= ~(VP9_REF_ALT);
			obj_surface = NULL;
		}

		vdenc_context->alt_ref_obj = obj_surface;

		/* remove the duplicated flag and ref frame list */
		if (vdenc_context->ref_frame_flag & VP9_REF_LAST) {
			if (pic_param->reference_frames[pic_param->ref_flags.bits.ref_last_idx] ==
				pic_param->reference_frames[pic_param->ref_flags.bits.ref_gf_idx]) {
				vdenc_context->ref_frame_flag &= ~(VP9_REF_GOLDEN);
				vdenc_context->golden_ref_obj = NULL;
			}

			if (pic_param->reference_frames[pic_param->ref_flags.bits.ref_last_idx] ==
				pic_param->reference_frames[pic_param->ref_flags.bits.ref_arf_idx]) {
				vdenc_context->ref_frame_flag &= ~(VP9_REF_ALT);
				vdenc_context->alt_ref_obj = NULL;
			}

			vdenc_context->num_ref_frames++;
		}

		if (vdenc_context->ref_frame_flag & VP9_REF_GOLDEN) {
			if (pic_param->reference_frames[pic_param->ref_flags.bits.ref_gf_idx] ==
				pic_param->reference_frames[pic_param->ref_flags.bits.ref_arf_idx]) {
				vdenc_context->ref_frame_flag &= ~(VP9_REF_ALT);
				vdenc_context->alt_ref_obj = NULL;
			}

			vdenc_context->num_ref_frames++;
		}

		if (vdenc_context->ref_frame_flag & VP9_REF_ALT) {
			vdenc_context->num_ref_frames++;
		}

		if (vdenc_context->ref_frame_flag == VP9_REF_NONE)
			return VA_STATUS_ERROR_INVALID_PARAMETER;
	}

	vdenc_context->hme_enabled = (vdenc_context->need_hme && vdenc_context->vp9_frame_type == VP9_FRAME_P);
	vdenc_context->hme_16x_enabled = (vdenc_context->hme_enabled && vdenc_context->has_hme_16x);

	if (pic_param->pic_flags.bits.segmentation_enabled) {
		if (!encode_state->q_matrix ||
			!encode_state->q_matrix->buffer) {
			return VA_STATUS_ERROR_INVALID_PARAMETER;
		}

		if (!encode_state->encmb_map ||
			!encode_state->encmb_map->bo)
			return VA_STATUS_ERROR_INVALID_PARAMETER;

		seg_param = (VAEncMiscParameterTypeVP9PerSegmantParam *)encode_state->q_matrix->buffer;
		vdenc_context->segment_param = seg_param;
		i965_dri_object_to_2d_gpe_resource(&vdenc_context->mb_segment_map_buffer_res,
										   encode_state->encmb_map->bo,
										   vdenc_context->frame_width_in_mi_units,
										   vdenc_context->frame_height_in_mi_units,
										   vdenc_context->frame_width_in_mi_units);
	}

	if (encode_state->seq_param_ext &&
		encode_state->seq_param_ext->buffer)
		seq_param = (VAEncSequenceParameterBufferVP9 *)encode_state->seq_param_ext->buffer;

	if (!seq_param) {
		seq_param = &vdenc_context->bogus_seq_param;
	}

	vdenc_context->pic_param = pic_param;
	vdenc_context->seq_param = seq_param;

	vdenc_context->frame_width = pic_param->frame_width_dst; // TODO, check dynamic scaling
	vdenc_context->frame_height = pic_param->frame_height_dst; // TODO, check dynamic scaling

	if (vdenc_context->max_frame_width < vdenc_context->frame_width)
		vdenc_context->max_frame_width = vdenc_context->frame_width;

	if (vdenc_context->max_frame_height < vdenc_context->frame_height)
		vdenc_context->max_frame_height = vdenc_context->frame_height;

	vdenc_context->frame_width_in_mi_units = ALIGN(vdenc_context->frame_width, 8) / 8;
	vdenc_context->frame_height_in_mi_units = ALIGN(vdenc_context->frame_height, 8) / 8;
	vdenc_context->frame_width_in_sbs = ALIGN(vdenc_context->frame_width, 64) / 64;
	vdenc_context->frame_height_in_sbs = ALIGN(vdenc_context->frame_height, 64) / 64;

	vdenc_context->down_scaled_width_4x = ALIGN(vdenc_context->frame_width / 4, 16);
	vdenc_context->down_scaled_height_4x = ALIGN(vdenc_context->frame_height / 4, 16);
	vdenc_context->down_scaled_width_16x = ALIGN(vdenc_context->frame_width / 16, 16);
	vdenc_context->down_scaled_height_16x = ALIGN(vdenc_context->frame_height / 16, 16);

	vdenc_context->frame_width_in_mbs = ALIGN(vdenc_context->frame_width, 16) / 16;
	vdenc_context->frame_height_in_mbs = ALIGN(vdenc_context->frame_height, 16) / 16;
	vdenc_context->down_scaled_width_in_mb4x = vdenc_context->down_scaled_width_4x / 16;
	vdenc_context->down_scaled_height_in_mb4x = vdenc_context->down_scaled_height_4x / 16;
	vdenc_context->down_scaled_width_in_mb16x = vdenc_context->down_scaled_width_16x / 16;
	vdenc_context->down_scaled_height_in_mb16x = vdenc_context->down_scaled_height_16x / 16;

	vdenc_context->dys_in_use = 0;

	if (pic_param->frame_width_src != pic_param->frame_width_dst ||
		pic_param->frame_height_src != pic_param->frame_height_dst)
		vdenc_context->dys_in_use = 1;

	vdenc_context->dys_ref_frame_flag = VP9_REF_NONE;

	if (vdenc_context->vp9_frame_type == VP9_FRAME_P) {
		vdenc_context->dys_ref_frame_flag = vdenc_context->ref_frame_flag;

		if ((vdenc_context->ref_frame_flag & VP9_REF_LAST) &&
			vdenc_context->last_ref_obj) {
			obj_surface = vdenc_context->last_ref_obj;
			vdenc_vp9_surface = (VDEncVP9Surface *)(obj_surface->private_data);

			if (vdenc_context->frame_width == vdenc_vp9_surface->frame_width &&
				vdenc_context->frame_height == vdenc_vp9_surface->frame_height)
				vdenc_context->dys_ref_frame_flag &= ~(VP9_REF_LAST);
		}

		if ((vdenc_context->ref_frame_flag & VP9_REF_GOLDEN) &&
			vdenc_context->golden_ref_obj) {
			obj_surface = vdenc_context->golden_ref_obj;
			vdenc_vp9_surface = (VDEncVP9Surface *)(obj_surface->private_data);

			if (vdenc_context->frame_width == vdenc_vp9_surface->frame_width &&
				vdenc_context->frame_height == vdenc_vp9_surface->frame_height)
				vdenc_context->dys_ref_frame_flag &= ~(VP9_REF_GOLDEN);
		}

		if ((vdenc_context->ref_frame_flag & VP9_REF_ALT) &&
			vdenc_context->alt_ref_obj) {
			obj_surface = vdenc_context->alt_ref_obj;
			vdenc_vp9_surface = (VDEncVP9Surface *)(obj_surface->private_data);

			if (vdenc_context->frame_width == vdenc_vp9_surface->frame_width &&
				vdenc_context->frame_height == vdenc_vp9_surface->frame_height)
				vdenc_context->dys_ref_frame_flag &= ~(VP9_REF_ALT);
		}

		if (vdenc_context->dys_ref_frame_flag)
			vdenc_context->dys_in_use = 1;
	}

	if (vdenc_context->dys_ref_frame_flag != VP9_REF_NONE &&
		vdenc_context->dys_multiple_pass_enbaled &&
		!vdenc_context->use_huc)
		vdenc_context->num_passes = 2;

	return VA_STATUS_SUCCESS;
}

static void
gen10_vdenc_vp9_update_streamin_state(VADriverContextP ctx,
									  struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_vdenc_vp9_streamin_state *streamin_state;
	int row, col, i;
	int bwidth = ALIGN(vdenc_context->frame_width, VP9_SUPER_BLOCK_WIDTH) / 32;
	int bheight = ALIGN(vdenc_context->frame_height, VP9_SUPER_BLOCK_HEIGHT) / 32;
	unsigned char *segid_buffer, segid;

	if (!vdenc_context->segment_param && !vdenc_context->hme_enabled)
		return;

	i965_zero_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);

	if (!vdenc_context->segment_param)
		return;

	streamin_state = (struct gen10_vdenc_vp9_streamin_state *)i965_map_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);

	if (!streamin_state)
		return;

	segid_buffer = (unsigned char *)i965_map_gpe_resource(&vdenc_context->mb_segment_map_buffer_res);

	if (!segid_buffer) {
		i965_unmap_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);
		return;
	}

	for (col = 0;  col < bwidth; col++) {
		for (row = 0; row < bheight; row++) {
			i = row * bwidth + col;
			segid = segid_buffer[i * 16];

			streamin_state[i].dw7.segid_enable = 1;
			streamin_state[i].dw7.segid_32x32_0_16x16_03_vp9_only = (segid | segid << 4 | segid << 8 | segid << 12);
			streamin_state[i].dw0.max_tu_size = 3;
			streamin_state[i].dw0.max_cu_size = 3;

			if ((i % 4) == 3 && !vdenc_context->is_key_frame) {
				if (!(streamin_state[i - 3].dw7.segid_32x32_0_16x16_03_vp9_only == streamin_state[i - 2].dw7.segid_32x32_0_16x16_03_vp9_only &&
					  streamin_state[i - 2].dw7.segid_32x32_0_16x16_03_vp9_only == streamin_state[i - 1].dw7.segid_32x32_0_16x16_03_vp9_only &&
					  streamin_state[i - 1].dw7.segid_32x32_0_16x16_03_vp9_only == streamin_state[i].dw7.segid_32x32_0_16x16_03_vp9_only)) {
					streamin_state[i - 3].dw0.max_cu_size = streamin_state[i - 2].dw0.max_cu_size = streamin_state[i - 1].dw0.max_cu_size = streamin_state[i].dw0.max_cu_size = 2;
				}
			}

			streamin_state[i].dw0.num_ime_predictors = 8;

			switch (encoder_context->quality_level) {
			case 7:
				streamin_state[i].dw0.num_ime_predictors = 4;
				streamin_state[i].dw6.num_merge_candidate_cu_8x8 = 0;
				streamin_state[i].dw6.num_merge_candidate_cu_16x16 = 2;
				streamin_state[i].dw6.num_merge_candidate_cu_32x32 = 2;
				streamin_state[i].dw6.num_merge_candidate_cu_64x64 = 2;

				break;

			case 1:
			case 4:
			default:
				streamin_state[i].dw6.num_merge_candidate_cu_8x8 = 1;
				streamin_state[i].dw6.num_merge_candidate_cu_16x16 = 2;
				streamin_state[i].dw6.num_merge_candidate_cu_32x32 = 3;
				streamin_state[i].dw6.num_merge_candidate_cu_64x64 = 4;

				break;
			}
		}
	}

	i965_unmap_gpe_resource(&vdenc_context->mb_segment_map_buffer_res);
	i965_unmap_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);
}

static VAStatus
gen10_vdenc_vp9_allocate_resources_once(VADriverContextP ctx,
										struct encode_state *encode_state,
										struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	int res_size;

	if (vdenc_context->allocate_once_done)
		return VA_STATUS_SUCCESS;

	i965_free_gpe_resource(&vdenc_context->brc_history_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_constant_data_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_bitstream_size_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_huc_data_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_brc_stat_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_brc_pak_stat_buffer_res);
	i965_free_gpe_resource(&vdenc_context->segmentid_buffer_res);

	res_size = VDENC_VP9_BRC_HISTORY_BUFFER_SIZE;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->brc_history_buffer_res,
								res_size,
								"Brc history buffer");

	res_size = VDENC_VP9_BRC_CONSTANT_DATA_SIZE;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->brc_constant_data_buffer_res,
								res_size,
								"Brc constant buffer");

	res_size = ALIGN(VDENC_VP9_BRC_BITSTREAM_SIZE_BUFFER_SIZE, 4096);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->brc_bitstream_size_buffer_res,
								res_size,
								"Brc bitstream buffer");

	res_size = ALIGN(VDENC_VP9_BRC_HUC_DATA_BUFFER_SIZE, 4096);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->brc_huc_data_buffer_res,
								res_size,
								"Brc huc data");

	res_size = ALIGN(VDENC_VP9_BRC_STATS_BUF_SIZE, 4096);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_brc_stat_buffer_res,
								res_size,
								"VDEnc brc statistics buffer");

	res_size = ALIGN(VDENC_VP9_BRC_PAK_STATS_BUF_SIZE, 4096);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_brc_pak_stat_buffer_res,
								res_size,
								"VDEnc brc pak statistics buffer");
	i965_zero_gpe_resource(&vdenc_context->vdenc_brc_pak_stat_buffer_res);

	res_size = vdenc_context->frame_width_in_sbs * vdenc_context->frame_height_in_sbs * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->segmentid_buffer_res,
								res_size,
								"VP9 segment id");

	i965_zero_gpe_resource(&vdenc_context->segmentid_buffer_res);

	vdenc_context->allocate_once_done = 1;

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_allocate_resources(VADriverContextP ctx,
								   struct encode_state *encode_state,
								   struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	int i, res_size;
	uint32_t frame_width_in_sbs, frame_height_in_sbs, frame_size_in_sbs;
	unsigned int width, height, pitch, depth_factor = 1;
	char *pbuffer;
	int allocate_flag;

	if (!vdenc_context->is_8bit)
		depth_factor = 2;

	gen10_vdenc_vp9_allocate_resources_once(ctx, encode_state, encoder_context);

	/* If the width/height of allocated buffer is greater than the expected,
	 * it is unnecessary to allocate it again
	 */
	if (vdenc_context->res_width >= vdenc_context->frame_width &&
		vdenc_context->res_height >= vdenc_context->frame_height) {

		return VA_STATUS_SUCCESS;
	}

	frame_width_in_sbs = vdenc_context->frame_width_in_sbs;
	frame_height_in_sbs = vdenc_context->frame_height_in_sbs;
	frame_size_in_sbs = frame_width_in_sbs * frame_height_in_sbs;

	vdenc_context->coding_unit_offset = ALIGN(frame_size_in_sbs * 16, 4096); /* 3 dws for HCP_PAK_OBJECT and 1 dw for padding zero */
	vdenc_context->mb_code_buffer_size = ALIGN(8 * frame_size_in_sbs * (5 + 64 * 8), 4096);
	res_size = vdenc_context->mb_code_buffer_size + 8 * 64;
	i965_free_gpe_resource(&vdenc_context->mb_code_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->mb_code_buffer_res,
								res_size,
								"VP9 mb_code surface");

	res_size = frame_width_in_sbs * 64;
	i965_free_gpe_resource(&vdenc_context->hvd_line_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->hvd_line_buffer_res,
								res_size,
								"VP9 hvd line line");

	i965_free_gpe_resource(&vdenc_context->hvd_tile_line_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->hvd_tile_line_buffer_res,
								res_size,
								"VP9 hvd tile_line line");

	i965_free_gpe_resource(&vdenc_context->deblocking_filter_line_buffer_res);
	res_size = frame_width_in_sbs * (18 * depth_factor) * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->deblocking_filter_line_buffer_res,
								res_size,
								"VP9 deblocking filter line");

	i965_free_gpe_resource(&vdenc_context->deblocking_filter_tile_line_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->deblocking_filter_tile_line_buffer_res,
								res_size,
								"VP9 deblocking tile line");

	i965_free_gpe_resource(&vdenc_context->deblocking_filter_tile_col_buffer_res);
	res_size = frame_height_in_sbs * (17 * depth_factor) * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->deblocking_filter_tile_col_buffer_res,
								res_size,
								"VP9 deblocking tile col");

	res_size = frame_width_in_sbs * 5 * 64;
	i965_free_gpe_resource(&vdenc_context->metadata_line_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->metadata_line_buffer_res,
								res_size,
								"VP9 metadata line");

	i965_free_gpe_resource(&vdenc_context->metadata_tile_line_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->metadata_tile_line_buffer_res,
								res_size,
								"VP9 metadata tile line");

	res_size = frame_height_in_sbs * 5 * 64;
	i965_free_gpe_resource(&vdenc_context->metadata_tile_col_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->metadata_tile_col_buffer_res,
								res_size,
								"VP9 metadata tile col");

	res_size = frame_size_in_sbs * 9 * 64;

	for (i = 0; i < 2; i++) {
		i965_free_gpe_resource(&vdenc_context->mv_temporal_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->mv_temporal_buffer_res[i],
									res_size,
									"VP9 temporal mv");
	}

	res_size = 32 * 64;

	for (i = 0; i < 4; i++) {
		i965_free_gpe_resource(&vdenc_context->prob_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->prob_buffer_res[i],
									res_size,
									"VP9 prob buffer");
	}

	i965_free_gpe_resource(&vdenc_context->prob_delta_buffer_res);
	res_size = 29 * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->prob_delta_buffer_res,
								res_size,
								"VP9 prob delta");

	i965_free_gpe_resource(&vdenc_context->compressed_header_buffer_res);
	res_size = 32 * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->compressed_header_buffer_res,
								res_size,
								"VP9 compressed input buffer");

	i965_free_gpe_resource(&vdenc_context->prob_counter_buffer_res);
	res_size = 193 * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->prob_counter_buffer_res,
								res_size,
								"VP9 prob counter");

	i965_free_gpe_resource(&vdenc_context->tile_record_streamout_buffer_res);
	res_size = frame_size_in_sbs * 64;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->tile_record_streamout_buffer_res,
								res_size,
								"VP9 tile record stream_out");

	i965_free_gpe_resource(&vdenc_context->cu_stat_streamout_buffer_res);
	res_size = frame_size_in_sbs * 64 * 8;
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->cu_stat_streamout_buffer_res,
								res_size,
								"VP9 CU stat stream_out");

	res_size = MAX(sizeof(struct vdenc_vp9_huc_prob_dmem), sizeof(struct vp9_huc_prob_dmem));
	res_size = ALIGN(res_size, 64);

	for (i = 0; i < 2; i++) {
		i965_free_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_prob_dmem_buffer_res[i],
									res_size,
									"huc prob dmem");
	}

	res_size = ALIGN(sizeof(vdenc_vp9_key_frame_default_probs) + sizeof(vdenc_vp9_inter_default_probs), 64);
	i965_free_gpe_resource(&vdenc_context->huc_default_prob_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_default_prob_buffer_res,
								res_size,
								"huc default prob dmem");

	pbuffer = (char *)i965_map_gpe_resource(&vdenc_context->huc_default_prob_buffer_res);

	if (!pbuffer)
		return VA_STATUS_ERROR_ALLOCATION_FAILED;

	memcpy(pbuffer, vdenc_vp9_key_frame_default_probs, sizeof(vdenc_vp9_key_frame_default_probs));
	pbuffer += sizeof(vdenc_vp9_key_frame_default_probs);
	memcpy(pbuffer, vdenc_vp9_inter_default_probs, sizeof(vdenc_vp9_inter_default_probs));

	i965_unmap_gpe_resource(&vdenc_context->huc_default_prob_buffer_res);

	res_size = 32 * 64;
	i965_free_gpe_resource(&vdenc_context->huc_prob_output_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_prob_output_buffer_res,
								res_size,
								"HuC prob output buffer");

	res_size = 80;
	i965_free_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res,
								res_size,
								"HuC pak insert uncompressed header read buffer");

	res_size = 80;
	i965_free_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_output_2nd_batchbuffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_pak_insert_uncompressed_header_output_2nd_batchbuffer_res,
								res_size,
								"HuC pak insert uncompressed header write buffer");

	res_size = 16; /* 4 dws */
	i965_free_gpe_resource(&vdenc_context->huc_status_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_status_buffer_res,
								res_size,
								"HuC status");

	width = vdenc_context->down_scaled_width_in_mb4x * 32;
	height = vdenc_context->down_scaled_height_in_mb4x * 40;
	pitch = ALIGN(width, 128);
	i965_free_gpe_resource(&vdenc_context->s4x_memv_data_buffer_res);
	allocate_flag = i965_gpe_allocate_2d_resource(i965->intel.bufmgr,
												  &vdenc_context->s4x_memv_data_buffer_res,
												  width, height,
												  ALIGN(width, 64),
												  "VP9 4x MEMV data");

	if (!allocate_flag)
		goto failed_allocation;

	width = vdenc_context->down_scaled_width_in_mb4x * 8;
	height = vdenc_context->down_scaled_height_in_mb4x * 40;
	pitch = ALIGN(width, 128);
	i965_free_gpe_resource(&vdenc_context->s4x_memv_distortion_buffer_res);
	allocate_flag = i965_gpe_allocate_2d_resource(i965->intel.bufmgr,
												  &vdenc_context->s4x_memv_distortion_buffer_res,
												  width, height,
												  ALIGN(width, 64),
												  "VP9 4x MEMV distorion");

	if (!allocate_flag)
		goto failed_allocation;

	width = ALIGN(vdenc_context->down_scaled_width_in_mb16x * 32, 64);
	height = vdenc_context->down_scaled_height_in_mb16x * 40;
	pitch = ALIGN(width, 128);
	i965_free_gpe_resource(&vdenc_context->s16x_memv_data_buffer_res);
	allocate_flag = i965_gpe_allocate_2d_resource(i965->intel.bufmgr,
												  &vdenc_context->s16x_memv_data_buffer_res,
												  width, height,
												  pitch,
												  "VP9 16x MEMV data");

	if (!allocate_flag)
		goto failed_allocation;

	width = vdenc_context->frame_width_in_mbs * 16;
	height = vdenc_context->frame_height_in_mbs * 8;
	pitch = ALIGN(width, 64);
	i965_free_gpe_resource(&vdenc_context->output_16x16_inter_modes_buffer_res);
	allocate_flag = i965_gpe_allocate_2d_resource(i965->intel.bufmgr,
												  &vdenc_context->output_16x16_inter_modes_buffer_res,
												  width, height,
												  ALIGN(width, 64),
												  "VP9 output inter_mode");

	if (!allocate_flag)
		goto failed_allocation;

	res_size = vdenc_context->frame_width_in_mbs * vdenc_context->frame_height_in_mbs * 16 * 4;

	for (i = 0; i < 2; i++) {
		i965_free_gpe_resource(&vdenc_context->mode_decision_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->mode_decision_buffer_res[i],
									res_size,
									"VP9 mode decision");
	}

	// buffers for VDEnc
	res_size = ALIGN(VDENC_HCP_VP9_PIC_STATE_SIZE + VDENC_HCP_VP9_SEGMENT_STATE_SIZE * 8 + VDENC_VDENC_CMD0_STATE_SIZE + VDENC_VDENC_CMD1_STATE_SIZE + 8, 4096);

	for (i = 0; i < 4; i++) {
		i965_free_gpe_resource(&vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[i],
									res_size,
									"VDEnc pic state input 2nd level batchbuffer");

		i965_free_gpe_resource(&vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[i],
									res_size,
									"VDEnc pic state output 2nd level batchbuffer");
	}

	i965_free_gpe_resource(&vdenc_context->vdenc_dys_pic_state_2nd_batchbuffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_dys_pic_state_2nd_batchbuffer_res,
								res_size,
								"VDEnc dys pic state 2nd level batchbuffer");

	i965_free_gpe_resource(&vdenc_context->vdenc_brc_init_reset_dmem_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_brc_init_reset_dmem_buffer_res,
								ALIGN(sizeof(struct vdenc_vp9_huc_brc_init_dmem), 64),
								"brc init&reset dmem buffer");

	for (i = 0; i < VDENC_VP9_BRC_MAX_NUM_OF_PASSES; i++) {
		i965_free_gpe_resource(&vdenc_context->vdenc_brc_update_dmem_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_brc_update_dmem_buffer_res[i],
									ALIGN(sizeof(struct vdenc_vp9_huc_brc_update_dmem), 64),
									"brc update dmem buffer");
	}

	i965_free_gpe_resource(&vdenc_context->vdenc_segment_map_stream_out_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_segment_map_stream_out_buffer_res,
								frame_size_in_sbs * 64,
								"VDEnc segment map stream out");

	i965_free_gpe_resource(&vdenc_context->vdenc_sse_src_pixel_row_store_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_sse_src_pixel_row_store_buffer_res,
								(frame_width_in_sbs + 2) * 32 * 64,
								"VDEnc sse src pixel row store");
	i965_zero_gpe_resource(&vdenc_context->vdenc_sse_src_pixel_row_store_buffer_res);

	i965_free_gpe_resource(&vdenc_context->vdenc_data_extension_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_data_extension_buffer_res,
								VDENC_VP9_HUC_DATA_EXTENSION_SIZE,
								"VDEnc data extension buffer");
	i965_zero_gpe_resource(&vdenc_context->vdenc_data_extension_buffer_res);

	i965_free_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_streamin_buffer_res,
								(ALIGN(vdenc_context->frame_width, VP9_SUPER_BLOCK_WIDTH) / 32) * (ALIGN(vdenc_context->frame_height, VP9_SUPER_BLOCK_HEIGHT) / 32) * 64,
								"VDEnc stream in");
	i965_zero_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);

	i965_free_gpe_resource(&vdenc_context->huc_status2_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_status2_buffer_res,
								64,
								"HuC Status 2");

	i965_free_gpe_resource(&vdenc_context->vdenc_row_store_scratch_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->vdenc_row_store_scratch_res,
								vdenc_context->frame_width_in_mbs * 64,
								"VDENC row store scratch buffer");

	for (i = 0; i < VDENC_VP9_BRC_MAX_NUM_OF_PASSES; i++) {
		i965_free_gpe_resource(&vdenc_context->huc_initializer_dmem_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_initializer_dmem_buffer_res[i],
									ALIGN(sizeof(struct huc_initializer_dmem), 64),
									"HuC Initializer DMEM buffer");
		i965_zero_gpe_resource(&vdenc_context->huc_initializer_dmem_buffer_res[i]);

		i965_free_gpe_resource(&vdenc_context->huc_initializer_data_buffer_res[i]);
		ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_initializer_data_buffer_res[i],
									ALIGN(sizeof(struct huc_initializer_data), 0x1000),
									"HuC Initializer Data buffer");
		i965_zero_gpe_resource(&vdenc_context->huc_initializer_data_buffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->huc_initializer_dys_dmem_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_initializer_dys_dmem_buffer_res,
								ALIGN(sizeof(struct huc_initializer_dmem), 64),
								"HuC Initializer DYS DMEM buffer");
	i965_zero_gpe_resource(&vdenc_context->huc_initializer_dys_dmem_buffer_res);

	i965_free_gpe_resource(&vdenc_context->huc_initializer_dys_data_buffer_res);
	ALLOC_VDENC_BUFFER_RESOURCE(vdenc_context->huc_initializer_dys_data_buffer_res,
								ALIGN(sizeof(struct huc_initializer_data), 0x1000),
								"HuC Initializer DYS data buffer");
	i965_zero_gpe_resource(&vdenc_context->huc_initializer_dys_data_buffer_res);

	if (!vdenc_context->frame_header_data) {
		/* allocate 512 bytes for generating the uncompressed header */
		vdenc_context->frame_header_data = calloc(1, 512);
	}

	vdenc_context->res_width = vdenc_context->frame_width;
	vdenc_context->res_height = vdenc_context->frame_height;

	return VA_STATUS_SUCCESS;

failed_allocation:
	return VA_STATUS_ERROR_ALLOCATION_FAILED;
}

static VAStatus
gen10_vdenc_vp9_uncompressed_header(VADriverContextP ctx,
									struct encode_state *encode_state,
									struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	VAEncPictureParameterBufferVP9  *pic_param;
	int driver_header_flag = 1; /* '1' means the driver should generate the uncompressed header */

	if (!vdenc_context->pic_param)
		return VA_STATUS_ERROR_INVALID_PARAMETER;

	pic_param = vdenc_context->pic_param;

	if (encode_state->packed_header_data_ext &&
		encode_state->packed_header_data_ext[0] &&
		pic_param->bit_offset_first_partition_size) {
		VAEncPackedHeaderParameterBuffer *param = NULL;

		param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_params_ext[0]->buffer;

		if (param->type == VAEncPackedHeaderRawData) {
			char *header_data;
			unsigned int length_in_bits;

			header_data = (char *)encode_state->packed_header_data_ext[0]->buffer;
			length_in_bits = param->bit_length;
			driver_header_flag = 0;

			vdenc_context->frame_header.bit_offset_first_partition_size = pic_param->bit_offset_first_partition_size;
			vdenc_context->frame_header_length = ALIGN(length_in_bits, 8) >> 3;
			vdenc_context->alias_insert_data = header_data;

			vdenc_context->frame_header.bit_offset_ref_lf_delta = pic_param->bit_offset_ref_lf_delta;
			vdenc_context->frame_header.bit_offset_mode_lf_delta = pic_param->bit_offset_mode_lf_delta;
			vdenc_context->frame_header.bit_offset_lf_level = pic_param->bit_offset_lf_level;
			vdenc_context->frame_header.bit_offset_qindex = pic_param->bit_offset_qindex;
			vdenc_context->frame_header.bit_offset_segmentation = pic_param->bit_offset_segmentation;
			vdenc_context->frame_header.bit_size_segmentation = pic_param->bit_size_segmentation;
		}
	}

	if (driver_header_flag) {
		memset(&vdenc_context->frame_header, 0, sizeof(vdenc_context->frame_header));
		intel_write_uncompressed_header(encode_state,
										VAProfileVP9Profile0,
										vdenc_context->frame_header_data,
										&vdenc_context->frame_header_length,
										&vdenc_context->frame_header);
		vdenc_context->alias_insert_data = vdenc_context->frame_header_data;
	}

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_check_dys_surfaces(VADriverContextP ctx,
								   struct object_surface *obj_surface,
								   uint32_t frame_width,
								   uint32_t frame_height)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct vdenc_vp9_surface *vdenc_vp9_surface;
	int dys_width_4x, dys_height_4x;
	int dys_width_8x, dys_height_8x;
	int dys_width_16x, dys_height_16x;

	/* As this is handled after the surface checking, it is unnecessary
	 * to check the surface bo and vp9_priv_surface again
	 */

	vdenc_vp9_surface = (struct vdenc_vp9_surface *)(obj_surface->private_data);

	if (!vdenc_vp9_surface)
		return VA_STATUS_ERROR_INVALID_SURFACE;

	/* if the frame_width/height of dys_surface is the same as
	 * the expected, it is unnecessary to allocate it again
	 */

	if (vdenc_vp9_surface->dys_frame_width == frame_width &&
		vdenc_vp9_surface->dys_frame_height == frame_height)
		return VA_STATUS_SUCCESS;

	if (vdenc_vp9_surface->dys_surface_obj) {
		i965_DestroySurfaces(vdenc_vp9_surface->ctx, &vdenc_vp9_surface->dys_surface_id, 1);
		vdenc_vp9_surface->dys_surface_id = VA_INVALID_SURFACE;
		vdenc_vp9_surface->dys_surface_obj = NULL;
	}

	if (vdenc_vp9_surface->dys_4x_surface_obj) {
		i965_DestroySurfaces(vdenc_vp9_surface->ctx, &vdenc_vp9_surface->dys_4x_surface_id, 1);
		vdenc_vp9_surface->dys_4x_surface_id = VA_INVALID_SURFACE;
		vdenc_vp9_surface->dys_4x_surface_obj = NULL;
	}

	if (vdenc_vp9_surface->dys_8x_surface_obj) {
		i965_DestroySurfaces(vdenc_vp9_surface->ctx, &vdenc_vp9_surface->dys_8x_surface_id, 1);
		vdenc_vp9_surface->dys_8x_surface_id = VA_INVALID_SURFACE;
		vdenc_vp9_surface->dys_8x_surface_obj = NULL;
	}

	i965_CreateSurfaces(ctx,
						frame_width,
						frame_height,
						VA_RT_FORMAT_YUV420,
						1,
						&vdenc_vp9_surface->dys_surface_id);
	vdenc_vp9_surface->dys_surface_obj = SURFACE(vdenc_vp9_surface->dys_surface_id);

	if (!vdenc_vp9_surface->dys_surface_obj) {
		return VA_STATUS_ERROR_ALLOCATION_FAILED;
	}

	i965_check_alloc_surface_bo(ctx,
								vdenc_vp9_surface->dys_surface_obj,
								1,
								VA_FOURCC('N', 'V', '1', '2'),
								SUBSAMPLE_YUV420);

	dys_width_4x = ALIGN(frame_width / 4, 16);
	dys_height_4x = ALIGN(frame_height / 4, 16);

	i965_CreateSurfaces(ctx,
						dys_width_4x,
						dys_height_4x,
						VA_RT_FORMAT_YUV420,
						1,
						&vdenc_vp9_surface->dys_4x_surface_id);

	vdenc_vp9_surface->dys_4x_surface_obj = SURFACE(vdenc_vp9_surface->dys_4x_surface_id);

	if (!vdenc_vp9_surface->dys_4x_surface_obj) {
		return VA_STATUS_ERROR_ALLOCATION_FAILED;
	}

	i965_check_alloc_surface_bo(ctx,
								vdenc_vp9_surface->dys_4x_surface_obj,
								1,
								VA_FOURCC('N', 'V', '1', '2'),
								SUBSAMPLE_YUV420);

	dys_width_8x = ALIGN(frame_width / 8, 16);
	dys_height_8x = ALIGN(frame_height / 8, 16);
	i965_CreateSurfaces(ctx,
						dys_width_8x,
						dys_height_8x,
						VA_RT_FORMAT_YUV420,
						1,
						&vdenc_vp9_surface->dys_8x_surface_id);
	vdenc_vp9_surface->dys_8x_surface_obj = SURFACE(vdenc_vp9_surface->dys_8x_surface_id);

	if (!vdenc_vp9_surface->dys_8x_surface_obj) {
		return VA_STATUS_ERROR_ALLOCATION_FAILED;
	}

	i965_check_alloc_surface_bo(ctx,
								vdenc_vp9_surface->dys_8x_surface_obj,
								1,
								VA_FOURCC('N', 'V', '1', '2'),
								SUBSAMPLE_YUV420);

	dys_width_16x = ALIGN(frame_width / 16, 16);
	dys_height_16x = ALIGN(frame_height / 16, 16);
	i965_CreateSurfaces(ctx,
						dys_width_16x,
						dys_height_16x,
						VA_RT_FORMAT_YUV420,
						1,
						&vdenc_vp9_surface->dys_16x_surface_id);
	vdenc_vp9_surface->dys_16x_surface_obj = SURFACE(vdenc_vp9_surface->dys_16x_surface_id);

	if (!vdenc_vp9_surface->dys_16x_surface_obj) {
		return VA_STATUS_ERROR_ALLOCATION_FAILED;
	}

	i965_check_alloc_surface_bo(ctx,
								vdenc_vp9_surface->dys_16x_surface_obj,
								1,
								VA_FOURCC('N', 'V', '1', '2'),
								SUBSAMPLE_YUV420);

	vdenc_vp9_surface->dys_frame_width = frame_width;
	vdenc_vp9_surface->dys_frame_height = frame_height;

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_prepare(VADriverContextP ctx,
						VAProfile profile,
						struct encode_state *encode_state,
						struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_coded_buffer_segment *coded_buffer_segment;
	struct object_surface *obj_surface;
	struct object_buffer *obj_buffer;
	VAStatus va_status;
	VAEncPictureParameterBufferVP9 *pic_param = NULL;
	VDEncVP9Surface *vdenc_vp9_surface;
	dri_bo *bo;
	char *pbuffer;

	va_status = gen10_vdenc_vp9_update_parameters(ctx, profile, encode_state, encoder_context);

	if (va_status != VA_STATUS_SUCCESS)
		return va_status;

	pic_param = vdenc_context->pic_param;

	/* Check reconstructed obj */
	obj_surface = encode_state->reconstructed_object;

	if (pic_param->frame_width_dst > obj_surface->orig_width ||
		pic_param->frame_height_dst > obj_surface->orig_height)
		return VA_STATUS_ERROR_INVALID_SURFACE;

	if (!vdenc_context->dys_enabled &&
		((pic_param->frame_width_src != pic_param->frame_width_dst) ||
		 (pic_param->frame_height_src != pic_param->frame_height_dst)))
		return VA_STATUS_ERROR_UNIMPLEMENTED;  // TODO

	i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);

	if (obj_surface->private_data == NULL) {
		vdenc_vp9_surface = calloc(sizeof(VDEncVP9Surface), 1);
		assert(vdenc_vp9_surface);

		vdenc_vp9_surface->ctx = ctx;
		vdenc_vp9_surface->frame_width = vdenc_context->frame_width;
		vdenc_vp9_surface->frame_height = vdenc_context->frame_height;

		i965_CreateSurfaces(ctx,
							vdenc_context->down_scaled_width_4x,
							vdenc_context->down_scaled_height_4x,
							VA_RT_FORMAT_YUV420,
							1,
							&vdenc_vp9_surface->scaled_4x_surface_id);
		vdenc_vp9_surface->scaled_4x_surface_obj = SURFACE(vdenc_vp9_surface->scaled_4x_surface_id);
		assert(vdenc_vp9_surface->scaled_4x_surface_obj);
		i965_check_alloc_surface_bo(ctx,
									vdenc_vp9_surface->scaled_4x_surface_obj,
									1,
									VA_FOURCC_NV12,
									SUBSAMPLE_YUV420);

		i965_CreateSurfaces(ctx,
							vdenc_context->down_scaled_width_4x >> 1,
							vdenc_context->down_scaled_height_4x >> 1,
							VA_RT_FORMAT_YUV420,
							1,
							&vdenc_vp9_surface->scaled_8x_surface_id);
		vdenc_vp9_surface->scaled_8x_surface_obj = SURFACE(vdenc_vp9_surface->scaled_8x_surface_id);
		assert(vdenc_vp9_surface->scaled_8x_surface_obj);
		i965_check_alloc_surface_bo(ctx,
									vdenc_vp9_surface->scaled_8x_surface_obj,
									1,
									VA_FOURCC_NV12,
									SUBSAMPLE_YUV420);

		i965_CreateSurfaces(ctx,
							vdenc_context->down_scaled_width_4x >> 2,
							vdenc_context->down_scaled_height_4x >> 2,
							VA_RT_FORMAT_YUV420,
							1,
							&vdenc_vp9_surface->scaled_16x_surface_id);
		vdenc_vp9_surface->scaled_16x_surface_obj = SURFACE(vdenc_vp9_surface->scaled_16x_surface_id);
		assert(vdenc_vp9_surface->scaled_16x_surface_obj);
		i965_check_alloc_surface_bo(ctx,
									vdenc_vp9_surface->scaled_16x_surface_obj,
									1,
									VA_FOURCC_NV12,
									SUBSAMPLE_YUV420);

		obj_surface->private_data = (void *)vdenc_vp9_surface;
		obj_surface->free_private_data = (void *)vdenc_free_vp9_surface;
	}

	vdenc_vp9_surface = (VDEncVP9Surface *)obj_surface->private_data;
	assert(vdenc_vp9_surface->scaled_4x_surface_obj);
	assert(vdenc_vp9_surface->scaled_8x_surface_obj);
	assert(vdenc_vp9_surface->scaled_16x_surface_obj);

	/* Check dys object */
	if (vdenc_context->dys_in_use &&
		(pic_param->frame_width_src != pic_param->frame_width_dst ||
		 pic_param->frame_height_src != pic_param->frame_height_dst)) {
		va_status = gen10_vdenc_vp9_check_dys_surfaces(ctx,
													   encode_state->reconstructed_object,
													   pic_param->frame_width_dst,
													   pic_param->frame_height_dst);

		if (va_status)
			return va_status;
	}

	if ((vdenc_context->dys_ref_frame_flag & VP9_REF_LAST) && vdenc_context->last_ref_obj) {
		va_status = gen10_vdenc_vp9_check_dys_surfaces(ctx,
													   vdenc_context->last_ref_obj,
													   vdenc_context->frame_width,
													   vdenc_context->frame_height);

		if (va_status)
			return va_status;
	}

	if ((vdenc_context->dys_ref_frame_flag & VP9_REF_GOLDEN) && vdenc_context->golden_ref_obj) {
		va_status = gen10_vdenc_vp9_check_dys_surfaces(ctx,
													   vdenc_context->golden_ref_obj,
													   vdenc_context->frame_width,
													   vdenc_context->frame_height);

		if (va_status)
			return va_status;
	}

	if ((vdenc_context->dys_ref_frame_flag & VP9_REF_ALT) && vdenc_context->alt_ref_obj) {
		va_status = gen10_vdenc_vp9_check_dys_surfaces(ctx,
													   vdenc_context->alt_ref_obj,
													   vdenc_context->frame_width,
													   vdenc_context->frame_height);

		if (va_status)
			return va_status;
	}

	/* Reconstructed res */
	i965_free_gpe_resource(&vdenc_context->recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_4x_recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_8x_recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_16x_recon_surface_res);
	i965_object_surface_to_2d_gpe_resource(&vdenc_context->recon_surface_res, obj_surface);
	i965_object_surface_to_2d_gpe_resource(&vdenc_context->scaled_4x_recon_surface_res, vdenc_vp9_surface->scaled_4x_surface_obj);
	i965_object_surface_to_2d_gpe_resource(&vdenc_context->scaled_8x_recon_surface_res, vdenc_vp9_surface->scaled_8x_surface_obj);
	i965_object_surface_to_2d_gpe_resource(&vdenc_context->scaled_16x_recon_surface_res, vdenc_vp9_surface->scaled_16x_surface_obj);

	/* Reference res */
	i965_free_gpe_resource(&vdenc_context->last_ref_res);
	i965_free_gpe_resource(&vdenc_context->golden_ref_res);
	i965_free_gpe_resource(&vdenc_context->alt_ref_res);

	if (vdenc_context->last_ref_obj) {
		if (vdenc_context->dys_ref_frame_flag & VP9_REF_LAST) {
			assert(vdenc_context->last_ref_obj->private_data);
			vdenc_vp9_surface = (struct vdenc_vp9_surface *)vdenc_context->last_ref_obj->private_data;
			obj_surface = vdenc_vp9_surface->dys_surface_obj;
			assert(obj_surface);
		} else
			obj_surface = vdenc_context->last_ref_obj;

		i965_object_surface_to_2d_gpe_resource(&vdenc_context->last_ref_res, obj_surface);
	}

	if (vdenc_context->golden_ref_obj) {
		if (vdenc_context->dys_ref_frame_flag & VP9_REF_GOLDEN) {
			assert(vdenc_context->golden_ref_obj->private_data);
			vdenc_vp9_surface = (struct vdenc_vp9_surface *)vdenc_context->golden_ref_obj->private_data;
			obj_surface = vdenc_vp9_surface->dys_surface_obj;
			assert(obj_surface);
		} else
			obj_surface = vdenc_context->golden_ref_obj;

		i965_object_surface_to_2d_gpe_resource(&vdenc_context->golden_ref_res, obj_surface);
	}

	if (vdenc_context->alt_ref_obj) {
		if (vdenc_context->dys_ref_frame_flag & VP9_REF_ALT) {
			assert(vdenc_context->alt_ref_obj->private_data);
			vdenc_vp9_surface = (struct vdenc_vp9_surface *)vdenc_context->alt_ref_obj->private_data;
			obj_surface = vdenc_vp9_surface->dys_surface_obj;
			assert(obj_surface);
		} else
			obj_surface = vdenc_context->alt_ref_obj;

		i965_object_surface_to_2d_gpe_resource(&vdenc_context->alt_ref_res, obj_surface);
	}

	/* Input YUV res */
	i965_free_gpe_resource(&vdenc_context->uncompressed_input_yuv_surface_res);

	if (vdenc_context->dys_in_use &&
		((pic_param->frame_width_src != pic_param->frame_width_dst) ||
		 (pic_param->frame_height_src != pic_param->frame_height_dst))) {
		assert(encode_state->reconstructed_object && encode_state->reconstructed_object->private_data);
		vdenc_vp9_surface = (struct vdenc_vp9_surface *)encode_state->reconstructed_object->private_data;
		obj_surface = vdenc_vp9_surface->dys_surface_obj;
		assert(obj_surface);
	} else {
		obj_surface = encode_state->input_yuv_object;
	}

	i965_object_surface_to_2d_gpe_resource(&vdenc_context->uncompressed_input_yuv_surface_res, obj_surface);

	/* Encoded bitstream */
	obj_buffer = encode_state->coded_buf_object;
	bo = obj_buffer->buffer_store->bo;
	i965_free_gpe_resource(&vdenc_context->compressed_bitstream.res);
	i965_dri_object_to_buffer_gpe_resource(&vdenc_context->compressed_bitstream.res, bo);
	vdenc_context->compressed_bitstream.start_offset = I965_CODEDBUFFER_HEADER_SIZE;
	vdenc_context->compressed_bitstream.end_offset = ALIGN(obj_buffer->size_element - 0x1000, 0x1000);

	/* Status buffer */
	i965_free_gpe_resource(&vdenc_context->status_bffuer.res);
	i965_dri_object_to_buffer_gpe_resource(&vdenc_context->status_bffuer.res, bo);
	vdenc_context->status_bffuer.base_offset = offsetof(struct i965_coded_buffer_segment, codec_private_data);
	vdenc_context->status_bffuer.size = ALIGN(sizeof(struct gen10_vdenc_vp9_status), 64);
	vdenc_context->status_bffuer.bytes_per_frame_offset = offsetof(struct gen10_vdenc_vp9_status, bytes_per_frame);
	assert(vdenc_context->status_bffuer.base_offset + vdenc_context->status_bffuer.size <
		   vdenc_context->compressed_bitstream.start_offset);

	dri_bo_map(bo, 1);

	coded_buffer_segment = (struct i965_coded_buffer_segment *)bo->virtual;
	coded_buffer_segment->mapped = 0;
	coded_buffer_segment->codec = encoder_context->codec;
	coded_buffer_segment->status_support = 1;

	pbuffer = bo->virtual;
	pbuffer += vdenc_context->status_bffuer.base_offset;
	memset(pbuffer, 0, vdenc_context->status_bffuer.size);

	dri_bo_unmap(bo);

	va_status = gen10_vdenc_vp9_allocate_resources(ctx, encode_state, encoder_context);

	if (va_status != VA_STATUS_SUCCESS)
		return va_status;

	gen10_vdenc_vp9_uncompressed_header(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_gpe_kernel_init(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_dys_src_frame(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_update_streamin_state(ctx, encoder_context);

	return VA_STATUS_SUCCESS;
}

static void
gen10_vdenc_vp9_huc_store_huc_status2(VADriverContextP ctx,
									  struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gpe_mi_store_register_mem_parameter mi_store_register_mem_params;
	struct gpe_mi_store_data_imm_parameter mi_store_data_imm_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;

	/* Write HUC_STATUS2 mask (1 << 6) */
	memset(&mi_store_data_imm_params, 0, sizeof(mi_store_data_imm_params));
	mi_store_data_imm_params.bo = vdenc_context->huc_status2_buffer_res.bo;
	mi_store_data_imm_params.offset = 0;
	mi_store_data_imm_params.dw0 = (1 << 6);
	gpe->mi_store_data_imm(ctx, batch, &mi_store_data_imm_params);

	/* Store HUC_STATUS2 */
	memset(&mi_store_register_mem_params, 0, sizeof(mi_store_register_mem_params));
	mi_store_register_mem_params.mmio_offset = VCS0_HUC_STATUS2;
	mi_store_register_mem_params.bo = vdenc_context->huc_status2_buffer_res.bo;
	mi_store_register_mem_params.offset = 4;
	gpe->mi_store_register_mem(ctx, batch, &mi_store_register_mem_params);
}

static VAStatus
gen10_vdenc_vp9_calculate_initial_qp(VADriverContextP ctx,
									 struct encode_state *encode_state,
									 struct intel_encoder_context *encoder_context,
									 unsigned int *init_qp_i,
									 unsigned int *init_qp_p)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	VAEncSequenceParameterBufferVP9 *seq_param = vdenc_context->seq_param;
	float x0 = 0, y0 = 1.19f, x1 = 1.75f, y1 = 1.75f;
	unsigned frame_size;
	int qp_i, qp_p, delat_qp;

	frame_size = (vdenc_context->frame_width * vdenc_context->frame_height * 3 / 2);
	qp_p = (int)(1.0 / 1.2 * pow(10.0,
								 (log10(frame_size * 2.0 / 3.0 * vdenc_context->framerate.num /
										((double)vdenc_context->target_bit_rate * vdenc_context->framerate.den)) - x0) *
								 (y1 - y0) / (x1 - x0) + y0) + 0.5);
	qp_p = qp_p * 5;
	qp_p -= 20;
	qp_p = CLAMP(1, 200, qp_p);
	qp_i = (qp_p > 4) ? (qp_p - 4) : qp_p;
	delat_qp = (seq_param->intra_period - 1) / 30 - 1;
	delat_qp = CLAMP(0, 20, delat_qp);
	qp_i -= delat_qp;
	qp_i = CLAMP(1, 200, qp_i);
	qp_p = qp_i + 20;

	*init_qp_i = qp_i;
	*init_qp_p = qp_p;

	return VA_STATUS_SUCCESS;
}

static void
gen10_vdenc_vp9_update_huc_brc_init_dmem(VADriverContextP ctx,
										 struct encode_state *encode_state,
										 struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct vdenc_vp9_huc_brc_init_dmem *dmem;
	VAEncSequenceParameterBufferVP9 *seq_param = vdenc_context->seq_param;
	unsigned int seq_max_frame_size, qp_i = 20, qp_p = 20;
	double input_bits_per_frame, bps_ratio;
	int i;

	if (!seq_param)
		return;

	seq_max_frame_size = seq_param->max_frame_width * seq_param->max_frame_height;

	assert(sizeof(*dmem) == sizeof(vdenc_vp9_huc_brc_init_dmem_data));
	dmem = (struct vdenc_vp9_huc_brc_init_dmem *)i965_map_gpe_resource(&vdenc_context->vdenc_brc_init_reset_dmem_buffer_res);

	if (!dmem)
		return;

	memcpy(dmem, vdenc_vp9_huc_brc_init_dmem_data, sizeof(*dmem));

	dmem->brc_func = vdenc_context->brc_initted ? 2 : 0;
	dmem->profile_level_max_frame = vdenc_context->max_frame_width * vdenc_context->max_frame_height;

	if (seq_max_frame_size)
		dmem->profile_level_max_frame = MIN(dmem->profile_level_max_frame, seq_max_frame_size);

	dmem->buffer_size = vdenc_context->vbv_buffer_size_in_bit;
	dmem->init_buffer_fullness = vdenc_context->init_vbv_buffer_fullness_in_bit;
	dmem->target_bitrate = vdenc_context->target_bit_rate;
	dmem->max_rate = vdenc_context->max_bit_rate;
	dmem->frame_rate_m = vdenc_context->framerate.num;
	dmem->frame_rate_d = vdenc_context->framerate.den;

	if (vdenc_context->internal_rate_mode == I965_BRC_CBR) {
		dmem->brc_flag = 0x10;
		dmem->max_rate = dmem->target_bitrate;
	} else if (vdenc_context->internal_rate_mode == I965_BRC_VBR)
		dmem->brc_flag = 0x20;

	if (dmem->max_rate < dmem->target_bitrate)
		dmem->max_rate = (dmem->target_bitrate << 1);

	dmem->num_p_in_gop = seq_param->intra_period - 1;
	dmem->frame_width = vdenc_context->frame_width;
	dmem->frame_height = vdenc_context->frame_height;
	dmem->min_qp = 0;
	dmem->max_qp = 255;
	dmem->enable_scaling = vdenc_context->dys_in_use;

	assert(ARRAY_ELEMS(dmem->inst_rate_thresh_i0) == ARRAY_ELEMS(dmem->inst_rate_thresh_p0));
	assert(ARRAY_ELEMS(dmem->inst_rate_thresh_i0) == ARRAY_ELEMS(vdenc_vp9_huc_inst_rate_thresh_i));
	assert(ARRAY_ELEMS(dmem->inst_rate_thresh_i0) == ARRAY_ELEMS(vdenc_vp9_huc_inst_rate_thresh_p));
	for (i = 0; i < ARRAY_ELEMS(dmem->inst_rate_thresh_i0); i++) {
		dmem->inst_rate_thresh_i0[i] = vdenc_vp9_huc_inst_rate_thresh_i[i];
		dmem->inst_rate_thresh_p0[i] = vdenc_vp9_huc_inst_rate_thresh_p[i];
	}

	input_bits_per_frame = ((double)dmem->max_rate * (double)dmem->frame_rate_d) / (double)dmem->frame_rate_m;

	if (dmem->buffer_size < (uint32_t)(input_bits_per_frame * 4))
		dmem->buffer_size = (uint32_t)(input_bits_per_frame * 4);

	if (dmem->init_buffer_fullness == 0)
		dmem->init_buffer_fullness = 7 * dmem->buffer_size / 8;

	if (dmem->init_buffer_fullness < (uint32_t)(input_bits_per_frame * 2))
		dmem->init_buffer_fullness = (uint32_t)(input_bits_per_frame * 2);

	if (dmem->init_buffer_fullness > dmem->buffer_size)
		dmem->init_buffer_fullness = dmem->buffer_size;

	bps_ratio = input_bits_per_frame /
				((double)vdenc_context->vbv_buffer_size_in_bit * vdenc_context->framerate.den / vdenc_context->framerate.num);

	if (bps_ratio < 0.1)
		bps_ratio = 0.1;

	if (bps_ratio > 3.5)
		bps_ratio = 3.5;

	for (i = 0; i < 4; i++) {
		dmem->dev_thresh_pb0[i] = (char)(-50 * pow(vdenc_brc_dev_threshpb0_fp_neg[i], bps_ratio));
		dmem->dev_thresh_pb0[i + 4] = (char)(50 * pow(vdenc_brc_dev_threshpb0_fp_pos[i], bps_ratio));

		dmem->dev_thresh_i0[i] = (char)(-50 * pow(vdenc_brc_dev_threshi0_fp_neg[i], bps_ratio));
		dmem->dev_thresh_i0[i + 4] = (char)(50 * pow(vdenc_brc_dev_threshi0_fp_pos[i], bps_ratio));

		dmem->dev_thresh_vbr0[i] = (char)(-50 * pow(vdenc_brc_dev_threshvbr0_neg[i], bps_ratio));
		dmem->dev_thresh_vbr0[i + 4] = (char)(100 * pow(vdenc_brc_dev_threshvbr0_pos[i], bps_ratio));
	}

	gen10_vdenc_vp9_calculate_initial_qp(ctx, encode_state, encoder_context, &qp_i, &qp_p);

	dmem->init_qp_i = qp_i;
	dmem->init_qp_p = qp_p;

	dmem->total_level = 1; // TODO for temporal

	i965_unmap_gpe_resource(&vdenc_context->vdenc_brc_init_reset_dmem_buffer_res);

	vdenc_context->input_bits_per_frame =
		((double)vdenc_context->max_bit_rate * vdenc_context->framerate.den) / vdenc_context->framerate.num;
	vdenc_context->current_target_buf_full_in_bits = vdenc_context->target_bit_rate;
}

static void
gen10_vdenc_vp9_huc_brc_init_reset(VADriverContextP ctx,
								   struct encode_state *encode_state,
								   struct intel_encoder_context *encoder_context)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_huc_pipe_mode_select_parameter pipe_mode_select_params;
	struct gen10_huc_imem_state_parameter imem_state_params;
	struct gen10_huc_dmem_state_parameter dmem_state_params;
	struct gen10_huc_virtual_addr_parameter virtual_addr_params;
	struct gen10_huc_start_parameter start_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	gen10_vdenc_vd_pipeline_flush_param pipeline_flush_params;

	memset(&imem_state_params, 0, sizeof(imem_state_params));
	imem_state_params.huc_firmware_descriptor = VDENC_VP9_HUC_BRC_INIT_RESET;
	gen10_huc_imem_state(ctx, batch, &imem_state_params);

	memset(&pipe_mode_select_params, 0, sizeof(pipe_mode_select_params));
	gen10_huc_pipe_mode_select(ctx, batch, &pipe_mode_select_params);

	gen10_vdenc_vp9_update_huc_brc_init_dmem(ctx, encode_state, encoder_context);
	memset(&dmem_state_params, 0, sizeof(dmem_state_params));
	dmem_state_params.huc_data_source_res = &vdenc_context->vdenc_brc_init_reset_dmem_buffer_res;
	dmem_state_params.huc_data_destination_base_address = VDENC_VP9_HUC_DMEM_DATA_OFFSET;
	dmem_state_params.huc_data_length = ALIGN(sizeof(struct vdenc_vp9_huc_brc_init_dmem), 64);
	gen10_huc_dmem_state(ctx, batch, &dmem_state_params);

	memset(&virtual_addr_params, 0, sizeof(virtual_addr_params));
	virtual_addr_params.regions[0].huc_surface_res = &vdenc_context->brc_history_buffer_res;
	virtual_addr_params.regions[0].is_target = 1;
	gen10_huc_virtual_addr_state(ctx, batch, &virtual_addr_params);

	gen10_vdenc_vp9_huc_store_huc_status2(ctx, encoder_context);

	memset(&start_params, 0, sizeof(start_params));
	start_params.last_stream_object = 1;
	gen10_huc_start(ctx, batch, &start_params);

	memset(&pipeline_flush_params, 0, sizeof(pipeline_flush_params));
	pipeline_flush_params.dw1.hevc_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_flush = 1;
	gen10_vdenc_vd_pipeline_flush(ctx, batch, &pipeline_flush_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	mi_flush_dw_params.video_pipeline_cache_invalidate = 1;
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);
}

static void
gen10_vdenc_vp9_update_huc_update_dmem(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	VAEncPictureParameterBufferVP9 *pic_param;
	struct vdenc_vp9_huc_brc_update_dmem *dmem;

	if (!vdenc_context->pic_param)
		return;

	pic_param = vdenc_context->pic_param;

	dmem = (struct vdenc_vp9_huc_brc_update_dmem *)i965_map_gpe_resource(&vdenc_context->vdenc_brc_update_dmem_buffer_res[vdenc_context->current_pass]);

	if (!dmem)
		return;

	assert(sizeof(struct vdenc_vp9_huc_brc_update_dmem) == sizeof(vdenc_vp9_huc_brc_update_dmem_data));
	memcpy(dmem, vdenc_vp9_huc_brc_update_dmem_data, sizeof(struct vdenc_vp9_huc_brc_update_dmem));

	if (vdenc_context->current_target_buf_full_in_bits > vdenc_context->vbv_buffer_size_in_bit) {
		dmem->overflow_flag = 1;
		vdenc_context->current_target_buf_full_in_bits -= vdenc_context->vbv_buffer_size_in_bit;
	}

	if (vdenc_context->current_pass == 0) {
		dmem->target_buf_fullness = vdenc_context->current_target_buf_full_in_bits;
	}

	dmem->frame_num = vdenc_context->frame_number;
	dmem->temporal_level = 0; // TODO
	dmem->hrd_buffer_fullness_upper = 0;
	dmem->hrd_buffer_fullness_lower = 0;

	dmem->cur_width = vdenc_context->frame_width;
	dmem->cur_height = vdenc_context->frame_height;
	dmem->current_frame_type = vdenc_context->is_key_frame ? 2 : 0;

	dmem->max_num_paks = vdenc_context->num_passes - 1; // no update for repak
	dmem->current_pak_pass = vdenc_context->current_pass;

	dmem->vdenc_igs_offset = vdenc_context->cmd1_state_offset_in_2nd_batchbuffer;
	dmem->second_level_batchbuffer_size = vdenc_context->huc_2nd_batchbuffer_size;
	dmem->pic_state_offset = vdenc_context->pic_state_offset_in_2nd_batchbuffer;

	dmem->acq_qp = pic_param->luma_ac_qindex;
	dmem->segment_map_generating = !!vdenc_context->segment_param;

	dmem->delta_qp_for_sad_zone0 = -5;
	dmem->delta_qp_for_sad_zone1 = -1;
	dmem->delta_qp_for_sad_zone2 = 1;
	dmem->delta_qp_for_sad_zone3 = 5;
	dmem->delta_qp_for_mv_zero = -5;
	dmem->delta_qp_for_mv_zone0 = -2;
	dmem->delta_qp_for_mv_zone1 = 1;
	dmem->delta_qp_for_mv_zone2 = 5;

	i965_unmap_gpe_resource(&vdenc_context->vdenc_brc_update_dmem_buffer_res[vdenc_context->current_pass]);
}

static void
gen10_vdenc_vp9_huc_brc_update_constant_data(VADriverContextP ctx,
											 struct encode_state *encode_state,
											 struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct huc_brc_update_constant_data *brc_buffer;

	brc_buffer = (struct huc_brc_update_constant_data *)i965_map_gpe_resource(&vdenc_context->brc_constant_data_buffer_res);

	if (!brc_buffer)
		return;

	assert(sizeof(vdenc_vp9_huc_brc_constant_data[0]) == VDENC_VP9_BRC_CONSTANT_DATA_SIZE);
	memcpy(brc_buffer, vdenc_vp9_huc_brc_constant_data[!vdenc_context->is_key_frame], VDENC_VP9_BRC_CONSTANT_DATA_SIZE);

	i965_unmap_gpe_resource(&vdenc_context->brc_constant_data_buffer_res);
}

static void
gen10_vdenc_vp9_huc_brc_update(VADriverContextP ctx,
							   struct encode_state *encode_state,
							   struct intel_encoder_context *encoder_context)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_huc_pipe_mode_select_parameter pipe_mode_select_params;
	struct gen10_huc_imem_state_parameter imem_state_params;
	struct gen10_huc_dmem_state_parameter dmem_state_params;
	struct gen10_huc_virtual_addr_parameter virtual_addr_params;
	struct gen10_huc_start_parameter start_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	gen10_vdenc_vd_pipeline_flush_param pipeline_flush_params;

	gen10_vdenc_vp9_huc_brc_update_constant_data(ctx, encode_state, encoder_context);

	memset(&imem_state_params, 0, sizeof(imem_state_params));
	imem_state_params.huc_firmware_descriptor = VDENC_VP9_HUC_BRC_UPDATE;
	gen10_huc_imem_state(ctx, batch, &imem_state_params);

	memset(&pipe_mode_select_params, 0, sizeof(pipe_mode_select_params));
	gen10_huc_pipe_mode_select(ctx, batch, &pipe_mode_select_params);

	gen10_vdenc_vp9_update_huc_update_dmem(ctx, encoder_context);

	memset(&dmem_state_params, 0, sizeof(dmem_state_params));
	dmem_state_params.huc_data_source_res = &vdenc_context->vdenc_brc_update_dmem_buffer_res[vdenc_context->current_pass];
	dmem_state_params.huc_data_destination_base_address = VDENC_VP9_HUC_DMEM_DATA_OFFSET;
	dmem_state_params.huc_data_length = ALIGN(sizeof(struct vdenc_vp9_huc_brc_update_dmem), 64);
	gen10_huc_dmem_state(ctx, batch, &dmem_state_params);

	memset(&virtual_addr_params, 0, sizeof(virtual_addr_params));
	virtual_addr_params.regions[0].huc_surface_res = &vdenc_context->brc_history_buffer_res;
	virtual_addr_params.regions[0].is_target = 1;
	virtual_addr_params.regions[1].huc_surface_res = &vdenc_context->vdenc_brc_stat_buffer_res;
	virtual_addr_params.regions[2].huc_surface_res = &vdenc_context->vdenc_brc_pak_stat_buffer_res;
	virtual_addr_params.regions[3].huc_surface_res = &vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[vdenc_context->current_pass];
	virtual_addr_params.regions[4].huc_surface_res = &vdenc_context->brc_huc_data_buffer_res;
	virtual_addr_params.regions[4].is_target = 1;
	virtual_addr_params.regions[5].huc_surface_res = &vdenc_context->brc_constant_data_buffer_res;
	virtual_addr_params.regions[6].huc_surface_res = &vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[0]; // the first for non-tile clip
	virtual_addr_params.regions[6].is_target = 1;
	virtual_addr_params.regions[7].huc_surface_res = &vdenc_context->brc_bitstream_size_buffer_res;
	gen10_huc_virtual_addr_state(ctx, batch, &virtual_addr_params);

	gen10_vdenc_vp9_huc_store_huc_status2(ctx, encoder_context);

	memset(&start_params, 0, sizeof(start_params));
	start_params.last_stream_object = 1;
	gen10_huc_start(ctx, batch, &start_params);

	memset(&pipeline_flush_params, 0, sizeof(pipeline_flush_params));
	pipeline_flush_params.dw1.hevc_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_flush = 1;
	gen10_vdenc_vd_pipeline_flush(ctx, batch, &pipeline_flush_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	mi_flush_dw_params.video_pipeline_cache_invalidate = 1;
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);

#if 0
	/* Store HUC_STATUS */
	memset(&mi_store_register_mem_params, 0, sizeof(mi_store_register_mem_params));
	mi_store_register_mem_params.mmio_offset = VCS0_HUC_STATUS;
	mi_store_register_mem_params.bo = vdenc_context->huc_status_buffer_res.bo;
	gpe->mi_store_register_mem(ctx, batch, &mi_store_register_mem_params);

	/* Write HUC_STATUS mask (1 << 31) */
	memset(&mi_store_data_imm_params, 0, sizeof(mi_store_data_imm_params));
	mi_store_data_imm_params.bo = vdenc_context->huc_status_buffer_res.bo;
	mi_store_data_imm_params.offset = 4;
	mi_store_data_imm_params.dw0 = (1 << 31);
	gpe->mi_store_data_imm(ctx, batch, &mi_store_data_imm_params);
#endif

	if (vdenc_context->current_pass == 0) {
		vdenc_context->current_target_buf_full_in_bits += vdenc_context->input_bits_per_frame;
	}
}

static void
gen10_vdenc_mfx_wait(VADriverContextP ctx,
					 struct encode_state *encode_state,
					 struct intel_encoder_context *encoder_context)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 1);

	OUT_BCS_BATCH(batch, MFX_WAIT);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_hcp_pipe_mode_select(VADriverContextP ctx,
									 struct encode_state *encode_state,
									 struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 6);

	OUT_BCS_BATCH(batch, HCP_PIPE_MODE_SELECT | (6 - 2));
	OUT_BCS_BATCH(batch,
				  (!!vdenc_context->brc_enabled << 12) |        // Frame level
				  (1 << 10) |
				  (HCP_CODEC_VP9 << 5) |
				  (0 << 3) | /* disable Pic Status / Error Report */
				  (!!vdenc_context->brc_enabled << 2) |         // Pipeline
				  HCP_CODEC_SELECT_ENCODE);
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch, 0);
	// OUT_BCS_BATCH(batch, (1 << 6));  // TODO check it later
	OUT_BCS_BATCH(batch, 0);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_hcp_surface_state(VADriverContextP ctx,
								  struct intel_encoder_context *encoder_context,
								  struct i965_gpe_resource *gpe_resource,
								  int id)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	if (!gpe_resource->bo)
		return;

	BEGIN_BCS_BATCH(batch, 3);
	OUT_BCS_BATCH(batch, HCP_SURFACE_STATE | (3 - 2));
	OUT_BCS_BATCH(batch,
				  (id << 28) |
				  (gpe_resource->pitch - 1));
	OUT_BCS_BATCH(batch,
				  (SURFACE_FORMAT_PLANAR_420_8 << 28) |
				  (gpe_resource->y_cb_offset));
	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_hcp_pipe_buf_addr_state(VADriverContextP ctx,
										struct encode_state *encode_state,
										struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	VAEncPictureParameterBufferVP9 *pic_param = vdenc_context->pic_param;
	unsigned int i;

	BEGIN_BCS_BATCH(batch, 104);

	OUT_BCS_BATCH(batch, HCP_PIPE_BUF_ADDR_STATE | (104 - 2));

	/* DW 1..3 decoded surface */
	OUT_BUFFER_3DW(batch, vdenc_context->recon_surface_res.bo, 1, 0, 0);

	/* DW 4..6 deblocking line */
	OUT_BUFFER_3DW(batch, vdenc_context->deblocking_filter_line_buffer_res.bo, 1, 0, 0);

	/* DW 7..9 deblocking tile line */
	OUT_BUFFER_3DW(batch, vdenc_context->deblocking_filter_tile_line_buffer_res.bo, 1, 0, 0);

	/* DW 10..12 deblocking tile col */
	OUT_BUFFER_3DW(batch, vdenc_context->deblocking_filter_tile_col_buffer_res.bo, 1, 0, 0);

	/* DW 13..15 metadata line */
	OUT_BUFFER_3DW(batch, vdenc_context->metadata_line_buffer_res.bo, 1, 0, 0);

	/* DW 16..18 metadata tile line */
	OUT_BUFFER_3DW(batch, vdenc_context->metadata_tile_line_buffer_res.bo, 1, 0, 0);

	/* DW 19..21 metadata tile col */
	OUT_BUFFER_3DW(batch, vdenc_context->metadata_tile_col_buffer_res.bo, 1, 0, 0);

	/* DW 22..30 SAO is not used for VP9 */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 31..33 Current Motion vector temporal buffer */
	OUT_BUFFER_3DW(batch, vdenc_context->mv_temporal_buffer_res[vdenc_context->curr_mv_temporal_index].bo, 1, 0, 0);

	/* DW 34..36 Not used */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* Only the first three reference_frame is used for VP9 */
	/* DW 37..52 for reference_frame */
	i = 0;

	if (vdenc_context->vp9_frame_type == VP9_FRAME_P) {
		for (i = 0; i < 3; i++) {
			if (encode_state->reference_objects[i] &&
				encode_state->reference_objects[i]->bo)
				OUT_BUFFER_2DW(batch, encode_state->reference_objects[i]->bo, 0, 0);
			else
				OUT_BUFFER_2DW(batch, NULL, 0, 0);
		}
	}

	for (; i < 8; i++) {
		OUT_BUFFER_2DW(batch, NULL, 0, 0);
	}

	OUT_BCS_BATCH(batch, i965->intel.mocs_state);

	/* DW 54..56 for source input */
	OUT_BUFFER_3DW(batch, vdenc_context->uncompressed_input_yuv_surface_res.bo, 0, 0, 0);

	/* DW 57..59 StreamOut is not used */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 60..62. Not used for encoder */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 63..65. ILDB Not used for encoder */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 66..81 For the collocated motion vector temporal buffer */
	if (vdenc_context->vp9_frame_type == VP9_FRAME_P) {
		int prev_index = vdenc_context->curr_mv_temporal_index ^ 0x01;
		OUT_BUFFER_2DW(batch, vdenc_context->mv_temporal_buffer_res[prev_index].bo, 0, 0);
	} else {
		OUT_BUFFER_2DW(batch, NULL, 0, 0);
	}

	for (i = 1; i < 8; i++) {
		OUT_BUFFER_2DW(batch, NULL, 0, 0);
	}

	OUT_BCS_BATCH(batch, i965->intel.mocs_state);

	/* DW 83..85 VP9 prob buffer */
	if (vdenc_context->current_pass == vdenc_context->num_passes - 1)
		OUT_BUFFER_3DW(batch, vdenc_context->huc_prob_output_buffer_res.bo, 1, 0, 0);
	else {
		int frame_ctx = pic_param->pic_flags.bits.frame_context_idx;

		OUT_BUFFER_3DW(batch, vdenc_context->prob_buffer_res[frame_ctx].bo, 1, 0, 0);
	}

	/* DW 86..88 Segment id buffer */
	OUT_BUFFER_3DW(batch, vdenc_context->segmentid_buffer_res.bo, 1, 0, 0);

	/* DW 89..91 HVD line rowstore buffer */
	OUT_BUFFER_3DW(batch, vdenc_context->hvd_line_buffer_res.bo, 1, 0, 0);

	/* DW 92..94 HVD tile line rowstore buffer */
	OUT_BUFFER_3DW(batch, vdenc_context->hvd_tile_line_buffer_res.bo, 1, 0, 0);

	/* DW 95..97 SAO streamout. Not used for VP9 */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 98..101 Frame Stat Stream out */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_brc_pak_stat_buffer_res.bo, 1, 0, 0);

	/* 101..103 */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_sse_src_pixel_row_store_buffer_res.bo, 1, 0, 0);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_hcp_ind_obj_base_addr_state(VADriverContextP ctx, struct encode_state *encode_state, struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 29);

	OUT_BCS_BATCH(batch, HCP_IND_OBJ_BASE_ADDR_STATE | (29 - 2));

	/* indirect bitstream object base */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);
	/* the upper bound of indirect bitstream object */
	OUT_BUFFER_2DW(batch, NULL, 0, 0);

	/* DW 6: Indirect CU object base address, ignored for vdenc */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW 9..11, PAK-BSE */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->compressed_bitstream.res.bo,
				   1,
				   vdenc_context->compressed_bitstream.start_offset,
				   0);
	OUT_BUFFER_2DW(batch,
				   vdenc_context->compressed_bitstream.res.bo,
				   1,
				   vdenc_context->compressed_bitstream.end_offset);

	/* DW 14..16 compressed header buffer */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->compressed_header_buffer_res.bo,
				   0,
				   0,
				   0);

	/* DW 17..19 prob counter streamout */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->prob_counter_buffer_res.bo,
				   1,
				   0,
				   0);

	/* DW 20..22 prob delta streamin */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->prob_delta_buffer_res.bo,
				   0,
				   0,
				   0);

	/* DW 23..25 Tile record streamout */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->tile_record_streamout_buffer_res.bo,
				   1,
				   0,
				   0);

	/* DW 26..28, VP9 PAK CU level Statistic streamout */
	OUT_BUFFER_3DW(batch,
				   vdenc_context->cu_stat_streamout_buffer_res.bo,
				   1,
				   0,
				   0);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdenc_pipe_mode_select(VADriverContextP ctx,
									   struct encode_state *encode_state,
									   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 2);

	OUT_BCS_BATCH(batch, VDENC_PIPE_MODE_SELECT | (2 - 2));
	OUT_BCS_BATCH(batch,
				  (0 << 12) |                   /* TODO, Bit Depth */
				  (0 << 9) |                    /* Must be 0 */
				  (vdenc_context->vdenc_pak_threshold_check_enable << 8) |
				  (1 << 7)  |                   /* Tlb prefetch enable */
				  (vdenc_context->vdenc_pak_object_streamout_enable << 6) |
				  (1 << 5)  |                   /* Frame Statistics Stream-Out Enable */
				  (VDENC_CODEC_VP9 << 0));

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdenc_src_surface_state(VADriverContextP ctx,
										struct intel_encoder_context *encoder_context,
										struct i965_gpe_resource *gpe_resource)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 6);

	OUT_BCS_BATCH(batch, VDENC_SRC_SURFACE_STATE | (6 - 2));
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch,
				  ((gpe_resource->height - 1) << 18) |
				  ((gpe_resource->width - 1) << 4));
	OUT_BCS_BATCH(batch,
				  (VDENC_SURFACE_PLANAR_420_8 << 28) |  /* 420 planar YUV surface, TODO: 10bits support  */
				  (1 << 27) |                           /* must be 1 for interleave U/V, hardware requirement */
				  ((gpe_resource->pitch - 1) << 3) |    /* pitch */
				  (0 << 2)  |                           /* must be 0 for interleave U/V */
				  (1 << 1)  |                           /* must be tiled */
				  (I965_TILEWALK_YMAJOR << 0));         /* tile walk, TILEWALK_YMAJOR */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource->y_cb_offset));         /* y offset for U(cb) */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource->y_cb_offset));         /* y offset for v(cr) */

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdenc_ref_surface_state(VADriverContextP ctx,
										struct intel_encoder_context *encoder_context,
										struct i965_gpe_resource *gpe_resource)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 6);

	OUT_BCS_BATCH(batch, VDENC_REF_SURFACE_STATE | (6 - 2));
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch,
				  ((gpe_resource->height - 1) << 18) |
				  ((gpe_resource->width - 1) << 4));
	OUT_BCS_BATCH(batch,
				  (VDENC_SURFACE_PLANAR_420_8 << 28) |  /* 420 planar YUV surface TODO: 10bits support */
				  (1 << 27) |                           /* must be 1 for interleave U/V, hardware requirement */
				  ((gpe_resource->pitch - 1) << 3) |    /* pitch */
				  (0 << 2)  |                           /* must be 0 for interleave U/V */
				  (1 << 1)  |                           /* must be tiled */
				  (I965_TILEWALK_YMAJOR << 0));         /* tile walk, TILEWALK_YMAJOR */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource->y_cb_offset));         /* y offset for U(cb) */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource->y_cb_offset));         /* y offset for v(cr) */

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdenc_ds_ref_surface_state(VADriverContextP ctx,
										   struct intel_encoder_context *encoder_context,
										   struct i965_gpe_resource *gpe_resource0,
										   struct i965_gpe_resource *gpe_resource1)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 10);

	OUT_BCS_BATCH(batch, VDENC_DS_REF_SURFACE_STATE | (10 - 2));
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch,
				  ((gpe_resource0->height - 1) << 18) |
				  ((gpe_resource0->width - 1) << 4));
	OUT_BCS_BATCH(batch,
				  (VDENC_SURFACE_PLANAR_420_8 << 28) |  /* 420 planar YUV surface TODO: 10bits surface */
				  (1 << 27) |                           /* must be 1 for interleave U/V, hardware requirement */
				  ((gpe_resource0->pitch - 1) << 3) |    /* pitch */
				  (0 << 2)  |                           /* must be 0 for interleave U/V */
				  (1 << 1)  |                           /* must be tiled */
				  (I965_TILEWALK_YMAJOR << 0));         /* tile walk, TILEWALK_YMAJOR */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource0->y_cb_offset));         /* y offset for U(cb) */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource0->y_cb_offset));         /* y offset for v(cr) */

	OUT_BCS_BATCH(batch,
				  ((gpe_resource1->height - 1) << 18) |
				  ((gpe_resource1->width - 1) << 4));
	OUT_BCS_BATCH(batch,
				  (VDENC_SURFACE_PLANAR_420_8 << 28) |  /* 420 planar YUV surface TODO: 10bits surface */
				  (1 << 27) |                           /* must be 1 for interleave U/V, hardware requirement */
				  ((gpe_resource1->pitch - 1) << 3) |    /* pitch */
				  (0 << 2)  |                           /* must be 0 for interleave U/V */
				  (1 << 1)  |                           /* must be tiled */
				  (I965_TILEWALK_YMAJOR << 0));         /* tile walk, TILEWALK_YMAJOR */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource1->y_cb_offset));         /* y offset for U(cb) */
	OUT_BCS_BATCH(batch,
				  (0 << 16) |                   /* must be 0 for interleave U/V */
				  (gpe_resource1->y_cb_offset));         /* y offset for v(cr) */

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vdenc_pipe_buf_addr_state(VADriverContextP ctx,
									  struct encode_state *encode_state,
									  struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct vdenc_vp9_surface *vdenc_vp9_surface0 = NULL, *vdenc_vp9_surface1 = NULL;

	if (vdenc_context->last_ref_obj)
		vdenc_vp9_surface0 = (struct vdenc_vp9_surface *)(vdenc_context->last_ref_obj->private_data);

	if (vdenc_context->golden_ref_obj)
		vdenc_vp9_surface1 = (struct vdenc_vp9_surface *)(vdenc_context->golden_ref_obj->private_data);

	BEGIN_BCS_BATCH(batch, 62);

	OUT_BCS_BATCH(batch, VDENC_PIPE_BUF_ADDR_STATE | (62 - 2));

	/* DW1-6 for DS 8x REF */
	if (vdenc_vp9_surface0 && vdenc_vp9_surface0->scaled_8x_surface_obj)
		OUT_BUFFER_3DW(batch, vdenc_vp9_surface0->scaled_8x_surface_obj->bo, 0, 0, 0);
	else
		OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	if (vdenc_vp9_surface1 && vdenc_vp9_surface1->scaled_8x_surface_obj)
		OUT_BUFFER_3DW(batch, vdenc_vp9_surface1->scaled_8x_surface_obj->bo, 0, 0, 0);
	else
		OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW7-9 for DS BWD REF0. B-frame is not supported */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW10-12 for uncompressed input data */
	OUT_BUFFER_3DW(batch, vdenc_context->uncompressed_input_yuv_surface_res.bo, 0, 0, 0);

	/* DW13-DW15 for streamin data */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_streamin_buffer_res.bo, 0, 0, 0);

	/* DW16-DW18 for row scratch buffer */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_row_store_scratch_res.bo, 1, 0, 0);

	/* DW19-DW21, mv temporal buffer */
	if (vdenc_context->vp9_frame_type == VP9_FRAME_P) {
		int prev_index = vdenc_context->curr_mv_temporal_index ^ 0x01;
		OUT_BUFFER_3DW(batch, vdenc_context->mv_temporal_buffer_res[prev_index].bo, 1, 0, 0);
	} else
		OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW22-DW30 for Last, Golden, Alt reference */
	OUT_BUFFER_3DW(batch, vdenc_context->last_ref_res.bo, 0, 0, 0);
	OUT_BUFFER_3DW(batch, vdenc_context->golden_ref_res.bo, 0, 0, 0);
	OUT_BUFFER_3DW(batch, vdenc_context->alt_ref_res.bo, 0, 0, 0);

	/* DW31-DW33 for BDW REF0. Ignored*/
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW34-DW36 for VDEnc statistics streamout */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_brc_stat_buffer_res.bo, 1, 0, 0);

	/* DW37..DW42. DS 4x REF */
	if (vdenc_vp9_surface0 && vdenc_vp9_surface0->scaled_4x_surface_obj)
		OUT_BUFFER_3DW(batch, vdenc_vp9_surface0->scaled_4x_surface_obj->bo, 0, 0, 0);
	else
		OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	if (vdenc_vp9_surface1 && vdenc_vp9_surface1->scaled_4x_surface_obj)
		OUT_BUFFER_3DW(batch, vdenc_vp9_surface1->scaled_4x_surface_obj->bo, 0, 0, 0);
	else
		OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW43..DW45. Not used */
	OUT_BUFFER_3DW(batch, NULL, 0, 0, 0);

	/* DW46..DW48. streamout for pak object command */
	OUT_BUFFER_3DW(batch, vdenc_context->mb_code_buffer_res.bo, 1, 0, 0);

	/* DW49..DW51. DS 8x */
	OUT_BUFFER_3DW(batch, vdenc_context->scaled_8x_recon_surface_res.bo, 1, 0, 0);

	/* DW52..DW54. DS 4x */
	OUT_BUFFER_3DW(batch, vdenc_context->scaled_4x_recon_surface_res.bo, 1, 0, 0);

	/* DW55..DW57. segment map streamout */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_segment_map_stream_out_buffer_res.bo, 1, 0, 0);

	/* DW58..DW60. */
	OUT_BUFFER_3DW(batch, vdenc_context->vdenc_segment_map_stream_out_buffer_res.bo, 1, 0, 0);

	/* DW 61. */
	OUT_BCS_BATCH(batch, 64 * 3);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdecn_weihgtsoffsets_state(VADriverContextP ctx,
										   struct encode_state *encode_state,
										   struct intel_encoder_context *encoder_context)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;

	BEGIN_BCS_BATCH(batch, 5);

	OUT_BCS_BATCH(batch, VDENC_WEIGHTSOFFSETS_STATE | (5 - 2));

	OUT_BCS_BATCH(batch, (0 << 24 |
						  1 << 16 |
						  0 << 8 |
						  1 << 0));
	OUT_BCS_BATCH(batch, (0 << 8 |
						  1 << 0));
	OUT_BCS_BATCH(batch, (0 << 24 |
						  1 << 16 |
						  0 << 8 |
						  1 << 0));
	OUT_BCS_BATCH(batch, (0 << 24 |
						  1 << 16 |
						  0 << 8 |
						  1 << 0));

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_vdenc_walker_state(VADriverContextP ctx,
								   struct encode_state *encode_state,
								   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	VAEncPictureParameterBufferVP9 *pic_param = vdenc_context->pic_param;

	BEGIN_BCS_BATCH(batch, 6);
	OUT_BCS_BATCH(batch, VDENC_WALKER_STATE | (6 - 2));

	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch, ((ALIGN(pic_param->frame_width_dst, 64) / 64) << 16 |
						  (ALIGN(pic_param->frame_height_dst, 64) / 64)));
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch, 0);
	OUT_BCS_BATCH(batch, pic_param->frame_width_dst - 1);

	ADVANCE_BCS_BATCH(batch);
}

static void
gen10_vdenc_vp9_hcp_vdenc_pipeline(VADriverContextP ctx,
								   struct encode_state *encode_state,
								   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gpe_mi_batch_buffer_start_parameter mi_batch_buffer_start_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	gen10_vdenc_vd_pipeline_flush_param pipeline_flush_params;

	if (vdenc_context->num_passes > 1 && vdenc_context->current_pass == (vdenc_context->num_passes - 1)) {
		struct gpe_mi_conditional_batch_buffer_end_parameter mi_conditional_batch_buffer_end_params;

		memset(&mi_conditional_batch_buffer_end_params, 0, sizeof(mi_conditional_batch_buffer_end_params));
		mi_conditional_batch_buffer_end_params.bo = vdenc_context->huc_status_buffer_res.bo;
		/* Muse use Mask mode */
		mi_conditional_batch_buffer_end_params.compare_mask_mode_disabled = 0;
		gpe->mi_conditional_batch_buffer_end(ctx, batch, &mi_conditional_batch_buffer_end_params);
	}

	gen10_vdenc_vp9_hcp_pipe_mode_select(ctx, encode_state, encoder_context);

	/* MFX_WAIT to make sure previous operation is done */
	gen10_vdenc_mfx_wait(ctx, encode_state, encoder_context);

	gen10_vdenc_vp9_hcp_surface_state(ctx, encoder_context, &vdenc_context->recon_surface_res, 0);
	gen10_vdenc_vp9_hcp_surface_state(ctx, encoder_context, &vdenc_context->uncompressed_input_yuv_surface_res, 1);
	gen10_vdenc_vp9_hcp_surface_state(ctx, encoder_context, &vdenc_context->last_ref_res, 2);
	gen10_vdenc_vp9_hcp_surface_state(ctx, encoder_context, &vdenc_context->golden_ref_res, 3);
	gen10_vdenc_vp9_hcp_surface_state(ctx, encoder_context, &vdenc_context->alt_ref_res, 4);

	gen10_vdenc_vp9_hcp_pipe_buf_addr_state(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_hcp_ind_obj_base_addr_state(ctx, encode_state, encoder_context);

	gen10_vdenc_vp9_vdenc_pipe_mode_select(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_vdenc_src_surface_state(ctx, encoder_context, &vdenc_context->uncompressed_input_yuv_surface_res);

	if (vdenc_context->is_key_frame)
		gen10_vdenc_vp9_vdenc_ref_surface_state(ctx, encoder_context, &vdenc_context->recon_surface_res);
	else {
		struct i965_gpe_resource *ref_gpe_res = &vdenc_context->last_ref_res;

		if (!ref_gpe_res->bo)
			ref_gpe_res = &vdenc_context->golden_ref_res;

		if (!ref_gpe_res->bo)
			ref_gpe_res = &vdenc_context->alt_ref_res;

		assert(ref_gpe_res->bo);
		gen10_vdenc_vp9_vdenc_ref_surface_state(ctx, encoder_context, ref_gpe_res);
	}

	gen10_vdenc_vp9_vdenc_ds_ref_surface_state(ctx, encoder_context, &vdenc_context->scaled_8x_recon_surface_res, &vdenc_context->scaled_4x_recon_surface_res);

	gen10_vdenc_vdenc_pipe_buf_addr_state(ctx, encode_state, encoder_context);

	memset(&mi_batch_buffer_start_params, 0, sizeof(mi_batch_buffer_start_params));
	mi_batch_buffer_start_params.is_second_level = 1; /* Must be the second level batch buffer */

	if (vdenc_context->use_huc)
		mi_batch_buffer_start_params.bo = vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[0].bo;
	else {
		if (vdenc_context->dys_ref_frame_flag != VP9_REF_NONE && vdenc_context->dys_multiple_pass_enbaled)
			mi_batch_buffer_start_params.bo = vdenc_context->vdenc_dys_pic_state_2nd_batchbuffer_res.bo;
		else
			mi_batch_buffer_start_params.bo = vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[vdenc_context->current_pass].bo;
	}

	gpe->mi_batch_buffer_start(ctx, batch, &mi_batch_buffer_start_params);

	if (vdenc_context->use_huc)
		mi_batch_buffer_start_params.bo = vdenc_context->huc_pak_insert_uncompressed_header_output_2nd_batchbuffer_res.bo;
	else {
		mi_batch_buffer_start_params.bo = vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res.bo;
	}

	gpe->mi_batch_buffer_start(ctx, batch, &mi_batch_buffer_start_params);

	gen10_vdenc_vp9_vdecn_weihgtsoffsets_state(ctx, encode_state, encoder_context);
	gen10_vdenc_vp9_vdenc_walker_state(ctx, encode_state, encoder_context);

	memset(&pipeline_flush_params, 0, sizeof(pipeline_flush_params));
	pipeline_flush_params.dw1.mfx_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_flush = 1;
	pipeline_flush_params.dw1.vd_cmd_msg_parser_done = 1;
	gen10_vdenc_vd_pipeline_flush(ctx, batch, &pipeline_flush_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	mi_flush_dw_params.video_pipeline_cache_invalidate = 1;
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);
}

static void
gen10_vdenc_vp9_context_brc_prepare(struct encode_state *encode_state,
									struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	unsigned int rate_control_mode = encoder_context->rate_control_mode;

	switch (rate_control_mode & 0x7f) {
	case VA_RC_CBR:
		vdenc_context->internal_rate_mode = I965_BRC_CBR;
		break;

	case VA_RC_VBR:
		vdenc_context->internal_rate_mode = I965_BRC_VBR;
		break;

	case VA_RC_CQP:
	default:
		vdenc_context->internal_rate_mode = I965_BRC_CQP;
		break;
	}

	if (encoder_context->quality_level == 0)
		encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_VP9;
}

static void
gen10_vdenc_vp9_read_status(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gpe_mi_store_register_mem_parameter mi_store_register_mem_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct gpe_mi_copy_mem_parameter mi_copy_mem_mem_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	unsigned int base_offset = vdenc_context->status_bffuer.base_offset;

	memset(&mi_store_register_mem_params, 0, sizeof(mi_store_register_mem_params));
	mi_store_register_mem_params.mmio_offset = HCP_VP9_BITSTREAM_BYTECOUNT_FRAME_REG;
	mi_store_register_mem_params.bo = vdenc_context->status_bffuer.res.bo;
	mi_store_register_mem_params.offset = base_offset + vdenc_context->status_bffuer.bytes_per_frame_offset;
	gpe->mi_store_register_mem(ctx, batch, &mi_store_register_mem_params);

	memset(&mi_copy_mem_mem_params, 0, sizeof(mi_copy_mem_mem_params));
	mi_copy_mem_mem_params.src_bo = vdenc_context->status_bffuer.res.bo;
	mi_copy_mem_mem_params.src_offset = base_offset + vdenc_context->status_bffuer.bytes_per_frame_offset;
	mi_copy_mem_mem_params.dst_bo = vdenc_context->brc_bitstream_size_buffer_res.bo;
	mi_copy_mem_mem_params.dst_offset = 0;
	gpe->mi_copy_mem_mem(ctx, batch, &mi_copy_mem_mem_params);

	mi_copy_mem_mem_params.dst_bo = vdenc_context->huc_prob_dmem_buffer_res[1].bo;
	mi_copy_mem_mem_params.dst_offset = offsetof(struct vdenc_vp9_huc_prob_dmem, frame_size);
	gpe->mi_copy_mem_mem(ctx, batch, &mi_copy_mem_mem_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);
}

static VAStatus
gen10_vdenc_vp9_check_capability(VADriverContextP ctx,
								 struct encode_state *encode_state,
								 struct intel_encoder_context *encoder_context)
{
	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_dys_ref_frames(VADriverContextP ctx,
							   struct encode_state *encode_state,
							   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;

	if (vdenc_context->dys_ref_frame_flag == VP9_REF_NONE)
		return VA_STATUS_SUCCESS;

	if (vdenc_context->current_pass == 0) {
		if (vdenc_context->dys_multiple_pass_enbaled) {
			vdenc_context->vdenc_pak_object_streamout_enable = 1; // TODO, double check this flag
		}
	}

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_fill_pak_insert_object_batchbuffer(VADriverContextP ctx,
												   struct encode_state *encode_state,
												   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	int uncompressed_header_length;
	unsigned int *cmd_ptr;
	unsigned int dw_length, bits_in_last_dw;

	if (vdenc_context->current_pass)
		return VA_STATUS_SUCCESS;

	assert(vdenc_context->alias_insert_data);
	uncompressed_header_length = vdenc_context->frame_header_length;
	cmd_ptr = i965_map_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res);

	if (!cmd_ptr)
		return VA_STATUS_ERROR_UNKNOWN;

	bits_in_last_dw = uncompressed_header_length % 4;
	bits_in_last_dw *= 8;

	if (bits_in_last_dw == 0)
		bits_in_last_dw = 32;

	/* get the DWORD length of the inserted_data */
	dw_length = ALIGN(uncompressed_header_length, 4) / 4;
	*cmd_ptr++ = HCP_INSERT_PAK_OBJECT | dw_length;

	*cmd_ptr++ = ((0 << 31) | /* indirect payload */
				  (0 << 16) | /* the start offset in first DW */
				  (0 << 15) |
				  (bits_in_last_dw << 8) | /* bits_in_last_dw */
				  (0 << 4) |  /* skip emulation byte count. 0 for VP9 */
				  (0 << 3) |  /* emulation flag. 0 for VP9 */
				  (1 << 2) |  /* last header flag. */
				  (1 << 1));  /* End of slice */
	memcpy(cmd_ptr, vdenc_context->alias_insert_data, dw_length * sizeof(unsigned int));

	cmd_ptr += dw_length;

	*cmd_ptr++ = MI_NOOP;
	*cmd_ptr++ = MI_BATCH_BUFFER_END;
	i965_unmap_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res);

	return VA_STATUS_SUCCESS;
}

static void
gen10_vdenc_vp9_fill_hcp_vp9_pic_state(VADriverContextP ctx,
									   struct encode_state *encode_state,
									   struct intel_encoder_context *encoder_context,
									   uint32_t *pcmd)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct object_surface *obj_surface;
	gen10_hcp_vp9_pic_state_param *param;
	VAEncPictureParameterBufferVP9 *pic_param;
	VDEncVP9Surface *vdenc_vp9_surface;
	unsigned int use_prev_frame_mvs;
	unsigned int scaled_h = 0, scaled_w = 0;
	unsigned int ref_frame_width, ref_frame_height;

	if (!vdenc_context->pic_param)
		return;

	pic_param = vdenc_context->pic_param;
	assert(sizeof(*param) == (VDENC_HCP_VP9_PIC_STATE_SIZE - 4));
	*pcmd++ = (HCP_VP9_PIC_STATE | (VDENC_HCP_VP9_PIC_STATE_SIZE_IN_DWS - 2));
	param = (gen10_hcp_vp9_pic_state_param *)pcmd;
	memset(param, 0, sizeof(*param));

	param->dw1.frame_width_in_pixels_minus1 = ALIGN(pic_param->frame_width_dst, 8) - 1;
	param->dw1.frame_height_in_pixels_minus1 = ALIGN(pic_param->frame_height_dst, 8) - 1;

	param->dw2.frame_type = !vdenc_context->is_key_frame;
	param->dw2.adapt_probabilities_flag = (!pic_param->pic_flags.bits.error_resilient_mode && !pic_param->pic_flags.bits.frame_parallel_decoding_mode);
	param->dw2.intra_only_flag = pic_param->pic_flags.bits.intra_only;
	param->dw2.allow_high_precision_mv = pic_param->pic_flags.bits.allow_high_precision_mv;
	param->dw2.motion_comp_filter_type = pic_param->pic_flags.bits.mcomp_filter_type;
	param->dw2.ref_frame_sign_bias_last = pic_param->ref_flags.bits.ref_last_sign_bias;
	param->dw2.ref_frame_sign_bias_golden = pic_param->ref_flags.bits.ref_gf_sign_bias;
	param->dw2.ref_frame_sign_bias_altref = pic_param->ref_flags.bits.ref_arf_sign_bias;
	param->dw2.hybrid_prediction_mode = (pic_param->pic_flags.bits.comp_prediction_mode == 2);
	param->dw2.selectable_tx_mode = (vdenc_context->tx_mode == TX_MODE_SELECT);
	param->dw2.refresh_frame_context = pic_param->pic_flags.bits.refresh_frame_context;
	param->dw2.error_resilient_mode = pic_param->pic_flags.bits.error_resilient_mode;
	param->dw2.frame_parallel_decoding_mode = pic_param->pic_flags.bits.frame_parallel_decoding_mode;
	param->dw2.filter_level = pic_param->filter_level;
	param->dw2.sharpness_level = pic_param->sharpness_level;
	param->dw2.segmentation_enabled = pic_param->pic_flags.bits.segmentation_enabled;
	param->dw2.segmentation_update_map = pic_param->pic_flags.bits.segmentation_update_map;
	param->dw2.segmentation_temporal_update = pic_param->pic_flags.bits.segmentation_temporal_update;
	param->dw2.lossless_mode = pic_param->pic_flags.bits.lossless_mode;

	param->dw3.log2_tile_column = pic_param->log2_tile_columns;
	param->dw3.log2_tile_row = pic_param->log2_tile_rows;
	param->dw3.sse_enable = vdenc_context->brc_enabled;

	if (vdenc_context->vp9_frame_type == VP9_FRAME_P) {
		if (pic_param->pic_flags.bits.error_resilient_mode ||
			vdenc_context->last_frame_status.is_key_frame ||
			vdenc_context->last_frame_status.intra_only ||
			!vdenc_context->last_frame_status.show_frame ||
			(pic_param->frame_width_dst != vdenc_context->last_frame_status.frame_width) ||
			(pic_param->frame_height_dst != vdenc_context->last_frame_status.frame_height))
			use_prev_frame_mvs = 0;
		else
			use_prev_frame_mvs = 1;

		param->dw2.last_frame_type = !vdenc_context->last_frame_status.is_key_frame;
		param->dw2.use_prev_in_find_mv_references = use_prev_frame_mvs;

		/* slot 0 is for last reference */
		obj_surface = encode_state->reference_objects[0];
		scaled_w = 0;
		scaled_h = 0;
		ref_frame_width = 1;
		ref_frame_height = 1;

		if (obj_surface && obj_surface->private_data) {
			vdenc_vp9_surface = obj_surface->private_data;
			ref_frame_width = vdenc_vp9_surface->frame_width;
			ref_frame_height = vdenc_vp9_surface->frame_height;
			scaled_w = (ref_frame_width << 14) / pic_param->frame_width_dst;
			scaled_h = (ref_frame_height << 14) / pic_param->frame_height_dst;
		}

		param->dw4.horizontal_scale_factor_for_last = scaled_w;
		param->dw4.vertical_scale_factor_for_last = scaled_h;
		param->dw7.last_frame_width_in_pixels_minus1 = ref_frame_width - 1;
		param->dw7.last_frame_height_in_pixels_minus1 = ref_frame_height - 1;

		/* slot 1 is for golden reference */
		obj_surface = encode_state->reference_objects[1];
		scaled_w = 0;
		scaled_h = 0;
		ref_frame_width = 1;
		ref_frame_height = 1;

		if (obj_surface && obj_surface->private_data) {
			vdenc_vp9_surface = obj_surface->private_data;
			ref_frame_width = vdenc_vp9_surface->frame_width;
			ref_frame_height = vdenc_vp9_surface->frame_height;
			scaled_w = (ref_frame_width << 14) / pic_param->frame_width_dst;
			scaled_h = (ref_frame_height << 14) / pic_param->frame_height_dst;
		}

		param->dw5.horizontal_scale_factor_for_golden = scaled_w;
		param->dw5.vertical_scale_factor_for_golden = scaled_h;
		param->dw8.golden_frame_width_in_pixels_minus1 = ref_frame_width - 1;
		param->dw8.golden_frame_height_in_pixels_minus1 = ref_frame_height - 1;

		/* slot 2 is for alt reference */
		obj_surface = encode_state->reference_objects[2];
		scaled_w = 0;
		scaled_h = 0;
		ref_frame_width = 1;
		ref_frame_height = 1;

		if (obj_surface && obj_surface->private_data) {
			vdenc_vp9_surface = obj_surface->private_data;
			ref_frame_width = vdenc_vp9_surface->frame_width;
			ref_frame_height = vdenc_vp9_surface->frame_height;
			scaled_w = (ref_frame_width << 14) / pic_param->frame_width_dst;
			scaled_h = (ref_frame_height << 14) / pic_param->frame_height_dst;
		}

		param->dw6.horizontal_scale_factor_for_altref = scaled_w;
		param->dw6.vertical_scale_factor_for_altref = scaled_h;
		param->dw9.altref_frame_width_in_pixels_minus1 = ref_frame_width - 1;
		param->dw9.altref_frame_height_in_pixels_minus1 = ref_frame_height - 1;
	}

	param->dw11.motion_comp_scaling = 1;
	param->dw13.base_qindex = pic_param->luma_ac_qindex;
	param->dw13.header_insertion_enable = 1;

	param->dw14.chroma_ac_qindex_delta = intel_convert_sign_mag(pic_param->chroma_ac_qindex_delta, 5);
	param->dw14.chroma_dc_qindex_delta = intel_convert_sign_mag(pic_param->chroma_dc_qindex_delta, 5);
	param->dw14.luma_dc_qindex_delta = intel_convert_sign_mag(pic_param->luma_dc_qindex_delta, 5);

	param->dw15.lf_ref_delta0 = intel_convert_sign_mag(pic_param->ref_lf_delta[0], 7);
	param->dw15.lf_ref_delta1 = intel_convert_sign_mag(pic_param->ref_lf_delta[1], 7);
	param->dw15.lf_ref_delta2 = intel_convert_sign_mag(pic_param->ref_lf_delta[2], 7);
	param->dw15.lf_ref_delta3 = intel_convert_sign_mag(pic_param->ref_lf_delta[3], 7);

	param->dw16.lf_mode_delta0 = intel_convert_sign_mag(pic_param->mode_lf_delta[0], 7);
	param->dw16.lf_mode_delta1 = intel_convert_sign_mag(pic_param->mode_lf_delta[1], 7);

	param->dw17.bit_offset_for_lf_ref_delta = vdenc_context->frame_header.bit_offset_ref_lf_delta;
	param->dw17.bit_offset_for_mode_delta = vdenc_context->frame_header.bit_offset_mode_lf_delta;

	param->dw18.bit_offset_for_lf_level = vdenc_context->frame_header.bit_offset_lf_level;
	param->dw18.bit_offset_for_qindex = vdenc_context->frame_header.bit_offset_qindex;

	param->dw32.bit_offset_for_first_partition_size = vdenc_context->frame_header.bit_offset_first_partition_size;

	param->dw19.vdenc_pak_only_pass = vdenc_context->pak_only_pass_enabled; // TODO, check the flag

	if (vdenc_context->max_bit_rate || vdenc_context->min_bit_rate) {
		param->dw20.frame_bitrate_max = (vdenc_context->max_bit_rate >> 12);
		param->dw20.frame_bitrate_max_unit = 1;
		param->dw21.frame_bitrate_min = (vdenc_context->min_bit_rate >> 12);
		param->dw21.frame_bitrate_min_unit = 1;
	}
}

static void
gen10_vdenc_vp9_fill_hcp_vp9_segment_state(VADriverContextP ctx,
										   struct encode_state *encode_state,
										   struct intel_encoder_context *encoder_context,
										   VAEncSegParamVP9 *seg_param,
										   int segment_id,
										   uint32_t *pcmd)
{
	gen10_hcp_vp9_segment_state_param *param;

	assert(sizeof(*param) == (VDENC_HCP_VP9_SEGMENT_STATE_SIZE - 4));
	*pcmd++ = (HCP_VP9_SEGMENT_STATE | (VDENC_HCP_VP9_SEGMENT_STATE_SIZE_IN_DWS - 2));
	param = (gen10_hcp_vp9_segment_state_param *)pcmd;
	memset(param, 0, sizeof(*param));

	param->dw1.segment_id = segment_id;
	param->dw2.segment_skipped = seg_param->seg_flags.bits.segment_reference_skipped;
	param->dw2.segment_reference = seg_param->seg_flags.bits.segment_reference;
	param->dw2.segment_reference_enabled = seg_param->seg_flags.bits.segment_reference_enabled;

	param->dw7.segment_qindex_delta = intel_convert_sign_mag(seg_param->segment_qindex_delta, 9);
	param->dw7.segment_lf_level_delta = intel_convert_sign_mag(seg_param->segment_lf_level_delta, 7);
}

static void
gen10_vdenc_vp9_fill_mi_batchbuffer_end(VADriverContextP ctx,
										struct encode_state *encode_state,
										struct intel_encoder_context *encoder_context,
										uint32_t *pcmd)
{
	*pcmd++ = MI_BATCH_BUFFER_END;
}

static void
gen10_vdenc_vp9_huc_initializer_init(VADriverContextP ctx,
									 struct encode_state *encode_state,
									 struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_gpe_resource *dmem_gpe_resource, *data_gpe_resource;
	struct huc_initializer_dmem *pdmem;
	struct huc_initializer_data *pdata;
	struct huc_initializer_input_command1 input_cmd1;
	VAEncPictureParameterBufferVP9 *pic_param;
	double qp_scale, lambda;
	uint8_t qp;
	int i;

	if (!vdenc_context->pic_param)
		return;

	pic_param = vdenc_context->pic_param;

	if (vdenc_context->dys_in_use) {
		dmem_gpe_resource = &vdenc_context->huc_initializer_dys_dmem_buffer_res;
		data_gpe_resource = &vdenc_context->huc_initializer_dys_data_buffer_res;
	} else {
		dmem_gpe_resource = &vdenc_context->huc_initializer_dmem_buffer_res[vdenc_context->current_pass];
		data_gpe_resource = &vdenc_context->huc_initializer_data_buffer_res[vdenc_context->current_pass];
	}

	pdata = i965_map_gpe_resource(data_gpe_resource);

	if (!pdata)
		return;

	memset(pdata, 0, sizeof(struct huc_initializer_data));
	pdata->total_commands = 2;

	pdata->input_command[0].id = 2;
	pdata->input_command[0].size_of_data = 1;

	if (vdenc_context->vp9_frame_type == VP9_FRAME_I)
		qp_scale = 0.31;
	else
		qp_scale = 0.33;

	qp = pic_param->luma_ac_qindex;
	lambda = qp_scale * vdenc_vp9_quant_ac[qp] / 8;

	pdata->input_command[0].data[0] = (uint32_t)(lambda * 4 + 0.5);

	pdata->input_command[1].id = 1;
	pdata->input_command[1].size_of_data = 0x14;

	memset(&input_cmd1, 0, sizeof(input_cmd1));
	input_cmd1.vdenc_streamin_enabled = (!!vdenc_context->segment_param || vdenc_context->hme_enabled);
	input_cmd1.segment_map_streamin_enabled = !!vdenc_context->segment_param;
	input_cmd1.pak_only_multi_pass_enabled = vdenc_context->pak_only_pass_enabled;

	if (vdenc_context->is_key_frame)
		input_cmd1.num_ref_idx_l0_active_minus1 = 0;
	else
		input_cmd1.num_ref_idx_l0_active_minus1 = vdenc_context->num_ref_frames - 1;;

	input_cmd1.sad_qp_lambda = (uint16_t)(lambda * 4 + 0.5);
	input_cmd1.rd_qp_lambda = (uint16_t)(lambda * lambda * 4 + 0.5);

	input_cmd1.dst_frame_width_minus1 = vdenc_context->frame_width - 1;
	input_cmd1.dst_frame_height_minus1 = vdenc_context->frame_height - 1;
	input_cmd1.segment_enabled = pic_param->pic_flags.bits.segmentation_enabled;
	input_cmd1.prev_frame_segment_enabled = vdenc_context->last_frame_status.segment_enabled;
	input_cmd1.luma_ac_qindex = pic_param->luma_ac_qindex;
	input_cmd1.luma_dc_qindex_delta = pic_param->luma_dc_qindex_delta;

	if (input_cmd1.segment_enabled && vdenc_context->segment_param) {
		VAEncMiscParameterTypeVP9PerSegmantParam *segment_param = vdenc_context->segment_param;
		VAEncSegParamVP9 *seg_param;

		for (i = 0; i < VP9_MAX_SEGMENTS; i++) {
			seg_param = &segment_param->seg_data[i];
			input_cmd1.segment_qindex_delta[i] = seg_param->segment_qindex_delta;
		}
	}

	memcpy(pdata->input_command[1].data, &input_cmd1, sizeof(input_cmd1));
	i965_unmap_gpe_resource(data_gpe_resource);

	pdmem = i965_map_gpe_resource(dmem_gpe_resource);

	if (!pdmem)
		return;

	pdmem->total_output_commands = 2;
	pdmem->codec = 1;
	pdmem->target_usage = encoder_context->quality_level;
	pdmem->frame_type = pic_param->pic_flags.bits.frame_type;

	pdmem->output_command[0].id = 2;
	pdmem->output_command[0].type = 1;
	pdmem->output_command[0].start_in_bytes = 0;

	pdmem->output_command[1].id = 1;
	pdmem->output_command[1].type = 1;
	pdmem->output_command[1].start_in_bytes = 544;

	pdmem->output_size = 544 + 148;

	i965_unmap_gpe_resource(dmem_gpe_resource);
}

static void
gen10_vdenc_vp9_huc_initializer(VADriverContextP ctx,
								struct encode_state *encode_state,
								struct intel_encoder_context *encoder_context,
								struct i965_gpe_resource *pic_state_buffer_res)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_huc_pipe_mode_select_parameter pipe_mode_select_params;
	struct gen10_huc_imem_state_parameter imem_state_params;
	struct gen10_huc_dmem_state_parameter dmem_state_params;
	struct gen10_huc_virtual_addr_parameter virtual_addr_params;
	struct gen10_huc_start_parameter start_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	gen10_vdenc_vd_pipeline_flush_param pipeline_flush_params;

	memset(&imem_state_params, 0, sizeof(imem_state_params));
	imem_state_params.huc_firmware_descriptor = VDENC_VP9_HUC_INITIALIZER;
	gen10_huc_imem_state(ctx, batch, &imem_state_params);

	memset(&pipe_mode_select_params, 0, sizeof(pipe_mode_select_params));
	gen10_huc_pipe_mode_select(ctx, batch, &pipe_mode_select_params);

	gen10_vdenc_vp9_huc_initializer_init(ctx, encode_state, encoder_context);

	memset(&dmem_state_params, 0, sizeof(dmem_state_params));

	if (vdenc_context->dys_in_use) {
		dmem_state_params.huc_data_source_res = &vdenc_context->huc_initializer_dys_dmem_buffer_res;
	} else {
		dmem_state_params.huc_data_source_res = &vdenc_context->huc_initializer_dmem_buffer_res[vdenc_context->current_pass];
	}

	dmem_state_params.huc_data_destination_base_address = VDENC_VP9_HUC_DMEM_DATA_OFFSET;
	dmem_state_params.huc_data_length = ALIGN(sizeof(struct huc_initializer_dmem), 64);
	gen10_huc_dmem_state(ctx, batch, &dmem_state_params);

	memset(&virtual_addr_params, 0, sizeof(virtual_addr_params));

	if (vdenc_context->dys_in_use)
		virtual_addr_params.regions[0].huc_surface_res = &vdenc_context->huc_initializer_dys_data_buffer_res;
	else
		virtual_addr_params.regions[0].huc_surface_res = &vdenc_context->huc_initializer_data_buffer_res[vdenc_context->current_pass];

	virtual_addr_params.regions[1].huc_surface_res = pic_state_buffer_res;
	virtual_addr_params.regions[1].is_target = 1;
	gen10_huc_virtual_addr_state(ctx, batch, &virtual_addr_params);

	memset(&start_params, 0, sizeof(start_params));
	start_params.last_stream_object = 1;
	gen10_huc_start(ctx, batch, &start_params);

	memset(&pipeline_flush_params, 0, sizeof(pipeline_flush_params));
	pipeline_flush_params.dw1.hevc_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_flush = 1;
	gen10_vdenc_vd_pipeline_flush(ctx, batch, &pipeline_flush_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	mi_flush_dw_params.video_pipeline_cache_invalidate = 1;
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);
}

static VAStatus
gen10_vdenc_vp9_fill_pic_state_batchbuffer(VADriverContextP ctx,
										   struct encode_state *encode_state,
										   struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct i965_gpe_resource *gpe_resource;
	VAEncPictureParameterBufferVP9 *pic_param;
	VAEncMiscParameterTypeVP9PerSegmantParam *seg_param, tmp_seg_param;
	char *pdata, *pdata_header;
	int i, segment_count;

	if (!vdenc_context->pic_param)
		return VA_STATUS_ERROR_INVALID_PARAMETER;

	pic_param = vdenc_context->pic_param;

	if ((vdenc_context->dys_ref_frame_flag != VP9_REF_NONE) && vdenc_context->dys_multiple_pass_enbaled)
		gpe_resource = &vdenc_context->vdenc_dys_pic_state_2nd_batchbuffer_res;
	else
		gpe_resource = &vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[vdenc_context->current_pass];

	pdata_header = pdata = i965_map_gpe_resource(gpe_resource);

	if (!pdata)
		return VA_STATUS_ERROR_UNKNOWN;

	pdata += VDENC_VDENC_CMD0_STATE_SIZE;
	vdenc_context->pic_state_offset_in_2nd_batchbuffer = pdata - pdata_header;
	gen10_vdenc_vp9_fill_hcp_vp9_pic_state(ctx, encode_state, encoder_context, (uint32_t *)pdata);
	pdata += VDENC_HCP_VP9_PIC_STATE_SIZE;

	seg_param = vdenc_context->segment_param;

	if (pic_param->pic_flags.bits.segmentation_enabled && seg_param)
		segment_count = VP9_MAX_SEGMENTS;
	else {
		segment_count = 1;
		memset(&tmp_seg_param, 0, sizeof(tmp_seg_param));
		seg_param = &tmp_seg_param;
	}

	for (i = 0; i < segment_count; i++) {
		gen10_vdenc_vp9_fill_hcp_vp9_segment_state(ctx, encode_state, encoder_context, &seg_param->seg_data[i], i, (uint32_t *)pdata);
		pdata += VDENC_HCP_VP9_SEGMENT_STATE_SIZE;
	}

	if (segment_count < VP9_MAX_SEGMENTS) {
		memset(pdata, 0, VDENC_HCP_VP9_SEGMENT_STATE_SIZE * (VP9_MAX_SEGMENTS - 1));
		pdata += VDENC_HCP_VP9_SEGMENT_STATE_SIZE * (VP9_MAX_SEGMENTS - 1);
	}

	vdenc_context->cmd1_state_offset_in_2nd_batchbuffer = pdata - pdata_header;
	pdata += VDENC_VDENC_CMD1_STATE_SIZE;

	gen10_vdenc_vp9_fill_mi_batchbuffer_end(ctx, encode_state, encoder_context, (uint32_t *)pdata);
	pdata += VDENC_BATCHBUFFER_END_SIZE;

	vdenc_context->huc_2nd_batchbuffer_size = pdata - pdata_header;

	i965_unmap_gpe_resource(gpe_resource);

	gen10_vdenc_vp9_huc_initializer(ctx,
									encode_state,
									encoder_context,
									gpe_resource);

	return VA_STATUS_SUCCESS;
}

static int
gen10_vdenc_vp9_get_reference_index(uint8_t refresh_flags)
{
	int index = 0;

	if (refresh_flags == 0) {
		return 0;
	}

	refresh_flags = ~refresh_flags;

	while (refresh_flags & 1) {
		refresh_flags >>= 1;
		index++;
	}

	return index;
}

static void
gen10_vdenc_vp9_update_huc_vp9_prob_dmem(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	VAEncPictureParameterBufferVP9 *pic_param = vdenc_context->pic_param;
	VAEncMiscParameterTypeVP9PerSegmantParam *seg_param = vdenc_context->segment_param;
	struct vdenc_vp9_huc_prob_dmem *dmem;
	int i;

	if (vdenc_context->current_pass == 0) {
		dmem = (struct vdenc_vp9_huc_prob_dmem *)i965_map_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[1]);

		if (!dmem)
			return;

		memcpy(dmem, vdenc_vp9_huc_prob_dmem_data, sizeof(struct vdenc_vp9_huc_prob_dmem));
		i965_unmap_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[1]);

		dmem = (struct vdenc_vp9_huc_prob_dmem *)i965_map_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[0]);

		if (!dmem)
			return;

		memcpy(dmem, vdenc_vp9_huc_prob_dmem_data, sizeof(struct vdenc_vp9_huc_prob_dmem));
	} else {
		dmem = (struct vdenc_vp9_huc_prob_dmem *)i965_map_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[1]);

		if (!dmem)
			return;
	}

	dmem->huc_pass_num = vdenc_context->is_super_frame_huc_pass ? VDENC_VP9_HUC_SUPERFRAME_PASS : !!vdenc_context->current_pass;
	dmem->frame_width = vdenc_context->frame_width;
	dmem->frame_height = vdenc_context->frame_height;

	if (!seg_param) {
		for (i = 0; i < VP9_MAX_SEGMENTS; i++) {
			dmem->segment_ref[i] = 0xff;
			dmem->segment_skip[i] = 0;
		}
	} else {
		for (i = 0; i < VP9_MAX_SEGMENTS; i++) {
			if (seg_param->seg_data[i].seg_flags.bits.segment_reference_enabled)
				dmem->segment_ref[i] = seg_param->seg_data[i].seg_flags.bits.segment_reference;
			else
				dmem->segment_ref[i] = 0xff;

			dmem->segment_skip[i] = seg_param->seg_data[i].seg_flags.bits.segment_reference_skipped;
		}
	}

	dmem->seg_code_abs = 0;
	dmem->seg_temporal_update = pic_param->pic_flags.bits.segmentation_temporal_update;
	dmem->last_ref_index = pic_param->ref_flags.bits.ref_last_idx;
	dmem->golden_ref_index = pic_param->ref_flags.bits.ref_gf_idx;
	dmem->alt_ref_index = pic_param->ref_flags.bits.ref_arf_idx;
	dmem->refresh_frame_flags = pic_param->refresh_frame_flags;
	dmem->ref_frame_flags = vdenc_context->ref_frame_flag;
	dmem->context_frame_types = vdenc_context->context_frame_types[pic_param->pic_flags.bits.frame_context_idx];
	dmem->frame_to_show = gen10_vdenc_vp9_get_reference_index(dmem->refresh_frame_flags);

	dmem->frame_ctrl.frame_type = pic_param->pic_flags.bits.frame_type;
	dmem->frame_ctrl.show_frame = pic_param->pic_flags.bits.show_frame;
	dmem->frame_ctrl.error_resilient_mode = pic_param->pic_flags.bits.error_resilient_mode;
	dmem->frame_ctrl.intra_only = pic_param->pic_flags.bits.intra_only;
	dmem->frame_ctrl.context_reset = pic_param->pic_flags.bits.reset_frame_context;
	dmem->frame_ctrl.last_ref_frame_bias = pic_param->ref_flags.bits.ref_last_sign_bias;
	dmem->frame_ctrl.golden_ref_frame_bias = pic_param->ref_flags.bits.ref_gf_sign_bias;
	dmem->frame_ctrl.alt_ref_frame_bias = pic_param->ref_flags.bits.ref_arf_sign_bias;
	dmem->frame_ctrl.allow_high_precision_mv = pic_param->pic_flags.bits.allow_high_precision_mv;
	dmem->frame_ctrl.mcomp_filter_mode = pic_param->pic_flags.bits.mcomp_filter_type;
	dmem->frame_ctrl.tx_mode = vdenc_context->tx_mode;
	dmem->frame_ctrl.refresh_frame_context = pic_param->pic_flags.bits.refresh_frame_context;
	dmem->frame_ctrl.frame_parallel_decode = pic_param->pic_flags.bits.frame_parallel_decoding_mode;
	dmem->frame_ctrl.comp_pred_mode = pic_param->pic_flags.bits.comp_prediction_mode;
	dmem->frame_ctrl.frame_context_idx = pic_param->pic_flags.bits.frame_context_idx;
	dmem->frame_ctrl.sharpness_level = pic_param->sharpness_level;
	dmem->frame_ctrl.seg_on = pic_param->pic_flags.bits.segmentation_enabled;
	dmem->frame_ctrl.seg_map_update = pic_param->pic_flags.bits.segmentation_update_map;
	dmem->frame_ctrl.seg_update_data = 0; // TODO
	dmem->frame_ctrl.log2tile_cols = pic_param->log2_tile_columns;
	dmem->frame_ctrl.log2tile_rows = pic_param->log2_tile_rows;

	dmem->streamin_segenable = !!seg_param;
	dmem->streamin_enable = !!seg_param; // TODO
	dmem->prev_frame_info.intra_only = vdenc_context->last_frame_status.intra_only;
	dmem->prev_frame_info.frame_width = vdenc_context->last_frame_status.frame_width;
	dmem->prev_frame_info.frame_height = vdenc_context->last_frame_status.frame_height;
	dmem->prev_frame_info.key_frame = vdenc_context->last_frame_status.is_key_frame;
	dmem->prev_frame_info.show_frame = vdenc_context->last_frame_status.show_frame;
	dmem->repak = (vdenc_context->num_passes > 1 && vdenc_context->current_pass == vdenc_context->num_passes - 1);

	if (dmem->repak && vdenc_context->has_adaptive_repak) {
		// do nothing so far
	}

	/* Must use vdenc_context->frame_header.bit_offset_first_partition_size to calculate dmem->uncomp_hdr_total_length_in_bits */
	dmem->loop_filter_level_bit_offset = vdenc_context->frame_header.bit_offset_lf_level;
	dmem->qindex_bit_offset = vdenc_context->frame_header.bit_offset_qindex;
	dmem->seg_bit_offset = vdenc_context->frame_header.bit_offset_segmentation + 1; // exclude segment_enable bit
	dmem->seg_length_in_bits = vdenc_context->frame_header.bit_size_segmentation - 1; // exclude segment_enable bit
	dmem->uncomp_hdr_total_length_in_bits = vdenc_context->frame_header.bit_offset_first_partition_size + 16;
	dmem->pic_state_offset = vdenc_context->pic_state_offset_in_2nd_batchbuffer;
	dmem->slb_block_size = vdenc_context->huc_2nd_batchbuffer_size;
	dmem->ivf_header_size = (vdenc_context->frame_number == 0) ? 44 : 12;

	i965_unmap_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[!!vdenc_context->current_pass]);
}

static void
gen10_vdenc_vp9_huc_vp9_prob(VADriverContextP ctx,
							 struct encode_state *encode_state,
							 struct intel_encoder_context *encoder_context)
{
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct gen10_huc_pipe_mode_select_parameter pipe_mode_select_params;
	struct gen10_huc_imem_state_parameter imem_state_params;
	struct gen10_huc_dmem_state_parameter dmem_state_params;
	struct gen10_huc_virtual_addr_parameter virtual_addr_params;
	struct gen10_huc_start_parameter start_params;
	struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
	struct gpe_mi_store_register_mem_parameter mi_store_register_mem_params;
	struct gpe_mi_store_data_imm_parameter mi_store_data_imm_params;
	VAEncPictureParameterBufferVP9 *pic_param;
	struct i965_gpe_table *gpe = vdenc_context->gpe_table;
	gen10_vdenc_vd_pipeline_flush_param pipeline_flush_params;

	if (!vdenc_context->pic_param)
		return;

	pic_param = vdenc_context->pic_param;

	memset(&imem_state_params, 0, sizeof(imem_state_params));
	imem_state_params.huc_firmware_descriptor = VDENC_VP9_HUC_PROB;
	gen10_huc_imem_state(ctx, batch, &imem_state_params);

	memset(&pipe_mode_select_params, 0, sizeof(pipe_mode_select_params));
	gen10_huc_pipe_mode_select(ctx, batch, &pipe_mode_select_params);

	gen10_vdenc_vp9_update_huc_vp9_prob_dmem(ctx, encoder_context);

	memset(&dmem_state_params, 0, sizeof(dmem_state_params));
	dmem_state_params.huc_data_source_res = &vdenc_context->huc_prob_dmem_buffer_res[!!vdenc_context->current_pass];
	dmem_state_params.huc_data_destination_base_address = VDENC_VP9_HUC_DMEM_DATA_OFFSET;
	dmem_state_params.huc_data_length = ALIGN(sizeof(struct vdenc_vp9_huc_prob_dmem), 64);
	gen10_huc_dmem_state(ctx, batch, &dmem_state_params);

	memset(&virtual_addr_params, 0, sizeof(virtual_addr_params));
	virtual_addr_params.regions[0].huc_surface_res = &vdenc_context->prob_buffer_res[pic_param->pic_flags.bits.frame_context_idx];
	virtual_addr_params.regions[0].is_target = 1;

	virtual_addr_params.regions[1].huc_surface_res = &vdenc_context->prob_counter_buffer_res;

	virtual_addr_params.regions[2].huc_surface_res = &vdenc_context->huc_prob_output_buffer_res;
	virtual_addr_params.regions[2].is_target = 1;

	virtual_addr_params.regions[3].huc_surface_res = &vdenc_context->prob_delta_buffer_res;
	virtual_addr_params.regions[3].is_target = 1;

	virtual_addr_params.regions[4].huc_surface_res = &vdenc_context->huc_pak_insert_uncompressed_header_output_2nd_batchbuffer_res;
	virtual_addr_params.regions[4].is_target = 1;

	virtual_addr_params.regions[5].huc_surface_res = &vdenc_context->compressed_header_buffer_res;
	virtual_addr_params.regions[5].is_target = 1;

	virtual_addr_params.regions[6].huc_surface_res = &vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[0];
	virtual_addr_params.regions[6].is_target = 1;

	if (vdenc_context->brc_enabled)
		virtual_addr_params.regions[7].huc_surface_res = &vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[0];
	else
		virtual_addr_params.regions[7].huc_surface_res = &vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[vdenc_context->current_pass];

	virtual_addr_params.regions[8].huc_surface_res = &vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res;

	virtual_addr_params.regions[9].huc_surface_res = &vdenc_context->huc_default_prob_buffer_res;

	virtual_addr_params.regions[10].huc_surface_res = &vdenc_context->compressed_bitstream.res;
	virtual_addr_params.regions[10].offset = vdenc_context->compressed_bitstream.start_offset;
	virtual_addr_params.regions[10].is_target = 1;

	virtual_addr_params.regions[11].huc_surface_res = &vdenc_context->vdenc_data_extension_buffer_res;
	virtual_addr_params.regions[11].is_target = 1;

	gen10_huc_virtual_addr_state(ctx, batch, &virtual_addr_params);

	gen10_vdenc_vp9_huc_store_huc_status2(ctx, encoder_context);

	memset(&start_params, 0, sizeof(start_params));
	start_params.last_stream_object = 1;
	gen10_huc_start(ctx, batch, &start_params);

	memset(&pipeline_flush_params, 0, sizeof(pipeline_flush_params));
	pipeline_flush_params.dw1.hevc_pipeline_done = 1;
	pipeline_flush_params.dw1.hevc_pipeline_flush = 1;
	gen10_vdenc_vd_pipeline_flush(ctx, batch, &pipeline_flush_params);

	memset(&mi_flush_dw_params, 0, sizeof(mi_flush_dw_params));
	mi_flush_dw_params.video_pipeline_cache_invalidate = 1;
	gpe->mi_flush_dw(ctx, batch, &mi_flush_dw_params);

	/* Write HUC_STATUS mask (1 << 31) */
	memset(&mi_store_data_imm_params, 0, sizeof(mi_store_data_imm_params));
	mi_store_data_imm_params.bo = vdenc_context->huc_status_buffer_res.bo;
	mi_store_data_imm_params.offset = 4;
	mi_store_data_imm_params.dw0 = (1 << 31);
	gpe->mi_store_data_imm(ctx, batch, &mi_store_data_imm_params);

	/* Store HUC_STATUS */
	memset(&mi_store_register_mem_params, 0, sizeof(mi_store_register_mem_params));
	mi_store_register_mem_params.mmio_offset = VCS0_HUC_STATUS;
	mi_store_register_mem_params.bo = vdenc_context->huc_status_buffer_res.bo;
	gpe->mi_store_register_mem(ctx, batch, &mi_store_register_mem_params);

	if (vdenc_context->is_super_frame_huc_pass) {
		// TODO, enable for super frame
	}
}

static VAStatus
gen10_vdenc_vp9_encode_picture(VADriverContextP ctx,
							   VAProfile profile,
							   struct encode_state *encode_state,
							   struct intel_encoder_context *encoder_context)
{
	VAStatus va_status;
	struct gen10_vdenc_vp9_context *vdenc_context = encoder_context->mfc_context;
	struct intel_batchbuffer *batch = encoder_context->base.batch;
	VAEncPictureParameterBufferVP9 *pic_param;

	va_status = gen10_vdenc_vp9_check_capability(ctx, encode_state, encoder_context);

	if (va_status != VA_STATUS_SUCCESS)
		return va_status;

	gen10_vdenc_vp9_prepare(ctx, profile, encode_state, encoder_context);

	vdenc_context->submit_batchbuffer = 1;
	vdenc_context->vdenc_pak_object_streamout_enable = 0;

	for (vdenc_context->current_pass = 0; vdenc_context->current_pass < vdenc_context->num_passes; vdenc_context->current_pass++) {
		vdenc_context->is_first_pass = (vdenc_context->current_pass == 0);
		vdenc_context->is_last_pass = (vdenc_context->current_pass == (vdenc_context->num_passes - 1));

		if (vdenc_context->submit_batchbuffer) {
			intel_batchbuffer_start_atomic_bcs_override(batch, 0x1000, BSD_RING0);
			intel_batchbuffer_emit_mi_flush(batch);
		}

		if (vdenc_context->dys_ref_frame_flag == VP9_REF_NONE) {
			if (vdenc_context->current_pass == 0 &&
				vdenc_context->brc_enabled) {
				vdenc_context->vdenc_pak_object_streamout_enable = 1;
			}
		} else {
			gen10_vdenc_vp9_dys_ref_frames(ctx, encode_state, encoder_context);
		}

		gen10_vdenc_vp9_fill_pak_insert_object_batchbuffer(ctx, encode_state, encoder_context);
		gen10_vdenc_vp9_fill_pic_state_batchbuffer(ctx, encode_state, encoder_context);

		intel_batchbuffer_emit_mi_flush(batch);

		if (vdenc_context->brc_enabled) {
			assert(vdenc_context->num_passes > 1);

			if (!vdenc_context->brc_initted || vdenc_context->brc_need_reset)
				gen10_vdenc_vp9_huc_brc_init_reset(ctx, encode_state, encoder_context);

			if (vdenc_context->current_pass < (vdenc_context->num_passes - 1) ||
				(vdenc_context->current_pass == 0 &&
				 vdenc_context->num_passes == 1))
				gen10_vdenc_vp9_huc_brc_update(ctx, encode_state, encoder_context);

			/* intel_batchbuffer_emit_mi_flush(batch); */
		}

		if ((vdenc_context->current_pass == 0) || (vdenc_context->current_pass == (vdenc_context->num_passes - 1)))
			gen10_vdenc_vp9_huc_vp9_prob(ctx, encode_state, encoder_context);

		gen10_vdenc_vp9_hcp_vdenc_pipeline(ctx, encode_state, encoder_context);
		gen10_vdenc_vp9_read_status(ctx, encoder_context);

		if (vdenc_context->submit_batchbuffer) {
			intel_batchbuffer_end_atomic(batch);
			intel_batchbuffer_flush(batch);
		}

		vdenc_context->brc_initted = 1;
		vdenc_context->brc_need_reset = 0;
	}

	assert(vdenc_context->pic_param);
	pic_param = vdenc_context->pic_param;
	vdenc_context->last_frame_status.frame_width = pic_param->frame_width_dst;
	vdenc_context->last_frame_status.frame_height = pic_param->frame_height_dst;
	vdenc_context->last_frame_status.is_key_frame = vdenc_context->is_key_frame;
	vdenc_context->last_frame_status.show_frame = pic_param->pic_flags.bits.show_frame;
	vdenc_context->last_frame_status.refresh_frame_context = pic_param->pic_flags.bits.refresh_frame_context;
	vdenc_context->last_frame_status.frame_context_idx = pic_param->pic_flags.bits.frame_context_idx;
	vdenc_context->last_frame_status.intra_only = (vdenc_context->vp9_frame_type == VP9_FRAME_I);
	vdenc_context->last_frame_status.segment_enabled = !!vdenc_context->segment_param;
	vdenc_context->context_frame_types[pic_param->pic_flags.bits.frame_context_idx] = pic_param->pic_flags.bits.frame_type;
	vdenc_context->frame_number++;
	vdenc_context->curr_mv_temporal_index ^= 1;
	vdenc_context->is_first_frame = 0;

	return VA_STATUS_SUCCESS;
}

static VAStatus
gen10_vdenc_vp9_pipeline(VADriverContextP ctx,
						 VAProfile profile,
						 struct encode_state *encode_state,
						 struct intel_encoder_context *encoder_context)
{
	VAStatus vaStatus;

	switch (profile) {
	case VAProfileVP9Profile0:
		vaStatus = gen10_vdenc_vp9_encode_picture(ctx, profile, encode_state, encoder_context);
		break;

	default:
		vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
		break;
	}

	return vaStatus;
}

static void
gen10_vdenc_vp9_free_resources(struct gen10_vdenc_vp9_context *vdenc_context)
{
	int i;

	/* PAK buffer */
	i965_free_gpe_resource(&vdenc_context->brc_history_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_constant_data_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_bitstream_size_buffer_res);
	i965_free_gpe_resource(&vdenc_context->brc_huc_data_buffer_res);

	/* HME */
	i965_free_gpe_resource(&vdenc_context->s4x_memv_data_buffer_res);
	i965_free_gpe_resource(&vdenc_context->s4x_memv_distortion_buffer_res);
	i965_free_gpe_resource(&vdenc_context->s16x_memv_data_buffer_res);
	i965_free_gpe_resource(&vdenc_context->output_16x16_inter_modes_buffer_res);

	for (i = 0; i < 2; i++) {
		i965_free_gpe_resource(&vdenc_context->mode_decision_buffer_res[i]);
		i965_free_gpe_resource(&vdenc_context->mv_temporal_buffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->mb_code_buffer_res);
	i965_free_gpe_resource(&vdenc_context->mb_segment_map_buffer_res);

	/* PAK resource */
	i965_free_gpe_resource(&vdenc_context->hvd_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->hvd_tile_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->deblocking_filter_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->deblocking_filter_tile_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->deblocking_filter_tile_col_buffer_res);

	i965_free_gpe_resource(&vdenc_context->metadata_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->metadata_tile_line_buffer_res);
	i965_free_gpe_resource(&vdenc_context->metadata_tile_col_buffer_res);

	i965_free_gpe_resource(&vdenc_context->segmentid_buffer_res);

	for (i = 0; i < 4; i++) {
		i965_free_gpe_resource(&vdenc_context->prob_buffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->prob_counter_buffer_res);
	i965_free_gpe_resource(&vdenc_context->prob_delta_buffer_res);

	i965_free_gpe_resource(&vdenc_context->compressed_header_buffer_res);
	i965_free_gpe_resource(&vdenc_context->tile_record_streamout_buffer_res);
	i965_free_gpe_resource(&vdenc_context->cu_stat_streamout_buffer_res);

	/* HuC */
	for (i = 0; i < 2; i++) {
		i965_free_gpe_resource(&vdenc_context->huc_prob_dmem_buffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->huc_default_prob_buffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_prob_output_buffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_input_2nd_batchbuffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_pak_insert_uncompressed_header_output_2nd_batchbuffer_res);

	/* VDEnc */
	i965_free_gpe_resource(&vdenc_context->vdenc_row_store_scratch_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_brc_stat_buffer_res);

	for (i = 0; i < 4; i++) {
		i965_free_gpe_resource(&vdenc_context->vdenc_pic_state_input_2nd_batchbuffer_res[i]);
		i965_free_gpe_resource(&vdenc_context->vdenc_pic_state_output_2nd_batchbuffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->vdenc_dys_pic_state_2nd_batchbuffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_brc_init_reset_dmem_buffer_res);

	for (i = 0; i < VDENC_VP9_BRC_MAX_NUM_OF_PASSES; i++)
		i965_free_gpe_resource(&vdenc_context->vdenc_brc_update_dmem_buffer_res[i]);

	i965_free_gpe_resource(&vdenc_context->vdenc_segment_map_stream_out_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_brc_pak_stat_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_sse_src_pixel_row_store_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_data_extension_buffer_res);
	i965_free_gpe_resource(&vdenc_context->vdenc_streamin_buffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_status2_buffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_status_buffer_res);

	/* Reconstructed picture */
	i965_free_gpe_resource(&vdenc_context->recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_4x_recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_8x_recon_surface_res);
	i965_free_gpe_resource(&vdenc_context->scaled_16x_recon_surface_res);

	/* HuC Initializer */
	for (i = 0; i < VDENC_VP9_BRC_MAX_NUM_OF_PASSES; i++) {
		i965_free_gpe_resource(&vdenc_context->huc_initializer_dmem_buffer_res[i]);
		i965_free_gpe_resource(&vdenc_context->huc_initializer_data_buffer_res[i]);
	}

	i965_free_gpe_resource(&vdenc_context->huc_initializer_dys_dmem_buffer_res);
	i965_free_gpe_resource(&vdenc_context->huc_initializer_dys_data_buffer_res);

	/* Reference */
	i965_free_gpe_resource(&vdenc_context->last_ref_res);
	i965_free_gpe_resource(&vdenc_context->golden_ref_res);
	i965_free_gpe_resource(&vdenc_context->alt_ref_res);

	/* Input YUV */
	i965_free_gpe_resource(&vdenc_context->uncompressed_input_yuv_surface_res);

	/* Compressed bitstream */
	i965_free_gpe_resource(&vdenc_context->compressed_bitstream.res);

	/* Status buffer */
	i965_free_gpe_resource(&vdenc_context->status_bffuer.res);

	free(vdenc_context->frame_header_data);
	vdenc_context->frame_header_data = NULL;
}


static void
gen10_vdenc_vp9_context_destroy(void *context)
{
	struct gen10_vdenc_vp9_context *vdenc_context = context;

	gen10_vdenc_vp9_kernel_context_destroy(vdenc_context);
	gen10_vdenc_vp9_free_resources(vdenc_context);

	free(vdenc_context);
}

static VAStatus
gen10_vdenc_vp9_context_get_status(VADriverContextP ctx,
								   struct intel_encoder_context *encoder_context,
								   struct i965_coded_buffer_segment *coded_buffer_segment)
{
	struct gen10_vdenc_vp9_status *vdenc_status = (struct gen10_vdenc_vp9_status *)coded_buffer_segment->codec_private_data;

	coded_buffer_segment->base.size = vdenc_status->bytes_per_frame;

	return VA_STATUS_SUCCESS;
}

Bool
gen10_vdenc_vp9_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
{
	struct i965_driver_data *i965 = i965_driver_data(ctx);
	struct gen10_vdenc_vp9_context *vdenc_context = calloc(1, sizeof(struct gen10_vdenc_vp9_context));

	if (!vdenc_context)
		return False;

	vdenc_context->gpe_table = &i965->gpe_table;
	vdenc_context->brc_initted = 0;
	vdenc_context->brc_need_reset = 0;
	vdenc_context->current_pass = 0;
	vdenc_context->num_passes = 1;
	vdenc_context->vdenc_pak_threshold_check_enable = 0;
	vdenc_context->dys_enabled = 0; // TODO
	vdenc_context->is_first_frame = 1;
	vdenc_context->has_hme = 0;
	vdenc_context->need_hme = 0;
	vdenc_context->hme_enabled = 0;
	vdenc_context->has_hme_16x = 0;
	vdenc_context->hme_16x_enabled = 0;
	vdenc_context->use_huc = 1;
	vdenc_context->multiple_pass_brc_enabled = 0;
	vdenc_context->has_adaptive_repak = 0;
	vdenc_context->use_hw_scoreboard = 1;
	vdenc_context->use_hw_non_stalling_scoreborad = 1; /* default: non-stalling */

	gen10_vdenc_vp9_gpe_context_init(ctx, encoder_context, vdenc_context);

	encoder_context->mfc_context = vdenc_context;
	encoder_context->mfc_context_destroy = gen10_vdenc_vp9_context_destroy;
	encoder_context->mfc_pipeline = gen10_vdenc_vp9_pipeline;
	encoder_context->mfc_brc_prepare = gen10_vdenc_vp9_context_brc_prepare;
	encoder_context->get_status = gen10_vdenc_vp9_context_get_status;

	return True;
}
