brintos

brintos / linux-shallow public Read only

0
0
Text · 86.0 KiB · c89aafa Raw
2747 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2/*3 * Wave5 series multi-standard codec IP - wave5 backend logic4 *5 * Copyright (C) 2021-2023 CHIPS&MEDIA INC6 */7 8#include <linux/iopoll.h>9#include <linux/bitfield.h>10#include "wave5-vpu.h"11#include "wave5.h"12#include "wave5-regdefine.h"13 14#define FIO_TIMEOUT			1000000015#define FIO_CTRL_READY			BIT(31)16#define FIO_CTRL_WRITE			BIT(16)17#define VPU_BUSY_CHECK_TIMEOUT		1000000018#define QUEUE_REPORT_MASK		0xffff19 20/* Encoder support fields */21#define W521_FEATURE_HEVC10BIT_ENC	BIT(3)22#define W521_FEATURE_AVC10BIT_ENC	BIT(11)23#define W521_FEATURE_AVC_ENCODER	BIT(1)24#define W521_FEATURE_HEVC_ENCODER	BIT(0)25 26/* Decoder support fields */27#define W521_FEATURE_AVC_DECODER	BIT(3)28#define W521_FEATURE_HEVC_DECODER	BIT(2)29#define W515_FEATURE_HEVC10BIT_DEC	BIT(1)30#define W515_FEATURE_HEVC_DECODER	BIT(0)31 32#define W521_FEATURE_BACKBONE		BIT(16)33#define W521_FEATURE_VCORE_BACKBONE	BIT(22)34#define W521_FEATURE_VCPU_BACKBONE	BIT(28)35 36#define REMAP_CTRL_MAX_SIZE_BITS	((W5_REMAP_MAX_SIZE >> 12) & 0x1ff)37#define REMAP_CTRL_REGISTER_VALUE(index)	(			\38	(BIT(31) | (index << 12) | BIT(11) | REMAP_CTRL_MAX_SIZE_BITS)	\39)40 41#define FASTIO_ADDRESS_MASK		GENMASK(15, 0)42#define SEQ_PARAM_PROFILE_MASK		GENMASK(30, 24)43 44static void _wave5_print_reg_err(struct vpu_device *vpu_dev, u32 reg_fail_reason,45				 const char *func);46#define PRINT_REG_ERR(dev, reason)	_wave5_print_reg_err((dev), (reason), __func__)47 48static inline const char *cmd_to_str(int cmd, bool is_dec)49{50	switch (cmd) {51	case W5_INIT_VPU:52		return "W5_INIT_VPU";53	case W5_WAKEUP_VPU:54		return "W5_WAKEUP_VPU";55	case W5_SLEEP_VPU:56		return "W5_SLEEP_VPU";57	case W5_CREATE_INSTANCE:58		return "W5_CREATE_INSTANCE";59	case W5_FLUSH_INSTANCE:60		return "W5_FLUSH_INSTANCE";61	case W5_DESTROY_INSTANCE:62		return "W5_DESTROY_INSTANCE";63	case W5_INIT_SEQ:64		return "W5_INIT_SEQ";65	case W5_SET_FB:66		return "W5_SET_FB";67	case W5_DEC_ENC_PIC:68		if (is_dec)69			return "W5_DEC_PIC";70		return "W5_ENC_PIC";71	case W5_ENC_SET_PARAM:72		return "W5_ENC_SET_PARAM";73	case W5_QUERY:74		return "W5_QUERY";75	case W5_UPDATE_BS:76		return "W5_UPDATE_BS";77	case W5_MAX_VPU_COMD:78		return "W5_MAX_VPU_COMD";79	default:80		return "UNKNOWN";81	}82}83 84static void _wave5_print_reg_err(struct vpu_device *vpu_dev, u32 reg_fail_reason,85				 const char *func)86{87	struct device *dev = vpu_dev->dev;88	u32 reg_val;89 90	switch (reg_fail_reason) {91	case WAVE5_SYSERR_QUEUEING_FAIL:92		reg_val = vpu_read_reg(vpu_dev, W5_RET_QUEUE_FAIL_REASON);93		dev_dbg(dev, "%s: queueing failure: 0x%x\n", func, reg_val);94		break;95	case WAVE5_SYSERR_RESULT_NOT_READY:96		dev_err(dev, "%s: result not ready: 0x%x\n", func, reg_fail_reason);97		break;98	case WAVE5_SYSERR_ACCESS_VIOLATION_HW:99		dev_err(dev, "%s: access violation: 0x%x\n", func, reg_fail_reason);100		break;101	case WAVE5_SYSERR_WATCHDOG_TIMEOUT:102		dev_err(dev, "%s: watchdog timeout: 0x%x\n", func, reg_fail_reason);103		break;104	case WAVE5_SYSERR_BUS_ERROR:105		dev_err(dev, "%s: bus error: 0x%x\n", func, reg_fail_reason);106		break;107	case WAVE5_SYSERR_DOUBLE_FAULT:108		dev_err(dev, "%s: double fault: 0x%x\n", func, reg_fail_reason);109		break;110	case WAVE5_SYSERR_VPU_STILL_RUNNING:111		dev_err(dev, "%s: still running: 0x%x\n", func, reg_fail_reason);112		break;113	case WAVE5_SYSERR_VLC_BUF_FULL:114		dev_err(dev, "%s: vlc buf full: 0x%x\n", func, reg_fail_reason);115		break;116	default:117		dev_err(dev, "%s: failure:: 0x%x\n", func, reg_fail_reason);118		break;119	}120}121 122static int wave5_wait_fio_readl(struct vpu_device *vpu_dev, u32 addr, u32 val)123{124	u32 ctrl;125	int ret;126 127	ctrl = addr & 0xffff;128	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl);129	ret = read_poll_timeout(wave5_vdi_read_register, ctrl, ctrl & FIO_CTRL_READY,130				0, FIO_TIMEOUT, false, vpu_dev, W5_VPU_FIO_CTRL_ADDR);131	if (ret)132		return ret;133 134	if (wave5_vdi_read_register(vpu_dev, W5_VPU_FIO_DATA) != val)135		return -ETIMEDOUT;136 137	return 0;138}139 140static void wave5_fio_writel(struct vpu_device *vpu_dev, unsigned int addr, unsigned int data)141{142	int ret;143	unsigned int ctrl;144 145	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_DATA, data);146	ctrl = FIELD_GET(FASTIO_ADDRESS_MASK, addr);147	ctrl |= FIO_CTRL_WRITE;148	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl);149	ret = read_poll_timeout(wave5_vdi_read_register, ctrl, ctrl & FIO_CTRL_READY, 0,150				FIO_TIMEOUT, false, vpu_dev, W5_VPU_FIO_CTRL_ADDR);151	if (ret)152		dev_dbg_ratelimited(vpu_dev->dev, "FIO write timeout: addr=0x%x data=%x\n",153				    ctrl, data);154}155 156static int wave5_wait_bus_busy(struct vpu_device *vpu_dev, unsigned int addr)157{158	u32 gdi_status_check_value = 0x3f;159 160	if (vpu_dev->product_code == WAVE515_CODE)161		gdi_status_check_value = 0x0738;162	if (vpu_dev->product_code == WAVE521C_CODE ||163	    vpu_dev->product_code == WAVE521_CODE ||164	    vpu_dev->product_code == WAVE521E1_CODE)165		gdi_status_check_value = 0x00ff1f3f;166 167	return wave5_wait_fio_readl(vpu_dev, addr, gdi_status_check_value);168}169 170static int wave5_wait_vpu_busy(struct vpu_device *vpu_dev, unsigned int addr)171{172	u32 data;173 174	return read_poll_timeout(wave5_vdi_read_register, data, data == 0,175				 0, VPU_BUSY_CHECK_TIMEOUT, false, vpu_dev, addr);176}177 178static int wave5_wait_vcpu_bus_busy(struct vpu_device *vpu_dev, unsigned int addr)179{180	return wave5_wait_fio_readl(vpu_dev, addr, 0);181}182 183bool wave5_vpu_is_init(struct vpu_device *vpu_dev)184{185	return vpu_read_reg(vpu_dev, W5_VCPU_CUR_PC) != 0;186}187 188unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev)189{190	u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);191 192	switch (val) {193	case WAVE515_CODE:194		return PRODUCT_ID_515;195	case WAVE521C_CODE:196		return PRODUCT_ID_521;197	case WAVE521_CODE:198	case WAVE521C_DUAL_CODE:199	case WAVE521E1_CODE:200	case WAVE511_CODE:201	case WAVE517_CODE:202	case WAVE537_CODE:203		dev_err(vpu_dev->dev, "Unsupported product id (%x)\n", val);204		break;205	default:206		dev_err(vpu_dev->dev, "Invalid product id (%x)\n", val);207		break;208	}209 210	return PRODUCT_ID_NONE;211}212 213static void wave5_bit_issue_command(struct vpu_device *vpu_dev, struct vpu_instance *inst, u32 cmd)214{215	u32 instance_index;216	u32 codec_mode;217 218	if (inst) {219		instance_index = inst->id;220		codec_mode = inst->std;221 222		vpu_write_reg(vpu_dev, W5_CMD_INSTANCE_INFO, (codec_mode << 16) |223			      (instance_index & 0xffff));224		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);225	}226 227	vpu_write_reg(vpu_dev, W5_COMMAND, cmd);228 229	if (inst) {230		dev_dbg(vpu_dev->dev, "%s: cmd=0x%x (%s)\n", __func__, cmd,231			cmd_to_str(cmd, inst->type == VPU_INST_TYPE_DEC));232	} else {233		dev_dbg(vpu_dev->dev, "%s: cmd=0x%x\n", __func__, cmd);234	}235 236	vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1);237}238 239static int wave5_vpu_firmware_command_queue_error_check(struct vpu_device *dev, u32 *fail_res)240{241	u32 reason = 0;242 243	/* Check if we were able to add a command into the VCPU QUEUE */244	if (!vpu_read_reg(dev, W5_RET_SUCCESS)) {245		reason = vpu_read_reg(dev, W5_RET_FAIL_REASON);246		PRINT_REG_ERR(dev, reason);247 248		/*249		 * The fail_res argument will be either NULL or 0.250		 * If the fail_res argument is NULL, then just return -EIO.251		 * Otherwise, assign the reason to fail_res, so that the252		 * calling function can use it.253		 */254		if (fail_res)255			*fail_res = reason;256		else257			return -EIO;258 259		if (reason == WAVE5_SYSERR_VPU_STILL_RUNNING)260			return -EBUSY;261	}262	return 0;263}264 265static int send_firmware_command(struct vpu_instance *inst, u32 cmd, bool check_success,266				 u32 *queue_status, u32 *fail_result)267{268	int ret;269 270	wave5_bit_issue_command(inst->dev, inst, cmd);271	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);272	if (ret) {273		dev_warn(inst->dev->dev, "%s: command: '%s', timed out\n", __func__,274			 cmd_to_str(cmd, inst->type == VPU_INST_TYPE_DEC));275		return -ETIMEDOUT;276	}277 278	if (queue_status)279		*queue_status = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);280 281	/* In some cases we want to send multiple commands before checking282	 * whether they are queued properly283	 */284	if (!check_success)285		return 0;286 287	return wave5_vpu_firmware_command_queue_error_check(inst->dev, fail_result);288}289 290static int wave5_send_query(struct vpu_device *vpu_dev, struct vpu_instance *inst,291			    enum query_opt query_opt)292{293	int ret;294 295	vpu_write_reg(vpu_dev, W5_QUERY_OPTION, query_opt);296	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);297	wave5_bit_issue_command(vpu_dev, inst, W5_QUERY);298 299	ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);300	if (ret) {301		dev_warn(vpu_dev->dev, "command: 'W5_QUERY', timed out opt=0x%x\n", query_opt);302		return ret;303	}304 305	return wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL);306}307 308static void setup_wave5_interrupts(struct vpu_device *vpu_dev)309{310	u32 reg_val = 0;311 312	if (vpu_dev->attr.support_encoders) {313		/* Encoder interrupt */314		reg_val |= BIT(INT_WAVE5_ENC_SET_PARAM);315		reg_val |= BIT(INT_WAVE5_ENC_PIC);316		reg_val |= BIT(INT_WAVE5_BSBUF_FULL);317	}318 319	if (vpu_dev->attr.support_decoders) {320		/* Decoder interrupt */321		reg_val |= BIT(INT_WAVE5_INIT_SEQ);322		reg_val |= BIT(INT_WAVE5_DEC_PIC);323		reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);324	}325 326	return vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);327}328 329static int setup_wave5_properties(struct device *dev)330{331	struct vpu_device *vpu_dev = dev_get_drvdata(dev);332	struct vpu_attr *p_attr = &vpu_dev->attr;333	u32 reg_val;334	u8 *str;335	int ret;336	u32 hw_config_def0, hw_config_def1, hw_config_feature;337 338	ret = wave5_send_query(vpu_dev, NULL, GET_VPU_INFO);339	if (ret)340		return ret;341 342	reg_val = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_NAME);343	str = (u8 *)&reg_val;344	p_attr->product_name[0] = str[3];345	p_attr->product_name[1] = str[2];346	p_attr->product_name[2] = str[1];347	p_attr->product_name[3] = str[0];348	p_attr->product_name[4] = 0;349 350	p_attr->product_id = wave5_vpu_get_product_id(vpu_dev);351	p_attr->product_version = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_VERSION);352	p_attr->fw_version = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION);353	p_attr->customer_id = vpu_read_reg(vpu_dev, W5_RET_CUSTOMER_ID);354	hw_config_def0 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF0);355	hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);356	hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);357 358	if (vpu_dev->product_code == WAVE515_CODE) {359		p_attr->support_hevc10bit_dec = FIELD_GET(W515_FEATURE_HEVC10BIT_DEC,360							  hw_config_feature);361		p_attr->support_decoders = FIELD_GET(W515_FEATURE_HEVC_DECODER,362						     hw_config_def1) << STD_HEVC;363	} else {364		p_attr->support_hevc10bit_enc = FIELD_GET(W521_FEATURE_HEVC10BIT_ENC,365							  hw_config_feature);366		p_attr->support_avc10bit_enc = FIELD_GET(W521_FEATURE_AVC10BIT_ENC,367							 hw_config_feature);368 369		p_attr->support_decoders = FIELD_GET(W521_FEATURE_AVC_DECODER,370						     hw_config_def1) << STD_AVC;371		p_attr->support_decoders |= FIELD_GET(W521_FEATURE_HEVC_DECODER,372						      hw_config_def1) << STD_HEVC;373		p_attr->support_encoders = FIELD_GET(W521_FEATURE_AVC_ENCODER,374						     hw_config_def1) << STD_AVC;375		p_attr->support_encoders |= FIELD_GET(W521_FEATURE_HEVC_ENCODER,376						      hw_config_def1) << STD_HEVC;377 378		p_attr->support_backbone = FIELD_GET(W521_FEATURE_BACKBONE,379						     hw_config_def0);380		p_attr->support_vcpu_backbone = FIELD_GET(W521_FEATURE_VCPU_BACKBONE,381							  hw_config_def0);382		p_attr->support_vcore_backbone = FIELD_GET(W521_FEATURE_VCORE_BACKBONE,383							   hw_config_def0);384	}385 386	setup_wave5_interrupts(vpu_dev);387 388	return 0;389}390 391int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision)392{393	u32 reg_val;394	int ret;395 396	ret = wave5_send_query(vpu_dev, NULL, GET_VPU_INFO);397	if (ret)398		return ret;399 400	reg_val = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION);401	if (revision) {402		*revision = reg_val;403		return 0;404	}405 406	return -EINVAL;407}408 409static void remap_page(struct vpu_device *vpu_dev, dma_addr_t code_base, u32 index)410{411	vpu_write_reg(vpu_dev, W5_VPU_REMAP_CTRL, REMAP_CTRL_REGISTER_VALUE(index));412	vpu_write_reg(vpu_dev, W5_VPU_REMAP_VADDR, index * W5_REMAP_MAX_SIZE);413	vpu_write_reg(vpu_dev, W5_VPU_REMAP_PADDR, code_base + index * W5_REMAP_MAX_SIZE);414}415 416int wave5_vpu_init(struct device *dev, u8 *fw, size_t size)417{418	struct vpu_buf *common_vb;419	dma_addr_t code_base, temp_base;420	u32 code_size, temp_size;421	u32 i, reg_val, reason_code;422	int ret;423	struct vpu_device *vpu_dev = dev_get_drvdata(dev);424 425	common_vb = &vpu_dev->common_mem;426 427	code_base = common_vb->daddr;428 429	if (vpu_dev->product_code == WAVE515_CODE)430		code_size = WAVE515_MAX_CODE_BUF_SIZE;431	else432		code_size = WAVE521_MAX_CODE_BUF_SIZE;433 434	/* ALIGN TO 4KB */435	code_size &= ~0xfff;436	if (code_size < size * 2)437		return -EINVAL;438 439	temp_base = code_base + code_size;440	temp_size = WAVE5_TEMPBUF_SIZE;441 442	ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size);443	if (ret < 0) {444		dev_err(vpu_dev->dev, "VPU init, Writing firmware to common buffer, fail: %d\n",445			ret);446		return ret;447	}448 449	vpu_write_reg(vpu_dev, W5_PO_CONF, 0);450 451	/* clear registers */452 453	for (i = W5_CMD_REG_BASE; i < W5_CMD_REG_END; i += 4)454		vpu_write_reg(vpu_dev, i, 0x00);455 456	remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);457	remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);458 459	vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);460	vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);461	vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);462	vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base);463	vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size);464 465	/* These register must be reset explicitly */466	vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);467 468	if (vpu_dev->product_code != WAVE515_CODE) {469		wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);470		wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);471		vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);472	}473 474	reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);475	if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {476		reg_val = ((WAVE5_PROC_AXI_ID << 28) |477			   (WAVE5_PRP_AXI_ID << 24) |478			   (WAVE5_FBD_Y_AXI_ID << 20) |479			   (WAVE5_FBC_Y_AXI_ID << 16) |480			   (WAVE5_FBD_C_AXI_ID << 12) |481			   (WAVE5_FBC_C_AXI_ID << 8) |482			   (WAVE5_PRI_AXI_ID << 4) |483			   WAVE5_SEC_AXI_ID);484		wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);485	}486 487	if (vpu_dev->product_code == WAVE515_CODE) {488		dma_addr_t task_buf_base;489 490		vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF, WAVE515_COMMAND_QUEUE_DEPTH);491		vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE, WAVE515_ONE_TASKBUF_SIZE);492 493		for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {494			task_buf_base = temp_base + temp_size +495					(i * WAVE515_ONE_TASKBUF_SIZE);496			vpu_write_reg(vpu_dev,497				      W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),498				      task_buf_base);499		}500 501		vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);502		vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);503	}504 505	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);506	vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);507	vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);508	ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);509	if (ret) {510		dev_err(vpu_dev->dev, "VPU init(W5_VPU_REMAP_CORE_START) timeout\n");511		return ret;512	}513 514	ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code);515	if (ret)516		return ret;517 518	return setup_wave5_properties(dev);519}520 521int wave5_vpu_build_up_dec_param(struct vpu_instance *inst,522				 struct dec_open_param *param)523{524	int ret;525	struct dec_info *p_dec_info = &inst->codec_info->dec_info;526	struct vpu_device *vpu_dev = inst->dev;527 528	p_dec_info->cycle_per_tick = 256;529	if (vpu_dev->sram_buf.size) {530		p_dec_info->sec_axi_info.use_bit_enable = 1;531		p_dec_info->sec_axi_info.use_ip_enable = 1;532		p_dec_info->sec_axi_info.use_lf_row_enable = 1;533	}534	switch (inst->std) {535	case W_HEVC_DEC:536		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_HEVC;537		break;538	case W_AVC_DEC:539		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_AVC;540		break;541	default:542		return -EINVAL;543	}544 545	if (vpu_dev->product == PRODUCT_ID_515)546		p_dec_info->vb_work.size = WAVE515DEC_WORKBUF_SIZE;547	else548		p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;549 550	ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work);551	if (ret)552		return ret;553 554	if (inst->dev->product_code != WAVE515_CODE)555		vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);556 557	wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);558 559	vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr);560	vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);561 562	if (inst->dev->product_code != WAVE515_CODE) {563		vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);564		vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);565	}566 567	vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr);568	vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size);569 570	/* NOTE: SDMA reads MSB first */571	vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, BITSTREAM_ENDIANNESS_BIG_ENDIAN);572 573	if (inst->dev->product_code != WAVE515_CODE) {574		/* This register must be reset explicitly */575		vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);576		vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1,577			      WAVE521_COMMAND_QUEUE_DEPTH - 1);578	}579 580	ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);581	if (ret) {582		wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work);583		return ret;584	}585 586	p_dec_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER);587 588	return 0;589}590 591int wave5_vpu_hw_flush_instance(struct vpu_instance *inst)592{593	struct dec_info *p_dec_info = &inst->codec_info->dec_info;594	u32 instance_queue_count, report_queue_count;595	u32 reg_val = 0;596	u32 fail_res = 0;597	int ret;598 599	ret = send_firmware_command(inst, W5_FLUSH_INSTANCE, true, &reg_val, &fail_res);600	if (ret)601		return ret;602 603	instance_queue_count = (reg_val >> 16) & 0xff;604	report_queue_count = (reg_val & QUEUE_REPORT_MASK);605	if (instance_queue_count != 0 || report_queue_count != 0) {606		dev_warn(inst->dev->dev,607			 "FLUSH_INSTANCE cmd didn't reset the amount of queued commands & reports");608	}609 610	/* reset our local copy of the counts */611	p_dec_info->instance_queue_count = 0;612	p_dec_info->report_queue_count = 0;613 614	return 0;615}616 617static u32 get_bitstream_options(struct dec_info *info)618{619	u32 bs_option = BSOPTION_ENABLE_EXPLICIT_END;620 621	if (info->stream_endflag)622		bs_option |= BSOPTION_HIGHLIGHT_STREAM_END;623	return bs_option;624}625 626int wave5_vpu_dec_init_seq(struct vpu_instance *inst)627{628	struct dec_info *p_dec_info = &inst->codec_info->dec_info;629	u32 bs_option, cmd_option = INIT_SEQ_NORMAL;630	u32 reg_val, fail_res;631	int ret;632 633	if (!inst->codec_info)634		return -EINVAL;635 636	vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);637	vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);638 639	bs_option = get_bitstream_options(p_dec_info);640 641	/* Without RD_PTR_VALID_FLAG Wave515 ignores RD_PTR value */642	if (inst->dev->product_code == WAVE515_CODE)643		bs_option |= BSOPTION_RD_PTR_VALID_FLAG;644 645	vpu_write_reg(inst->dev, W5_BS_OPTION, bs_option);646 647	vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);648	vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);649 650	ret = send_firmware_command(inst, W5_INIT_SEQ, true, &reg_val, &fail_res);651	if (ret)652		return ret;653 654	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;655	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);656 657	dev_dbg(inst->dev->dev, "%s: init seq sent (queue %u : %u)\n", __func__,658		p_dec_info->instance_queue_count, p_dec_info->report_queue_count);659 660	return 0;661}662 663static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initial_info *info)664{665	u32 reg_val;666	u32 profile_compatibility_flag;667	struct dec_info *p_dec_info = &inst->codec_info->dec_info;668 669	p_dec_info->stream_rd_ptr = wave5_dec_get_rd_ptr(inst);670	info->rd_ptr = p_dec_info->stream_rd_ptr;671 672	p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC);673 674	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE);675	info->pic_width = ((reg_val >> 16) & 0xffff);676	info->pic_height = (reg_val & 0xffff);677	info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REQUIRED_FB);678 679	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_LEFT_RIGHT);680	info->pic_crop_rect.left = (reg_val >> 16) & 0xffff;681	info->pic_crop_rect.right = reg_val & 0xffff;682	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_TOP_BOTTOM);683	info->pic_crop_rect.top = (reg_val >> 16) & 0xffff;684	info->pic_crop_rect.bottom = reg_val & 0xffff;685 686	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_COLOR_SAMPLE_INFO);687	info->luma_bitdepth = reg_val & 0xf;688	info->chroma_bitdepth = (reg_val >> 4) & 0xf;689 690	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_SEQ_PARAM);691	profile_compatibility_flag = (reg_val >> 12) & 0xff;692	info->profile = (reg_val >> 24) & 0x1f;693 694	if (inst->std == W_HEVC_DEC) {695		/* guessing profile */696		if (!info->profile) {697			if ((profile_compatibility_flag & 0x06) == 0x06)698				info->profile = HEVC_PROFILE_MAIN; /* main profile */699			else if (profile_compatibility_flag & 0x04)700				info->profile = HEVC_PROFILE_MAIN10; /* main10 profile */701			else if (profile_compatibility_flag & 0x08)702				/* main still picture profile */703				info->profile = HEVC_PROFILE_STILLPICTURE;704			else705				info->profile = HEVC_PROFILE_MAIN; /* for old version HM */706		}707	} else if (inst->std == W_AVC_DEC) {708		info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val);709	}710 711	if (inst->dev->product_code != WAVE515_CODE) {712		info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);713		info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);714		p_dec_info->vlc_buf_size = info->vlc_buf_size;715		p_dec_info->param_buf_size = info->param_buf_size;716	}717}718 719int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info)720{721	int ret;722	u32 reg_val;723	struct dec_info *p_dec_info = &inst->codec_info->dec_info;724 725	vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr);726	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size);727	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM, REPORT_PARAM_ENDIANNESS_BIG_ENDIAN);728 729	/* send QUERY cmd */730	ret = wave5_send_query(inst->dev, inst, GET_RESULT);731	if (ret)732		return ret;733 734	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);735 736	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;737	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);738 739	dev_dbg(inst->dev->dev, "%s: init seq complete (queue %u : %u)\n", __func__,740		p_dec_info->instance_queue_count, p_dec_info->report_queue_count);741 742	/* this is not a fatal error, set ret to -EIO but don't return immediately */743	if (vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_SUCCESS) != 1) {744		info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_DEC_ERR_INFO);745		ret = -EIO;746	}747 748	wave5_get_dec_seq_result(inst, info);749 750	return ret;751}752 753int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_buffer *fb_arr,754				       enum tiled_map_type map_type, unsigned int count)755{756	int ret;757	struct dec_info *p_dec_info = &inst->codec_info->dec_info;758	struct dec_initial_info *init_info = &p_dec_info->initial_info;759	size_t remain, idx, j, i, cnt_8_chunk, size;760	u32 start_no, end_no;761	u32 reg_val, cbcr_interleave, nv21, pic_size;762	u32 addr_y, addr_cb, addr_cr;763	u32 mv_col_size, frame_width, frame_height, fbc_y_tbl_size, fbc_c_tbl_size;764	struct vpu_buf vb_buf;765	bool justified = WTL_RIGHT_JUSTIFIED;766	u32 format_no = WTL_PIXEL_8BIT;767	u32 color_format = 0;768	u32 pixel_order = 1;769	u32 bwb_flag = (map_type == LINEAR_FRAME_MAP) ? 1 : 0;770 771	cbcr_interleave = inst->cbcr_interleave;772	nv21 = inst->nv21;773	mv_col_size = 0;774	fbc_y_tbl_size = 0;775	fbc_c_tbl_size = 0;776 777	if (map_type >= COMPRESSED_FRAME_MAP) {778		cbcr_interleave = 0;779		nv21 = 0;780 781		switch (inst->std) {782		case W_HEVC_DEC:783			mv_col_size = WAVE5_DEC_HEVC_BUF_SIZE(init_info->pic_width,784							      init_info->pic_height);785			break;786		case W_AVC_DEC:787			mv_col_size = WAVE5_DEC_AVC_BUF_SIZE(init_info->pic_width,788							     init_info->pic_height);789			break;790		default:791			return -EINVAL;792		}793 794		if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC) {795			size = ALIGN(ALIGN(mv_col_size, 16), BUFFER_MARGIN) + BUFFER_MARGIN;796			ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_mv, count, size);797			if (ret)798				goto free_mv_buffers;799		}800 801		frame_width = init_info->pic_width;802		frame_height = init_info->pic_height;803		fbc_y_tbl_size = ALIGN(WAVE5_FBC_LUMA_TABLE_SIZE(frame_width, frame_height), 16);804		fbc_c_tbl_size = ALIGN(WAVE5_FBC_CHROMA_TABLE_SIZE(frame_width, frame_height), 16);805 806		size = ALIGN(fbc_y_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN;807		ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_fbc_y_tbl, count, size);808		if (ret)809			goto free_fbc_y_tbl_buffers;810 811		size = ALIGN(fbc_c_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN;812		ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_fbc_c_tbl, count, size);813		if (ret)814			goto free_fbc_c_tbl_buffers;815 816		pic_size = (init_info->pic_width << 16) | (init_info->pic_height);817 818		if (inst->dev->product_code != WAVE515_CODE) {819			vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +820				(p_dec_info->param_buf_size * WAVE521_COMMAND_QUEUE_DEPTH);821			vb_buf.daddr = 0;822 823			if (vb_buf.size != p_dec_info->vb_task.size) {824				wave5_vdi_free_dma_memory(inst->dev,825							  &p_dec_info->vb_task);826				ret = wave5_vdi_allocate_dma_memory(inst->dev,827								    &vb_buf);828				if (ret)829					goto free_fbc_c_tbl_buffers;830 831				p_dec_info->vb_task = vb_buf;832			}833 834			vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,835				      p_dec_info->vb_task.daddr);836			vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE,837				      vb_buf.size);838		}839	} else {840		pic_size = (init_info->pic_width << 16) | (init_info->pic_height);841 842		if (inst->output_format == FORMAT_422)843			color_format = 1;844	}845	vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size);846 847	reg_val = (bwb_flag << 28) |848		  (pixel_order << 23) |849		  (justified << 22) |850		  (format_no << 20) |851		  (color_format << 19) |852		  (nv21 << 17) |853		  (cbcr_interleave << 16) |854		  (fb_arr[0].stride);855	vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val);856 857	remain = count;858	cnt_8_chunk = DIV_ROUND_UP(count, 8);859	idx = 0;860	for (j = 0; j < cnt_8_chunk; j++) {861		reg_val = (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3);862		vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val);863		start_no = j * 8;864		end_no = start_no + ((remain >= 8) ? 8 : remain) - 1;865 866		vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no);867 868		for (i = 0; i < 8 && i < remain; i++) {869			addr_y = fb_arr[i + start_no].buf_y;870			addr_cb = fb_arr[i + start_no].buf_cb;871			addr_cr = fb_arr[i + start_no].buf_cr;872			vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), addr_y);873			vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4), addr_cb);874			if (map_type >= COMPRESSED_FRAME_MAP) {875				/* luma FBC offset table */876				vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4),877					      p_dec_info->vb_fbc_y_tbl[idx].daddr);878				/* chroma FBC offset table */879				vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4),880					      p_dec_info->vb_fbc_c_tbl[idx].daddr);881				vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2),882					      p_dec_info->vb_mv[idx].daddr);883			} else {884				vpu_write_reg(inst->dev, W5_ADDR_CR_BASE0 + (i << 4), addr_cr);885				vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4), 0);886				vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2), 0);887			}888			idx++;889		}890		remain -= i;891 892		ret = send_firmware_command(inst, W5_SET_FB, false, NULL, NULL);893		if (ret)894			goto free_buffers;895	}896 897	reg_val = vpu_read_reg(inst->dev, W5_RET_SUCCESS);898	if (!reg_val) {899		ret = -EIO;900		goto free_buffers;901	}902 903	return 0;904 905free_buffers:906	wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);907free_fbc_c_tbl_buffers:908	for (i = 0; i < count; i++)909		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[i]);910free_fbc_y_tbl_buffers:911	for (i = 0; i < count; i++)912		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[i]);913free_mv_buffers:914	for (i = 0; i < count; i++)915		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[i]);916	return ret;917}918 919static u32 wave5_vpu_dec_validate_sec_axi(struct vpu_instance *inst)920{921	u32 bitdepth = inst->codec_info->dec_info.initial_info.luma_bitdepth;922	struct dec_info *p_dec_info = &inst->codec_info->dec_info;923	u32 bit_size = 0, ip_size = 0, lf_size = 0, ret = 0;924	u32 sram_size = inst->dev->sram_size;925	u32 width = inst->src_fmt.width;926 927	if (!sram_size)928		return 0;929 930	/*931	 * TODO: calculate bit_size, ip_size, lf_size from width and bitdepth932	 * for Wave521.933	 */934	if (inst->dev->product_code == WAVE515_CODE) {935		bit_size = DIV_ROUND_UP(width, 16) * 5 * 8;936		ip_size = ALIGN(width, 16) * 2 * bitdepth / 8;937		lf_size = ALIGN(width, 16) * 10 * bitdepth / 8;938	}939 940	if (p_dec_info->sec_axi_info.use_bit_enable && sram_size >= bit_size) {941		ret |= BIT(0);942		sram_size -= bit_size;943	}944 945	if (p_dec_info->sec_axi_info.use_ip_enable && sram_size >= ip_size) {946		ret |= BIT(9);947		sram_size -= ip_size;948	}949 950	if (p_dec_info->sec_axi_info.use_lf_row_enable && sram_size >= lf_size)951		ret |= BIT(15);952 953	return ret;954}955 956int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res)957{958	u32 reg_val;959	struct dec_info *p_dec_info = &inst->codec_info->dec_info;960	int ret;961 962	vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);963	vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);964 965	vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));966 967	/* secondary AXI */968	reg_val = wave5_vpu_dec_validate_sec_axi(inst);969	vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val);970 971	/* set attributes of user buffer */972	vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);973 974	vpu_write_reg(inst->dev, W5_COMMAND_OPTION, DEC_PIC_NORMAL);975	vpu_write_reg(inst->dev, W5_CMD_DEC_TEMPORAL_ID_PLUS1,976		      (p_dec_info->target_spatial_id << 9) |977		      (p_dec_info->temp_id_select_mode << 8) | p_dec_info->target_temp_id);978	vpu_write_reg(inst->dev, W5_CMD_SEQ_CHANGE_ENABLE_FLAG, p_dec_info->seq_change_mask);979	/* When reordering is disabled we force the latency of the framebuffers */980	vpu_write_reg(inst->dev, W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1, !p_dec_info->reorder_enable);981 982	ret = send_firmware_command(inst, W5_DEC_ENC_PIC, true, &reg_val, fail_res);983	if (ret == -ETIMEDOUT)984		return ret;985 986	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;987	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);988 989	dev_dbg(inst->dev->dev, "%s: dec pic sent (queue %u : %u)\n", __func__,990		p_dec_info->instance_queue_count, p_dec_info->report_queue_count);991 992	if (ret)993		return ret;994 995	return 0;996}997 998int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result)999{1000	int ret;1001	u32 index, nal_unit_type, reg_val, sub_layer_info;1002	struct dec_info *p_dec_info = &inst->codec_info->dec_info;1003	struct vpu_device *vpu_dev = inst->dev;1004 1005	vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr);1006	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size);1007	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM, REPORT_PARAM_ENDIANNESS_BIG_ENDIAN);1008 1009	/* send QUERY cmd */1010	ret = wave5_send_query(vpu_dev, inst, GET_RESULT);1011	if (ret)1012		return ret;1013 1014	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);1015 1016	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;1017	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);1018 1019	dev_dbg(inst->dev->dev, "%s: dec pic complete (queue %u : %u)\n", __func__,1020		p_dec_info->instance_queue_count, p_dec_info->report_queue_count);1021 1022	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_TYPE);1023 1024	nal_unit_type = (reg_val >> 4) & 0x3f;1025 1026	if (inst->std == W_HEVC_DEC) {1027		if (reg_val & 0x04)1028			result->pic_type = PIC_TYPE_B;1029		else if (reg_val & 0x02)1030			result->pic_type = PIC_TYPE_P;1031		else if (reg_val & 0x01)1032			result->pic_type = PIC_TYPE_I;1033		else1034			result->pic_type = PIC_TYPE_MAX;1035		if ((nal_unit_type == 19 || nal_unit_type == 20) && result->pic_type == PIC_TYPE_I)1036			/* IDR_W_RADL, IDR_N_LP */1037			result->pic_type = PIC_TYPE_IDR;1038	} else if (inst->std == W_AVC_DEC) {1039		if (reg_val & 0x04)1040			result->pic_type = PIC_TYPE_B;1041		else if (reg_val & 0x02)1042			result->pic_type = PIC_TYPE_P;1043		else if (reg_val & 0x01)1044			result->pic_type = PIC_TYPE_I;1045		else1046			result->pic_type = PIC_TYPE_MAX;1047		if (nal_unit_type == 5 && result->pic_type == PIC_TYPE_I)1048			result->pic_type = PIC_TYPE_IDR;1049	}1050	index = vpu_read_reg(inst->dev, W5_RET_DEC_DISPLAY_INDEX);1051	result->index_frame_display = index;1052	index = vpu_read_reg(inst->dev, W5_RET_DEC_DECODED_INDEX);1053	result->index_frame_decoded = index;1054	result->index_frame_decoded_for_tiled = index;1055 1056	sub_layer_info = vpu_read_reg(inst->dev, W5_RET_DEC_SUB_LAYER_INFO);1057	result->temporal_id = sub_layer_info & 0x7;1058 1059	if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC) {1060		result->decoded_poc = -1;1061		if (result->index_frame_decoded >= 0 ||1062		    result->index_frame_decoded == DECODED_IDX_FLAG_SKIP)1063			result->decoded_poc = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC);1064	}1065 1066	result->sequence_changed = vpu_read_reg(inst->dev, W5_RET_DEC_NOTIFICATION);1067	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE);1068	result->dec_pic_width = reg_val >> 16;1069	result->dec_pic_height = reg_val & 0xffff;1070 1071	if (result->sequence_changed) {1072		memcpy((void *)&p_dec_info->new_seq_info, (void *)&p_dec_info->initial_info,1073		       sizeof(struct dec_initial_info));1074		wave5_get_dec_seq_result(inst, &p_dec_info->new_seq_info);1075	}1076 1077	result->dec_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_DEC_HOST_CMD_TICK);1078	result->dec_decode_end_tick = vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_ENC_TICK);1079 1080	if (!p_dec_info->first_cycle_check) {1081		result->frame_cycle =1082			(result->dec_decode_end_tick - result->dec_host_cmd_tick) *1083			p_dec_info->cycle_per_tick;1084		vpu_dev->last_performance_cycles = result->dec_decode_end_tick;1085		p_dec_info->first_cycle_check = true;1086	} else if (result->index_frame_decoded_for_tiled != -1) {1087		result->frame_cycle =1088			(result->dec_decode_end_tick - vpu_dev->last_performance_cycles) *1089			p_dec_info->cycle_per_tick;1090		vpu_dev->last_performance_cycles = result->dec_decode_end_tick;1091		if (vpu_dev->last_performance_cycles < result->dec_host_cmd_tick)1092			result->frame_cycle =1093				(result->dec_decode_end_tick - result->dec_host_cmd_tick) *1094				p_dec_info->cycle_per_tick;1095	}1096 1097	/* no remaining command. reset frame cycle. */1098	if (p_dec_info->instance_queue_count == 0 && p_dec_info->report_queue_count == 0)1099		p_dec_info->first_cycle_check = false;1100 1101	return 0;1102}1103 1104int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size)1105{1106	struct vpu_buf *common_vb;1107	dma_addr_t code_base, temp_base;1108	dma_addr_t old_code_base, temp_size;1109	u32 code_size, reason_code;1110	u32 reg_val;1111	struct vpu_device *vpu_dev = dev_get_drvdata(dev);1112 1113	common_vb = &vpu_dev->common_mem;1114 1115	code_base = common_vb->daddr;1116 1117	if (vpu_dev->product_code == WAVE515_CODE)1118		code_size = WAVE515_MAX_CODE_BUF_SIZE;1119	else1120		code_size = WAVE521_MAX_CODE_BUF_SIZE;1121 1122	/* ALIGN TO 4KB */1123	code_size &= ~0xfff;1124	if (code_size < size * 2)1125		return -EINVAL;1126 1127	temp_base = code_base + code_size;1128	temp_size = WAVE5_TEMPBUF_SIZE;1129 1130	old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR);1131 1132	if (old_code_base != code_base + W5_REMAP_INDEX1 * W5_REMAP_MAX_SIZE) {1133		int ret;1134 1135		ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size);1136		if (ret < 0) {1137			dev_err(vpu_dev->dev,1138				"VPU init, Writing firmware to common buffer, fail: %d\n", ret);1139			return ret;1140		}1141 1142		vpu_write_reg(vpu_dev, W5_PO_CONF, 0);1143 1144		ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT);1145		if (ret < 0) {1146			dev_err(vpu_dev->dev, "VPU init, Resetting the VPU, fail: %d\n", ret);1147			return ret;1148		}1149 1150		remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);1151		remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);1152 1153		vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);1154		vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);1155		vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);1156		vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base);1157		vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size);1158 1159		/* These register must be reset explicitly */1160		vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);1161 1162		if (vpu_dev->product_code != WAVE515_CODE) {1163			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);1164			wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);1165			vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);1166		}1167 1168		reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);1169		if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {1170			reg_val = ((WAVE5_PROC_AXI_ID << 28) |1171					(WAVE5_PRP_AXI_ID << 24) |1172					(WAVE5_FBD_Y_AXI_ID << 20) |1173					(WAVE5_FBC_Y_AXI_ID << 16) |1174					(WAVE5_FBD_C_AXI_ID << 12) |1175					(WAVE5_FBC_C_AXI_ID << 8) |1176					(WAVE5_PRI_AXI_ID << 4) |1177					WAVE5_SEC_AXI_ID);1178			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);1179		}1180 1181		if (vpu_dev->product_code == WAVE515_CODE) {1182			dma_addr_t task_buf_base;1183			u32 i;1184 1185			vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,1186				      WAVE515_COMMAND_QUEUE_DEPTH);1187			vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,1188				      WAVE515_ONE_TASKBUF_SIZE);1189 1190			for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {1191				task_buf_base = temp_base + temp_size +1192						(i * WAVE515_ONE_TASKBUF_SIZE);1193				vpu_write_reg(vpu_dev,1194					      W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),1195					      task_buf_base);1196			}1197 1198			vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,1199				      vpu_dev->sram_buf.daddr);1200			vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,1201				      vpu_dev->sram_buf.size);1202		}1203 1204		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);1205		vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);1206		vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);1207 1208		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);1209		if (ret) {1210			dev_err(vpu_dev->dev, "VPU reinit(W5_VPU_REMAP_CORE_START) timeout\n");1211			return ret;1212		}1213 1214		ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code);1215		if (ret)1216			return ret;1217	}1218 1219	return setup_wave5_properties(dev);1220}1221 1222static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,1223				size_t size)1224{1225	u32 reg_val;1226	struct vpu_buf *common_vb;1227	dma_addr_t code_base, temp_base;1228	u32 code_size, temp_size, reason_code;1229	struct vpu_device *vpu_dev = dev_get_drvdata(dev);1230	int ret;1231 1232	if (i_sleep_wake) {1233		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);1234		if (ret)1235			return ret;1236 1237		/*1238		 * Declare who has ownership for the host interface access1239		 * 1 = VPU1240		 * 0 = Host processor1241		 */1242		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);1243		vpu_write_reg(vpu_dev, W5_COMMAND, W5_SLEEP_VPU);1244		/* Send an interrupt named HOST to the VPU */1245		vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1);1246 1247		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);1248		if (ret)1249			return ret;1250 1251		ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code);1252		if (ret)1253			return ret;1254	} else { /* restore */1255		common_vb = &vpu_dev->common_mem;1256 1257		code_base = common_vb->daddr;1258 1259		if (vpu_dev->product_code == WAVE515_CODE)1260			code_size = WAVE515_MAX_CODE_BUF_SIZE;1261		else1262			code_size = WAVE521_MAX_CODE_BUF_SIZE;1263 1264		/* ALIGN TO 4KB */1265		code_size &= ~0xfff;1266		if (code_size < size * 2) {1267			dev_err(dev, "size too small\n");1268			return -EINVAL;1269		}1270 1271		temp_base = code_base + code_size;1272		temp_size = WAVE5_TEMPBUF_SIZE;1273 1274		/* Power on without DEBUG mode */1275		vpu_write_reg(vpu_dev, W5_PO_CONF, 0);1276 1277		remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);1278		remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);1279 1280		vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);1281		vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);1282		vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);1283 1284		/* These register must be reset explicitly */1285		vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);1286 1287		if (vpu_dev->product_code != WAVE515_CODE) {1288			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);1289			wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);1290			vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);1291		}1292 1293		setup_wave5_interrupts(vpu_dev);1294 1295		reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);1296		if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {1297			reg_val = ((WAVE5_PROC_AXI_ID << 28) |1298					(WAVE5_PRP_AXI_ID << 24) |1299					(WAVE5_FBD_Y_AXI_ID << 20) |1300					(WAVE5_FBC_Y_AXI_ID << 16) |1301					(WAVE5_FBD_C_AXI_ID << 12) |1302					(WAVE5_FBC_C_AXI_ID << 8) |1303					(WAVE5_PRI_AXI_ID << 4) |1304					WAVE5_SEC_AXI_ID);1305			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);1306		}1307 1308		if (vpu_dev->product_code == WAVE515_CODE) {1309			dma_addr_t task_buf_base;1310			u32 i;1311 1312			vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,1313				      WAVE515_COMMAND_QUEUE_DEPTH);1314			vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,1315				      WAVE515_ONE_TASKBUF_SIZE);1316 1317			for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {1318				task_buf_base = temp_base + temp_size +1319						(i * WAVE515_ONE_TASKBUF_SIZE);1320				vpu_write_reg(vpu_dev,1321					      W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),1322					      task_buf_base);1323			}1324 1325			vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,1326				      vpu_dev->sram_buf.daddr);1327			vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,1328				      vpu_dev->sram_buf.size);1329		}1330 1331		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);1332		vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);1333		/* Start VPU after settings */1334		vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);1335 1336		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);1337		if (ret) {1338			dev_err(vpu_dev->dev, "VPU wakeup(W5_VPU_REMAP_CORE_START) timeout\n");1339			return ret;1340		}1341 1342		return wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code);1343	}1344 1345	return 0;1346}1347 1348int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode)1349{1350	u32 val = 0;1351	int ret = 0;1352	struct vpu_device *vpu_dev = dev_get_drvdata(dev);1353	struct vpu_attr *p_attr = &vpu_dev->attr;1354	/* VPU doesn't send response. force to set BUSY flag to 0. */1355	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 0);1356 1357	if (reset_mode == SW_RESET_SAFETY) {1358		ret = wave5_vpu_sleep_wake(dev, true, NULL, 0);1359		if (ret)1360			return ret;1361	}1362 1363	val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);1364	if ((val >> 16) & 0x1)1365		p_attr->support_backbone = true;1366	if ((val >> 22) & 0x1)1367		p_attr->support_vcore_backbone = true;1368	if ((val >> 28) & 0x1)1369		p_attr->support_vcpu_backbone = true;1370 1371	/* waiting for completion of bus transaction */1372	if (p_attr->support_backbone) {1373		dev_dbg(dev, "%s: backbone supported\n", __func__);1374 1375		if (p_attr->support_vcore_backbone) {1376			if (p_attr->support_vcpu_backbone) {1377				/* step1 : disable request */1378				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0xFF);1379 1380				/* step2 : waiting for completion of bus transaction */1381				ret = wave5_wait_vcpu_bus_busy(vpu_dev,1382							       W5_BACKBONE_BUS_STATUS_VCPU);1383				if (ret) {1384					wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00);1385					return ret;1386				}1387			}1388			/* step1 : disable request */1389			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x7);1390 1391			/* step2 : waiting for completion of bus transaction */1392			if (wave5_wait_bus_busy(vpu_dev, W5_BACKBONE_BUS_STATUS_VCORE0)) {1393				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);1394				return -EBUSY;1395			}1396		} else {1397			/* step1 : disable request */1398			wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x7);1399 1400			/* step2 : waiting for completion of bus transaction */1401			if (wave5_wait_bus_busy(vpu_dev, W5_COMBINED_BACKBONE_BUS_STATUS)) {1402				wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00);1403				return -EBUSY;1404			}1405		}1406	} else {1407		dev_dbg(dev, "%s: backbone NOT supported\n", __func__);1408		/* step1 : disable request */1409		wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x100);1410 1411		/* step2 : waiting for completion of bus transaction */1412		ret = wave5_wait_bus_busy(vpu_dev, W5_GDI_BUS_STATUS);1413		if (ret) {1414			wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00);1415			return ret;1416		}1417	}1418 1419	switch (reset_mode) {1420	case SW_RESET_ON_BOOT:1421	case SW_RESET_FORCE:1422	case SW_RESET_SAFETY:1423		val = W5_RST_BLOCK_ALL;1424		break;1425	default:1426		return -EINVAL;1427	}1428 1429	if (val) {1430		vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, val);1431 1432		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_RESET_STATUS);1433		if (ret) {1434			vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0);1435			return ret;1436		}1437		vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0);1438	}1439	/* step3 : must clear GDI_BUS_CTRL after done SW_RESET */1440	if (p_attr->support_backbone) {1441		if (p_attr->support_vcore_backbone) {1442			if (p_attr->support_vcpu_backbone)1443				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00);1444			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);1445		} else {1446			wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00);1447		}1448	} else {1449		wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00);1450	}1451	if (reset_mode == SW_RESET_SAFETY || reset_mode == SW_RESET_FORCE)1452		ret = wave5_vpu_sleep_wake(dev, false, NULL, 0);1453 1454	return ret;1455}1456 1457int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res)1458{1459	return send_firmware_command(inst, W5_DESTROY_INSTANCE, true, NULL, fail_res);1460}1461 1462int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos)1463{1464	struct dec_info *p_dec_info = &inst->codec_info->dec_info;1465 1466	p_dec_info->stream_endflag = eos ? 1 : 0;1467	vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));1468	vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);1469 1470	return send_firmware_command(inst, W5_UPDATE_BS, true, NULL, NULL);1471}1472 1473int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index)1474{1475	struct dec_info *p_dec_info = &inst->codec_info->dec_info;1476	int ret;1477 1478	vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, BIT(index));1479	vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, 0);1480 1481	ret = wave5_send_query(inst->dev, inst, UPDATE_DISP_FLAG);1482	if (ret)1483		return ret;1484 1485	p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC);1486 1487	return 0;1488}1489 1490int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index)1491{1492	int ret;1493 1494	vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, 0);1495	vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, BIT(index));1496 1497	ret = wave5_send_query(inst->dev, inst, UPDATE_DISP_FLAG);1498	if (ret)1499		return ret;1500 1501	return 0;1502}1503 1504int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags)1505{1506	u32 interrupt_reason;1507 1508	interrupt_reason = vpu_read_reg(inst->dev, W5_VPU_VINT_REASON_USR);1509	interrupt_reason &= ~flags;1510	vpu_write_reg(inst->dev, W5_VPU_VINT_REASON_USR, interrupt_reason);1511 1512	return 0;1513}1514 1515dma_addr_t wave5_dec_get_rd_ptr(struct vpu_instance *inst)1516{1517	int ret;1518 1519	ret = wave5_send_query(inst->dev, inst, GET_BS_RD_PTR);1520	if (ret)1521		return inst->codec_info->dec_info.stream_rd_ptr;1522 1523	return vpu_read_reg(inst->dev, W5_RET_QUERY_DEC_BS_RD_PTR);1524}1525 1526int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr)1527{1528	int ret;1529 1530	vpu_write_reg(inst->dev, W5_RET_QUERY_DEC_SET_BS_RD_PTR, addr);1531 1532	ret = wave5_send_query(inst->dev, inst, SET_BS_RD_PTR);1533 1534	return ret;1535}1536 1537/************************************************************************/1538/* ENCODER functions */1539/************************************************************************/1540 1541int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst,1542				 struct enc_open_param *open_param)1543{1544	int ret;1545	struct enc_info *p_enc_info = &inst->codec_info->enc_info;1546	u32 reg_val;1547	struct vpu_device *vpu_dev = dev_get_drvdata(dev);1548	dma_addr_t buffer_addr;1549	size_t buffer_size;1550 1551	p_enc_info->cycle_per_tick = 256;1552	if (vpu_dev->sram_buf.size) {1553		p_enc_info->sec_axi_info.use_enc_rdo_enable = 1;1554		p_enc_info->sec_axi_info.use_enc_lf_enable = 1;1555	}1556 1557	p_enc_info->vb_work.size = WAVE521ENC_WORKBUF_SIZE;1558	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &p_enc_info->vb_work);1559	if (ret) {1560		memset(&p_enc_info->vb_work, 0, sizeof(p_enc_info->vb_work));1561		return ret;1562	}1563 1564	wave5_vdi_clear_memory(vpu_dev, &p_enc_info->vb_work);1565 1566	vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_enc_info->vb_work.daddr);1567	vpu_write_reg(inst->dev, W5_WORK_SIZE, p_enc_info->vb_work.size);1568 1569	vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);1570	vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);1571 1572	reg_val = (open_param->line_buf_int_en << 6) | BITSTREAM_ENDIANNESS_BIG_ENDIAN;1573	vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val);1574	vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);1575	vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, WAVE521_COMMAND_QUEUE_DEPTH - 1);1576 1577	/* This register must be reset explicitly */1578	vpu_write_reg(inst->dev, W5_CMD_ENC_SRC_OPTIONS, 0);1579	vpu_write_reg(inst->dev, W5_CMD_ENC_VCORE_INFO, 1);1580 1581	ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);1582	if (ret)1583		goto free_vb_work;1584 1585	buffer_addr = open_param->bitstream_buffer;1586	buffer_size = open_param->bitstream_buffer_size;1587	p_enc_info->stream_rd_ptr = buffer_addr;1588	p_enc_info->stream_wr_ptr = buffer_addr;1589	p_enc_info->line_buf_int_en = open_param->line_buf_int_en;1590	p_enc_info->stream_buf_start_addr = buffer_addr;1591	p_enc_info->stream_buf_size = buffer_size;1592	p_enc_info->stream_buf_end_addr = buffer_addr + buffer_size;1593	p_enc_info->stride = 0;1594	p_enc_info->initial_info_obtained = false;1595	p_enc_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER);1596 1597	return 0;1598free_vb_work:1599	if (wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work))1600		memset(&p_enc_info->vb_work, 0, sizeof(p_enc_info->vb_work));1601	return ret;1602}1603 1604static void wave5_set_enc_crop_info(u32 codec, struct enc_wave_param *param, int rot_mode,1605				    int src_width, int src_height)1606{1607	int aligned_width = (codec == W_HEVC_ENC) ? ALIGN(src_width, 32) : ALIGN(src_width, 16);1608	int aligned_height = (codec == W_HEVC_ENC) ? ALIGN(src_height, 32) : ALIGN(src_height, 16);1609	int pad_right, pad_bot;1610	int crop_right, crop_left, crop_top, crop_bot;1611	int prp_mode = rot_mode >> 1; /* remove prp_enable bit */1612 1613	if (codec == W_HEVC_ENC &&1614	    (!rot_mode || prp_mode == 14)) /* prp_mode 14 : hor_mir && ver_mir && rot_180 */1615		return;1616 1617	pad_right = aligned_width - src_width;1618	pad_bot = aligned_height - src_height;1619 1620	if (param->conf_win_right > 0)1621		crop_right = param->conf_win_right + pad_right;1622	else1623		crop_right = pad_right;1624 1625	if (param->conf_win_bot > 0)1626		crop_bot = param->conf_win_bot + pad_bot;1627	else1628		crop_bot = pad_bot;1629 1630	crop_top = param->conf_win_top;1631	crop_left = param->conf_win_left;1632 1633	param->conf_win_top = crop_top;1634	param->conf_win_left = crop_left;1635	param->conf_win_bot = crop_bot;1636	param->conf_win_right = crop_right;1637 1638	switch (prp_mode) {1639	case 0:1640		return;1641	case 1:1642	case 15:1643		param->conf_win_top = crop_right;1644		param->conf_win_left = crop_top;1645		param->conf_win_bot = crop_left;1646		param->conf_win_right = crop_bot;1647		break;1648	case 2:1649	case 12:1650		param->conf_win_top = crop_bot;1651		param->conf_win_left = crop_right;1652		param->conf_win_bot = crop_top;1653		param->conf_win_right = crop_left;1654		break;1655	case 3:1656	case 13:1657		param->conf_win_top = crop_left;1658		param->conf_win_left = crop_bot;1659		param->conf_win_bot = crop_right;1660		param->conf_win_right = crop_top;1661		break;1662	case 4:1663	case 10:1664		param->conf_win_top = crop_bot;1665		param->conf_win_bot = crop_top;1666		break;1667	case 8:1668	case 6:1669		param->conf_win_left = crop_right;1670		param->conf_win_right = crop_left;1671		break;1672	case 5:1673	case 11:1674		param->conf_win_top = crop_left;1675		param->conf_win_left = crop_top;1676		param->conf_win_bot = crop_right;1677		param->conf_win_right = crop_bot;1678		break;1679	case 7:1680	case 9:1681		param->conf_win_top = crop_right;1682		param->conf_win_left = crop_bot;1683		param->conf_win_bot = crop_left;1684		param->conf_win_right = crop_top;1685		break;1686	default:1687		WARN(1, "Invalid prp_mode: %d, must be in range of 1 - 15\n", prp_mode);1688	}1689}1690 1691int wave5_vpu_enc_init_seq(struct vpu_instance *inst)1692{1693	u32 reg_val = 0, rot_mir_mode, fixed_cu_size_mode = 0x7;1694	struct enc_info *p_enc_info = &inst->codec_info->enc_info;1695	struct enc_open_param *p_open_param = &p_enc_info->open_param;1696	struct enc_wave_param *p_param = &p_open_param->wave_param;1697 1698	/*1699	 * OPT_COMMON:1700	 *	the last SET_PARAM command should be called with OPT_COMMON1701	 */1702	rot_mir_mode = 0;1703	if (p_enc_info->rotation_enable) {1704		switch (p_enc_info->rotation_angle) {1705		case 0:1706			rot_mir_mode |= NONE_ROTATE;1707			break;1708		case 90:1709			rot_mir_mode |= ROT_CLOCKWISE_90;1710			break;1711		case 180:1712			rot_mir_mode |= ROT_CLOCKWISE_180;1713			break;1714		case 270:1715			rot_mir_mode |= ROT_CLOCKWISE_270;1716			break;1717		}1718	}1719 1720	if (p_enc_info->mirror_enable) {1721		switch (p_enc_info->mirror_direction) {1722		case MIRDIR_NONE:1723			rot_mir_mode |= NONE_ROTATE;1724			break;1725		case MIRDIR_VER:1726			rot_mir_mode |= MIR_VER_FLIP;1727			break;1728		case MIRDIR_HOR:1729			rot_mir_mode |= MIR_HOR_FLIP;1730			break;1731		case MIRDIR_HOR_VER:1732			rot_mir_mode |= MIR_HOR_VER_FLIP;1733			break;1734		}1735	}1736 1737	wave5_set_enc_crop_info(inst->std, p_param, rot_mir_mode, p_open_param->pic_width,1738				p_open_param->pic_height);1739 1740	/* SET_PARAM + COMMON */1741	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SET_PARAM_OPTION, OPT_COMMON);1742	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SRC_SIZE, p_open_param->pic_height << 161743			| p_open_param->pic_width);1744	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN, VDI_LITTLE_ENDIAN);1745 1746	reg_val = p_param->profile |1747		(p_param->level << 3) |1748		(p_param->internal_bit_depth << 14);1749	if (inst->std == W_HEVC_ENC)1750		reg_val |= (p_param->tier << 12) |1751			(p_param->tmvp_enable << 23) |1752			(p_param->sao_enable << 24) |1753			(p_param->skip_intra_trans << 25) |1754			(p_param->strong_intra_smooth_enable << 27) |1755			(p_param->en_still_picture << 30);1756	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SPS_PARAM, reg_val);1757 1758	reg_val = (p_param->lossless_enable) |1759		(p_param->const_intra_pred_flag << 1) |1760		(p_param->lf_cross_slice_boundary_enable << 2) |1761		(p_param->wpp_enable << 4) |1762		(p_param->disable_deblk << 5) |1763		((p_param->beta_offset_div2 & 0xF) << 6) |1764		((p_param->tc_offset_div2 & 0xF) << 10) |1765		((p_param->chroma_cb_qp_offset & 0x1F) << 14) |1766		((p_param->chroma_cr_qp_offset & 0x1F) << 19) |1767		(p_param->transform8x8_enable << 29) |1768		(p_param->entropy_coding_mode << 30);1769	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_PPS_PARAM, reg_val);1770 1771	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_GOP_PARAM, p_param->gop_preset_idx);1772 1773	if (inst->std == W_AVC_ENC)1774		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM, p_param->intra_qp |1775				((p_param->intra_period & 0x7ff) << 6) |1776				((p_param->avc_idr_period & 0x7ff) << 17));1777	else if (inst->std == W_HEVC_ENC)1778		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM,1779			      p_param->decoding_refresh_type | (p_param->intra_qp << 3) |1780				(p_param->intra_period << 16));1781 1782	reg_val = (p_param->rdo_skip << 2) |1783		(p_param->lambda_scaling_enable << 3) |1784		(fixed_cu_size_mode << 5) |1785		(p_param->intra_nx_n_enable << 8) |1786		(p_param->max_num_merge << 18);1787 1788	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RDO_PARAM, reg_val);1789 1790	if (inst->std == W_AVC_ENC)1791		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH,1792			      p_param->intra_mb_refresh_arg << 16 | p_param->intra_mb_refresh_mode);1793	else if (inst->std == W_HEVC_ENC)1794		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH,1795			      p_param->intra_refresh_arg << 16 | p_param->intra_refresh_mode);1796 1797	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_FRAME_RATE, p_open_param->frame_rate_info);1798	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_TARGET_RATE, p_open_param->bit_rate);1799 1800	reg_val = p_open_param->rc_enable |1801		(p_param->hvs_qp_enable << 2) |1802		(p_param->hvs_qp_scale << 4) |1803		((p_param->initial_rc_qp & 0x3F) << 14) |1804		(p_open_param->vbv_buffer_size << 20);1805	if (inst->std == W_AVC_ENC)1806		reg_val |= (p_param->mb_level_rc_enable << 1);1807	else if (inst->std == W_HEVC_ENC)1808		reg_val |= (p_param->cu_level_rc_enable << 1);1809	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_PARAM, reg_val);1810 1811	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM,1812		      p_param->rc_weight_buf << 8 | p_param->rc_weight_param);1813 1814	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_MIN_MAX_QP, p_param->min_qp_i |1815		      (p_param->max_qp_i << 6) | (p_param->hvs_max_delta_qp << 12));1816 1817	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP, p_param->min_qp_p |1818		      (p_param->max_qp_p << 6) | (p_param->min_qp_b << 12) |1819		      (p_param->max_qp_b << 18));1820 1821	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3, 0);1822	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7, 0);1823	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_ROT_PARAM, rot_mir_mode);1824 1825	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_BG_PARAM, 0);1826	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR, 0);1827	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT,1828		      p_param->conf_win_bot << 16 | p_param->conf_win_top);1829	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT,1830		      p_param->conf_win_right << 16 | p_param->conf_win_left);1831 1832	if (inst->std == W_AVC_ENC)1833		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE,1834			      p_param->avc_slice_arg << 16 | p_param->avc_slice_mode);1835	else if (inst->std == W_HEVC_ENC)1836		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE,1837			      p_param->independ_slice_mode_arg << 16 |1838			      p_param->independ_slice_mode);1839 1840	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR, 0);1841	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK, 0);1842	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_TIME_SCALE, 0);1843	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE, 0);1844 1845	if (inst->std == W_HEVC_ENC) {1846		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU04, 0);1847		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU08, 0);1848		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU16, 0);1849		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU32, 0);1850		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU08, 0);1851		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU16, 0);1852		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU32, 0);1853		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_DEPENDENT_SLICE,1854			      p_param->depend_slice_mode_arg << 16 | p_param->depend_slice_mode);1855 1856		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_PARAM, 0);1857 1858		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_WEIGHT,1859			      p_param->nr_intra_weight_y |1860			      (p_param->nr_intra_weight_cb << 5) |1861			      (p_param->nr_intra_weight_cr << 10) |1862			      (p_param->nr_inter_weight_y << 15) |1863			      (p_param->nr_inter_weight_cb << 20) |1864			      (p_param->nr_inter_weight_cr << 25));1865	}1866	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_VUI_HRD_PARAM, 0);1867 1868	return send_firmware_command(inst, W5_ENC_SET_PARAM, true, NULL, NULL);1869}1870 1871int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info)1872{1873	int ret;1874	u32 reg_val;1875	struct enc_info *p_enc_info = &inst->codec_info->enc_info;1876 1877	/* send QUERY cmd */1878	ret = wave5_send_query(inst->dev, inst, GET_RESULT);1879	if (ret)1880		return ret;1881 1882	dev_dbg(inst->dev->dev, "%s: init seq\n", __func__);1883 1884	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);1885 1886	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;1887	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);1888 1889	if (vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS) != 1) {1890		info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO);1891		ret = -EIO;1892	} else {1893		info->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO);1894	}1895 1896	info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_ENC_NUM_REQUIRED_FB);1897	info->min_src_frame_count = vpu_read_reg(inst->dev, W5_RET_ENC_MIN_SRC_BUF_NUM);1898	info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);1899	info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);1900	p_enc_info->vlc_buf_size = info->vlc_buf_size;1901	p_enc_info->param_buf_size = info->param_buf_size;1902 1903	return ret;1904}1905 1906static u32 calculate_luma_stride(u32 width, u32 bit_depth)1907{1908	return ALIGN(ALIGN(width, 16) * ((bit_depth > 8) ? 5 : 4), 32);1909}1910 1911static u32 calculate_chroma_stride(u32 width, u32 bit_depth)1912{1913	return ALIGN(ALIGN(width / 2, 16) * ((bit_depth > 8) ? 5 : 4), 32);1914}1915 1916int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst,1917				       struct frame_buffer *fb_arr, enum tiled_map_type map_type,1918				       unsigned int count)1919{1920	struct vpu_device *vpu_dev = dev_get_drvdata(dev);1921	int ret = 0;1922	u32 stride;1923	u32 start_no, end_no;1924	size_t remain, idx, j, i, cnt_8_chunk;1925	u32 reg_val = 0, pic_size = 0, mv_col_size, fbc_y_tbl_size, fbc_c_tbl_size;1926	u32 sub_sampled_size = 0;1927	u32 luma_stride, chroma_stride;1928	u32 buf_height = 0, buf_width = 0;1929	u32 bit_depth;1930	bool avc_encoding = (inst->std == W_AVC_ENC);1931	struct vpu_buf vb_mv = {0};1932	struct vpu_buf vb_fbc_y_tbl = {0};1933	struct vpu_buf vb_fbc_c_tbl = {0};1934	struct vpu_buf vb_sub_sam_buf = {0};1935	struct vpu_buf vb_task = {0};1936	struct enc_open_param *p_open_param;1937	struct enc_info *p_enc_info = &inst->codec_info->enc_info;1938 1939	p_open_param = &p_enc_info->open_param;1940	mv_col_size = 0;1941	fbc_y_tbl_size = 0;1942	fbc_c_tbl_size = 0;1943	stride = p_enc_info->stride;1944	bit_depth = p_open_param->wave_param.internal_bit_depth;1945 1946	if (avc_encoding) {1947		buf_width = ALIGN(p_open_param->pic_width, 16);1948		buf_height = ALIGN(p_open_param->pic_height, 16);1949 1950		if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&1951		    !(p_enc_info->rotation_angle == 180 &&1952					p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {1953			buf_width = ALIGN(p_open_param->pic_width, 16);1954			buf_height = ALIGN(p_open_param->pic_height, 16);1955		}1956 1957		if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) {1958			buf_width = ALIGN(p_open_param->pic_height, 16);1959			buf_height = ALIGN(p_open_param->pic_width, 16);1960		}1961	} else {1962		buf_width = ALIGN(p_open_param->pic_width, 8);1963		buf_height = ALIGN(p_open_param->pic_height, 8);1964 1965		if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&1966		    !(p_enc_info->rotation_angle == 180 &&1967					p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {1968			buf_width = ALIGN(p_open_param->pic_width, 32);1969			buf_height = ALIGN(p_open_param->pic_height, 32);1970		}1971 1972		if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) {1973			buf_width = ALIGN(p_open_param->pic_height, 32);1974			buf_height = ALIGN(p_open_param->pic_width, 32);1975		}1976	}1977 1978	pic_size = (buf_width << 16) | buf_height;1979 1980	if (avc_encoding) {1981		mv_col_size = WAVE5_ENC_AVC_BUF_SIZE(buf_width, buf_height);1982		vb_mv.daddr = 0;1983		vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;1984	} else {1985		mv_col_size = WAVE5_ENC_HEVC_BUF_SIZE(buf_width, buf_height);1986		mv_col_size = ALIGN(mv_col_size, 16);1987		vb_mv.daddr = 0;1988		vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;1989	}1990 1991	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_mv);1992	if (ret)1993		return ret;1994 1995	p_enc_info->vb_mv = vb_mv;1996 1997	fbc_y_tbl_size = ALIGN(WAVE5_FBC_LUMA_TABLE_SIZE(buf_width, buf_height), 16);1998	fbc_c_tbl_size = ALIGN(WAVE5_FBC_CHROMA_TABLE_SIZE(buf_width, buf_height), 16);1999 2000	vb_fbc_y_tbl.daddr = 0;2001	vb_fbc_y_tbl.size = ALIGN(fbc_y_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;2002	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_y_tbl);2003	if (ret)2004		goto free_vb_fbc_y_tbl;2005 2006	p_enc_info->vb_fbc_y_tbl = vb_fbc_y_tbl;2007 2008	vb_fbc_c_tbl.daddr = 0;2009	vb_fbc_c_tbl.size = ALIGN(fbc_c_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;2010	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_c_tbl);2011	if (ret)2012		goto free_vb_fbc_c_tbl;2013 2014	p_enc_info->vb_fbc_c_tbl = vb_fbc_c_tbl;2015 2016	if (avc_encoding)2017		sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE_AVC(buf_width, buf_height);2018	else2019		sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE(buf_width, buf_height);2020	vb_sub_sam_buf.size = ALIGN(sub_sampled_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;2021	vb_sub_sam_buf.daddr = 0;2022	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_sub_sam_buf);2023	if (ret)2024		goto free_vb_sam_buf;2025 2026	p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf;2027 2028	vb_task.size = (p_enc_info->vlc_buf_size * VLC_BUF_NUM) +2029			(p_enc_info->param_buf_size * WAVE521_COMMAND_QUEUE_DEPTH);2030	vb_task.daddr = 0;2031	if (p_enc_info->vb_task.size == 0) {2032		ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task);2033		if (ret)2034			goto free_vb_task;2035 2036		p_enc_info->vb_task = vb_task;2037 2038		vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,2039			      p_enc_info->vb_task.daddr);2040		vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_task.size);2041	}2042 2043	/* set sub-sampled buffer base addr */2044	vpu_write_reg(inst->dev, W5_ADDR_SUB_SAMPLED_FB_BASE, vb_sub_sam_buf.daddr);2045	/* set sub-sampled buffer size for one frame */2046	vpu_write_reg(inst->dev, W5_SUB_SAMPLED_ONE_FB_SIZE, sub_sampled_size);2047 2048	vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size);2049 2050	/* set stride of luma/chroma for compressed buffer */2051	if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&2052	    !(p_enc_info->rotation_angle == 180 &&2053	    p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {2054		luma_stride = calculate_luma_stride(buf_width, bit_depth);2055		chroma_stride = calculate_chroma_stride(buf_width / 2, bit_depth);2056	} else {2057		luma_stride = calculate_luma_stride(p_open_param->pic_width, bit_depth);2058		chroma_stride = calculate_chroma_stride(p_open_param->pic_width / 2, bit_depth);2059	}2060 2061	vpu_write_reg(inst->dev, W5_FBC_STRIDE, luma_stride << 16 | chroma_stride);2062	vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, stride);2063 2064	remain = count;2065	cnt_8_chunk = DIV_ROUND_UP(count, 8);2066	idx = 0;2067	for (j = 0; j < cnt_8_chunk; j++) {2068		reg_val = (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3);2069		vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val);2070		start_no = j * 8;2071		end_no = start_no + ((remain >= 8) ? 8 : remain) - 1;2072 2073		vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no);2074 2075		for (i = 0; i < 8 && i < remain; i++) {2076			vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), fb_arr[i +2077					start_no].buf_y);2078			vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4),2079				      fb_arr[i + start_no].buf_cb);2080			/* luma FBC offset table */2081			vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4),2082				      vb_fbc_y_tbl.daddr + idx * fbc_y_tbl_size);2083			/* chroma FBC offset table */2084			vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4),2085				      vb_fbc_c_tbl.daddr + idx * fbc_c_tbl_size);2086 2087			vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2),2088				      vb_mv.daddr + idx * mv_col_size);2089			idx++;2090		}2091		remain -= i;2092 2093		ret = send_firmware_command(inst, W5_SET_FB, false, NULL, NULL);2094		if (ret)2095			goto free_vb_mem;2096	}2097 2098	ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL);2099	if (ret)2100		goto free_vb_mem;2101 2102	return ret;2103 2104free_vb_mem:2105	wave5_vdi_free_dma_memory(vpu_dev, &vb_task);2106free_vb_task:2107	wave5_vdi_free_dma_memory(vpu_dev, &vb_sub_sam_buf);2108free_vb_sam_buf:2109	wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_c_tbl);2110free_vb_fbc_c_tbl:2111	wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_y_tbl);2112free_vb_fbc_y_tbl:2113	wave5_vdi_free_dma_memory(vpu_dev, &vb_mv);2114	return ret;2115}2116 2117static u32 wave5_vpu_enc_validate_sec_axi(struct vpu_instance *inst)2118{2119	struct enc_info *p_enc_info = &inst->codec_info->enc_info;2120	u32 rdo_size = 0, lf_size = 0, ret = 0;2121	u32 sram_size = inst->dev->sram_size;2122 2123	if (!sram_size)2124		return 0;2125 2126	/*2127	 * TODO: calculate rdo_size and lf_size from inst->src_fmt.width and2128	 * inst->codec_info->enc_info.open_param.wave_param.internal_bit_depth2129	 */2130 2131	if (p_enc_info->sec_axi_info.use_enc_rdo_enable && sram_size >= rdo_size) {2132		ret |= BIT(11);2133		sram_size -= rdo_size;2134	}2135 2136	if (p_enc_info->sec_axi_info.use_enc_lf_enable && sram_size >= lf_size)2137		ret |= BIT(15);2138 2139	return ret;2140}2141 2142int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res)2143{2144	u32 src_frame_format;2145	u32 reg_val = 0;2146	u32 src_stride_c = 0;2147	struct enc_info *p_enc_info = &inst->codec_info->enc_info;2148	struct frame_buffer *p_src_frame = option->source_frame;2149	struct enc_open_param *p_open_param = &p_enc_info->open_param;2150	bool justified = WTL_RIGHT_JUSTIFIED;2151	u32 format_no = WTL_PIXEL_8BIT;2152	int ret;2153 2154	vpu_write_reg(inst->dev, W5_CMD_ENC_BS_START_ADDR, option->pic_stream_buffer_addr);2155	vpu_write_reg(inst->dev, W5_CMD_ENC_BS_SIZE, option->pic_stream_buffer_size);2156	p_enc_info->stream_buf_start_addr = option->pic_stream_buffer_addr;2157	p_enc_info->stream_buf_size = option->pic_stream_buffer_size;2158	p_enc_info->stream_buf_end_addr =2159		option->pic_stream_buffer_addr + option->pic_stream_buffer_size;2160 2161	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI);2162	/* secondary AXI */2163	reg_val = wave5_vpu_enc_validate_sec_axi(inst);2164	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val);2165 2166	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_REPORT_PARAM, 0);2167 2168	/*2169	 * CODEOPT_ENC_VCL is used to implicitly encode header/headers to generate bitstream.2170	 * (use ENC_PUT_VIDEO_HEADER for give_command to encode only a header)2171	 */2172	if (option->code_option.implicit_header_encode)2173		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION,2174			      CODEOPT_ENC_HEADER_IMPLICIT | CODEOPT_ENC_VCL |2175			      (option->code_option.encode_aud << 5) |2176			      (option->code_option.encode_eos << 6) |2177			      (option->code_option.encode_eob << 7));2178	else2179		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION,2180			      option->code_option.implicit_header_encode |2181			      (option->code_option.encode_vcl << 1) |2182			      (option->code_option.encode_vps << 2) |2183			      (option->code_option.encode_sps << 3) |2184			      (option->code_option.encode_pps << 4) |2185			      (option->code_option.encode_aud << 5) |2186			      (option->code_option.encode_eos << 6) |2187			      (option->code_option.encode_eob << 7));2188 2189	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PIC_PARAM, 0);2190 2191	if (option->src_end_flag)2192		/* no more source images. */2193		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, 0xFFFFFFFF);2194	else2195		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, option->src_idx);2196 2197	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_Y, p_src_frame->buf_y);2198	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_U, p_src_frame->buf_cb);2199	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_V, p_src_frame->buf_cr);2200 2201	switch (p_open_param->src_format) {2202	case FORMAT_420:2203	case FORMAT_422:2204	case FORMAT_YUYV:2205	case FORMAT_YVYU:2206	case FORMAT_UYVY:2207	case FORMAT_VYUY:2208		justified = WTL_LEFT_JUSTIFIED;2209		format_no = WTL_PIXEL_8BIT;2210		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :2211			(p_src_frame->stride / 2);2212		src_stride_c = (p_open_param->src_format == FORMAT_422) ? src_stride_c * 2 :2213			src_stride_c;2214		break;2215	case FORMAT_420_P10_16BIT_MSB:2216	case FORMAT_422_P10_16BIT_MSB:2217	case FORMAT_YUYV_P10_16BIT_MSB:2218	case FORMAT_YVYU_P10_16BIT_MSB:2219	case FORMAT_UYVY_P10_16BIT_MSB:2220	case FORMAT_VYUY_P10_16BIT_MSB:2221		justified = WTL_RIGHT_JUSTIFIED;2222		format_no = WTL_PIXEL_16BIT;2223		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :2224			(p_src_frame->stride / 2);2225		src_stride_c = (p_open_param->src_format ==2226				FORMAT_422_P10_16BIT_MSB) ? src_stride_c * 2 : src_stride_c;2227		break;2228	case FORMAT_420_P10_16BIT_LSB:2229	case FORMAT_422_P10_16BIT_LSB:2230	case FORMAT_YUYV_P10_16BIT_LSB:2231	case FORMAT_YVYU_P10_16BIT_LSB:2232	case FORMAT_UYVY_P10_16BIT_LSB:2233	case FORMAT_VYUY_P10_16BIT_LSB:2234		justified = WTL_LEFT_JUSTIFIED;2235		format_no = WTL_PIXEL_16BIT;2236		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :2237			(p_src_frame->stride / 2);2238		src_stride_c = (p_open_param->src_format ==2239				FORMAT_422_P10_16BIT_LSB) ? src_stride_c * 2 : src_stride_c;2240		break;2241	case FORMAT_420_P10_32BIT_MSB:2242	case FORMAT_422_P10_32BIT_MSB:2243	case FORMAT_YUYV_P10_32BIT_MSB:2244	case FORMAT_YVYU_P10_32BIT_MSB:2245	case FORMAT_UYVY_P10_32BIT_MSB:2246	case FORMAT_VYUY_P10_32BIT_MSB:2247		justified = WTL_RIGHT_JUSTIFIED;2248		format_no = WTL_PIXEL_32BIT;2249		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :2250			ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave);2251		src_stride_c = (p_open_param->src_format ==2252				FORMAT_422_P10_32BIT_MSB) ? src_stride_c * 2 : src_stride_c;2253		break;2254	case FORMAT_420_P10_32BIT_LSB:2255	case FORMAT_422_P10_32BIT_LSB:2256	case FORMAT_YUYV_P10_32BIT_LSB:2257	case FORMAT_YVYU_P10_32BIT_LSB:2258	case FORMAT_UYVY_P10_32BIT_LSB:2259	case FORMAT_VYUY_P10_32BIT_LSB:2260		justified = WTL_LEFT_JUSTIFIED;2261		format_no = WTL_PIXEL_32BIT;2262		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :2263			ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave);2264		src_stride_c = (p_open_param->src_format ==2265				FORMAT_422_P10_32BIT_LSB) ? src_stride_c * 2 : src_stride_c;2266		break;2267	default:2268		return -EINVAL;2269	}2270 2271	src_frame_format = (inst->cbcr_interleave << 1) | (inst->nv21);2272	switch (p_open_param->packed_format) {2273	case PACKED_YUYV:2274		src_frame_format = 4;2275		break;2276	case PACKED_YVYU:2277		src_frame_format = 5;2278		break;2279	case PACKED_UYVY:2280		src_frame_format = 6;2281		break;2282	case PACKED_VYUY:2283		src_frame_format = 7;2284		break;2285	default:2286		break;2287	}2288 2289	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_STRIDE,2290		      (p_src_frame->stride << 16) | src_stride_c);2291	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_FORMAT, src_frame_format |2292		      (format_no << 3) | (justified << 5) | (PIC_SRC_ENDIANNESS_BIG_ENDIAN << 6));2293 2294	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR, 0);2295	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM, 0);2296	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_LONGTERM_PIC, 0);2297	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y, 0);2298	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C, 0);2299	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y, 0);2300	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C, 0);2301	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_INFO, 0);2302	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR, 0);2303	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_INFO, 0);2304	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR, 0);2305 2306	ret = send_firmware_command(inst, W5_DEC_ENC_PIC, true, &reg_val, fail_res);2307	if (ret == -ETIMEDOUT)2308		return ret;2309 2310	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;2311	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);2312 2313	if (ret)2314		return ret;2315 2316	return 0;2317}2318 2319int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result)2320{2321	int ret;2322	u32 encoding_success;2323	u32 reg_val;2324	struct enc_info *p_enc_info = &inst->codec_info->enc_info;2325	struct vpu_device *vpu_dev = inst->dev;2326 2327	ret = wave5_send_query(inst->dev, inst, GET_RESULT);2328	if (ret)2329		return ret;2330 2331	dev_dbg(inst->dev->dev, "%s: enc pic complete\n", __func__);2332 2333	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);2334 2335	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;2336	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);2337 2338	encoding_success = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS);2339	if (!encoding_success) {2340		result->error_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO);2341		return -EIO;2342	}2343 2344	result->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO);2345 2346	reg_val = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_TYPE);2347	result->pic_type = reg_val & 0xFFFF;2348 2349	result->enc_vcl_nut = vpu_read_reg(inst->dev, W5_RET_ENC_VCL_NUT);2350	/*2351	 * To get the reconstructed frame use the following index on2352	 * inst->frame_buf2353	 */2354	result->recon_frame_index = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_IDX);2355	result->enc_pic_byte = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_BYTE);2356	result->enc_src_idx = vpu_read_reg(inst->dev, W5_RET_ENC_USED_SRC_IDX);2357	p_enc_info->stream_wr_ptr = vpu_read_reg(inst->dev, W5_RET_ENC_WR_PTR);2358	p_enc_info->stream_rd_ptr = vpu_read_reg(inst->dev, W5_RET_ENC_RD_PTR);2359 2360	result->bitstream_buffer = vpu_read_reg(inst->dev, W5_RET_ENC_RD_PTR);2361	result->rd_ptr = p_enc_info->stream_rd_ptr;2362	result->wr_ptr = p_enc_info->stream_wr_ptr;2363 2364	/*result for header only(no vcl) encoding */2365	if (result->recon_frame_index == RECON_IDX_FLAG_HEADER_ONLY)2366		result->bitstream_size = result->enc_pic_byte;2367	else if (result->recon_frame_index < 0)2368		result->bitstream_size = 0;2369	else2370		result->bitstream_size = result->enc_pic_byte;2371 2372	result->enc_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_ENC_HOST_CMD_TICK);2373	result->enc_encode_end_tick = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_END_TICK);2374 2375	if (!p_enc_info->first_cycle_check) {2376		result->frame_cycle = (result->enc_encode_end_tick - result->enc_host_cmd_tick) *2377			p_enc_info->cycle_per_tick;2378		p_enc_info->first_cycle_check = true;2379	} else {2380		result->frame_cycle =2381			(result->enc_encode_end_tick - vpu_dev->last_performance_cycles) *2382			p_enc_info->cycle_per_tick;2383		if (vpu_dev->last_performance_cycles < result->enc_host_cmd_tick)2384			result->frame_cycle = (result->enc_encode_end_tick -2385					result->enc_host_cmd_tick) * p_enc_info->cycle_per_tick;2386	}2387	vpu_dev->last_performance_cycles = result->enc_encode_end_tick;2388 2389	return 0;2390}2391 2392int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res)2393{2394	return send_firmware_command(inst, W5_DESTROY_INSTANCE, true, NULL, fail_res);2395}2396 2397static bool wave5_vpu_enc_check_common_param_valid(struct vpu_instance *inst,2398						   struct enc_open_param *open_param)2399{2400	bool low_delay = true;2401	struct enc_wave_param *param = &open_param->wave_param;2402	struct vpu_device *vpu_dev = inst->dev;2403	struct device *dev = vpu_dev->dev;2404	u32 num_ctu_row = (open_param->pic_height + 64 - 1) / 64;2405	u32 num_ctu_col = (open_param->pic_width + 64 - 1) / 64;2406	u32 ctu_sz = num_ctu_col * num_ctu_row;2407 2408	if (inst->std == W_HEVC_ENC && low_delay &&2409	    param->decoding_refresh_type == DEC_REFRESH_TYPE_CRA) {2410		dev_warn(dev,2411			 "dec_refresh_type(CRA) shouldn't be used together with low delay GOP\n");2412		dev_warn(dev, "Suggested configuration parameter: decoding refresh type (IDR)\n");2413		param->decoding_refresh_type = 2;2414	}2415 2416	if (param->wpp_enable && param->independ_slice_mode) {2417		unsigned int num_ctb_in_width = ALIGN(open_param->pic_width, 64) >> 6;2418 2419		if (param->independ_slice_mode_arg % num_ctb_in_width) {2420			dev_err(dev, "independ_slice_mode_arg %u must be a multiple of %u\n",2421				param->independ_slice_mode_arg, num_ctb_in_width);2422			return false;2423		}2424	}2425 2426	/* multi-slice & wpp */2427	if (param->wpp_enable && param->depend_slice_mode) {2428		dev_err(dev, "wpp_enable && depend_slice_mode cannot be used simultaneously\n");2429		return false;2430	}2431 2432	if (!param->independ_slice_mode && param->depend_slice_mode) {2433		dev_err(dev, "depend_slice_mode requires independ_slice_mode\n");2434		return false;2435	} else if (param->independ_slice_mode &&2436		   param->depend_slice_mode == DEPEND_SLICE_MODE_RECOMMENDED &&2437		   param->independ_slice_mode_arg < param->depend_slice_mode_arg) {2438		dev_err(dev, "independ_slice_mode_arg: %u must be smaller than %u\n",2439			param->independ_slice_mode_arg, param->depend_slice_mode_arg);2440		return false;2441	}2442 2443	if (param->independ_slice_mode && param->independ_slice_mode_arg > 65535) {2444		dev_err(dev, "independ_slice_mode_arg: %u must be smaller than 65535\n",2445			param->independ_slice_mode_arg);2446		return false;2447	}2448 2449	if (param->depend_slice_mode && param->depend_slice_mode_arg > 65535) {2450		dev_err(dev, "depend_slice_mode_arg: %u must be smaller than 65535\n",2451			param->depend_slice_mode_arg);2452		return false;2453	}2454 2455	if (param->conf_win_top % 2) {2456		dev_err(dev, "conf_win_top: %u, must be a multiple of 2\n", param->conf_win_top);2457		return false;2458	}2459 2460	if (param->conf_win_bot % 2) {2461		dev_err(dev, "conf_win_bot: %u, must be a multiple of 2\n", param->conf_win_bot);2462		return false;2463	}2464 2465	if (param->conf_win_left % 2) {2466		dev_err(dev, "conf_win_left: %u, must be a multiple of 2\n", param->conf_win_left);2467		return false;2468	}2469 2470	if (param->conf_win_right % 2) {2471		dev_err(dev, "conf_win_right: %u, Must be a multiple of 2\n",2472			param->conf_win_right);2473		return false;2474	}2475 2476	if (param->lossless_enable && open_param->rc_enable) {2477		dev_err(dev, "option rate_control cannot be used with lossless_coding\n");2478		return false;2479	}2480 2481	if (param->lossless_enable && !param->skip_intra_trans) {2482		dev_err(dev, "option intra_trans_skip must be enabled with lossless_coding\n");2483		return false;2484	}2485 2486	/* intra refresh */2487	if (param->intra_refresh_mode && param->intra_refresh_arg == 0) {2488		dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u must be > 0\n",2489			param->intra_refresh_mode, param->intra_refresh_arg);2490		return false;2491	}2492	switch (param->intra_refresh_mode) {2493	case REFRESH_MODE_CTU_ROWS:2494		if (param->intra_mb_refresh_arg > num_ctu_row)2495			goto invalid_refresh_argument;2496		break;2497	case REFRESH_MODE_CTU_COLUMNS:2498		if (param->intra_refresh_arg > num_ctu_col)2499			goto invalid_refresh_argument;2500		break;2501	case REFRESH_MODE_CTU_STEP_SIZE:2502		if (param->intra_refresh_arg > ctu_sz)2503			goto invalid_refresh_argument;2504		break;2505	case REFRESH_MODE_CTUS:2506		if (param->intra_refresh_arg > ctu_sz)2507			goto invalid_refresh_argument;2508		if (param->lossless_enable) {2509			dev_err(dev, "mode: %u cannot be used lossless_enable",2510				param->intra_refresh_mode);2511			return false;2512		}2513	}2514	return true;2515 2516invalid_refresh_argument:2517	dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u > W(%u)xH(%u)\n",2518		param->intra_refresh_mode, param->intra_refresh_arg,2519		num_ctu_row, num_ctu_col);2520	return false;2521}2522 2523static bool wave5_vpu_enc_check_param_valid(struct vpu_device *vpu_dev,2524					    struct enc_open_param *open_param)2525{2526	struct enc_wave_param *param = &open_param->wave_param;2527 2528	if (open_param->rc_enable) {2529		if (param->min_qp_i > param->max_qp_i || param->min_qp_p > param->max_qp_p ||2530		    param->min_qp_b > param->max_qp_b) {2531			dev_err(vpu_dev->dev, "Configuration failed because min_qp is greater than max_qp\n");2532			dev_err(vpu_dev->dev, "Suggested configuration parameters: min_qp = max_qp\n");2533			return false;2534		}2535 2536		if (open_param->bit_rate <= (int)open_param->frame_rate_info) {2537			dev_err(vpu_dev->dev,2538				"enc_bit_rate: %u must be greater than the frame_rate: %u\n",2539				open_param->bit_rate, (int)open_param->frame_rate_info);2540			return false;2541		}2542	}2543 2544	return true;2545}2546 2547int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param)2548{2549	u32 pic_width;2550	u32 pic_height;2551	s32 product_id = inst->dev->product;2552	struct vpu_attr *p_attr = &inst->dev->attr;2553	struct enc_wave_param *param;2554 2555	if (!open_param)2556		return -EINVAL;2557 2558	param = &open_param->wave_param;2559	pic_width = open_param->pic_width;2560	pic_height = open_param->pic_height;2561 2562	if (inst->id >= MAX_NUM_INSTANCE) {2563		dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n",2564			inst->id, MAX_NUM_INSTANCE);2565		return -EOPNOTSUPP;2566	}2567 2568	if (inst->std != W_HEVC_ENC &&2569	    !(inst->std == W_AVC_ENC && product_id == PRODUCT_ID_521)) {2570		dev_err(inst->dev->dev, "Unsupported encoder-codec & product combination\n");2571		return -EOPNOTSUPP;2572	}2573 2574	if (param->internal_bit_depth == 10) {2575		if (inst->std == W_HEVC_ENC && !p_attr->support_hevc10bit_enc) {2576			dev_err(inst->dev->dev,2577				"Flag support_hevc10bit_enc must be set to encode 10bit HEVC\n");2578			return -EOPNOTSUPP;2579		} else if (inst->std == W_AVC_ENC && !p_attr->support_avc10bit_enc) {2580			dev_err(inst->dev->dev,2581				"Flag support_avc10bit_enc must be set to encode 10bit AVC\n");2582			return -EOPNOTSUPP;2583		}2584	}2585 2586	if (!open_param->frame_rate_info) {2587		dev_err(inst->dev->dev, "No frame rate information.\n");2588		return -EINVAL;2589	}2590 2591	if (open_param->bit_rate > MAX_BIT_RATE) {2592		dev_err(inst->dev->dev, "Invalid encoding bit-rate: %u (valid: 0-%u)\n",2593			open_param->bit_rate, MAX_BIT_RATE);2594		return -EINVAL;2595	}2596 2597	if (pic_width < W5_MIN_ENC_PIC_WIDTH || pic_width > W5_MAX_ENC_PIC_WIDTH ||2598	    pic_height < W5_MIN_ENC_PIC_HEIGHT || pic_height > W5_MAX_ENC_PIC_HEIGHT) {2599		dev_err(inst->dev->dev, "Invalid encoding dimension: %ux%u\n",2600			pic_width, pic_height);2601		return -EINVAL;2602	}2603 2604	if (param->profile) {2605		if (inst->std == W_HEVC_ENC) {2606			if ((param->profile != HEVC_PROFILE_MAIN ||2607			     (param->profile == HEVC_PROFILE_MAIN &&2608			      param->internal_bit_depth > 8)) &&2609			    (param->profile != HEVC_PROFILE_MAIN10 ||2610			     (param->profile == HEVC_PROFILE_MAIN10 &&2611			      param->internal_bit_depth < 10)) &&2612			    param->profile != HEVC_PROFILE_STILLPICTURE) {2613				dev_err(inst->dev->dev,2614					"Invalid HEVC encoding profile: %u (bit-depth: %u)\n",2615					param->profile, param->internal_bit_depth);2616				return -EINVAL;2617			}2618		} else if (inst->std == W_AVC_ENC) {2619			if ((param->internal_bit_depth > 8 &&2620			     param->profile != H264_PROFILE_HIGH10)) {2621				dev_err(inst->dev->dev,2622					"Invalid AVC encoding profile: %u (bit-depth: %u)\n",2623					param->profile, param->internal_bit_depth);2624				return -EINVAL;2625			}2626		}2627	}2628 2629	if (param->decoding_refresh_type > DEC_REFRESH_TYPE_IDR) {2630		dev_err(inst->dev->dev, "Invalid decoding refresh type: %u (valid: 0-2)\n",2631			param->decoding_refresh_type);2632		return -EINVAL;2633	}2634 2635	if (param->intra_refresh_mode > REFRESH_MODE_CTUS) {2636		dev_err(inst->dev->dev, "Invalid intra refresh mode: %d (valid: 0-4)\n",2637			param->intra_refresh_mode);2638		return -EINVAL;2639	}2640 2641	if (inst->std == W_HEVC_ENC && param->independ_slice_mode &&2642	    param->depend_slice_mode > DEPEND_SLICE_MODE_BOOST) {2643		dev_err(inst->dev->dev,2644			"Can't combine slice modes: independent and fast dependent for HEVC\n");2645		return -EINVAL;2646	}2647 2648	if (!param->disable_deblk) {2649		if (param->beta_offset_div2 < -6 || param->beta_offset_div2 > 6) {2650			dev_err(inst->dev->dev, "Invalid beta offset: %d (valid: -6-6)\n",2651				param->beta_offset_div2);2652			return -EINVAL;2653		}2654 2655		if (param->tc_offset_div2 < -6 || param->tc_offset_div2 > 6) {2656			dev_err(inst->dev->dev, "Invalid tc offset: %d (valid: -6-6)\n",2657				param->tc_offset_div2);2658			return -EINVAL;2659		}2660	}2661 2662	if (param->intra_qp > MAX_INTRA_QP) {2663		dev_err(inst->dev->dev,2664			"Invalid intra quantization parameter: %u (valid: 0-%u)\n",2665			param->intra_qp, MAX_INTRA_QP);2666		return -EINVAL;2667	}2668 2669	if (open_param->rc_enable) {2670		if (param->min_qp_i > MAX_INTRA_QP || param->max_qp_i > MAX_INTRA_QP ||2671		    param->min_qp_p > MAX_INTRA_QP || param->max_qp_p > MAX_INTRA_QP ||2672		    param->min_qp_b > MAX_INTRA_QP || param->max_qp_b > MAX_INTRA_QP) {2673			dev_err(inst->dev->dev,2674				"Invalid quantization parameter min/max values: "2675				"I: %u-%u, P: %u-%u, B: %u-%u (valid for each: 0-%u)\n",2676				param->min_qp_i, param->max_qp_i, param->min_qp_p, param->max_qp_p,2677				param->min_qp_b, param->max_qp_b, MAX_INTRA_QP);2678			return -EINVAL;2679		}2680 2681		if (param->hvs_qp_enable && param->hvs_max_delta_qp > MAX_HVS_MAX_DELTA_QP) {2682			dev_err(inst->dev->dev,2683				"Invalid HVS max delta quantization parameter: %u (valid: 0-%u)\n",2684				param->hvs_max_delta_qp, MAX_HVS_MAX_DELTA_QP);2685			return -EINVAL;2686		}2687 2688		if (open_param->vbv_buffer_size < MIN_VBV_BUFFER_SIZE ||2689		    open_param->vbv_buffer_size > MAX_VBV_BUFFER_SIZE) {2690			dev_err(inst->dev->dev, "VBV buffer size: %u (valid: %u-%u)\n",2691				open_param->vbv_buffer_size, MIN_VBV_BUFFER_SIZE,2692				MAX_VBV_BUFFER_SIZE);2693			return -EINVAL;2694		}2695	}2696 2697	if (!wave5_vpu_enc_check_common_param_valid(inst, open_param))2698		return -EINVAL;2699 2700	if (!wave5_vpu_enc_check_param_valid(inst->dev, open_param))2701		return -EINVAL;2702 2703	if (param->chroma_cb_qp_offset < -12 || param->chroma_cb_qp_offset > 12) {2704		dev_err(inst->dev->dev,2705			"Invalid chroma Cb quantization parameter offset: %d (valid: -12-12)\n",2706			param->chroma_cb_qp_offset);2707		return -EINVAL;2708	}2709 2710	if (param->chroma_cr_qp_offset < -12 || param->chroma_cr_qp_offset > 12) {2711		dev_err(inst->dev->dev,2712			"Invalid chroma Cr quantization parameter offset: %d (valid: -12-12)\n",2713			param->chroma_cr_qp_offset);2714		return -EINVAL;2715	}2716 2717	if (param->intra_refresh_mode == REFRESH_MODE_CTU_STEP_SIZE && !param->intra_refresh_arg) {2718		dev_err(inst->dev->dev,2719			"Intra refresh mode CTU step-size requires an argument\n");2720		return -EINVAL;2721	}2722 2723	if (inst->std == W_HEVC_ENC) {2724		if (param->nr_intra_weight_y > MAX_INTRA_WEIGHT ||2725		    param->nr_intra_weight_cb > MAX_INTRA_WEIGHT ||2726		    param->nr_intra_weight_cr > MAX_INTRA_WEIGHT) {2727			dev_err(inst->dev->dev,2728				"Invalid intra weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n",2729				param->nr_intra_weight_y, param->nr_intra_weight_cb,2730				param->nr_intra_weight_cr, MAX_INTRA_WEIGHT);2731			return -EINVAL;2732		}2733 2734		if (param->nr_inter_weight_y > MAX_INTER_WEIGHT ||2735		    param->nr_inter_weight_cb > MAX_INTER_WEIGHT ||2736		    param->nr_inter_weight_cr > MAX_INTER_WEIGHT) {2737			dev_err(inst->dev->dev,2738				"Invalid inter weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n",2739				param->nr_inter_weight_y, param->nr_inter_weight_cb,2740				param->nr_inter_weight_cr, MAX_INTER_WEIGHT);2741			return -EINVAL;2742		}2743	}2744 2745	return 0;2746}2747