root/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. komeda_crtc_update_clock_ratio
  2. komeda_crtc_atomic_check
  3. komeda_crtc_prepare
  4. komeda_crtc_unprepare
  5. komeda_crtc_handle_event
  6. komeda_crtc_do_flush
  7. komeda_crtc_atomic_enable
  8. komeda_crtc_atomic_disable
  9. komeda_crtc_atomic_flush
  10. komeda_calc_min_aclk_rate
  11. komeda_crtc_get_aclk
  12. komeda_crtc_mode_valid
  13. komeda_crtc_mode_fixup
  14. komeda_crtc_reset
  15. komeda_crtc_atomic_duplicate_state
  16. komeda_crtc_atomic_destroy_state
  17. komeda_crtc_vblank_enable
  18. komeda_crtc_vblank_disable
  19. komeda_kms_setup_crtcs
  20. get_crtc_primary
  21. komeda_crtc_add
  22. komeda_kms_add_crtcs

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
   4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
   5  *
   6  */
   7 #include <linux/clk.h>
   8 #include <linux/pm_runtime.h>
   9 #include <linux/spinlock.h>
  10 
  11 #include <drm/drm_atomic.h>
  12 #include <drm/drm_atomic_helper.h>
  13 #include <drm/drm_crtc_helper.h>
  14 #include <drm/drm_plane_helper.h>
  15 #include <drm/drm_print.h>
  16 #include <drm/drm_vblank.h>
  17 
  18 #include "komeda_dev.h"
  19 #include "komeda_kms.h"
  20 
  21 static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st)
  22 {
  23         u64 pxlclk, aclk;
  24 
  25         if (!kcrtc_st->base.active) {
  26                 kcrtc_st->clock_ratio = 0;
  27                 return;
  28         }
  29 
  30         pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000ULL;
  31         aclk = komeda_crtc_get_aclk(kcrtc_st);
  32 
  33         kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk);
  34 }
  35 
  36 /**
  37  * komeda_crtc_atomic_check - build display output data flow
  38  * @crtc: DRM crtc
  39  * @state: the crtc state object
  40  *
  41  * crtc_atomic_check is the final check stage, so beside build a display data
  42  * pipeline according to the crtc_state, but still needs to release or disable
  43  * the unclaimed pipeline resources.
  44  *
  45  * RETURNS:
  46  * Zero for success or -errno
  47  */
  48 static int
  49 komeda_crtc_atomic_check(struct drm_crtc *crtc,
  50                          struct drm_crtc_state *state)
  51 {
  52         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
  53         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(state);
  54         int err;
  55 
  56         if (drm_atomic_crtc_needs_modeset(state))
  57                 komeda_crtc_update_clock_ratio(kcrtc_st);
  58 
  59         if (state->active) {
  60                 err = komeda_build_display_data_flow(kcrtc, kcrtc_st);
  61                 if (err)
  62                         return err;
  63         }
  64 
  65         /* release unclaimed pipeline resources */
  66         err = komeda_release_unclaimed_resources(kcrtc->slave, kcrtc_st);
  67         if (err)
  68                 return err;
  69 
  70         err = komeda_release_unclaimed_resources(kcrtc->master, kcrtc_st);
  71         if (err)
  72                 return err;
  73 
  74         return 0;
  75 }
  76 
  77 /* For active a crtc, mainly need two parts of preparation
  78  * 1. adjust display operation mode.
  79  * 2. enable needed clk
  80  */
  81 static int
  82 komeda_crtc_prepare(struct komeda_crtc *kcrtc)
  83 {
  84         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
  85         struct komeda_pipeline *master = kcrtc->master;
  86         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state);
  87         struct drm_display_mode *mode = &kcrtc_st->base.adjusted_mode;
  88         u32 new_mode;
  89         int err;
  90 
  91         mutex_lock(&mdev->lock);
  92 
  93         new_mode = mdev->dpmode | BIT(master->id);
  94         if (WARN_ON(new_mode == mdev->dpmode)) {
  95                 err = 0;
  96                 goto unlock;
  97         }
  98 
  99         err = mdev->funcs->change_opmode(mdev, new_mode);
 100         if (err) {
 101                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
 102                           mdev->dpmode, new_mode);
 103                 goto unlock;
 104         }
 105 
 106         mdev->dpmode = new_mode;
 107         /* Only need to enable aclk on single display mode, but no need to
 108          * enable aclk it on dual display mode, since the dual mode always
 109          * switch from single display mode, the aclk already enabled, no need
 110          * to enable it again.
 111          */
 112         if (new_mode != KOMEDA_MODE_DUAL_DISP) {
 113                 err = clk_set_rate(mdev->aclk, komeda_crtc_get_aclk(kcrtc_st));
 114                 if (err)
 115                         DRM_ERROR("failed to set aclk.\n");
 116                 err = clk_prepare_enable(mdev->aclk);
 117                 if (err)
 118                         DRM_ERROR("failed to enable aclk.\n");
 119         }
 120 
 121         err = clk_set_rate(master->pxlclk, mode->crtc_clock * 1000);
 122         if (err)
 123                 DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id);
 124         err = clk_prepare_enable(master->pxlclk);
 125         if (err)
 126                 DRM_ERROR("failed to enable pxl clk for pipe%d.\n", master->id);
 127 
 128 unlock:
 129         mutex_unlock(&mdev->lock);
 130 
 131         return err;
 132 }
 133 
 134 static int
 135 komeda_crtc_unprepare(struct komeda_crtc *kcrtc)
 136 {
 137         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
 138         struct komeda_pipeline *master = kcrtc->master;
 139         u32 new_mode;
 140         int err;
 141 
 142         mutex_lock(&mdev->lock);
 143 
 144         new_mode = mdev->dpmode & (~BIT(master->id));
 145 
 146         if (WARN_ON(new_mode == mdev->dpmode)) {
 147                 err = 0;
 148                 goto unlock;
 149         }
 150 
 151         err = mdev->funcs->change_opmode(mdev, new_mode);
 152         if (err) {
 153                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
 154                           mdev->dpmode, new_mode);
 155                 goto unlock;
 156         }
 157 
 158         mdev->dpmode = new_mode;
 159 
 160         clk_disable_unprepare(master->pxlclk);
 161         if (new_mode == KOMEDA_MODE_INACTIVE)
 162                 clk_disable_unprepare(mdev->aclk);
 163 
 164 unlock:
 165         mutex_unlock(&mdev->lock);
 166 
 167         return err;
 168 }
 169 
 170 void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
 171                               struct komeda_events *evts)
 172 {
 173         struct drm_crtc *crtc = &kcrtc->base;
 174         u32 events = evts->pipes[kcrtc->master->id];
 175 
 176         if (events & KOMEDA_EVENT_VSYNC)
 177                 drm_crtc_handle_vblank(crtc);
 178 
 179         if (events & KOMEDA_EVENT_EOW) {
 180                 struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
 181 
 182                 if (wb_conn)
 183                         drm_writeback_signal_completion(&wb_conn->base, 0);
 184                 else
 185                         DRM_WARN("CRTC[%d]: EOW happen but no wb_connector.\n",
 186                                  drm_crtc_index(&kcrtc->base));
 187         }
 188         /* will handle it together with the write back support */
 189         if (events & KOMEDA_EVENT_EOW)
 190                 DRM_DEBUG("EOW.\n");
 191 
 192         if (events & KOMEDA_EVENT_FLIP) {
 193                 unsigned long flags;
 194                 struct drm_pending_vblank_event *event;
 195 
 196                 spin_lock_irqsave(&crtc->dev->event_lock, flags);
 197                 if (kcrtc->disable_done) {
 198                         complete_all(kcrtc->disable_done);
 199                         kcrtc->disable_done = NULL;
 200                 } else if (crtc->state->event) {
 201                         event = crtc->state->event;
 202                         /*
 203                          * Consume event before notifying drm core that flip
 204                          * happened.
 205                          */
 206                         crtc->state->event = NULL;
 207                         drm_crtc_send_vblank_event(crtc, event);
 208                 } else {
 209                         DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
 210                                  drm_crtc_index(&kcrtc->base));
 211                 }
 212                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 213         }
 214 }
 215 
 216 static void
 217 komeda_crtc_do_flush(struct drm_crtc *crtc,
 218                      struct drm_crtc_state *old)
 219 {
 220         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 221         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);
 222         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
 223         struct komeda_pipeline *master = kcrtc->master;
 224         struct komeda_pipeline *slave = kcrtc->slave;
 225         struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
 226         struct drm_connector_state *conn_st;
 227 
 228         DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",
 229                          drm_crtc_index(crtc),
 230                          kcrtc_st->active_pipes, kcrtc_st->affected_pipes);
 231 
 232         /* step 1: update the pipeline/component state to HW */
 233         if (has_bit(master->id, kcrtc_st->affected_pipes))
 234                 komeda_pipeline_update(master, old->state);
 235 
 236         if (slave && has_bit(slave->id, kcrtc_st->affected_pipes))
 237                 komeda_pipeline_update(slave, old->state);
 238 
 239         conn_st = wb_conn ? wb_conn->base.base.state : NULL;
 240         if (conn_st && conn_st->writeback_job)
 241                 drm_writeback_queue_job(&wb_conn->base, conn_st);
 242 
 243         /* step 2: notify the HW to kickoff the update */
 244         mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);
 245 }
 246 
 247 static void
 248 komeda_crtc_atomic_enable(struct drm_crtc *crtc,
 249                           struct drm_crtc_state *old)
 250 {
 251         komeda_crtc_prepare(to_kcrtc(crtc));
 252         drm_crtc_vblank_on(crtc);
 253         WARN_ON(drm_crtc_vblank_get(crtc));
 254         komeda_crtc_do_flush(crtc, old);
 255 }
 256 
 257 static void
 258 komeda_crtc_atomic_disable(struct drm_crtc *crtc,
 259                            struct drm_crtc_state *old)
 260 {
 261         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 262         struct komeda_crtc_state *old_st = to_kcrtc_st(old);
 263         struct komeda_dev *mdev = crtc->dev->dev_private;
 264         struct komeda_pipeline *master = kcrtc->master;
 265         struct komeda_pipeline *slave  = kcrtc->slave;
 266         struct completion *disable_done = &crtc->state->commit->flip_done;
 267         struct completion temp;
 268         int timeout;
 269 
 270         DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x.\n",
 271                          drm_crtc_index(crtc),
 272                          old_st->active_pipes, old_st->affected_pipes);
 273 
 274         if (slave && has_bit(slave->id, old_st->active_pipes))
 275                 komeda_pipeline_disable(slave, old->state);
 276 
 277         if (has_bit(master->id, old_st->active_pipes))
 278                 komeda_pipeline_disable(master, old->state);
 279 
 280         /* crtc_disable has two scenarios according to the state->active switch.
 281          * 1. active -> inactive
 282          *    this commit is a disable commit. and the commit will be finished
 283          *    or done after the disable operation. on this case we can directly
 284          *    use the crtc->state->event to tracking the HW disable operation.
 285          * 2. active -> active
 286          *    the crtc->commit is not for disable, but a modeset operation when
 287          *    crtc is active, such commit actually has been completed by 3
 288          *    DRM operations:
 289          *    crtc_disable, update_planes(crtc_flush), crtc_enable
 290          *    so on this case the crtc->commit is for the whole process.
 291          *    we can not use it for tracing the disable, we need a temporary
 292          *    flip_done for tracing the disable. and crtc->state->event for
 293          *    the crtc_enable operation.
 294          *    That's also the reason why skip modeset commit in
 295          *    komeda_crtc_atomic_flush()
 296          */
 297         if (crtc->state->active) {
 298                 struct komeda_pipeline_state *pipe_st;
 299                 /* clear the old active_comps to zero */
 300                 pipe_st = komeda_pipeline_get_old_state(master, old->state);
 301                 pipe_st->active_comps = 0;
 302 
 303                 init_completion(&temp);
 304                 kcrtc->disable_done = &temp;
 305                 disable_done = &temp;
 306         }
 307 
 308         mdev->funcs->flush(mdev, master->id, 0);
 309 
 310         /* wait the disable take affect.*/
 311         timeout = wait_for_completion_timeout(disable_done, HZ);
 312         if (timeout == 0) {
 313                 DRM_ERROR("disable pipeline%d timeout.\n", kcrtc->master->id);
 314                 if (crtc->state->active) {
 315                         unsigned long flags;
 316 
 317                         spin_lock_irqsave(&crtc->dev->event_lock, flags);
 318                         kcrtc->disable_done = NULL;
 319                         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 320                 }
 321         }
 322 
 323         drm_crtc_vblank_put(crtc);
 324         drm_crtc_vblank_off(crtc);
 325         komeda_crtc_unprepare(kcrtc);
 326 }
 327 
 328 static void
 329 komeda_crtc_atomic_flush(struct drm_crtc *crtc,
 330                          struct drm_crtc_state *old)
 331 {
 332         /* commit with modeset will be handled in enable/disable */
 333         if (drm_atomic_crtc_needs_modeset(crtc->state))
 334                 return;
 335 
 336         komeda_crtc_do_flush(crtc, old);
 337 }
 338 
 339 /* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */
 340 static unsigned long
 341 komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc,
 342                           unsigned long pxlclk)
 343 {
 344         /* Once dual-link one display pipeline drives two display outputs,
 345          * the aclk needs run on the double rate of pxlclk
 346          */
 347         if (kcrtc->master->dual_link)
 348                 return pxlclk * 2;
 349         else
 350                 return pxlclk;
 351 }
 352 
 353 /* Get current aclk rate that specified by state */
 354 unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st)
 355 {
 356         struct drm_crtc *crtc = kcrtc_st->base.crtc;
 357         struct komeda_dev *mdev = crtc->dev->dev_private;
 358         unsigned long pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000;
 359         unsigned long min_aclk;
 360 
 361         min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), pxlclk);
 362 
 363         return clk_round_rate(mdev->aclk, min_aclk);
 364 }
 365 
 366 static enum drm_mode_status
 367 komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m)
 368 {
 369         struct komeda_dev *mdev = crtc->dev->dev_private;
 370         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 371         struct komeda_pipeline *master = kcrtc->master;
 372         unsigned long min_pxlclk, min_aclk;
 373 
 374         if (m->flags & DRM_MODE_FLAG_INTERLACE)
 375                 return MODE_NO_INTERLACE;
 376 
 377         min_pxlclk = m->clock * 1000;
 378         if (master->dual_link)
 379                 min_pxlclk /= 2;
 380 
 381         if (min_pxlclk != clk_round_rate(master->pxlclk, min_pxlclk)) {
 382                 DRM_DEBUG_ATOMIC("pxlclk doesn't support %lu Hz\n", min_pxlclk);
 383 
 384                 return MODE_NOCLOCK;
 385         }
 386 
 387         min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), min_pxlclk);
 388         if (clk_round_rate(mdev->aclk, min_aclk) < min_aclk) {
 389                 DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %lu.\n",
 390                                  m->name, min_pxlclk);
 391 
 392                 return MODE_CLOCK_HIGH;
 393         }
 394 
 395         return MODE_OK;
 396 }
 397 
 398 static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc,
 399                                    const struct drm_display_mode *m,
 400                                    struct drm_display_mode *adjusted_mode)
 401 {
 402         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 403         unsigned long clk_rate;
 404 
 405         drm_mode_set_crtcinfo(adjusted_mode, 0);
 406         /* In dual link half the horizontal settings */
 407         if (kcrtc->master->dual_link) {
 408                 adjusted_mode->crtc_clock /= 2;
 409                 adjusted_mode->crtc_hdisplay /= 2;
 410                 adjusted_mode->crtc_hsync_start /= 2;
 411                 adjusted_mode->crtc_hsync_end /= 2;
 412                 adjusted_mode->crtc_htotal /= 2;
 413         }
 414 
 415         clk_rate = adjusted_mode->crtc_clock * 1000;
 416         /* crtc_clock will be used as the komeda output pixel clock */
 417         adjusted_mode->crtc_clock = clk_round_rate(kcrtc->master->pxlclk,
 418                                                    clk_rate) / 1000;
 419 
 420         return true;
 421 }
 422 
 423 static const struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {
 424         .atomic_check   = komeda_crtc_atomic_check,
 425         .atomic_flush   = komeda_crtc_atomic_flush,
 426         .atomic_enable  = komeda_crtc_atomic_enable,
 427         .atomic_disable = komeda_crtc_atomic_disable,
 428         .mode_valid     = komeda_crtc_mode_valid,
 429         .mode_fixup     = komeda_crtc_mode_fixup,
 430 };
 431 
 432 static void komeda_crtc_reset(struct drm_crtc *crtc)
 433 {
 434         struct komeda_crtc_state *state;
 435 
 436         if (crtc->state)
 437                 __drm_atomic_helper_crtc_destroy_state(crtc->state);
 438 
 439         kfree(to_kcrtc_st(crtc->state));
 440         crtc->state = NULL;
 441 
 442         state = kzalloc(sizeof(*state), GFP_KERNEL);
 443         if (state) {
 444                 crtc->state = &state->base;
 445                 crtc->state->crtc = crtc;
 446         }
 447 }
 448 
 449 static struct drm_crtc_state *
 450 komeda_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 451 {
 452         struct komeda_crtc_state *old = to_kcrtc_st(crtc->state);
 453         struct komeda_crtc_state *new;
 454 
 455         new = kzalloc(sizeof(*new), GFP_KERNEL);
 456         if (!new)
 457                 return NULL;
 458 
 459         __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
 460 
 461         new->affected_pipes = old->active_pipes;
 462         new->clock_ratio = old->clock_ratio;
 463         new->max_slave_zorder = old->max_slave_zorder;
 464 
 465         return &new->base;
 466 }
 467 
 468 static void komeda_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 469                                              struct drm_crtc_state *state)
 470 {
 471         __drm_atomic_helper_crtc_destroy_state(state);
 472         kfree(to_kcrtc_st(state));
 473 }
 474 
 475 static int komeda_crtc_vblank_enable(struct drm_crtc *crtc)
 476 {
 477         struct komeda_dev *mdev = crtc->dev->dev_private;
 478         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 479 
 480         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, true);
 481         return 0;
 482 }
 483 
 484 static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
 485 {
 486         struct komeda_dev *mdev = crtc->dev->dev_private;
 487         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
 488 
 489         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, false);
 490 }
 491 
 492 static const struct drm_crtc_funcs komeda_crtc_funcs = {
 493         .gamma_set              = drm_atomic_helper_legacy_gamma_set,
 494         .destroy                = drm_crtc_cleanup,
 495         .set_config             = drm_atomic_helper_set_config,
 496         .page_flip              = drm_atomic_helper_page_flip,
 497         .reset                  = komeda_crtc_reset,
 498         .atomic_duplicate_state = komeda_crtc_atomic_duplicate_state,
 499         .atomic_destroy_state   = komeda_crtc_atomic_destroy_state,
 500         .enable_vblank          = komeda_crtc_vblank_enable,
 501         .disable_vblank         = komeda_crtc_vblank_disable,
 502 };
 503 
 504 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
 505                            struct komeda_dev *mdev)
 506 {
 507         struct komeda_crtc *crtc;
 508         struct komeda_pipeline *master;
 509         char str[16];
 510         int i;
 511 
 512         kms->n_crtcs = 0;
 513 
 514         for (i = 0; i < mdev->n_pipelines; i++) {
 515                 crtc = &kms->crtcs[kms->n_crtcs];
 516                 master = mdev->pipelines[i];
 517 
 518                 crtc->master = master;
 519                 crtc->slave  = komeda_pipeline_get_slave(master);
 520 
 521                 if (crtc->slave)
 522                         sprintf(str, "pipe-%d", crtc->slave->id);
 523                 else
 524                         sprintf(str, "None");
 525 
 526                 DRM_INFO("CRTC-%d: master(pipe-%d) slave(%s).\n",
 527                          kms->n_crtcs, master->id, str);
 528 
 529                 kms->n_crtcs++;
 530         }
 531 
 532         return 0;
 533 }
 534 
 535 static struct drm_plane *
 536 get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
 537 {
 538         struct komeda_plane *kplane;
 539         struct drm_plane *plane;
 540 
 541         drm_for_each_plane(plane, &kms->base) {
 542                 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
 543                         continue;
 544 
 545                 kplane = to_kplane(plane);
 546                 /* only master can be primary */
 547                 if (kplane->layer->base.pipeline == crtc->master)
 548                         return plane;
 549         }
 550 
 551         return NULL;
 552 }
 553 
 554 static int komeda_crtc_add(struct komeda_kms_dev *kms,
 555                            struct komeda_crtc *kcrtc)
 556 {
 557         struct drm_crtc *crtc = &kcrtc->base;
 558         int err;
 559 
 560         err = drm_crtc_init_with_planes(&kms->base, crtc,
 561                                         get_crtc_primary(kms, kcrtc), NULL,
 562                                         &komeda_crtc_funcs, NULL);
 563         if (err)
 564                 return err;
 565 
 566         drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
 567         drm_crtc_vblank_reset(crtc);
 568 
 569         crtc->port = kcrtc->master->of_output_port;
 570 
 571         return err;
 572 }
 573 
 574 int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
 575 {
 576         int i, err;
 577 
 578         for (i = 0; i < kms->n_crtcs; i++) {
 579                 err = komeda_crtc_add(kms, &kms->crtcs[i]);
 580                 if (err)
 581                         return err;
 582         }
 583 
 584         return 0;
 585 }

/* [<][>][^][v][top][bottom][index][help] */