Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: platform: mtk-mdp3: reconfigure shared memory

For performance and multi-chip support, use dynamic layout instead of
statically configured pools.
Divide the shared memory into the 3 64-bit aligned layouts listed below:

vpu->param_addr -> +-----------------------------------------+
| |
| To SCP : Input frame parameters |
| (struct img_ipi_frameparam) |
| |
+-----------------------------------------+

vpu->work_addr -> +-----------------------------------------+
| |
| In SCP : Reserve for SCP calculation |
| |
+-----------------------------------------+

vpu->config_addr -> +-----------------------------------------+
| |
| From SCP : Output component config |
| (struct img_config) |
| |
+-----------------------------------------+

Signed-off-by: Moudy Ho <moudy.ho@mediatek.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>

authored by

Moudy Ho and committed by
Hans Verkuil
b4e52199 09e694f1

+97 -147
+2 -2
drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h
··· 11 11 12 12 /* 13 13 * ISP-MDP generic output information 14 - * MD5 of the target SCP blob: 15 - * 6da52bdcf4bf76a0983b313e1d4745d6 14 + * MD5 of the target SCP prebuild: 15 + * 2d995ddb5c3b0cf26e96d6a823481886 16 16 */ 17 17 18 18 #define IMG_MAX_SUBFRAMES_8183 14
+3 -10
drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c
··· 87 87 dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); 88 88 mdp_set_dst_config(&param.outputs[0], frame, &dst_vb->vb2_buf); 89 89 90 - ret = mdp_vpu_process(&ctx->vpu, &param); 90 + ret = mdp_vpu_process(&ctx->mdp_dev->vpu, &param); 91 91 if (ret) { 92 92 dev_err(&ctx->mdp_dev->pdev->dev, 93 93 "VPU MDP process failed: %d\n", ret); 94 94 goto worker_end; 95 95 } 96 96 97 - task.config = ctx->vpu.config; 97 + task.config = ctx->mdp_dev->vpu.config; 98 98 task.param = &param; 99 99 task.composes[0] = &frame->compose; 100 100 task.cmdq_cb = NULL; ··· 150 150 151 151 if (!mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { 152 152 ret = mdp_vpu_get_locked(ctx->mdp_dev); 153 - if (ret) 154 - return ret; 155 - 156 - ret = mdp_vpu_ctx_init(&ctx->vpu, &ctx->mdp_dev->vpu, 157 - MDP_DEV_M2M); 158 153 if (ret) { 159 154 dev_err(&ctx->mdp_dev->pdev->dev, 160 155 "VPU init failed %d\n", ret); ··· 636 641 637 642 mutex_lock(&mdp->m2m_lock); 638 643 v4l2_m2m_ctx_release(ctx->m2m_ctx); 639 - if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { 640 - mdp_vpu_ctx_deinit(&ctx->vpu); 644 + if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) 641 645 mdp_vpu_put_locked(mdp); 642 - } 643 646 644 647 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 645 648 v4l2_fh_del(&ctx->fh);
-1
drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.h
··· 33 33 struct v4l2_ctrl_handler ctrl_handler; 34 34 struct mdp_m2m_ctrls ctrls; 35 35 struct v4l2_m2m_ctx *m2m_ctx; 36 - struct mdp_vpu_ctx vpu; 37 36 u32 frame_count[MDP_M2M_MAX]; 38 37 39 38 struct mdp_frameparam curr_param;
+85 -112
drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c
··· 10 10 #include "mtk-mdp3-core.h" 11 11 12 12 #define MDP_VPU_MESSAGE_TIMEOUT 500U 13 - #define vpu_alloc_size 0x600000 14 13 15 14 static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu) 16 15 { ··· 18 19 19 20 static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu) 20 21 { 21 - if (vpu->work && vpu->work_addr) 22 - return 0; 22 + struct device *dev; 23 23 24 - vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size, 25 - &vpu->work_addr, GFP_KERNEL); 24 + if (IS_ERR_OR_NULL(vpu)) 25 + goto err_return; 26 26 27 - if (!vpu->work) 28 - return -ENOMEM; 29 - else 30 - return 0; 27 + dev = scp_get_device(vpu->scp); 28 + 29 + if (!vpu->param) { 30 + vpu->param = dma_alloc_wc(dev, vpu->param_size, 31 + &vpu->param_addr, GFP_KERNEL); 32 + if (!vpu->param) 33 + goto err_return; 34 + } 35 + 36 + if (!vpu->work) { 37 + vpu->work = dma_alloc_wc(dev, vpu->work_size, 38 + &vpu->work_addr, GFP_KERNEL); 39 + if (!vpu->work) 40 + goto err_free_param; 41 + } 42 + 43 + if (!vpu->config) { 44 + vpu->config = dma_alloc_wc(dev, vpu->config_size, 45 + &vpu->config_addr, GFP_KERNEL); 46 + if (!vpu->config) 47 + goto err_free_work; 48 + } 49 + 50 + return 0; 51 + 52 + err_free_work: 53 + dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr); 54 + vpu->work = NULL; 55 + err_free_param: 56 + dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr); 57 + vpu->param = NULL; 58 + err_return: 59 + return -ENOMEM; 31 60 } 32 61 33 62 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu) 34 63 { 64 + struct device *dev; 65 + 66 + if (IS_ERR_OR_NULL(vpu)) 67 + return; 68 + 69 + dev = scp_get_device(vpu->scp); 70 + 71 + if (vpu->param && vpu->param_addr) 72 + dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr); 73 + 35 74 if (vpu->work && vpu->work_addr) 36 - dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size, 37 - vpu->work, vpu->work_addr); 75 + dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr); 76 + 77 + if (vpu->config && vpu->config_addr) 78 + dma_free_wc(dev, vpu->config_size, vpu->config, vpu->config_addr); 38 79 } 39 80 40 81 static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len, ··· 108 69 struct img_sw_addr *addr = (struct img_sw_addr *)data; 109 70 struct img_ipi_frameparam *param = 110 71 (struct img_ipi_frameparam *)(unsigned long)addr->va; 111 - struct mdp_vpu_ctx *ctx = 112 - (struct mdp_vpu_ctx *)(unsigned long)param->drv_data; 72 + struct mdp_vpu_dev *vpu = 73 + (struct mdp_vpu_dev *)(unsigned long)param->drv_data; 113 74 114 75 if (param->state) { 115 - struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev); 76 + struct mdp_dev *mdp = vpu_to_mdp(vpu); 116 77 117 78 dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state); 118 79 } 119 - ctx->vpu_dev->status = param->state; 120 - complete(&ctx->vpu_dev->ipi_acked); 80 + vpu->status = param->state; 81 + complete(&vpu->ipi_acked); 121 82 } 122 83 123 84 int mdp_vpu_register(struct mdp_dev *mdp) ··· 196 157 struct mdp_ipi_init_msg msg = { 197 158 .drv_data = (unsigned long)vpu, 198 159 }; 199 - size_t mem_size; 200 - phys_addr_t pool; 201 - const size_t pool_size = sizeof(struct mdp_config_pool); 202 160 struct mdp_dev *mdp = vpu_to_mdp(vpu); 203 161 int err; 204 162 ··· 208 172 goto err_work_size; 209 173 /* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */ 210 174 211 - mem_size = vpu_alloc_size; 175 + mutex_lock(vpu->lock); 176 + vpu->work_size = ALIGN(vpu->work_size, 64); 177 + vpu->param_size = ALIGN(sizeof(struct img_ipi_frameparam), 64); 178 + vpu->config_size = ALIGN(sizeof(struct img_config), 64); 212 179 err = mdp_vpu_shared_mem_alloc(vpu); 180 + mutex_unlock(vpu->lock); 213 181 if (err) { 214 182 dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); 215 183 goto err_mem_alloc; 216 184 } 217 185 218 - pool = ALIGN((uintptr_t)vpu->work + vpu->work_size, 8); 219 - if (pool + pool_size - (uintptr_t)vpu->work > mem_size) { 220 - dev_err(&mdp->pdev->dev, 221 - "VPU memory insufficient: %zx + %zx > %zx", 222 - vpu->work_size, pool_size, mem_size); 223 - err = -ENOMEM; 224 - goto err_mem_size; 225 - } 226 - 227 186 dev_dbg(&mdp->pdev->dev, 228 - "VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)", 187 + "VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx", 188 + vpu->param, &vpu->param_addr, vpu->param_size, 229 189 vpu->work, &vpu->work_addr, vpu->work_size, 230 - &pool, pool_size, mem_size); 231 - vpu->pool = (struct mdp_config_pool *)(uintptr_t)pool; 190 + vpu->config, &vpu->config_addr, vpu->config_size); 191 + 232 192 msg.work_addr = vpu->work_addr; 233 193 msg.work_size = vpu->work_size; 234 194 err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg)); 235 195 if (err) 236 196 goto err_work_size; 237 197 238 - memset(vpu->pool, 0, sizeof(*vpu->pool)); 239 198 return 0; 240 199 241 200 err_work_size: ··· 243 212 break; 244 213 } 245 214 return err; 246 - err_mem_size: 247 215 err_mem_alloc: 248 216 return err; 249 217 } ··· 257 227 return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg)); 258 228 } 259 229 260 - static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu, 261 - enum mdp_config_id id, uint32_t *addr) 230 + int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param) 262 231 { 263 - struct img_config *config; 264 - 265 - if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) 266 - return ERR_PTR(-EINVAL); 267 - 268 - mutex_lock(vpu->lock); 269 - vpu->pool->cfg_count[id]++; 270 - config = &vpu->pool->configs[id]; 271 - *addr = vpu->work_addr + ((uintptr_t)config - (uintptr_t)vpu->work); 272 - mutex_unlock(vpu->lock); 273 - 274 - return config; 275 - } 276 - 277 - static int mdp_config_put(struct mdp_vpu_dev *vpu, 278 - enum mdp_config_id id, 279 - const struct img_config *config) 280 - { 281 - int err = 0; 282 - 283 - if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) 284 - return -EINVAL; 285 - if (vpu->lock) 286 - mutex_lock(vpu->lock); 287 - if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id]) 288 - err = -EINVAL; 289 - else 290 - vpu->pool->cfg_count[id]--; 291 - if (vpu->lock) 292 - mutex_unlock(vpu->lock); 293 - return err; 294 - } 295 - 296 - int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu, 297 - enum mdp_config_id id) 298 - { 299 - ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr); 300 - if (IS_ERR(ctx->config)) { 301 - int err = PTR_ERR(ctx->config); 302 - 303 - ctx->config = NULL; 304 - return err; 305 - } 306 - ctx->config_id = id; 307 - ctx->vpu_dev = vpu; 308 - return 0; 309 - } 310 - 311 - int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx) 312 - { 313 - int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config); 314 - 315 - ctx->config_id = 0; 316 - ctx->config = NULL; 317 - ctx->inst_addr = 0; 318 - return err; 319 - } 320 - 321 - int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param) 322 - { 323 - struct mdp_vpu_dev *vpu = ctx->vpu_dev; 324 232 struct mdp_dev *mdp = vpu_to_mdp(vpu); 325 233 struct img_sw_addr addr; 326 234 327 - if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) { 328 - if (mdp_vpu_shared_mem_alloc(vpu)) { 329 - dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); 330 - return -ENOMEM; 331 - } 235 + mutex_lock(vpu->lock); 236 + if (mdp_vpu_shared_mem_alloc(vpu)) { 237 + dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); 238 + mutex_unlock(vpu->lock); 239 + return -ENOMEM; 332 240 } 333 - memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size); 334 - memset(ctx->config, 0, sizeof(*ctx->config)); 335 - param->config_data.va = (unsigned long)ctx->config; 336 - param->config_data.pa = ctx->inst_addr; 337 - param->drv_data = (unsigned long)ctx; 338 241 339 - memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param)); 340 - addr.pa = ctx->vpu_dev->work_addr; 341 - addr.va = (uintptr_t)ctx->vpu_dev->work; 342 - return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME, 343 - &addr, sizeof(addr)); 242 + memset(vpu->param, 0, vpu->param_size); 243 + memset(vpu->work, 0, vpu->work_size); 244 + memset(vpu->config, 0, vpu->config_size); 245 + 246 + param->self_data.va = (unsigned long)vpu->work; 247 + param->self_data.pa = vpu->work_addr; 248 + param->config_data.va = (unsigned long)vpu->config; 249 + param->config_data.pa = vpu->config_addr; 250 + param->drv_data = (unsigned long)vpu; 251 + memcpy(vpu->param, param, sizeof(*param)); 252 + 253 + addr.pa = vpu->param_addr; 254 + addr.va = (unsigned long)vpu->param; 255 + mutex_unlock(vpu->lock); 256 + return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_FRAME, &addr, sizeof(addr)); 344 257 }
+7 -22
drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.h
··· 37 37 u32 work_addr; 38 38 } __packed; 39 39 40 - enum mdp_config_id { 41 - MDP_DEV_M2M = 0, 42 - MDP_CONFIG_POOL_SIZE /* ALWAYS keep at the end */ 43 - }; 44 - 45 - struct mdp_config_pool { 46 - u64 cfg_count[MDP_CONFIG_POOL_SIZE]; 47 - struct img_config configs[MDP_CONFIG_POOL_SIZE]; 48 - }; 49 - 50 40 struct mdp_vpu_dev { 51 41 /* synchronization protect for accessing vpu working buffer info */ 52 42 struct mutex *lock; 53 43 struct mtk_scp *scp; 54 44 struct completion ipi_acked; 45 + void *param; 46 + dma_addr_t param_addr; 47 + size_t param_size; 55 48 void *work; 56 49 dma_addr_t work_addr; 57 50 size_t work_size; 58 - struct mdp_config_pool *pool; 51 + void *config; 52 + dma_addr_t config_addr; 53 + size_t config_size; 59 54 u32 status; 60 - }; 61 - 62 - struct mdp_vpu_ctx { 63 - struct mdp_vpu_dev *vpu_dev; 64 - u32 config_id; 65 - struct img_config *config; 66 - u32 inst_addr; 67 55 }; 68 56 69 57 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu); 70 58 int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, 71 59 struct mutex *lock /* for sync */); 72 60 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu); 73 - int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu, 74 - enum mdp_config_id id); 75 - int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx); 76 - int mdp_vpu_process(struct mdp_vpu_ctx *vpu, struct img_ipi_frameparam *param); 61 + int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param); 77 62 78 63 #endif /* __MTK_MDP3_VPU_H__ */