vdec_vpu_if.c (7199B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2016 MediaTek Inc. 4 * Author: PC Chen <pc.chen@mediatek.com> 5 */ 6 7#include "mtk_vcodec_drv.h" 8#include "mtk_vcodec_util.h" 9#include "vdec_drv_if.h" 10#include "vdec_ipi_msg.h" 11#include "vdec_vpu_if.h" 12#include "mtk_vcodec_fw.h" 13 14static void handle_init_ack_msg(const struct vdec_vpu_ipi_init_ack *msg) 15{ 16 struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *) 17 (unsigned long)msg->ap_inst_addr; 18 19 mtk_vcodec_debug(vpu, "+ ap_inst_addr = 0x%llx", msg->ap_inst_addr); 20 21 /* mapping VPU address to kernel virtual address */ 22 /* the content in vsi is initialized to 0 in VPU */ 23 vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler, 24 msg->vpu_inst_addr); 25 vpu->inst_addr = msg->vpu_inst_addr; 26 27 mtk_vcodec_debug(vpu, "- vpu_inst_addr = 0x%x", vpu->inst_addr); 28 29 /* Set default ABI version if dealing with unversioned firmware. */ 30 vpu->fw_abi_version = 0; 31 /* 32 * Instance ID is only used if ABI version >= 2. Initialize it with 33 * garbage by default. 34 */ 35 vpu->inst_id = 0xdeadbeef; 36 37 /* VPU firmware does not contain a version field. */ 38 if (mtk_vcodec_fw_get_type(vpu->ctx->dev->fw_handler) == VPU) 39 return; 40 41 /* Check firmware version. */ 42 vpu->fw_abi_version = msg->vdec_abi_version; 43 mtk_vcodec_debug(vpu, "firmware version 0x%x\n", vpu->fw_abi_version); 44 switch (vpu->fw_abi_version) { 45 case 1: 46 break; 47 case 2: 48 vpu->inst_id = msg->inst_id; 49 break; 50 default: 51 mtk_vcodec_err(vpu, "unhandled firmware version 0x%x\n", 52 vpu->fw_abi_version); 53 vpu->failure = 1; 54 break; 55 } 56} 57 58static void handle_get_param_msg_ack(const struct vdec_vpu_ipi_get_param_ack *msg) 59{ 60 struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *) 61 (unsigned long)msg->ap_inst_addr; 62 63 mtk_vcodec_debug(vpu, "+ ap_inst_addr = 0x%llx", msg->ap_inst_addr); 64 65 /* param_type is enum vdec_get_param_type */ 66 switch (msg->param_type) { 67 case GET_PARAM_PIC_INFO: 68 vpu->fb_sz[0] = msg->data[0]; 69 vpu->fb_sz[1] = msg->data[1]; 70 break; 71 default: 72 mtk_vcodec_err(vpu, "invalid get param type=%d", msg->param_type); 73 vpu->failure = 1; 74 break; 75 } 76} 77 78/* 79 * vpu_dec_ipi_handler - Handler for VPU ipi message. 80 * 81 * @data: ipi message 82 * @len : length of ipi message 83 * @priv: callback private data which is passed by decoder when register. 84 * 85 * This function runs in interrupt context and it means there's an IPI MSG 86 * from VPU. 87 */ 88static void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv) 89{ 90 const struct vdec_vpu_ipi_ack *msg = data; 91 struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *) 92 (unsigned long)msg->ap_inst_addr; 93 94 mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id); 95 96 vpu->failure = msg->status; 97 vpu->signaled = 1; 98 99 if (msg->status == 0) { 100 switch (msg->msg_id) { 101 case VPU_IPIMSG_DEC_INIT_ACK: 102 handle_init_ack_msg(data); 103 break; 104 105 case VPU_IPIMSG_DEC_START_ACK: 106 case VPU_IPIMSG_DEC_END_ACK: 107 case VPU_IPIMSG_DEC_DEINIT_ACK: 108 case VPU_IPIMSG_DEC_RESET_ACK: 109 case VPU_IPIMSG_DEC_CORE_ACK: 110 case VPU_IPIMSG_DEC_CORE_END_ACK: 111 break; 112 113 case VPU_IPIMSG_DEC_GET_PARAM_ACK: 114 handle_get_param_msg_ack(data); 115 break; 116 default: 117 mtk_vcodec_err(vpu, "invalid msg=%X", msg->msg_id); 118 break; 119 } 120 } 121 122 mtk_vcodec_debug(vpu, "- id=%X", msg->msg_id); 123} 124 125static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len) 126{ 127 int err, id, msgid; 128 129 msgid = *(uint32_t *)msg; 130 mtk_vcodec_debug(vpu, "id=%X", msgid); 131 132 vpu->failure = 0; 133 vpu->signaled = 0; 134 135 if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) { 136 if (msgid == AP_IPIMSG_DEC_CORE || 137 msgid == AP_IPIMSG_DEC_CORE_END) 138 id = vpu->core_id; 139 else 140 id = vpu->id; 141 } else { 142 id = vpu->id; 143 } 144 145 err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg, 146 len, 2000); 147 if (err) { 148 mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d", 149 id, msgid, err); 150 return err; 151 } 152 153 return vpu->failure; 154} 155 156static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id) 157{ 158 struct vdec_ap_ipi_cmd msg; 159 int err = 0; 160 161 mtk_vcodec_debug(vpu, "+ id=%X", msg_id); 162 163 memset(&msg, 0, sizeof(msg)); 164 msg.msg_id = msg_id; 165 if (vpu->fw_abi_version < 2) 166 msg.vpu_inst_addr = vpu->inst_addr; 167 else 168 msg.inst_id = vpu->inst_id; 169 msg.codec_type = vpu->codec_type; 170 171 err = vcodec_vpu_send_msg(vpu, &msg, sizeof(msg)); 172 mtk_vcodec_debug(vpu, "- id=%X ret=%d", msg_id, err); 173 return err; 174} 175 176int vpu_dec_init(struct vdec_vpu_inst *vpu) 177{ 178 struct vdec_ap_ipi_init msg; 179 int err; 180 181 mtk_vcodec_debug_enter(vpu); 182 183 init_waitqueue_head(&vpu->wq); 184 vpu->handler = vpu_dec_ipi_handler; 185 186 err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id, 187 vpu->handler, "vdec", NULL); 188 if (err) { 189 mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err); 190 return err; 191 } 192 193 if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) { 194 err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, 195 vpu->core_id, vpu->handler, 196 "vdec", NULL); 197 if (err) { 198 mtk_vcodec_err(vpu, "vpu_ipi_register core fail status=%d", err); 199 return err; 200 } 201 } 202 203 memset(&msg, 0, sizeof(msg)); 204 msg.msg_id = AP_IPIMSG_DEC_INIT; 205 msg.ap_inst_addr = (unsigned long)vpu; 206 msg.codec_type = vpu->codec_type; 207 208 mtk_vcodec_debug(vpu, "vdec_inst=%p", vpu); 209 210 err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg)); 211 mtk_vcodec_debug(vpu, "- ret=%d", err); 212 return err; 213} 214 215int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len) 216{ 217 struct vdec_ap_ipi_dec_start msg; 218 int i; 219 int err = 0; 220 221 mtk_vcodec_debug_enter(vpu); 222 223 if (len > ARRAY_SIZE(msg.data)) { 224 mtk_vcodec_err(vpu, "invalid len = %d\n", len); 225 return -EINVAL; 226 } 227 228 memset(&msg, 0, sizeof(msg)); 229 msg.msg_id = AP_IPIMSG_DEC_START; 230 if (vpu->fw_abi_version < 2) 231 msg.vpu_inst_addr = vpu->inst_addr; 232 else 233 msg.inst_id = vpu->inst_id; 234 235 for (i = 0; i < len; i++) 236 msg.data[i] = data[i]; 237 msg.codec_type = vpu->codec_type; 238 239 err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg)); 240 mtk_vcodec_debug(vpu, "- ret=%d", err); 241 return err; 242} 243 244int vpu_dec_get_param(struct vdec_vpu_inst *vpu, uint32_t *data, 245 unsigned int len, unsigned int param_type) 246{ 247 struct vdec_ap_ipi_get_param msg; 248 int err; 249 250 mtk_vcodec_debug_enter(vpu); 251 252 if (len > ARRAY_SIZE(msg.data)) { 253 mtk_vcodec_err(vpu, "invalid len = %d\n", len); 254 return -EINVAL; 255 } 256 257 memset(&msg, 0, sizeof(msg)); 258 msg.msg_id = AP_IPIMSG_DEC_GET_PARAM; 259 msg.inst_id = vpu->inst_id; 260 memcpy(msg.data, data, sizeof(unsigned int) * len); 261 msg.param_type = param_type; 262 msg.codec_type = vpu->codec_type; 263 264 err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg)); 265 mtk_vcodec_debug(vpu, "- ret=%d", err); 266 return err; 267} 268 269int vpu_dec_core(struct vdec_vpu_inst *vpu) 270{ 271 return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_CORE); 272} 273 274int vpu_dec_end(struct vdec_vpu_inst *vpu) 275{ 276 return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_END); 277} 278 279int vpu_dec_core_end(struct vdec_vpu_inst *vpu) 280{ 281 return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_CORE_END); 282} 283 284int vpu_dec_deinit(struct vdec_vpu_inst *vpu) 285{ 286 return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_DEINIT); 287} 288 289int vpu_dec_reset(struct vdec_vpu_inst *vpu) 290{ 291 return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_RESET); 292}