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/mailbox_controller.h> 8 #include <linux/platform_device.h> 9 #include "mtk-mdp3-cmdq.h" 10 #include "mtk-mdp3-comp.h" 11 #include "mtk-mdp3-core.h" 12 #include "mtk-mdp3-m2m.h" 13 14 #define MDP_PATH_MAX_COMPS IMG_MAX_COMPONENTS 15 16 struct mdp_path { 17 struct mdp_dev *mdp_dev; 18 struct mdp_comp_ctx comps[MDP_PATH_MAX_COMPS]; 19 u32 num_comps; 20 const struct img_config *config; 21 const struct img_ipi_frameparam *param; 22 const struct v4l2_rect *composes[IMG_MAX_HW_OUTPUTS]; 23 struct v4l2_rect bounds[IMG_MAX_HW_OUTPUTS]; 24 }; 25 26 #define has_op(ctx, op) \ 27 ((ctx)->comp->ops && (ctx)->comp->ops->op) 28 #define call_op(ctx, op, ...) \ 29 (has_op(ctx, op) ? (ctx)->comp->ops->op(ctx, ##__VA_ARGS__) : 0) 30 31 static bool is_output_disabled(const struct img_compparam *param, u32 count) 32 { 33 return (count < param->num_subfrms) ? 34 (param->frame.output_disable || 35 param->subfrms[count].tile_disable) : 36 true; 37 } 38 39 static int mdp_path_subfrm_require(const struct mdp_path *path, 40 struct mdp_cmdq_cmd *cmd, 41 s32 *mutex_id, u32 count) 42 { 43 const struct img_config *config = path->config; 44 const struct mdp_comp_ctx *ctx; 45 const struct mtk_mdp_driver_data *data = path->mdp_dev->mdp_data; 46 struct device *dev = &path->mdp_dev->pdev->dev; 47 struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex; 48 int id, index; 49 50 /* Decide which mutex to use based on the current pipeline */ 51 switch (path->comps[0].comp->id) { 52 case MDP_COMP_RDMA0: 53 *mutex_id = MDP_PIPE_RDMA0; 54 break; 55 case MDP_COMP_ISP_IMGI: 56 *mutex_id = MDP_PIPE_IMGI; 57 break; 58 case MDP_COMP_WPEI: 59 *mutex_id = MDP_PIPE_WPEI; 60 break; 61 case MDP_COMP_WPEI2: 62 *mutex_id = MDP_PIPE_WPEI2; 63 break; 64 default: 65 dev_err(dev, "Unknown pipeline and no mutex is assigned"); 66 return -EINVAL; 67 } 68 69 /* Set mutex mod */ 70 for (index = 0; index < config->num_components; index++) { 71 ctx = &path->comps[index]; 72 if (is_output_disabled(ctx->param, count)) 73 continue; 74 id = ctx->comp->id; 75 mtk_mutex_write_mod(mutex[*mutex_id], 76 data->mdp_mutex_table_idx[id], false); 77 } 78 79 mtk_mutex_write_sof(mutex[*mutex_id], 80 MUTEX_SOF_IDX_SINGLE_MODE); 81 82 return 0; 83 } 84 85 static int mdp_path_subfrm_run(const struct mdp_path *path, 86 struct mdp_cmdq_cmd *cmd, 87 s32 *mutex_id, u32 count) 88 { 89 const struct img_config *config = path->config; 90 const struct mdp_comp_ctx *ctx; 91 struct device *dev = &path->mdp_dev->pdev->dev; 92 struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex; 93 int index; 94 s32 event; 95 96 if (-1 == *mutex_id) { 97 dev_err(dev, "Incorrect mutex id"); 98 return -EINVAL; 99 } 100 101 /* Wait WROT SRAM shared to DISP RDMA */ 102 /* Clear SOF event for each engine */ 103 for (index = 0; index < config->num_components; index++) { 104 ctx = &path->comps[index]; 105 if (is_output_disabled(ctx->param, count)) 106 continue; 107 event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF]; 108 if (event != MDP_GCE_NO_EVENT) 109 MM_REG_CLEAR(cmd, event); 110 } 111 112 /* Enable the mutex */ 113 mtk_mutex_enable_by_cmdq(mutex[*mutex_id], (void *)&cmd->pkt); 114 115 /* Wait SOF events and clear mutex modules (optional) */ 116 for (index = 0; index < config->num_components; index++) { 117 ctx = &path->comps[index]; 118 if (is_output_disabled(ctx->param, count)) 119 continue; 120 event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF]; 121 if (event != MDP_GCE_NO_EVENT) 122 MM_REG_WAIT(cmd, event); 123 } 124 125 return 0; 126 } 127 128 static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path) 129 { 130 const struct img_config *config = path->config; 131 int index, ret; 132 133 if (config->num_components < 1) 134 return -EINVAL; 135 136 for (index = 0; index < config->num_components; index++) { 137 ret = mdp_comp_ctx_config(mdp, &path->comps[index], 138 &config->components[index], 139 path->param); 140 if (ret) 141 return ret; 142 } 143 144 return 0; 145 } 146 147 static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd, 148 struct mdp_path *path, u32 count) 149 { 150 const struct img_config *config = path->config; 151 const struct img_mmsys_ctrl *ctrl = &config->ctrls[count]; 152 const struct img_mux *set; 153 struct mdp_comp_ctx *ctx; 154 s32 mutex_id; 155 int index, ret; 156 157 /* Acquire components */ 158 ret = mdp_path_subfrm_require(path, cmd, &mutex_id, count); 159 if (ret) 160 return ret; 161 /* Enable mux settings */ 162 for (index = 0; index < ctrl->num_sets; index++) { 163 set = &ctrl->sets[index]; 164 cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg, 165 set->value, 0xFFFFFFFF); 166 } 167 /* Config sub-frame information */ 168 for (index = (config->num_components - 1); index >= 0; index--) { 169 ctx = &path->comps[index]; 170 if (is_output_disabled(ctx->param, count)) 171 continue; 172 ret = call_op(ctx, config_subfrm, cmd, count); 173 if (ret) 174 return ret; 175 } 176 /* Run components */ 177 ret = mdp_path_subfrm_run(path, cmd, &mutex_id, count); 178 if (ret) 179 return ret; 180 /* Wait components done */ 181 for (index = 0; index < config->num_components; index++) { 182 ctx = &path->comps[index]; 183 if (is_output_disabled(ctx->param, count)) 184 continue; 185 ret = call_op(ctx, wait_comp_event, cmd); 186 if (ret) 187 return ret; 188 } 189 /* Advance to the next sub-frame */ 190 for (index = 0; index < config->num_components; index++) { 191 ctx = &path->comps[index]; 192 ret = call_op(ctx, advance_subfrm, cmd, count); 193 if (ret) 194 return ret; 195 } 196 /* Disable mux settings */ 197 for (index = 0; index < ctrl->num_sets; index++) { 198 set = &ctrl->sets[index]; 199 cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg, 200 0, 0xFFFFFFFF); 201 } 202 203 return 0; 204 } 205 206 static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd, 207 struct mdp_path *path) 208 { 209 const struct img_config *config = path->config; 210 struct mdp_comp_ctx *ctx; 211 int index, count, ret; 212 213 /* Config path frame */ 214 /* Reset components */ 215 for (index = 0; index < config->num_components; index++) { 216 ctx = &path->comps[index]; 217 ret = call_op(ctx, init_comp, cmd); 218 if (ret) 219 return ret; 220 } 221 /* Config frame mode */ 222 for (index = 0; index < config->num_components; index++) { 223 const struct v4l2_rect *compose = 224 path->composes[ctx->param->outputs[0]]; 225 226 ctx = &path->comps[index]; 227 ret = call_op(ctx, config_frame, cmd, compose); 228 if (ret) 229 return ret; 230 } 231 232 /* Config path sub-frames */ 233 for (count = 0; count < config->num_subfrms; count++) { 234 ret = mdp_path_config_subfrm(cmd, path, count); 235 if (ret) 236 return ret; 237 } 238 /* Post processing information */ 239 for (index = 0; index < config->num_components; index++) { 240 ctx = &path->comps[index]; 241 ret = call_op(ctx, post_process, cmd); 242 if (ret) 243 return ret; 244 } 245 return 0; 246 } 247 248 static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, 249 size_t size) 250 { 251 struct device *dev; 252 dma_addr_t dma_addr; 253 254 pkt->va_base = kzalloc(size, GFP_KERNEL); 255 if (!pkt->va_base) { 256 kfree(pkt); 257 return -ENOMEM; 258 } 259 pkt->buf_size = size; 260 pkt->cl = (void *)client; 261 262 dev = client->chan->mbox->dev; 263 dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, 264 DMA_TO_DEVICE); 265 if (dma_mapping_error(dev, dma_addr)) { 266 dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); 267 kfree(pkt->va_base); 268 return -ENOMEM; 269 } 270 271 pkt->pa_base = dma_addr; 272 273 return 0; 274 } 275 276 static void mdp_cmdq_pkt_destroy(struct cmdq_pkt *pkt) 277 { 278 struct cmdq_client *client = (struct cmdq_client *)pkt->cl; 279 280 dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size, 281 DMA_TO_DEVICE); 282 kfree(pkt->va_base); 283 pkt->va_base = NULL; 284 } 285 286 static void mdp_auto_release_work(struct work_struct *work) 287 { 288 struct mdp_cmdq_cmd *cmd; 289 struct mdp_dev *mdp; 290 291 cmd = container_of(work, struct mdp_cmdq_cmd, auto_release_work); 292 mdp = cmd->mdp; 293 294 mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); 295 mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps, 296 cmd->num_comps); 297 298 atomic_dec(&mdp->job_count); 299 wake_up(&mdp->callback_wq); 300 301 mdp_cmdq_pkt_destroy(&cmd->pkt); 302 kfree(cmd->comps); 303 cmd->comps = NULL; 304 kfree(cmd); 305 cmd = NULL; 306 } 307 308 static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg) 309 { 310 struct mdp_cmdq_cmd *cmd; 311 struct cmdq_cb_data *data; 312 struct mdp_dev *mdp; 313 struct device *dev; 314 315 if (!mssg) { 316 pr_info("%s:no callback data\n", __func__); 317 return; 318 } 319 320 data = (struct cmdq_cb_data *)mssg; 321 cmd = container_of(data->pkt, struct mdp_cmdq_cmd, pkt); 322 mdp = cmd->mdp; 323 dev = &mdp->pdev->dev; 324 325 if (cmd->mdp_ctx) 326 mdp_m2m_job_finish(cmd->mdp_ctx); 327 328 if (cmd->user_cmdq_cb) { 329 struct cmdq_cb_data user_cb_data; 330 331 user_cb_data.sta = data->sta; 332 user_cb_data.pkt = data->pkt; 333 cmd->user_cmdq_cb(user_cb_data); 334 } 335 336 INIT_WORK(&cmd->auto_release_work, mdp_auto_release_work); 337 if (!queue_work(mdp->clock_wq, &cmd->auto_release_work)) { 338 dev_err(dev, "%s:queue_work fail!\n", __func__); 339 mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); 340 mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps, 341 cmd->num_comps); 342 343 atomic_dec(&mdp->job_count); 344 wake_up(&mdp->callback_wq); 345 346 mdp_cmdq_pkt_destroy(&cmd->pkt); 347 kfree(cmd->comps); 348 cmd->comps = NULL; 349 kfree(cmd); 350 cmd = NULL; 351 } 352 } 353 354 int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) 355 { 356 struct mdp_path *path = NULL; 357 struct mdp_cmdq_cmd *cmd = NULL; 358 struct mdp_comp *comps = NULL; 359 struct device *dev = &mdp->pdev->dev; 360 int i, ret; 361 362 atomic_inc(&mdp->job_count); 363 if (atomic_read(&mdp->suspended)) { 364 atomic_dec(&mdp->job_count); 365 return -ECANCELED; 366 } 367 368 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 369 if (!cmd) { 370 ret = -ENOMEM; 371 goto err_cmdq_data; 372 } 373 374 if (mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K)) { 375 ret = -ENOMEM; 376 goto err_cmdq_data; 377 } 378 379 comps = kcalloc(param->config->num_components, sizeof(*comps), 380 GFP_KERNEL); 381 if (!comps) { 382 ret = -ENOMEM; 383 goto err_cmdq_data; 384 } 385 386 path = kzalloc(sizeof(*path), GFP_KERNEL); 387 if (!path) { 388 ret = -ENOMEM; 389 goto err_cmdq_data; 390 } 391 392 path->mdp_dev = mdp; 393 path->config = param->config; 394 path->param = param->param; 395 for (i = 0; i < param->param->num_outputs; i++) { 396 path->bounds[i].left = 0; 397 path->bounds[i].top = 0; 398 path->bounds[i].width = 399 param->param->outputs[i].buffer.format.width; 400 path->bounds[i].height = 401 param->param->outputs[i].buffer.format.height; 402 path->composes[i] = param->composes[i] ? 403 param->composes[i] : &path->bounds[i]; 404 } 405 406 ret = mdp_path_ctx_init(mdp, path); 407 if (ret) { 408 dev_err(dev, "mdp_path_ctx_init error\n"); 409 goto err_cmdq_data; 410 } 411 412 mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); 413 414 ret = mdp_path_config(mdp, cmd, path); 415 if (ret) { 416 dev_err(dev, "mdp_path_config error\n"); 417 goto err_cmdq_data; 418 } 419 cmdq_pkt_finalize(&cmd->pkt); 420 421 for (i = 0; i < param->config->num_components; i++) 422 memcpy(&comps[i], path->comps[i].comp, 423 sizeof(struct mdp_comp)); 424 425 mdp->cmdq_clt->client.rx_callback = mdp_handle_cmdq_callback; 426 cmd->mdp = mdp; 427 cmd->user_cmdq_cb = param->cmdq_cb; 428 cmd->user_cb_data = param->cb_data; 429 cmd->comps = comps; 430 cmd->num_comps = param->config->num_components; 431 cmd->mdp_ctx = param->mdp_ctx; 432 433 ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd->comps, cmd->num_comps); 434 if (ret) { 435 dev_err(dev, "comp %d failed to enable clock!\n", ret); 436 goto err_clock_off; 437 } 438 439 dma_sync_single_for_device(mdp->cmdq_clt->chan->mbox->dev, 440 cmd->pkt.pa_base, cmd->pkt.cmd_buf_size, 441 DMA_TO_DEVICE); 442 ret = mbox_send_message(mdp->cmdq_clt->chan, &cmd->pkt); 443 if (ret < 0) { 444 dev_err(dev, "mbox send message fail %d!\n", ret); 445 goto err_clock_off; 446 } 447 mbox_client_txdone(mdp->cmdq_clt->chan, 0); 448 449 kfree(path); 450 return 0; 451 452 err_clock_off: 453 mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); 454 mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps, 455 cmd->num_comps); 456 err_cmdq_data: 457 kfree(path); 458 atomic_dec(&mdp->job_count); 459 wake_up(&mdp->callback_wq); 460 if (cmd && cmd->pkt.buf_size > 0) 461 mdp_cmdq_pkt_destroy(&cmd->pkt); 462 kfree(comps); 463 kfree(cmd); 464 return ret; 465 } 466 EXPORT_SYMBOL_GPL(mdp_cmdq_send); 467