From nobody Wed Nov 27 04:59:03 2024 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 312FA1AAE28; Mon, 14 Oct 2024 09:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728896959; cv=none; b=oYfxIjhWaSR1K3vbaLTi4bvqvgX0FerzW2CLQR7Oq3FgvVr2Gu94+6yGSa66MdyzaFyRMEXJ9CoKiQUSQXUkDi7Rn+gxeVwZsrxzIZDjpNGE5cO5n00aC2J7ANB376yNTavsecy2e5GPZLjwfApPZnJTuBjnCRHUMLNd1SqhFXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728896959; c=relaxed/simple; bh=M4J6alsnIyDReiNX3iuGJIBhhsAr88b5KnsE0+x14sw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=sGzPPmA862o48tLw24wxjU3vu3w0bhd0nFHFYNjtWbGwygSSoQ7ImEDrI67BrhKgvWP7jfAnwMhF2qMAjXJqXIvJebfzctOij00Z4eDh30bHHXeNSS6jnNeKcMUqb1JvBYhe2ZnID8KZaEEeycSF6gXA6OSFI0Yp8YhPlVlRqeo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=fpKARMTP; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="fpKARMTP" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 49DKrJvF027371; Mon, 14 Oct 2024 09:09:06 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 5eZ4TneSofu9SFvmvi/qE/8UuoVMqTyr4I43jvoHq9s=; b=fpKARMTPcgFd+3/t bX65jY6EMGMRR8XhhFYOvy2CuGW99la0ecWZcph+YQMkGYDoL8euQ3soXsBXr58y P/DhUzUekpUXSDyodEoNUzy+sGPcOydcOH68g3H6wKC4xv+2MNdMq2hPQIoQZV0d jkjpKRubeRFpfiQAvg9Eo336GiceRKQylp1F0PNCiFa2C5T5v/uXBFAE3SCDf1s6 jUX4YQvK+cq0U2288t3m1m7zLLzcRD4ervJlYL+Zvk7RfLPiiP+L/Xe2VYTg2LoA QvndIycl0OosK7oGVyl9WY61vdOaVzlcKrFrcZcQ3TFMLJ0iCIvfISLyX8/Wj1CR MyAMQQ== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 427hg73uq4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 14 Oct 2024 09:09:05 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 49E994mD019770 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 14 Oct 2024 09:09:04 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Mon, 14 Oct 2024 02:09:00 -0700 From: Dikshita Agarwal Date: Mon, 14 Oct 2024 14:37:40 +0530 Subject: [PATCH v4 19/28] media: iris: allocate, initialize and queue internal buffers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20241014-qcom-video-iris-v4-v4-19-c5eaa4e9ab9e@quicinc.com> References: <20241014-qcom-video-iris-v4-v4-0-c5eaa4e9ab9e@quicinc.com> In-Reply-To: <20241014-qcom-video-iris-v4-v4-0-c5eaa4e9ab9e@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , , , , , Dikshita Agarwal X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1728896854; l=48548; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=M4J6alsnIyDReiNX3iuGJIBhhsAr88b5KnsE0+x14sw=; b=SV8G6RzcklrKF9AyUX2cVoL5+xRzNvlORBPOU0DleUXmZG2//q8RxROlDqlU2iaD7HJdE3+xE w9Atg6PJh84CFGA8YsBor3ueSRdPO+mskgo1JGP7nMNDZn2K6tuHHy2 X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: Y_P5x4EWlnjb69Vyn--7hADaOyVAn2RA X-Proofpoint-GUID: Y_P5x4EWlnjb69Vyn--7hADaOyVAn2RA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 lowpriorityscore=0 spamscore=0 adultscore=0 priorityscore=1501 suspectscore=0 bulkscore=0 phishscore=0 malwarescore=0 impostorscore=0 mlxscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2410140066 Implement functions for creating, queueing, releasing and destroying buffers for internal usage. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_buffer.c | 206 ++++++++++++++++++ drivers/media/platform/qcom/iris/iris_buffer.h | 7 + drivers/media/platform/qcom/iris/iris_hfi_common.h | 4 + .../platform/qcom/iris/iris_hfi_gen1_command.c | 127 ++++++++++- .../platform/qcom/iris/iris_hfi_gen1_defines.h | 37 ++++ .../platform/qcom/iris/iris_hfi_gen1_response.c | 4 + .../platform/qcom/iris/iris_hfi_gen2_command.c | 132 ++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 41 ++++ .../platform/qcom/iris/iris_hfi_gen2_response.c | 149 ++++++++++++- .../platform/qcom/iris/iris_platform_common.h | 5 + .../platform/qcom/iris/iris_platform_sm8550.c | 17 ++ drivers/media/platform/qcom/iris/iris_vdec.c | 32 +++ drivers/media/platform/qcom/iris/iris_vidc.c | 11 + drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 233 +++++++++++++++++= +++- drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 77 ++++++- 16 files changed, 1087 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media= /platform/qcom/iris/iris_buffer.c index 55cbffb7e268..9fa97375d61f 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -7,6 +7,7 @@ =20 #include "iris_buffer.h" #include "iris_instance.h" +#include "iris_vpu_buffer.h" =20 #define PIXELS_4K 4096 #define MAX_WIDTH 4096 @@ -228,6 +229,211 @@ int iris_get_buffer_size(struct iris_inst *inst, } } =20 +static void iris_fill_internal_buf_info(struct iris_inst *inst, + enum iris_buffer_type buffer_type) +{ + struct iris_buffers *buffers =3D &inst->buffers[buffer_type]; + + buffers->size =3D iris_vpu_buf_size(inst, buffer_type); + buffers->min_count =3D iris_vpu_buf_count(inst, buffer_type); +} + +void iris_get_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data =3D inst->core->iris_platf= orm_data; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type =3D platform_data->dec_ip_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_ip_int_buf_tbl_size; + for (i =3D 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type =3D platform_data->dec_op_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_op_int_buf_tbl_size; + for (i =3D 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } +} + +static int iris_create_internal_buffer(struct iris_inst *inst, + enum iris_buffer_type buffer_type, u32 index) +{ + struct iris_buffers *buffers =3D &inst->buffers[buffer_type]; + struct iris_core *core =3D inst->core; + struct iris_buffer *buffer; + + if (!buffers->size) + return 0; + + buffer =3D kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + INIT_LIST_HEAD(&buffer->list); + buffer->type =3D buffer_type; + buffer->index =3D index; + buffer->buffer_size =3D buffers->size; + buffer->dma_attrs =3D DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; + list_add_tail(&buffer->list, &buffers->list); + + buffer->kvaddr =3D dma_alloc_attrs(core->dev, buffer->buffer_size, + &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); + if (!buffer->kvaddr) + return -ENOMEM; + + return 0; +} + +int iris_create_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data =3D inst->core->iris_platf= orm_data; + u32 internal_buffer_count, i, j; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type =3D platform_data->dec_ip_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type =3D platform_data->dec_op_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_op_int_buf_tbl_size; + } + + for (i =3D 0; i < internal_buffer_count; i++) { + buffers =3D &inst->buffers[internal_buf_type[i]]; + for (j =3D 0; j < buffers->min_count; j++) { + ret =3D iris_create_internal_buffer(inst, internal_buf_type[i], j); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) +{ + const struct iris_hfi_command_ops *hfi_ops =3D inst->core->hfi_ops; + int ret; + + ret =3D hfi_ops->session_queue_buf(inst, buf); + if (ret) + return ret; + + buf->attr &=3D ~BUF_ATTR_DEFERRED; + buf->attr |=3D BUF_ATTR_QUEUED; + + return 0; +} + +int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data =3D inst->core->iris_platf= orm_data; + struct iris_buffer *buffer, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type =3D platform_data->dec_ip_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type =3D platform_data->dec_op_int_buf_tbl; + internal_buffer_count =3D platform_data->dec_op_int_buf_tbl_size; + } + + for (i =3D 0; i < internal_buffer_count; i++) { + buffers =3D &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + ret =3D iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffe= r *buffer) +{ + struct iris_core *core =3D inst->core; + + list_del(&buffer->list); + dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + buffer->device_addr, buffer->dma_attrs); + kfree(buffer); + + return 0; +} + +int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data =3D inst->core->iris_platf= orm_data; + struct iris_buffer *buf, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 i, len; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type =3D platform_data->dec_ip_int_buf_tbl; + len =3D platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type =3D platform_data->dec_op_int_buf_tbl; + len =3D platform_data->dec_op_int_buf_tbl_size; + } + + for (i =3D 0; i < len; i++) { + buffers =3D &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buf, next, &buffers->list, list) { + ret =3D iris_destroy_internal_buffer(inst, buf); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) +{ + struct iris_buffers *buffers =3D &inst->buffers[BUF_PERSIST]; + struct iris_buffer *buffer, *next; + int ret; + u32 i; + + if (!list_empty(&buffers->list)) + return 0; + + iris_fill_internal_buf_info(inst, BUF_PERSIST); + + for (i =3D 0; i < buffers->min_count; i++) { + ret =3D iris_create_internal_buffer(inst, BUF_PERSIST, i); + if (ret) + return ret; + } + + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + ret =3D iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + + return 0; +} + void iris_vb2_queue_error(struct iris_inst *inst) { struct v4l2_m2m_ctx *m2m_ctx =3D inst->m2m_ctx; diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media= /platform/qcom/iris/iris_buffer.h index 98844e89e0e3..41e090e9f0b0 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -102,6 +102,13 @@ struct iris_buffers { }; =20 int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buf= fer_type); +void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffe= r *buffer); +int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); +int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); void iris_vb2_queue_error(struct iris_inst *inst); =20 #endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/m= edia/platform/qcom/iris/iris_hfi_common.h index fa409a9b3f04..9a6bb72e6134 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -9,6 +9,8 @@ #include #include =20 +#include "iris_buffer.h" + struct iris_inst; struct iris_core; =20 @@ -114,6 +116,8 @@ struct iris_hfi_command_ops { void *payload, u32 payload_size); int (*session_open)(struct iris_inst *inst); int (*session_start)(struct iris_inst *inst, u32 plane); + int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buff= er); + int (*session_release_buf)(struct iris_inst *inst, struct iris_buffer *bu= ffer); int (*session_stop)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/dri= vers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 8d6e455334e0..ee7d9beca33b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -8,6 +8,24 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" =20 +static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer= _type) +{ + switch (buffer_type) { + case BUF_INPUT: + return HFI_BUFFER_INPUT; + case BUF_OUTPUT: + return HFI_BUFFER_OUTPUT; + case BUF_PERSIST: + return HFI_BUFFER_INTERNAL_PERSIST_1; + case BUF_BIN: + return HFI_BUFFER_INTERNAL_SCRATCH; + case BUF_SCRATCH_1: + return HFI_BUFFER_INTERNAL_SCRATCH_1; + default: + return -EINVAL; + } +} + static int iris_hfi_gen1_sys_init(struct iris_core *core) { struct hfi_sys_init_pkt sys_init_pkt; @@ -183,6 +201,111 @@ static int iris_hfi_gen1_session_stop(struct iris_ins= t *inst, u32 plane) return ret; } =20 +static int iris_hfi_gen1_queue_internal_buffer(struct iris_inst *inst, str= uct iris_buffer *buf) +{ + struct hfi_session_set_buffers_pkt *int_pkt; + u32 buffer_type, i; + u32 packet_size; + int ret; + + packet_size =3D struct_size(int_pkt, buffer_info, 1); + int_pkt =3D kzalloc(packet_size, GFP_KERNEL); + if (!int_pkt) + return -ENOMEM; + + int_pkt->shdr.hdr.pkt_type =3D HFI_CMD_SESSION_SET_BUFFERS; + int_pkt->shdr.session_id =3D inst->session_id; + int_pkt->buffer_size =3D buf->buffer_size; + int_pkt->min_buffer_size =3D buf->buffer_size; + int_pkt->num_buffers =3D 1; + int_pkt->extradata_size =3D 0; + int_pkt->shdr.hdr.size =3D packet_size; + for (i =3D 0; i < int_pkt->num_buffers; i++) + int_pkt->buffer_info[i] =3D buf->device_addr; + buffer_type =3D iris_hfi_gen1_buf_type_from_driver(buf->type); + if (buffer_type =3D=3D -EINVAL) { + ret =3D -EINVAL; + goto exit; + } + + int_pkt->buffer_type =3D buffer_type; + ret =3D iris_hfi_queue_cmd_write(inst->core, int_pkt, int_pkt->shdr.hdr.s= ize); + +exit: + kfree(int_pkt); + + return ret; +} + +static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, stru= ct iris_buffer *buf) +{ + switch (buf->type) { + case BUF_PERSIST: + case BUF_BIN: + case BUF_SCRATCH_1: + return iris_hfi_gen1_queue_internal_buffer(inst, buf); + default: + return -EINVAL; + } +} + +static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, str= uct iris_buffer *buf) +{ + struct hfi_session_release_buffer_pkt *pkt; + u32 packet_size, buffer_type, i; + int ret; + + buffer_type =3D iris_hfi_gen1_buf_type_from_driver(buf->type); + if (buffer_type =3D=3D -EINVAL) + return -EINVAL; + + if (buffer_type =3D=3D HFI_BUFFER_INPUT) + return 0; + + packet_size =3D sizeof(*pkt) + sizeof(struct hfi_buffer_info); + pkt =3D kzalloc(packet_size, GFP_KERNEL); + if (!pkt) + return -ENOMEM; + + pkt->shdr.hdr.pkt_type =3D HFI_CMD_SESSION_RELEASE_BUFFERS; + pkt->shdr.session_id =3D inst->session_id; + pkt->buffer_size =3D buf->buffer_size; + pkt->num_buffers =3D 1; + + if (buffer_type =3D=3D HFI_BUFFER_OUTPUT || + buffer_type =3D=3D HFI_BUFFER_OUTPUT2) { + struct hfi_buffer_info *bi; + + bi =3D (struct hfi_buffer_info *)pkt->buffer_info; + for (i =3D 0; i < pkt->num_buffers; i++) { + bi->buffer_addr =3D buf->device_addr; + bi->extradata_addr =3D 0; + } + pkt->shdr.hdr.size =3D packet_size; + } else { + for (i =3D 0; i < pkt->num_buffers; i++) + pkt->buffer_info[i] =3D buf->device_addr; + pkt->extradata_size =3D 0; + pkt->shdr.hdr.size =3D + sizeof(struct hfi_session_set_buffers_pkt) + + ((pkt->num_buffers) * sizeof(u32)); + } + + pkt->response_req =3D true; + pkt->buffer_type =3D buffer_type; + + ret =3D iris_hfi_queue_cmd_write(inst->core, pkt, pkt->shdr.hdr.size); + if (ret) + goto exit; + + ret =3D iris_wait_for_session_response(inst, false); + +exit: + kfree(pkt); + + return ret; +} + static int iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_= pkt *packet, struct iris_inst *inst, u32 ptype, void *pdata) @@ -495,7 +618,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *= inst) =20 if (iris_split_mode_enabled(inst)) { bufsz.type =3D HFI_BUFFER_OUTPUT; - bufsz.size =3D iris_vpu_dec_dpb_size(inst); + bufsz.size =3D iris_vpu_buf_size(inst, BUF_DPB); =20 ret =3D hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); if (ret) @@ -600,6 +723,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_= command_ops =3D { .session_set_config_params =3D iris_hfi_gen1_session_set_config_params, .session_set_property =3D iris_hfi_gen1_session_set_property, .session_start =3D iris_hfi_gen1_session_start, + .session_queue_buf =3D iris_hfi_gen1_session_queue_buffer, + .session_release_buf =3D iris_hfi_gen1_session_unset_buffers, .session_stop =3D iris_hfi_gen1_session_stop, .session_close =3D iris_hfi_gen1_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/dri= vers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 8b48a082bcd3..5527233b03e5 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -24,11 +24,13 @@ #define HFI_CMD_SYS_SESSION_END 0x10008 =20 #define HFI_CMD_SESSION_SET_PROPERTY 0x11001 +#define HFI_CMD_SESSION_SET_BUFFERS 0x11002 =20 #define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 #define HFI_CMD_SESSION_START 0x211002 #define HFI_CMD_SESSION_STOP 0x211003 #define HFI_CMD_SESSION_FLUSH 0x211008 +#define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c =20 #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 @@ -53,6 +55,9 @@ #define HFI_BUFFER_INPUT 0x1 #define HFI_BUFFER_OUTPUT 0x2 #define HFI_BUFFER_OUTPUT2 0x3 +#define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 +#define HFI_BUFFER_INTERNAL_SCRATCH 0x6 +#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 =20 #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 @@ -80,6 +85,7 @@ #define HFI_MSG_SESSION_STOP 0x221003 #define HFI_MSG_SESSION_FLUSH 0x221006 #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a +#define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c =20 struct hfi_pkt_hdr { u32 size; @@ -128,11 +134,36 @@ struct hfi_sys_pc_prep_pkt { struct hfi_pkt_hdr hdr; }; =20 +struct hfi_session_set_buffers_pkt { + struct hfi_session_hdr_pkt shdr; + u32 buffer_type; + u32 buffer_size; + u32 extradata_size; + u32 min_buffer_size; + u32 num_buffers; + u32 buffer_info[]; +}; + struct hfi_session_flush_pkt { struct hfi_session_hdr_pkt shdr; u32 flush_type; }; =20 +struct hfi_session_release_buffer_pkt { + struct hfi_session_hdr_pkt shdr; + u32 buffer_type; + u32 buffer_size; + u32 extradata_size; + u32 response_req; + u32 num_buffers; + u32 buffer_info[]; +}; + +struct hfi_buffer_info { + u32 buffer_addr; + u32 extradata_addr; +}; + struct hfi_msg_event_notify_pkt { struct hfi_session_hdr_pkt shdr; u32 event_id; @@ -227,6 +258,12 @@ struct hfi_multi_stream { u32 enable; }; =20 +struct hfi_msg_session_release_buffers_done_pkt { + struct hfi_msg_session_hdr_pkt shdr; + u32 num_buffers; + u32 buffer_info[]; +}; + struct hfi_msg_sys_debug_pkt { struct hfi_pkt_hdr hdr; u32 msg_type; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/dr= ivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index db5858ec04ea..a84bb00388d9 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -176,6 +176,10 @@ static const struct iris_hfi_gen1_response_pkt_info pk= t_infos[] =3D { .pkt =3D HFI_MSG_SESSION_RELEASE_RESOURCES, .pkt_sz =3D sizeof(struct hfi_msg_session_hdr_pkt), }, + { + .pkt =3D HFI_MSG_SESSION_RELEASE_BUFFERS, + .pkt_sz =3D sizeof(struct hfi_msg_session_release_buffers_done_pkt), + }, }; =20 static void iris_hfi_gen1_handle_response(struct iris_core *core, void *re= sponse) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/dri= vers/media/platform/qcom/iris/iris_hfi_gen2_command.c index dddaa074cae1..cc75231f07f1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -100,6 +100,24 @@ static u32 iris_hfi_gen2_get_port(u32 plane) } } =20 +static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buff= er_type) +{ + switch (buffer_type) { + case BUF_INPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + return HFI_PORT_BITSTREAM; + case BUF_OUTPUT: + case BUF_DPB: + return HFI_PORT_RAW; + case BUF_PERSIST: + default: + return HFI_PORT_NONE; + } +} + static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 = packet_type, u32 flag, u32 plane, u32 payload_type, void *payload, u32 payload_size) @@ -719,6 +737,118 @@ static int iris_hfi_gen2_session_stop(struct iris_ins= t *inst, u32 plane) return iris_wait_for_session_response(inst, false); } =20 +static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer= _type) +{ + switch (buffer_type) { + case BUF_INPUT: + return HFI_BUFFER_BITSTREAM; + case BUF_OUTPUT: + return HFI_BUFFER_RAW; + case BUF_BIN: + return HFI_BUFFER_BIN; + case BUF_COMV: + return HFI_BUFFER_COMV; + case BUF_NON_COMV: + return HFI_BUFFER_NON_COMV; + case BUF_LINE: + return HFI_BUFFER_LINE; + case BUF_DPB: + return HFI_BUFFER_DPB; + case BUF_PERSIST: + return HFI_BUFFER_PERSIST; + default: + return 0; + } +} + +static int iris_set_num_comv(struct iris_inst *inst) +{ + struct platform_inst_caps *caps; + struct iris_core *core =3D inst->core; + u32 num_comv; + + caps =3D core->iris_platform_data->inst_caps; + num_comv =3D caps->num_comv; + + return core->hfi_ops->session_set_property(inst, + HFI_PROP_COMV_BUFFER_COUNT, + HFI_HOST_FLAGS_NONE, + HFI_PORT_BITSTREAM, + HFI_PAYLOAD_U32, + &num_comv, sizeof(u32)); +} + +static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct ir= is_hfi_buffer *buf) +{ + memset(buf, 0, sizeof(*buf)); + buf->type =3D iris_hfi_gen2_buf_type_from_driver(buffer->type); + buf->index =3D buffer->index; + buf->base_address =3D buffer->device_addr; + buf->addr_offset =3D 0; + buf->buffer_size =3D buffer->buffer_size; + + if (buffer->type =3D=3D BUF_INPUT) + buf->buffer_size =3D ALIGN(buffer->buffer_size, 256); + buf->data_offset =3D buffer->data_offset; + buf->data_size =3D buffer->data_size; + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + buf->flags |=3D HFI_BUF_HOST_FLAG_RELEASE; + buf->flags |=3D HFI_BUF_HOST_FLAGS_CB_NON_SECURE; + buf->timestamp =3D buffer->timestamp; +} + +static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, stru= ct iris_buffer *buffer) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 =3D to_iris_inst_hfi_gen2(inst); + struct iris_hfi_buffer hfi_buffer; + u32 port; + int ret; + + iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + if (buffer->type =3D=3D BUF_COMV) { + ret =3D iris_set_num_comv(inst); + if (ret) + return ret; + } + + port =3D iris_hfi_gen2_get_port_from_buf_type(buffer->type); + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_BUFFER, + HFI_HOST_FLAGS_INTR_REQUIRED, + port, + inst->session_id, + HFI_PAYLOAD_STRUCTURE, + &hfi_buffer, + sizeof(hfi_buffer)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + +static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, st= ruct iris_buffer *buffer) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 =3D to_iris_inst_hfi_gen2(inst); + struct iris_hfi_buffer hfi_buffer; + u32 port; + + iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + hfi_buffer.flags |=3D HFI_BUF_HOST_FLAG_RELEASE; + port =3D iris_hfi_gen2_get_port_from_buf_type(buffer->type); + + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_BUFFER, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED), + port, + inst->session_id, + HFI_PAYLOAD_STRUCTURE, + &hfi_buffer, + sizeof(hfi_buffer)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops =3D { .sys_init =3D iris_hfi_gen2_sys_init, .sys_image_version =3D iris_hfi_gen2_sys_image_version, @@ -728,6 +858,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_= command_ops =3D { .session_set_config_params =3D iris_hfi_gen2_session_set_config_params, .session_set_property =3D iris_hfi_gen2_session_set_property, .session_start =3D iris_hfi_gen2_session_start, + .session_queue_buf =3D iris_hfi_gen2_session_queue_buffer, + .session_release_buf =3D iris_hfi_gen2_session_release_buffer, .session_stop =3D iris_hfi_gen2_session_stop, .session_close =3D iris_hfi_gen2_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/dri= vers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 92c44841c67d..d9a903ee1e06 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -17,6 +17,7 @@ #define HFI_CMD_CLOSE 0x01000004 #define HFI_CMD_START 0x01000005 #define HFI_CMD_STOP 0x01000006 +#define HFI_CMD_BUFFER 0x01000009 #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B #define HFI_CMD_END 0x01FFFFFF =20 @@ -53,6 +54,7 @@ #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 #define HFI_PROP_NO_OUTPUT 0x0300016a +#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193 #define HFI_PROP_END 0x03FFFFFF =20 #define HFI_SESSION_ERROR_BEGIN 0x04000000 @@ -105,6 +107,13 @@ enum hfi_buffer_type { HFI_BUFFER_VPSS =3D 0x0000000D, }; =20 +enum hfi_buffer_host_flags { + HFI_BUF_HOST_FLAG_RELEASE =3D 0x00000001, + HFI_BUF_HOST_FLAG_READONLY =3D 0x00000010, + HFI_BUF_HOST_FLAG_CODEC_CONFIG =3D 0x00000100, + HFI_BUF_HOST_FLAGS_CB_NON_SECURE =3D 0x00000200, +}; + enum hfi_packet_firmware_flags { HFI_FW_FLAGS_SUCCESS =3D 0x00000001, HFI_FW_FLAGS_INFORMATION =3D 0x00000002, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/driv= ers/media/platform/qcom/iris/iris_hfi_gen2_packet.h index bb86abd25adb..3083a5174cdc 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h @@ -61,6 +61,47 @@ struct iris_hfi_packet { u32 payload[]; }; =20 +/** + * struct iris_hfi_buffer + * + * @type: buffer type indicated by "enum hfi_buffer_type" + * FW needs to return proper type for any buffer command. + * @index: index of the buffer + * @base_address: base address of the buffer. + * This buffer address is always 4KBytes aligned. + * @addr_offset: accessible buffer offset from base address + * Decoder bitstream buffer: 256 Bytes aligned + * Firmware can uniquely identify a buffer based on + * base_address & addr_offset. + * HW can read memory only from base_address+addr_offset. + * @buffer_size: accessible buffer size in bytes starting from addr_offset + * @data_offset: data starts from "base_address + addr_offset + data_offse= t" + * RAW buffer: data_offset is 0. Restriction: 4KBytes aligned + * decoder bitstream buffer: no restriction (can be any valu= e) + * @data_size: data size in bytes + * @flags: buffer flags. It is represented as bit masks. + * host buffer flags are "enum hfi_buffer_host_flags" + * firmware buffer flags are "enum hfi_buffer_firmware_flags" + * @timestamp: timestamp of the buffer in nano seconds (ns) + * It is Presentation timestamp (PTS) for encoder & decoder. + * Decoder: it is pass through from bitstream to raw buffer. + * firmware does not need to return as part of input = buffer done. + * For any internal buffers: there is no timestamp. Host sets = as 0. + * @reserved: reserved for future use + */ +struct iris_hfi_buffer { + u32 type; + u32 index; + u64 base_address; + u32 addr_offset; + u32 buffer_size; + u32 data_offset; + u32 data_size; + u64 timestamp; + u32 flags; + u32 reserved[5]; +}; + u32 iris_hfi_gen2_get_color_primaries(u32 primaries); u32 iris_hfi_gen2_get_transfer_char(u32 characterstics); u32 iris_hfi_gen2_get_matrix_coefficients(u32 coefficients); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/dr= ivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index ebd82ef13424..9639c7eabd6b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -25,6 +25,94 @@ struct iris_hfi_gen2_packet_handle { int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); }; =20 +static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) +{ + switch (buf_type) { + case HFI_BUFFER_BITSTREAM: + return BUF_INPUT; + case HFI_BUFFER_RAW: + return BUF_OUTPUT; + case HFI_BUFFER_BIN: + return BUF_BIN; + case HFI_BUFFER_ARP: + return BUF_ARP; + case HFI_BUFFER_COMV: + return BUF_COMV; + case HFI_BUFFER_NON_COMV: + return BUF_NON_COMV; + case HFI_BUFFER_LINE: + return BUF_LINE; + case HFI_BUFFER_DPB: + return BUF_DPB; + case HFI_BUFFER_PERSIST: + return BUF_PERSIST; + default: + return 0; + } +} + +static bool iris_hfi_gen2_is_valid_hfi_buffer_type(u32 buffer_type) +{ + switch (buffer_type) { + case HFI_BUFFER_BITSTREAM: + case HFI_BUFFER_RAW: + case HFI_BUFFER_BIN: + case HFI_BUFFER_ARP: + case HFI_BUFFER_COMV: + case HFI_BUFFER_NON_COMV: + case HFI_BUFFER_LINE: + case HFI_BUFFER_DPB: + case HFI_BUFFER_PERSIST: + case HFI_BUFFER_VPSS: + return true; + default: + return false; + } +} + +static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) +{ + if (port =3D=3D HFI_PORT_NONE && buffer_type !=3D HFI_BUFFER_PERSIST) + return false; + + if (port !=3D HFI_PORT_BITSTREAM && port !=3D HFI_PORT_RAW) + return false; + + return true; +} + +static bool iris_hfi_gen2_validate_packet_payload(struct iris_hfi_packet *= pkt) +{ + u32 payload_size =3D 0; + + switch (pkt->payload_info) { + case HFI_PAYLOAD_U32: + case HFI_PAYLOAD_S32: + case HFI_PAYLOAD_Q16: + case HFI_PAYLOAD_U32_ENUM: + case HFI_PAYLOAD_32_PACKED: + payload_size =3D 4; + break; + case HFI_PAYLOAD_U64: + case HFI_PAYLOAD_S64: + case HFI_PAYLOAD_64_PACKED: + payload_size =3D 8; + break; + case HFI_PAYLOAD_STRUCTURE: + if (pkt->type =3D=3D HFI_CMD_BUFFER) + payload_size =3D sizeof(struct iris_hfi_buffer); + break; + default: + payload_size =3D 0; + break; + } + + if (pkt->size < sizeof(struct iris_hfi_packet) + payload_size) + return false; + + return true; +} + static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_p= kt) { u8 *response_limit =3D core_resp_pkt + IFACEQ_CORE_PKT_SIZE; @@ -146,9 +234,65 @@ static void iris_hfi_gen2_handle_session_close(struct = iris_inst *inst, complete(&inst->completion); } =20 +static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *= inst, + struct iris_hfi_buffer *buffer) +{ + struct iris_buffer *buf, *iter; + struct iris_buffers *buffers; + u32 buf_type; + int ret =3D 0; + bool found; + + buf_type =3D iris_hfi_gen2_buf_type_to_driver(buffer->type); + buffers =3D &inst->buffers[buf_type]; + + found =3D false; + list_for_each_entry(iter, &buffers->list, list) { + if (iter->device_addr =3D=3D buffer->base_address) { + found =3D true; + buf =3D iter; + break; + } + } + if (!found) + return -EINVAL; + + buf->attr &=3D ~BUF_ATTR_QUEUED; + + if (buf->attr & BUF_ATTR_PENDING_RELEASE) + ret =3D iris_destroy_internal_buffer(inst, buf); + + return ret; +} + +static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + struct iris_hfi_packet *pkt) +{ + struct iris_hfi_buffer *buffer; + + if (pkt->payload_info =3D=3D HFI_PAYLOAD_NONE) + return 0; + + if (!iris_hfi_gen2_validate_packet_payload(pkt)) { + iris_inst_change_state(inst, IRIS_INST_ERROR); + return 0; + } + + buffer =3D (struct iris_hfi_buffer *)((u8 *)pkt + sizeof(*pkt)); + if (!iris_hfi_gen2_is_valid_hfi_buffer_type(buffer->type)) + return 0; + + if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) + return 0; + + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); +} + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, struct iris_hfi_packet *pkt) { + int ret =3D 0; + switch (pkt->type) { case HFI_CMD_CLOSE: iris_hfi_gen2_handle_session_close(inst, pkt); @@ -156,11 +300,14 @@ static int iris_hfi_gen2_handle_session_command(struc= t iris_inst *inst, case HFI_CMD_STOP: complete(&inst->completion); break; + case HFI_CMD_BUFFER: + ret =3D iris_hfi_gen2_handle_session_buffer(inst, pkt); + break; default: break; } =20 - return 0; + return ret; } =20 static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/driv= ers/media/platform/qcom/iris/iris_platform_common.h index 914283802219..090646aa80ff 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -67,6 +67,7 @@ struct platform_inst_caps { u32 min_frame_height; u32 max_frame_height; u32 max_mbpf; + u32 num_comv; }; =20 enum platform_inst_fw_cap_type { @@ -151,6 +152,10 @@ struct iris_platform_data { unsigned int dec_input_prop_size; const u32 *dec_output_prop; unsigned int dec_output_prop_size; + const u32 *dec_ip_int_buf_tbl; + unsigned int dec_ip_int_buf_tbl_size; + const u32 *dec_op_int_buf_tbl; + unsigned int dec_op_int_buf_tbl_size; }; =20 #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/driv= ers/media/platform/qcom/iris/iris_platform_sm8550.c index 0f1eb530b232..2a45e605e140 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -126,6 +126,7 @@ static struct platform_inst_caps platform_inst_cap_sm85= 50 =3D { .min_frame_height =3D 96, .max_frame_height =3D 8192, .max_mbpf =3D (8192 * 4352) / 256, + .num_comv =3D 0, }; =20 static void iris_set_sm8550_preset_registers(struct iris_core *core) @@ -192,6 +193,17 @@ static const u32 sm8550_vdec_subscribe_output_properti= es[] =3D { HFI_PROP_CABAC_SESSION, }; =20 +static const u32 sm8550_dec_ip_int_buf_tbl[] =3D { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, +}; + +static const u32 sm8550_dec_op_int_buf_tbl[] =3D { + BUF_DPB, +}; + struct iris_platform_data sm8550_data =3D { .get_instance =3D iris_hfi_gen2_get_instance, .init_hfi_command_ops =3D iris_hfi_gen2_command_ops_init, @@ -232,4 +244,9 @@ struct iris_platform_data sm8550_data =3D { .dec_input_prop_size =3D ARRAY_SIZE(sm8550_vdec_subscribe_input_propertie= s), .dec_output_prop =3D sm8550_vdec_subscribe_output_properties, .dec_output_prop_size =3D ARRAY_SIZE(sm8550_vdec_subscribe_output_propert= ies), + + .dec_ip_int_buf_tbl =3D sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size =3D ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl =3D sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size =3D ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/p= latform/qcom/iris/iris_vdec.c index f0242cb4a071..9cd77b551df4 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -292,6 +292,24 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; =20 + ret =3D iris_alloc_and_queue_persist_bufs(inst); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + ret =3D iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MP= LANE); + if (ret) + return ret; + + ret =3D iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPL= ANE); + if (ret) + return ret; + + ret =3D iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLA= NE); + if (ret) + return ret; + return iris_vdec_process_streamon_input(inst); } =20 @@ -316,10 +334,24 @@ int iris_vdec_streamon_output(struct iris_inst *inst) if (ret) return ret; =20 + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + ret =3D iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_M= PLANE); + if (ret) + return ret; + + ret =3D iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MP= LANE); + if (ret) + return ret; + ret =3D iris_vdec_process_streamon_output(inst); if (ret) goto error; =20 + ret =3D iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPL= ANE); + if (ret) + goto error; + return ret; =20 error: diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/p= latform/qcom/iris/iris_vidc.c index 615f57bfaddc..bab9ca52de69 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -146,6 +146,15 @@ int iris_open(struct file *filp) =20 mutex_init(&inst->lock); mutex_init(&inst->ctx_q_lock); + + INIT_LIST_HEAD(&inst->buffers[BUF_BIN].list); + INIT_LIST_HEAD(&inst->buffers[BUF_ARP].list); + INIT_LIST_HEAD(&inst->buffers[BUF_COMV].list); + INIT_LIST_HEAD(&inst->buffers[BUF_NON_COMV].list); + INIT_LIST_HEAD(&inst->buffers[BUF_LINE].list); + INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list); + INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list); + INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list); init_completion(&inst->completion); init_completion(&inst->flush_completion); =20 @@ -218,6 +227,8 @@ int iris_close(struct file *filp) iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); iris_v4l2_fh_deinit(inst); + iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/m= edia/platform/qcom/iris/iris_vpu_buffer.c index 0a65a17f13d2..05e200bcf8c5 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -6,7 +6,167 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" =20 -u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) +static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32= num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv =3D ((frame_width * frame_height) <=3D BIN_BUFFER_THRESHOLD) ? + ((BIN_BUFFER_THRESHOLD * 3) >> 1) : + ((frame_width * frame_height * 3) >> 1); + size_bin_hdr =3D size_yuv * H264_CABAC_HDR_RATIO_HD_TOT; + size_bin_res =3D size_yuv * H264_CABAC_RES_RATIO_HD_TOT; + size_bin_hdr =3D ALIGN(size_bin_hdr / num_vpp_pipes, + DMA_ALIGNMENT) * num_vpp_pipes; + size_bin_res =3D ALIGN(size_bin_res / num_vpp_pipes, + DMA_ALIGNMENT) * num_vpp_pipes; + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num= _vpp_pipes) +{ + u32 n_aligned_h =3D ALIGN(frame_height, 16); + u32 n_aligned_w =3D ALIGN(frame_width, 16); + + return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + +static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _c= omv_bufcount) +{ + u32 frame_height_in_mbs =3D DIV_ROUND_UP(frame_height, 16); + u32 frame_width_in_mbs =3D DIV_ROUND_UP(frame_width, 16); + u32 col_zero_aligned_width =3D (frame_width_in_mbs << 2); + u32 col_mv_aligned_width =3D (frame_width_in_mbs << 7); + u32 col_zero_size, size_colloc; + + col_mv_aligned_width =3D ALIGN(col_mv_aligned_width, 16); + col_zero_aligned_width =3D ALIGN(col_zero_aligned_width, 16); + col_zero_size =3D col_zero_aligned_width * + ((frame_height_in_mbs + 1) >> 1); + col_zero_size =3D ALIGN(col_zero_size, 64); + col_zero_size <<=3D 1; + col_zero_size =3D ALIGN(col_zero_size, 512); + size_colloc =3D col_mv_aligned_width * ((frame_height_in_mbs + 1) >> 1); + size_colloc =3D ALIGN(size_colloc, 64); + size_colloc <<=3D 1; + size_colloc =3D ALIGN(size_colloc, 512); + size_colloc +=3D (col_zero_size + SIZE_H264D_BUFTAB_T * 2); + + return (size_colloc * (_comv_bufcount)) + 512; +} + +static u32 size_h264d_bse_cmd_buf(u32 frame_height) +{ + u32 height =3D ALIGN(frame_height, 32); + + return min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * + SIZE_H264D_BSE_CMD_PER_BUF; +} + +static u32 size_h264d_vpp_cmd_buf(u32 frame_height) +{ + u32 size, height =3D ALIGN(frame_height, 32); + + size =3D min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * + SIZE_H264D_VPP_CMD_PER_BUF; + + return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; +} + +static u32 hfi_buffer_persist_h264d(void) +{ + return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 + + H264_DISPLAY_BUF_SIZE * H264_NUM_FRM_INFO + + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA, + DMA_ALIGNMENT); +} + +static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u3= 2 num_vpp_pipes) +{ + u32 size_bse, size_vpp, size; + + size_bse =3D size_h264d_bse_cmd_buf(frame_height); + size_vpp =3D size_h264d_vpp_cmd_buf(frame_height); + size =3D ALIGN(size_bse, DMA_ALIGNMENT) + + ALIGN(size_vpp, DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + +static u32 size_vpss_lb(u32 frame_width, u32 frame_height) +{ + u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; + u32 opb_wr_top_line_chroma_buffer_size; + u32 opb_wr_top_line_luma_buffer_size; + u32 macrotiling_size =3D 32; + + opb_wr_top_line_luma_buffer_size =3D + ALIGN(frame_width, macrotiling_size) / macrotiling_size * 256; + opb_wr_top_line_luma_buffer_size =3D + ALIGN(opb_wr_top_line_luma_buffer_size, DMA_ALIGNMENT) + + (MAX_TILE_COLUMNS - 1) * 256; + opb_wr_top_line_luma_buffer_size =3D + max_t(u32, opb_wr_top_line_luma_buffer_size, (32 * ALIGN(frame_height, 8= ))); + opb_wr_top_line_chroma_buffer_size =3D opb_wr_top_line_luma_buffer_size; + opb_lb_wr_llb_uv_buffer_size =3D + ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); + opb_lb_wr_llb_y_buffer_size =3D + ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); + return opb_wr_top_line_luma_buffer_size + + opb_wr_top_line_chroma_buffer_size + + opb_lb_wr_llb_uv_buffer_size + + opb_lb_wr_llb_y_buffer_size; +} + +static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, + bool is_opb, u32 num_vpp_pipes) +{ + u32 vpss_lb_size =3D 0; + u32 size; + + size =3D ALIGN(size_h264d_lb_fe_top_data(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_top_ctrl(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp= _pipes + + ALIGN(size_h264d_lb_se_top_ctrl(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_se_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp= _pipes + + ALIGN(size_h264d_lb_pe_top_data(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) = * 2 + + ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT); + size =3D ALIGN(size, DMA_ALIGNMENT); + if (is_opb) + vpss_lb_size =3D size_vpss_lb(frame_width, frame_height); + + return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT); +} + +static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes =3D inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f =3D inst->fmt_src; + u32 height =3D f->fmt.pix_mp.height; + u32 width =3D f->fmt.pix_mp.width; + + return hfi_buffer_bin_h264d(width, height, num_vpp_pipes); +} + +static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) +{ + u32 num_comv =3D inst->buffers[BUF_OUTPUT].min_count; + struct v4l2_format *f =3D inst->fmt_src; + u32 height =3D f->fmt.pix_mp.height; + u32 width =3D f->fmt.pix_mp.width; + + return hfi_buffer_comv_h264d(width, height, num_comv); +} + +static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) +{ + return hfi_buffer_persist_h264d(); +} + +static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) return iris_get_buffer_size(inst, BUF_DPB); @@ -14,6 +174,70 @@ u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) return 0; } =20 +static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes =3D inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f =3D inst->fmt_src; + u32 height =3D f->fmt.pix_mp.height; + u32 width =3D f->fmt.pix_mp.width; + + return hfi_buffer_non_comv_h264d(width, height, num_vpp_pipes); +} + +static u32 iris_vpu_dec_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes =3D inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f =3D inst->fmt_src; + u32 height =3D f->fmt.pix_mp.height; + u32 width =3D f->fmt.pix_mp.width; + bool is_opb =3D false; + + if (iris_split_mode_enabled(inst)) + is_opb =3D true; + + return hfi_buffer_line_h264d(width, height, is_opb, num_vpp_pipes); +} + +static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) +{ + return iris_vpu_dec_comv_size(inst) + + iris_vpu_dec_non_comv_size(inst) + + iris_vpu_dec_line_size(inst); +} + +struct iris_vpu_buf_type_handle { + enum iris_buffer_type type; + u32 (*handle)(struct iris_inst *inst); +}; + +int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer= _type) +{ + const struct iris_vpu_buf_type_handle *buf_type_handle_arr; + u32 size =3D 0, buf_type_handle_size, i; + + static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle= [] =3D { + {BUF_BIN, iris_vpu_dec_bin_size }, + {BUF_COMV, iris_vpu_dec_comv_size }, + {BUF_NON_COMV, iris_vpu_dec_non_comv_size }, + {BUF_LINE, iris_vpu_dec_line_size }, + {BUF_PERSIST, iris_vpu_dec_persist_size }, + {BUF_DPB, iris_vpu_dec_dpb_size }, + {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, + }; + + buf_type_handle_size =3D ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr =3D dec_internal_buf_type_handle; + + for (i =3D 0; i < buf_type_handle_size; i++) { + if (buf_type_handle_arr[i].type =3D=3D buffer_type) { + size =3D buf_type_handle_arr[i].handle(inst); + break; + } + } + + return size; +} + static inline int iris_vpu_dpb_count(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) { @@ -31,6 +255,13 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iri= s_buffer_type buffer_type return MIN_BUFFERS; case BUF_OUTPUT: return inst->fw_min_count; + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + case BUF_PERSIST: + case BUF_SCRATCH_1: + return 1; /* internal buffer count needed by firmware is 1 */ case BUF_DPB: return iris_vpu_dpb_count(inst); default: diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/m= edia/platform/qcom/iris/iris_vpu_buffer.h index 03a181c5754d..1bc598ee9c20 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -10,7 +10,82 @@ struct iris_inst; =20 #define MIN_BUFFERS 4 =20 -u32 iris_vpu_dec_dpb_size(struct iris_inst *inst); +#define DMA_ALIGNMENT 256 + +#define NUM_HW_PIC_BUF 32 +#define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf)) + +#define MAX_TILE_COLUMNS 32 +#define BIN_BUFFER_THRESHOLD (1280 * 736) +#define VPP_CMD_MAX_SIZE (BIT(20)) +#define H264D_MAX_SLICE 1800 + +#define SIZE_H264D_BUFTAB_T 256 +#define SIZE_H264D_BSE_CMD_PER_BUF (32 * 4) +#define SIZE_H264D_VPP_CMD_PER_BUF 512 + +#define NUM_SLIST_BUF_H264 (256 + 32) +#define SIZE_SLIST_BUF_H264 512 +#define H264_DISPLAY_BUF_SIZE 3328 +#define H264_NUM_FRM_INFO 66 + +#define SIZE_SEI_USERDATA 4096 + +#define H264_CABAC_HDR_RATIO_HD_TOT 1 +#define H264_CABAC_RES_RATIO_HD_TOT 3 +#define SIZE_H264D_HW_PIC_T (BIT(11)) + +#define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 +#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16 +#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 +#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 + +static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) +{ + return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; +} + +static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width,= 16); +} + +static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height= , 16); +} + +static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width,= 16); +} + +static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height= , 16); +} + +static inline u32 size_h264d_lb_pe_top_data(u32 frame_width) +{ + return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width,= 16); +} + +static inline u32 size_h264d_lb_vsp_top(u32 frame_width) +{ + return (DIV_ROUND_UP(frame_width, 16) << 7); +} + +static inline u32 size_h264d_lb_recon_dma_metadata_wr(u32 frame_height) +{ + return ALIGN(frame_height, 16) * 32; +} + +static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) +{ + return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 1= 28; +} + +int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer= _type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffe= r_type); =20 #endif --=20 2.34.1