1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/string_choices.h> 7 #include "mdp5_kms.h" 8 #include "mdp5_ctl.h" 9 10 /* 11 * CTL - MDP Control Pool Manager 12 * 13 * Controls are shared between all display interfaces. 14 * 15 * They are intended to be used for data path configuration. 16 * The top level register programming describes the complete data path for 17 * a specific data path ID - REG_MDP5_CTL_*(<id>, ...) 18 * 19 * Hardware capabilities determine the number of concurrent data paths 20 */ 21 22 #define CTL_STAT_BUSY 0x1 23 #define CTL_STAT_BOOKED 0x2 24 25 struct mdp5_ctl { 26 struct mdp5_ctl_manager *ctlm; 27 28 u32 id; 29 30 /* CTL status bitmask */ 31 u32 status; 32 33 bool encoder_enabled; 34 35 /* pending flush_mask bits */ 36 u32 flush_mask; 37 38 /* REG_MDP5_CTL_*(<id>) registers access info + lock: */ 39 spinlock_t hw_lock; 40 u32 reg_offset; 41 42 /* when do CTL registers need to be flushed? (mask of trigger bits) */ 43 u32 pending_ctl_trigger; 44 45 bool cursor_on; 46 }; 47 48 struct mdp5_ctl_manager { 49 struct drm_device *dev; 50 51 /* number of CTL / Layer Mixers in this hw config: */ 52 u32 nlm; 53 u32 nctl; 54 55 /* to filter out non-present bits in the current hardware config */ 56 u32 flush_hw_mask; 57 58 /* pool of CTLs + lock to protect resource allocation (ctls[i].busy) */ 59 spinlock_t pool_lock; 60 struct mdp5_ctl ctls[MAX_CTL]; 61 }; 62 63 static inline 64 struct mdp5_kms *get_kms(struct mdp5_ctl_manager *ctl_mgr) 65 { 66 struct msm_drm_private *priv = ctl_mgr->dev->dev_private; 67 68 return to_mdp5_kms(to_mdp_kms(priv->kms)); 69 } 70 71 static inline 72 void ctl_write(struct mdp5_ctl *ctl, u32 reg, u32 data) 73 { 74 struct mdp5_kms *mdp5_kms = get_kms(ctl->ctlm); 75 76 (void)ctl->reg_offset; /* TODO use this instead of mdp5_write */ 77 mdp5_write(mdp5_kms, reg, data); 78 } 79 80 static inline 81 u32 ctl_read(struct mdp5_ctl *ctl, u32 reg) 82 { 83 struct mdp5_kms *mdp5_kms = get_kms(ctl->ctlm); 84 85 (void)ctl->reg_offset; /* TODO use this instead of mdp5_write */ 86 return mdp5_read(mdp5_kms, reg); 87 } 88 89 static void set_display_intf(struct mdp5_kms *mdp5_kms, 90 struct mdp5_interface *intf) 91 { 92 unsigned long flags; 93 u32 intf_sel; 94 95 spin_lock_irqsave(&mdp5_kms->resource_lock, flags); 96 intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL); 97 98 switch (intf->num) { 99 case 0: 100 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK; 101 intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf->type); 102 break; 103 case 1: 104 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK; 105 intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf->type); 106 break; 107 case 2: 108 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK; 109 intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf->type); 110 break; 111 case 3: 112 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK; 113 intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf->type); 114 break; 115 default: 116 BUG(); 117 break; 118 } 119 120 mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel); 121 spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags); 122 } 123 124 static void set_ctl_op(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline) 125 { 126 unsigned long flags; 127 struct mdp5_interface *intf = pipeline->intf; 128 u32 ctl_op = 0; 129 130 if (!mdp5_cfg_intf_is_virtual(intf->type)) 131 ctl_op |= MDP5_CTL_OP_INTF_NUM(INTF0 + intf->num); 132 133 switch (intf->type) { 134 case INTF_DSI: 135 if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND) 136 ctl_op |= MDP5_CTL_OP_CMD_MODE; 137 break; 138 139 case INTF_WB: 140 if (intf->mode == MDP5_INTF_WB_MODE_LINE) 141 ctl_op |= MDP5_CTL_OP_MODE(MODE_WB_2_LINE); 142 break; 143 144 default: 145 break; 146 } 147 148 if (pipeline->r_mixer) 149 ctl_op |= MDP5_CTL_OP_PACK_3D_ENABLE | 150 MDP5_CTL_OP_PACK_3D(1); 151 152 spin_lock_irqsave(&ctl->hw_lock, flags); 153 ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id), ctl_op); 154 spin_unlock_irqrestore(&ctl->hw_lock, flags); 155 } 156 157 int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline) 158 { 159 struct mdp5_kms *mdp5_kms = get_kms(ctl->ctlm); 160 struct mdp5_interface *intf = pipeline->intf; 161 162 /* Virtual interfaces need not set a display intf (e.g.: Writeback) */ 163 if (!mdp5_cfg_intf_is_virtual(intf->type)) 164 set_display_intf(mdp5_kms, intf); 165 166 set_ctl_op(ctl, pipeline); 167 168 return 0; 169 } 170 171 static bool start_signal_needed(struct mdp5_ctl *ctl, 172 struct mdp5_pipeline *pipeline) 173 { 174 struct mdp5_interface *intf = pipeline->intf; 175 176 if (!ctl->encoder_enabled) 177 return false; 178 179 switch (intf->type) { 180 case INTF_WB: 181 return true; 182 case INTF_DSI: 183 return intf->mode == MDP5_INTF_DSI_MODE_COMMAND; 184 default: 185 return false; 186 } 187 } 188 189 /* 190 * send_start_signal() - Overlay Processor Start Signal 191 * 192 * For a given control operation (display pipeline), a START signal needs to be 193 * executed in order to kick off operation and activate all layers. 194 * e.g.: DSI command mode, Writeback 195 */ 196 static void send_start_signal(struct mdp5_ctl *ctl) 197 { 198 unsigned long flags; 199 200 spin_lock_irqsave(&ctl->hw_lock, flags); 201 ctl_write(ctl, REG_MDP5_CTL_START(ctl->id), 1); 202 spin_unlock_irqrestore(&ctl->hw_lock, flags); 203 } 204 205 /** 206 * mdp5_ctl_set_encoder_state() - set the encoder state 207 * 208 * @ctl: the CTL instance 209 * @pipeline: the encoder's INTF + MIXER configuration 210 * @enabled: true, when encoder is ready for data streaming; false, otherwise. 211 * 212 * Note: 213 * This encoder state is needed to trigger START signal (data path kickoff). 214 */ 215 int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, 216 struct mdp5_pipeline *pipeline, 217 bool enabled) 218 { 219 struct mdp5_interface *intf = pipeline->intf; 220 221 if (WARN_ON(!ctl)) 222 return -EINVAL; 223 224 ctl->encoder_enabled = enabled; 225 DBG("intf_%d: %s", intf->num, str_on_off(enabled)); 226 227 if (start_signal_needed(ctl, pipeline)) { 228 send_start_signal(ctl); 229 } 230 231 return 0; 232 } 233 234 /* 235 * Note: 236 * CTL registers need to be flushed after calling this function 237 * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask) 238 */ 239 int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline, 240 int cursor_id, bool enable) 241 { 242 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; 243 unsigned long flags; 244 u32 blend_cfg; 245 struct mdp5_hw_mixer *mixer = pipeline->mixer; 246 247 if (WARN_ON(!mixer)) { 248 DRM_DEV_ERROR(ctl_mgr->dev->dev, "CTL %d cannot find LM", 249 ctl->id); 250 return -EINVAL; 251 } 252 253 if (pipeline->r_mixer) { 254 DRM_DEV_ERROR(ctl_mgr->dev->dev, "unsupported configuration"); 255 return -EINVAL; 256 } 257 258 spin_lock_irqsave(&ctl->hw_lock, flags); 259 260 blend_cfg = ctl_read(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, mixer->lm)); 261 262 if (enable) 263 blend_cfg |= MDP5_CTL_LAYER_REG_CURSOR_OUT; 264 else 265 blend_cfg &= ~MDP5_CTL_LAYER_REG_CURSOR_OUT; 266 267 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, mixer->lm), blend_cfg); 268 ctl->cursor_on = enable; 269 270 spin_unlock_irqrestore(&ctl->hw_lock, flags); 271 272 ctl->pending_ctl_trigger = mdp_ctl_flush_mask_cursor(cursor_id); 273 274 return 0; 275 } 276 277 static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe, 278 enum mdp_mixer_stage_id stage) 279 { 280 switch (pipe) { 281 case SSPP_VIG0: return MDP5_CTL_LAYER_REG_VIG0(stage); 282 case SSPP_VIG1: return MDP5_CTL_LAYER_REG_VIG1(stage); 283 case SSPP_VIG2: return MDP5_CTL_LAYER_REG_VIG2(stage); 284 case SSPP_RGB0: return MDP5_CTL_LAYER_REG_RGB0(stage); 285 case SSPP_RGB1: return MDP5_CTL_LAYER_REG_RGB1(stage); 286 case SSPP_RGB2: return MDP5_CTL_LAYER_REG_RGB2(stage); 287 case SSPP_DMA0: return MDP5_CTL_LAYER_REG_DMA0(stage); 288 case SSPP_DMA1: return MDP5_CTL_LAYER_REG_DMA1(stage); 289 case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage); 290 case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage); 291 case SSPP_CURSOR0: 292 case SSPP_CURSOR1: 293 default: return 0; 294 } 295 } 296 297 static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe, 298 enum mdp_mixer_stage_id stage) 299 { 300 if (stage < STAGE6 && (pipe != SSPP_CURSOR0 && pipe != SSPP_CURSOR1)) 301 return 0; 302 303 switch (pipe) { 304 case SSPP_VIG0: return MDP5_CTL_LAYER_EXT_REG_VIG0_BIT3; 305 case SSPP_VIG1: return MDP5_CTL_LAYER_EXT_REG_VIG1_BIT3; 306 case SSPP_VIG2: return MDP5_CTL_LAYER_EXT_REG_VIG2_BIT3; 307 case SSPP_RGB0: return MDP5_CTL_LAYER_EXT_REG_RGB0_BIT3; 308 case SSPP_RGB1: return MDP5_CTL_LAYER_EXT_REG_RGB1_BIT3; 309 case SSPP_RGB2: return MDP5_CTL_LAYER_EXT_REG_RGB2_BIT3; 310 case SSPP_DMA0: return MDP5_CTL_LAYER_EXT_REG_DMA0_BIT3; 311 case SSPP_DMA1: return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3; 312 case SSPP_VIG3: return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3; 313 case SSPP_RGB3: return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3; 314 case SSPP_CURSOR0: return MDP5_CTL_LAYER_EXT_REG_CURSOR0(stage); 315 case SSPP_CURSOR1: return MDP5_CTL_LAYER_EXT_REG_CURSOR1(stage); 316 default: return 0; 317 } 318 } 319 320 static void mdp5_ctl_reset_blend_regs(struct mdp5_ctl *ctl) 321 { 322 unsigned long flags; 323 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; 324 int i; 325 326 spin_lock_irqsave(&ctl->hw_lock, flags); 327 328 for (i = 0; i < ctl_mgr->nlm; i++) { 329 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, i), 0x0); 330 ctl_write(ctl, REG_MDP5_CTL_LAYER_EXT_REG(ctl->id, i), 0x0); 331 } 332 333 spin_unlock_irqrestore(&ctl->hw_lock, flags); 334 } 335 336 #define PIPE_LEFT 0 337 #define PIPE_RIGHT 1 338 int mdp5_ctl_blend(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline, 339 enum mdp5_pipe stage[][MAX_PIPE_STAGE], 340 enum mdp5_pipe r_stage[][MAX_PIPE_STAGE], 341 u32 stage_cnt, u32 ctl_blend_op_flags) 342 { 343 struct mdp5_hw_mixer *mixer = pipeline->mixer; 344 struct mdp5_hw_mixer *r_mixer = pipeline->r_mixer; 345 unsigned long flags; 346 u32 blend_cfg = 0, blend_ext_cfg = 0; 347 u32 r_blend_cfg = 0, r_blend_ext_cfg = 0; 348 int i, start_stage; 349 350 mdp5_ctl_reset_blend_regs(ctl); 351 352 if (ctl_blend_op_flags & MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT) { 353 start_stage = STAGE0; 354 blend_cfg |= MDP5_CTL_LAYER_REG_BORDER_COLOR; 355 if (r_mixer) 356 r_blend_cfg |= MDP5_CTL_LAYER_REG_BORDER_COLOR; 357 } else { 358 start_stage = STAGE_BASE; 359 } 360 361 for (i = start_stage; stage_cnt && i <= STAGE_MAX; i++) { 362 blend_cfg |= 363 mdp_ctl_blend_mask(stage[i][PIPE_LEFT], i) | 364 mdp_ctl_blend_mask(stage[i][PIPE_RIGHT], i); 365 blend_ext_cfg |= 366 mdp_ctl_blend_ext_mask(stage[i][PIPE_LEFT], i) | 367 mdp_ctl_blend_ext_mask(stage[i][PIPE_RIGHT], i); 368 if (r_mixer) { 369 r_blend_cfg |= 370 mdp_ctl_blend_mask(r_stage[i][PIPE_LEFT], i) | 371 mdp_ctl_blend_mask(r_stage[i][PIPE_RIGHT], i); 372 r_blend_ext_cfg |= 373 mdp_ctl_blend_ext_mask(r_stage[i][PIPE_LEFT], i) | 374 mdp_ctl_blend_ext_mask(r_stage[i][PIPE_RIGHT], i); 375 } 376 } 377 378 spin_lock_irqsave(&ctl->hw_lock, flags); 379 if (ctl->cursor_on) 380 blend_cfg |= MDP5_CTL_LAYER_REG_CURSOR_OUT; 381 382 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, mixer->lm), blend_cfg); 383 ctl_write(ctl, REG_MDP5_CTL_LAYER_EXT_REG(ctl->id, mixer->lm), 384 blend_ext_cfg); 385 if (r_mixer) { 386 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, r_mixer->lm), 387 r_blend_cfg); 388 ctl_write(ctl, REG_MDP5_CTL_LAYER_EXT_REG(ctl->id, r_mixer->lm), 389 r_blend_ext_cfg); 390 } 391 spin_unlock_irqrestore(&ctl->hw_lock, flags); 392 393 ctl->pending_ctl_trigger = mdp_ctl_flush_mask_lm(mixer->lm); 394 if (r_mixer) 395 ctl->pending_ctl_trigger |= mdp_ctl_flush_mask_lm(r_mixer->lm); 396 397 DBG("lm%d: blend config = 0x%08x. ext_cfg = 0x%08x", mixer->lm, 398 blend_cfg, blend_ext_cfg); 399 if (r_mixer) 400 DBG("lm%d: blend config = 0x%08x. ext_cfg = 0x%08x", 401 r_mixer->lm, r_blend_cfg, r_blend_ext_cfg); 402 403 return 0; 404 } 405 406 u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf) 407 { 408 if (intf->type == INTF_WB) 409 return MDP5_CTL_FLUSH_WB; 410 411 switch (intf->num) { 412 case 0: return MDP5_CTL_FLUSH_TIMING_0; 413 case 1: return MDP5_CTL_FLUSH_TIMING_1; 414 case 2: return MDP5_CTL_FLUSH_TIMING_2; 415 case 3: return MDP5_CTL_FLUSH_TIMING_3; 416 default: return 0; 417 } 418 } 419 420 u32 mdp_ctl_flush_mask_cursor(int cursor_id) 421 { 422 switch (cursor_id) { 423 case 0: return MDP5_CTL_FLUSH_CURSOR_0; 424 case 1: return MDP5_CTL_FLUSH_CURSOR_1; 425 default: return 0; 426 } 427 } 428 429 u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe) 430 { 431 switch (pipe) { 432 case SSPP_VIG0: return MDP5_CTL_FLUSH_VIG0; 433 case SSPP_VIG1: return MDP5_CTL_FLUSH_VIG1; 434 case SSPP_VIG2: return MDP5_CTL_FLUSH_VIG2; 435 case SSPP_RGB0: return MDP5_CTL_FLUSH_RGB0; 436 case SSPP_RGB1: return MDP5_CTL_FLUSH_RGB1; 437 case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2; 438 case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0; 439 case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1; 440 case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3; 441 case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3; 442 case SSPP_CURSOR0: return MDP5_CTL_FLUSH_CURSOR_0; 443 case SSPP_CURSOR1: return MDP5_CTL_FLUSH_CURSOR_1; 444 default: return 0; 445 } 446 } 447 448 u32 mdp_ctl_flush_mask_lm(int lm) 449 { 450 switch (lm) { 451 case 0: return MDP5_CTL_FLUSH_LM0; 452 case 1: return MDP5_CTL_FLUSH_LM1; 453 case 2: return MDP5_CTL_FLUSH_LM2; 454 case 3: return MDP5_CTL_FLUSH_LM3; 455 case 4: return MDP5_CTL_FLUSH_LM4; 456 case 5: return MDP5_CTL_FLUSH_LM5; 457 default: return 0; 458 } 459 } 460 461 static u32 fix_sw_flush(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline, 462 u32 flush_mask) 463 { 464 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; 465 u32 sw_mask = 0; 466 #define BIT_NEEDS_SW_FIX(bit) \ 467 (!(ctl_mgr->flush_hw_mask & bit) && (flush_mask & bit)) 468 469 /* for some targets, cursor bit is the same as LM bit */ 470 if (BIT_NEEDS_SW_FIX(MDP5_CTL_FLUSH_CURSOR_0)) 471 sw_mask |= mdp_ctl_flush_mask_lm(pipeline->mixer->lm); 472 473 return sw_mask; 474 } 475 476 /** 477 * mdp5_ctl_commit() - Register Flush 478 * 479 * @ctl: the CTL instance 480 * @pipeline: the encoder's INTF + MIXER configuration 481 * @flush_mask: bitmask of display controller hw blocks to flush 482 * @start: if true, immediately update flush registers and set START 483 * bit, otherwise accumulate flush_mask bits until we are 484 * ready to START 485 * 486 * The flush register is used to indicate several registers are all 487 * programmed, and are safe to update to the back copy of the double 488 * buffered registers. 489 * 490 * Some registers FLUSH bits are shared when the hardware does not have 491 * dedicated bits for them; handling these is the job of fix_sw_flush(). 492 * 493 * CTL registers need to be flushed in some circumstances; if that is the 494 * case, some trigger bits will be present in both flush mask and 495 * ctl->pending_ctl_trigger. 496 * 497 * Return H/W flushed bit mask. 498 */ 499 u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, 500 struct mdp5_pipeline *pipeline, 501 u32 flush_mask, bool start) 502 { 503 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; 504 unsigned long flags; 505 u32 flush_id = ctl->id; 506 u32 curr_ctl_flush_mask; 507 508 VERB("flush_mask=%x, trigger=%x", flush_mask, ctl->pending_ctl_trigger); 509 510 if (ctl->pending_ctl_trigger & flush_mask) { 511 flush_mask |= MDP5_CTL_FLUSH_CTL; 512 ctl->pending_ctl_trigger = 0; 513 } 514 515 flush_mask |= fix_sw_flush(ctl, pipeline, flush_mask); 516 517 flush_mask &= ctl_mgr->flush_hw_mask; 518 519 curr_ctl_flush_mask = flush_mask; 520 521 if (!start) { 522 ctl->flush_mask |= flush_mask; 523 return curr_ctl_flush_mask; 524 } else { 525 flush_mask |= ctl->flush_mask; 526 ctl->flush_mask = 0; 527 } 528 529 if (flush_mask) { 530 spin_lock_irqsave(&ctl->hw_lock, flags); 531 ctl_write(ctl, REG_MDP5_CTL_FLUSH(flush_id), flush_mask); 532 spin_unlock_irqrestore(&ctl->hw_lock, flags); 533 } 534 535 if (start_signal_needed(ctl, pipeline)) { 536 send_start_signal(ctl); 537 } 538 539 return curr_ctl_flush_mask; 540 } 541 542 u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl) 543 { 544 return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id)); 545 } 546 547 int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl) 548 { 549 return WARN_ON(!ctl) ? -EINVAL : ctl->id; 550 } 551 552 /* 553 * mdp5_ctl_request() - CTL allocation 554 * 555 * Try to return booked CTL for @intf_num is 1 or 2, unbooked for other INTFs. 556 * If no CTL is available in preferred category, allocate from the other one. 557 * 558 * @return fail if no CTL is available. 559 */ 560 struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctl_mgr, 561 int intf_num) 562 { 563 struct mdp5_ctl *ctl = NULL; 564 const u32 checkm = CTL_STAT_BUSY | CTL_STAT_BOOKED; 565 u32 match = ((intf_num == 1) || (intf_num == 2)) ? CTL_STAT_BOOKED : 0; 566 unsigned long flags; 567 int c; 568 569 spin_lock_irqsave(&ctl_mgr->pool_lock, flags); 570 571 /* search the preferred */ 572 for (c = 0; c < ctl_mgr->nctl; c++) 573 if ((ctl_mgr->ctls[c].status & checkm) == match) 574 goto found; 575 576 dev_warn(ctl_mgr->dev->dev, 577 "fall back to the other CTL category for INTF %d!\n", intf_num); 578 579 match ^= CTL_STAT_BOOKED; 580 for (c = 0; c < ctl_mgr->nctl; c++) 581 if ((ctl_mgr->ctls[c].status & checkm) == match) 582 goto found; 583 584 DRM_DEV_ERROR(ctl_mgr->dev->dev, "No more CTL available!"); 585 goto unlock; 586 587 found: 588 ctl = &ctl_mgr->ctls[c]; 589 ctl->status |= CTL_STAT_BUSY; 590 ctl->pending_ctl_trigger = 0; 591 DBG("CTL %d allocated", ctl->id); 592 593 unlock: 594 spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); 595 return ctl; 596 } 597 598 void mdp5_ctlm_hw_reset(struct mdp5_ctl_manager *ctl_mgr) 599 { 600 unsigned long flags; 601 int c; 602 603 for (c = 0; c < ctl_mgr->nctl; c++) { 604 struct mdp5_ctl *ctl = &ctl_mgr->ctls[c]; 605 606 spin_lock_irqsave(&ctl->hw_lock, flags); 607 ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id), 0); 608 spin_unlock_irqrestore(&ctl->hw_lock, flags); 609 } 610 } 611 612 struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, 613 void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd) 614 { 615 struct mdp5_ctl_manager *ctl_mgr; 616 const struct mdp5_cfg_hw *hw_cfg = mdp5_cfg_get_hw_config(cfg_hnd); 617 const struct mdp5_ctl_block *ctl_cfg = &hw_cfg->ctl; 618 unsigned long flags; 619 int c, ret; 620 621 ctl_mgr = devm_kzalloc(dev->dev, sizeof(*ctl_mgr), GFP_KERNEL); 622 if (!ctl_mgr) { 623 DRM_DEV_ERROR(dev->dev, "failed to allocate CTL manager\n"); 624 return ERR_PTR(-ENOMEM); 625 } 626 627 if (WARN_ON(ctl_cfg->count > MAX_CTL)) { 628 DRM_DEV_ERROR(dev->dev, "Increase static pool size to at least %d\n", 629 ctl_cfg->count); 630 return ERR_PTR(-ENOSPC); 631 } 632 633 /* initialize the CTL manager: */ 634 ctl_mgr->dev = dev; 635 ctl_mgr->nlm = hw_cfg->lm.count; 636 ctl_mgr->nctl = ctl_cfg->count; 637 ctl_mgr->flush_hw_mask = ctl_cfg->flush_hw_mask; 638 spin_lock_init(&ctl_mgr->pool_lock); 639 640 /* initialize each CTL of the pool: */ 641 spin_lock_irqsave(&ctl_mgr->pool_lock, flags); 642 for (c = 0; c < ctl_mgr->nctl; c++) { 643 struct mdp5_ctl *ctl = &ctl_mgr->ctls[c]; 644 645 if (WARN_ON(!ctl_cfg->base[c])) { 646 DRM_DEV_ERROR(dev->dev, "CTL_%d: base is null!\n", c); 647 ret = -EINVAL; 648 spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); 649 return ERR_PTR(ret); 650 } 651 ctl->ctlm = ctl_mgr; 652 ctl->id = c; 653 ctl->reg_offset = ctl_cfg->base[c]; 654 ctl->status = 0; 655 spin_lock_init(&ctl->hw_lock); 656 } 657 658 spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); 659 DBG("Pool of %d CTLs created.", ctl_mgr->nctl); 660 661 return ctl_mgr; 662 } 663