1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 MediaTek Inc. 4 * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com> 5 */ 6 7 #include <linux/remoteproc.h> 8 #include <linux/remoteproc/mtk_scp.h> 9 #include "mtk-mdp3-vpu.h" 10 #include "mtk-mdp3-core.h" 11 12 #define MDP_VPU_MESSAGE_TIMEOUT 500U 13 #define vpu_alloc_size 0x600000 14 15 static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu) 16 { 17 return container_of(vpu, struct mdp_dev, vpu); 18 } 19 20 static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu) 21 { 22 if (vpu->work && vpu->work_addr) 23 return 0; 24 25 vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size, 26 &vpu->work_addr, GFP_KERNEL); 27 28 if (!vpu->work) 29 return -ENOMEM; 30 else 31 return 0; 32 } 33 34 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu) 35 { 36 if (vpu->work && vpu->work_addr) 37 dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size, 38 vpu->work, vpu->work_addr); 39 } 40 41 static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len, 42 void *priv) 43 { 44 struct mdp_ipi_init_msg *msg = (struct mdp_ipi_init_msg *)data; 45 struct mdp_vpu_dev *vpu = 46 (struct mdp_vpu_dev *)(unsigned long)msg->drv_data; 47 48 if (!vpu->work_size) 49 vpu->work_size = msg->work_size; 50 51 vpu->status = msg->status; 52 complete(&vpu->ipi_acked); 53 } 54 55 static void mdp_vpu_ipi_handle_deinit_ack(void *data, unsigned int len, 56 void *priv) 57 { 58 struct mdp_ipi_deinit_msg *msg = (struct mdp_ipi_deinit_msg *)data; 59 struct mdp_vpu_dev *vpu = 60 (struct mdp_vpu_dev *)(unsigned long)msg->drv_data; 61 62 vpu->status = msg->status; 63 complete(&vpu->ipi_acked); 64 } 65 66 static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len, 67 void *priv) 68 { 69 struct img_sw_addr *addr = (struct img_sw_addr *)data; 70 struct img_ipi_frameparam *param = 71 (struct img_ipi_frameparam *)(unsigned long)addr->va; 72 struct mdp_vpu_ctx *ctx = 73 (struct mdp_vpu_ctx *)(unsigned long)param->drv_data; 74 75 if (param->state) { 76 struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev); 77 78 dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state); 79 } 80 ctx->vpu_dev->status = param->state; 81 complete(&ctx->vpu_dev->ipi_acked); 82 } 83 84 int mdp_vpu_register(struct mdp_dev *mdp) 85 { 86 int err; 87 struct mtk_scp *scp = mdp->scp; 88 struct device *dev = &mdp->pdev->dev; 89 90 err = scp_ipi_register(scp, SCP_IPI_MDP_INIT, 91 mdp_vpu_ipi_handle_init_ack, NULL); 92 if (err) { 93 dev_err(dev, "scp_ipi_register failed %d\n", err); 94 goto err_ipi_init; 95 } 96 err = scp_ipi_register(scp, SCP_IPI_MDP_DEINIT, 97 mdp_vpu_ipi_handle_deinit_ack, NULL); 98 if (err) { 99 dev_err(dev, "scp_ipi_register failed %d\n", err); 100 goto err_ipi_deinit; 101 } 102 err = scp_ipi_register(scp, SCP_IPI_MDP_FRAME, 103 mdp_vpu_ipi_handle_frame_ack, NULL); 104 if (err) { 105 dev_err(dev, "scp_ipi_register failed %d\n", err); 106 goto err_ipi_frame; 107 } 108 return 0; 109 110 err_ipi_frame: 111 scp_ipi_unregister(scp, SCP_IPI_MDP_DEINIT); 112 err_ipi_deinit: 113 scp_ipi_unregister(scp, SCP_IPI_MDP_INIT); 114 err_ipi_init: 115 116 return err; 117 } 118 119 void mdp_vpu_unregister(struct mdp_dev *mdp) 120 { 121 scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_INIT); 122 scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_DEINIT); 123 scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_FRAME); 124 } 125 126 static int mdp_vpu_sendmsg(struct mdp_vpu_dev *vpu, enum scp_ipi_id id, 127 void *buf, unsigned int len) 128 { 129 struct mdp_dev *mdp = vpu_to_mdp(vpu); 130 unsigned int t = MDP_VPU_MESSAGE_TIMEOUT; 131 int ret; 132 133 if (!vpu->scp) { 134 dev_dbg(&mdp->pdev->dev, "vpu scp is NULL"); 135 return -EINVAL; 136 } 137 ret = scp_ipi_send(vpu->scp, id, buf, len, 2000); 138 139 if (ret) { 140 dev_err(&mdp->pdev->dev, "scp_ipi_send failed %d\n", ret); 141 return -EPERM; 142 } 143 ret = wait_for_completion_timeout(&vpu->ipi_acked, 144 msecs_to_jiffies(t)); 145 if (!ret) 146 ret = -ETIME; 147 else if (vpu->status) 148 ret = -EINVAL; 149 else 150 ret = 0; 151 return ret; 152 } 153 154 int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, 155 struct mutex *lock) 156 { 157 struct mdp_ipi_init_msg msg = { 158 .drv_data = (unsigned long)vpu, 159 }; 160 size_t mem_size; 161 phys_addr_t pool; 162 const size_t pool_size = sizeof(struct mdp_config_pool); 163 struct mdp_dev *mdp = vpu_to_mdp(vpu); 164 int err; 165 166 init_completion(&vpu->ipi_acked); 167 vpu->scp = scp; 168 vpu->lock = lock; 169 vpu->work_size = 0; 170 err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg)); 171 if (err) 172 goto err_work_size; 173 /* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */ 174 175 mem_size = vpu_alloc_size; 176 if (mdp_vpu_shared_mem_alloc(vpu)) { 177 dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); 178 goto err_mem_alloc; 179 } 180 181 pool = ALIGN((uintptr_t)vpu->work + vpu->work_size, 8); 182 if (pool + pool_size - (uintptr_t)vpu->work > mem_size) { 183 dev_err(&mdp->pdev->dev, 184 "VPU memory insufficient: %zx + %zx > %zx", 185 vpu->work_size, pool_size, mem_size); 186 err = -ENOMEM; 187 goto err_mem_size; 188 } 189 190 dev_dbg(&mdp->pdev->dev, 191 "VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)", 192 vpu->work, &vpu->work_addr, vpu->work_size, 193 &pool, pool_size, mem_size); 194 vpu->pool = (struct mdp_config_pool *)(uintptr_t)pool; 195 msg.work_addr = vpu->work_addr; 196 msg.work_size = vpu->work_size; 197 err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg)); 198 if (err) 199 goto err_work_size; 200 201 memset(vpu->pool, 0, sizeof(*vpu->pool)); 202 return 0; 203 204 err_work_size: 205 switch (vpu->status) { 206 case -MDP_IPI_EBUSY: 207 err = -EBUSY; 208 break; 209 case -MDP_IPI_ENOMEM: 210 err = -ENOSPC; /* -ENOMEM */ 211 break; 212 } 213 return err; 214 err_mem_size: 215 err_mem_alloc: 216 return err; 217 } 218 219 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu) 220 { 221 struct mdp_ipi_deinit_msg msg = { 222 .drv_data = (unsigned long)vpu, 223 .work_addr = vpu->work_addr, 224 }; 225 226 return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg)); 227 } 228 229 static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu, 230 enum mdp_config_id id, uint32_t *addr) 231 { 232 struct img_config *config; 233 234 if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) 235 return ERR_PTR(-EINVAL); 236 237 mutex_lock(vpu->lock); 238 vpu->pool->cfg_count[id]++; 239 config = &vpu->pool->configs[id]; 240 *addr = vpu->work_addr + ((uintptr_t)config - (uintptr_t)vpu->work); 241 mutex_unlock(vpu->lock); 242 243 return config; 244 } 245 246 static int mdp_config_put(struct mdp_vpu_dev *vpu, 247 enum mdp_config_id id, 248 const struct img_config *config) 249 { 250 int err = 0; 251 252 if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) 253 return -EINVAL; 254 if (vpu->lock) 255 mutex_lock(vpu->lock); 256 if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id]) 257 err = -EINVAL; 258 else 259 vpu->pool->cfg_count[id]--; 260 if (vpu->lock) 261 mutex_unlock(vpu->lock); 262 return err; 263 } 264 265 int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu, 266 enum mdp_config_id id) 267 { 268 ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr); 269 if (IS_ERR(ctx->config)) { 270 int err = PTR_ERR(ctx->config); 271 272 ctx->config = NULL; 273 return err; 274 } 275 ctx->config_id = id; 276 ctx->vpu_dev = vpu; 277 return 0; 278 } 279 280 int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx) 281 { 282 int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config); 283 284 ctx->config_id = 0; 285 ctx->config = NULL; 286 ctx->inst_addr = 0; 287 return err; 288 } 289 290 int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param) 291 { 292 struct mdp_vpu_dev *vpu = ctx->vpu_dev; 293 struct mdp_dev *mdp = vpu_to_mdp(vpu); 294 struct img_sw_addr addr; 295 296 if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) { 297 if (mdp_vpu_shared_mem_alloc(vpu)) { 298 dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); 299 return -ENOMEM; 300 } 301 } 302 memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size); 303 memset(ctx->config, 0, sizeof(*ctx->config)); 304 param->config_data.va = (unsigned long)ctx->config; 305 param->config_data.pa = ctx->inst_addr; 306 param->drv_data = (unsigned long)ctx; 307 308 memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param)); 309 addr.pa = ctx->vpu_dev->work_addr; 310 addr.va = (uintptr_t)ctx->vpu_dev->work; 311 return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME, 312 &addr, sizeof(addr)); 313 } 314