brintos

brintos / linux-shallow public Read only

0
0
Text · 9.7 KiB · 51bb7ee Raw
382 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2016 MediaTek Inc.4 * Author: PoChun Lin <pochun.lin@mediatek.com>5 */6 7#include "mtk_vcodec_enc_drv.h"8#include "venc_ipi_msg.h"9#include "venc_vpu_if.h"10 11static void handle_enc_init_msg(struct venc_vpu_inst *vpu, const void *data)12{13	const struct venc_vpu_ipi_msg_init *msg = data;14 15	vpu->inst_addr = msg->vpu_inst_addr;16	vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,17					     msg->vpu_inst_addr);18 19	/* Firmware version field value is unspecified on MT8173. */20	if (mtk_vcodec_fw_get_type(vpu->ctx->dev->fw_handler) == VPU)21		return;22 23	/* Check firmware version. */24	mtk_venc_debug(vpu->ctx, "firmware version: 0x%x\n", msg->venc_abi_version);25	switch (msg->venc_abi_version) {26	case 1:27		break;28	default:29		mtk_venc_err(vpu->ctx, "unhandled firmware version 0x%x\n",30			     msg->venc_abi_version);31		vpu->failure = 1;32		break;33	}34}35 36static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, const void *data)37{38	const struct venc_vpu_ipi_msg_enc *msg = data;39 40	vpu->state = msg->state;41	vpu->bs_size = msg->bs_size;42	vpu->is_key_frm = msg->is_key_frm;43}44 45static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct venc_vpu_inst *vpu)46{47	struct mtk_vcodec_enc_ctx *ctx;48	int ret = false;49 50	mutex_lock(&enc_dev->dev_ctx_lock);51	list_for_each_entry(ctx, &enc_dev->ctx_list, list) {52		if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {53			ret = true;54			break;55		}56	}57	mutex_unlock(&enc_dev->dev_ctx_lock);58 59	return ret;60}61 62static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)63{64	struct mtk_vcodec_enc_dev *enc_dev;65	const struct venc_vpu_ipi_msg_common *msg = data;66	struct venc_vpu_inst *vpu;67 68	enc_dev = (struct mtk_vcodec_enc_dev *)priv;69	vpu = (struct venc_vpu_inst *)(unsigned long)msg->venc_inst;70	if (!priv || !vpu) {71		pr_err(MTK_DBG_V4L2_STR "venc_inst is NULL, did the SCP hang or crash?");72		return;73	}74 75	mtk_venc_debug(vpu->ctx, "msg_id %x inst %p status %d", msg->msg_id, vpu, msg->status);76	if (!vpu_enc_check_ap_inst(enc_dev, vpu) || msg->msg_id < VPU_IPIMSG_ENC_INIT_DONE ||77	    msg->msg_id > VPU_IPIMSG_ENC_DEINIT_DONE) {78		mtk_v4l2_venc_err(vpu->ctx, "venc msg id not correctly => 0x%x", msg->msg_id);79		vpu->failure = -EINVAL;80		goto error;81	}82 83	vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK);84	if (vpu->failure) {85		mtk_venc_err(vpu->ctx, "vpu enc status failure %d", vpu->failure);86		goto error;87	}88 89	switch (msg->msg_id) {90	case VPU_IPIMSG_ENC_INIT_DONE:91		handle_enc_init_msg(vpu, data);92		break;93	case VPU_IPIMSG_ENC_SET_PARAM_DONE:94		break;95	case VPU_IPIMSG_ENC_ENCODE_DONE:96		handle_enc_encode_msg(vpu, data);97		break;98	case VPU_IPIMSG_ENC_DEINIT_DONE:99		break;100	default:101		mtk_venc_err(vpu->ctx, "unknown msg id %x", msg->msg_id);102		break;103	}104 105error:106	vpu->signaled = 1;107}108 109static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg,110			    int len)111{112	int status;113 114	if (!vpu->ctx->dev->fw_handler) {115		mtk_venc_err(vpu->ctx, "inst dev is NULL");116		return -EINVAL;117	}118 119	status = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, vpu->id, msg,120					len, 2000);121	if (status) {122		mtk_venc_err(vpu->ctx, "vpu_ipi_send msg_id %x len %d fail %d",123			     *(uint32_t *)msg, len, status);124		return -EINVAL;125	}126	if (vpu->failure)127		return -EINVAL;128 129	return 0;130}131 132int vpu_enc_init(struct venc_vpu_inst *vpu)133{134	int status;135	struct venc_ap_ipi_msg_init out;136 137	init_waitqueue_head(&vpu->wq_hd);138	vpu->signaled = 0;139	vpu->failure = 0;140	vpu->ctx->vpu_inst = vpu;141 142	status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,143					    vpu_enc_ipi_handler, "venc",144					    vpu->ctx->dev);145 146	if (status) {147		mtk_venc_err(vpu->ctx, "vpu_ipi_register fail %d", status);148		return -EINVAL;149	}150 151	memset(&out, 0, sizeof(out));152	out.msg_id = AP_IPIMSG_ENC_INIT;153	out.venc_inst = (unsigned long)vpu;154	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {155		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_INIT fail");156		return -EINVAL;157	}158 159	if (IS_ERR_OR_NULL(vpu->vsi)) {160		mtk_venc_err(vpu->ctx, "invalid venc vsi");161		return -EINVAL;162	}163 164	return 0;165}166 167static unsigned int venc_enc_param_crop_right(struct venc_vpu_inst *vpu,168					      struct venc_enc_param *enc_prm)169{170	unsigned int img_crop_right = enc_prm->buf_width - enc_prm->width;171 172	return img_crop_right % 16;173}174 175static unsigned int venc_enc_param_crop_bottom(struct venc_enc_param *enc_prm)176{177	return round_up(enc_prm->height, 16) - enc_prm->height;178}179 180static unsigned int venc_enc_param_num_mb(struct venc_enc_param *enc_prm)181{182	return DIV_ROUND_UP(enc_prm->width, 16) *183	       DIV_ROUND_UP(enc_prm->height, 16);184}185 186int vpu_enc_set_param(struct venc_vpu_inst *vpu,187		      enum venc_set_param_type id,188		      struct venc_enc_param *enc_param)189{190	const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx);191	size_t msg_size = is_ext ?192		sizeof(struct venc_ap_ipi_msg_set_param_ext) :193		sizeof(struct venc_ap_ipi_msg_set_param);194	struct venc_ap_ipi_msg_set_param_ext out;195 196	mtk_venc_debug(vpu->ctx, "id %d ->", id);197 198	memset(&out, 0, sizeof(out));199	out.base.msg_id = AP_IPIMSG_ENC_SET_PARAM;200	out.base.vpu_inst_addr = vpu->inst_addr;201	out.base.param_id = id;202	switch (id) {203	case VENC_SET_PARAM_ENC:204		if (is_ext) {205			out.base.data_item = 3;206			out.base.data[0] =207				venc_enc_param_crop_right(vpu, enc_param);208			out.base.data[1] =209				venc_enc_param_crop_bottom(enc_param);210			out.base.data[2] = venc_enc_param_num_mb(enc_param);211		} else {212			out.base.data_item = 0;213		}214		break;215	case VENC_SET_PARAM_FORCE_INTRA:216		out.base.data_item = 0;217		break;218	case VENC_SET_PARAM_ADJUST_BITRATE:219		out.base.data_item = 1;220		out.base.data[0] = enc_param->bitrate;221		break;222	case VENC_SET_PARAM_ADJUST_FRAMERATE:223		out.base.data_item = 1;224		out.base.data[0] = enc_param->frm_rate;225		break;226	case VENC_SET_PARAM_GOP_SIZE:227		out.base.data_item = 1;228		out.base.data[0] = enc_param->gop_size;229		break;230	case VENC_SET_PARAM_INTRA_PERIOD:231		out.base.data_item = 1;232		out.base.data[0] = enc_param->intra_period;233		break;234	case VENC_SET_PARAM_SKIP_FRAME:235		out.base.data_item = 0;236		break;237	default:238		mtk_venc_err(vpu->ctx, "id %d not supported", id);239		return -EINVAL;240	}241	if (vpu_enc_send_msg(vpu, &out, msg_size)) {242		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_SET_PARAM %d fail", id);243		return -EINVAL;244	}245 246	mtk_venc_debug(vpu->ctx, "id %d <-", id);247 248	return 0;249}250 251static int vpu_enc_encode_32bits(struct venc_vpu_inst *vpu,252				 unsigned int bs_mode,253				 struct venc_frm_buf *frm_buf,254				 struct mtk_vcodec_mem *bs_buf,255				 struct venc_frame_info *frame_info)256{257	const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx);258	size_t msg_size = is_ext ?259		sizeof(struct venc_ap_ipi_msg_enc_ext) :260		sizeof(struct venc_ap_ipi_msg_enc);261	struct venc_ap_ipi_msg_enc_ext out;262 263	mtk_venc_debug(vpu->ctx, "bs_mode %d ->", bs_mode);264 265	memset(&out, 0, sizeof(out));266	out.base.msg_id = AP_IPIMSG_ENC_ENCODE;267	out.base.vpu_inst_addr = vpu->inst_addr;268	out.base.bs_mode = bs_mode;269	if (frm_buf) {270		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&271		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&272		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {273			out.base.input_addr[0] = frm_buf->fb_addr[0].dma_addr;274			out.base.input_addr[1] = frm_buf->fb_addr[1].dma_addr;275			out.base.input_addr[2] = frm_buf->fb_addr[2].dma_addr;276		} else {277			mtk_venc_err(vpu->ctx, "dma_addr not align to 16");278			return -EINVAL;279		}280	}281	if (bs_buf) {282		out.base.bs_addr = bs_buf->dma_addr;283		out.base.bs_size = bs_buf->size;284	}285	if (is_ext && frame_info) {286		out.data_item = 3;287		out.data[0] = frame_info->frm_count;288		out.data[1] = frame_info->skip_frm_count;289		out.data[2] = frame_info->frm_type;290	}291	if (vpu_enc_send_msg(vpu, &out, msg_size)) {292		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_ENCODE %d fail", bs_mode);293		return -EINVAL;294	}295 296	return 0;297}298 299static int vpu_enc_encode_34bits(struct venc_vpu_inst *vpu,300				 unsigned int bs_mode,301				 struct venc_frm_buf *frm_buf,302				 struct mtk_vcodec_mem *bs_buf,303				 struct venc_frame_info *frame_info)304{305	struct venc_ap_ipi_msg_enc_ext_34 out;306	size_t msg_size = sizeof(struct venc_ap_ipi_msg_enc_ext_34);307 308	mtk_venc_debug(vpu->ctx, "bs_mode %d ->", bs_mode);309 310	memset(&out, 0, sizeof(out));311	out.msg_id = AP_IPIMSG_ENC_ENCODE;312	out.vpu_inst_addr = vpu->inst_addr;313	out.bs_mode = bs_mode;314 315	if (frm_buf) {316		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&317		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&318		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {319			out.input_addr[0] = frm_buf->fb_addr[0].dma_addr;320			out.input_addr[1] = frm_buf->fb_addr[1].dma_addr;321			out.input_addr[2] = frm_buf->fb_addr[2].dma_addr;322		} else {323			mtk_venc_err(vpu->ctx, "dma_addr not align to 16");324			return -EINVAL;325		}326	}327	if (bs_buf) {328		out.bs_addr = bs_buf->dma_addr;329		out.bs_size = bs_buf->size;330	}331	if (frame_info) {332		out.data_item = 3;333		out.data[0] = frame_info->frm_count;334		out.data[1] = frame_info->skip_frm_count;335		out.data[2] = frame_info->frm_type;336	}337	if (vpu_enc_send_msg(vpu, &out, msg_size)) {338		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_ENCODE %d fail", bs_mode);339		return -EINVAL;340	}341 342	return 0;343}344 345int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,346		   struct venc_frm_buf *frm_buf,347		   struct mtk_vcodec_mem *bs_buf,348		   struct venc_frame_info *frame_info)349{350	int ret;351 352	if (MTK_ENC_IOVA_IS_34BIT(vpu->ctx))353		ret = vpu_enc_encode_34bits(vpu, bs_mode,354					    frm_buf, bs_buf, frame_info);355	else356		ret = vpu_enc_encode_32bits(vpu, bs_mode,357					    frm_buf, bs_buf, frame_info);358 359	if (ret)360		return ret;361 362	mtk_venc_debug(vpu->ctx, "bs_mode %d state %d size %d key_frm %d <-",363		       bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm);364 365	return 0;366}367 368int vpu_enc_deinit(struct venc_vpu_inst *vpu)369{370	struct venc_ap_ipi_msg_deinit out;371 372	memset(&out, 0, sizeof(out));373	out.msg_id = AP_IPIMSG_ENC_DEINIT;374	out.vpu_inst_addr = vpu->inst_addr;375	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {376		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_DEINIT fail");377		return -EINVAL;378	}379 380	return 0;381}382