| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012 Russell King |
|---|
| 3 | 4 | * Rewritten from the dovefb driver, and Armada510 manuals. |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 6 | + |
|---|
| 9 | 7 | #include <linux/clk.h> |
|---|
| 10 | 8 | #include <linux/component.h> |
|---|
| 9 | +#include <linux/module.h> |
|---|
| 11 | 10 | #include <linux/of_device.h> |
|---|
| 12 | 11 | #include <linux/platform_device.h> |
|---|
| 13 | | -#include <drm/drmP.h> |
|---|
| 12 | + |
|---|
| 14 | 13 | #include <drm/drm_atomic.h> |
|---|
| 15 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 16 | | -#include <drm/drm_plane_helper.h> |
|---|
| 17 | 14 | #include <drm/drm_atomic_helper.h> |
|---|
| 15 | +#include <drm/drm_plane_helper.h> |
|---|
| 16 | +#include <drm/drm_probe_helper.h> |
|---|
| 17 | +#include <drm/drm_vblank.h> |
|---|
| 18 | + |
|---|
| 18 | 19 | #include "armada_crtc.h" |
|---|
| 19 | 20 | #include "armada_drm.h" |
|---|
| 20 | 21 | #include "armada_fb.h" |
|---|
| .. | .. |
|---|
| 130 | 131 | } |
|---|
| 131 | 132 | } |
|---|
| 132 | 133 | |
|---|
| 134 | +static void armada_drm_update_gamma(struct drm_crtc *crtc) |
|---|
| 135 | +{ |
|---|
| 136 | + struct drm_property_blob *blob = crtc->state->gamma_lut; |
|---|
| 137 | + void __iomem *base = drm_to_armada_crtc(crtc)->base; |
|---|
| 138 | + int i; |
|---|
| 139 | + |
|---|
| 140 | + if (blob) { |
|---|
| 141 | + struct drm_color_lut *lut = blob->data; |
|---|
| 142 | + |
|---|
| 143 | + armada_updatel(CFG_CSB_256x8, CFG_CSB_256x8 | CFG_PDWN256x8, |
|---|
| 144 | + base + LCD_SPU_SRAM_PARA1); |
|---|
| 145 | + |
|---|
| 146 | + for (i = 0; i < 256; i++) { |
|---|
| 147 | + writel_relaxed(drm_color_lut_extract(lut[i].red, 8), |
|---|
| 148 | + base + LCD_SPU_SRAM_WRDAT); |
|---|
| 149 | + writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_YR, |
|---|
| 150 | + base + LCD_SPU_SRAM_CTRL); |
|---|
| 151 | + readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN); |
|---|
| 152 | + writel_relaxed(drm_color_lut_extract(lut[i].green, 8), |
|---|
| 153 | + base + LCD_SPU_SRAM_WRDAT); |
|---|
| 154 | + writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_UG, |
|---|
| 155 | + base + LCD_SPU_SRAM_CTRL); |
|---|
| 156 | + readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN); |
|---|
| 157 | + writel_relaxed(drm_color_lut_extract(lut[i].blue, 8), |
|---|
| 158 | + base + LCD_SPU_SRAM_WRDAT); |
|---|
| 159 | + writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_VB, |
|---|
| 160 | + base + LCD_SPU_SRAM_CTRL); |
|---|
| 161 | + readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN); |
|---|
| 162 | + } |
|---|
| 163 | + armada_updatel(CFG_GAMMA_ENA, CFG_GAMMA_ENA, |
|---|
| 164 | + base + LCD_SPU_DMA_CTRL0); |
|---|
| 165 | + } else { |
|---|
| 166 | + armada_updatel(0, CFG_GAMMA_ENA, base + LCD_SPU_DMA_CTRL0); |
|---|
| 167 | + armada_updatel(CFG_PDWN256x8, CFG_CSB_256x8 | CFG_PDWN256x8, |
|---|
| 168 | + base + LCD_SPU_SRAM_PARA1); |
|---|
| 169 | + } |
|---|
| 170 | +} |
|---|
| 171 | + |
|---|
| 172 | +static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc, |
|---|
| 173 | + const struct drm_display_mode *mode) |
|---|
| 174 | +{ |
|---|
| 175 | + struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
|---|
| 176 | + |
|---|
| 177 | + if (mode->vscan > 1) |
|---|
| 178 | + return MODE_NO_VSCAN; |
|---|
| 179 | + |
|---|
| 180 | + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
|---|
| 181 | + return MODE_NO_DBLESCAN; |
|---|
| 182 | + |
|---|
| 183 | + if (mode->flags & DRM_MODE_FLAG_HSKEW) |
|---|
| 184 | + return MODE_H_ILLEGAL; |
|---|
| 185 | + |
|---|
| 186 | + /* We can't do interlaced modes if we don't have the SPU_ADV_REG */ |
|---|
| 187 | + if (!dcrtc->variant->has_spu_adv_reg && |
|---|
| 188 | + mode->flags & DRM_MODE_FLAG_INTERLACE) |
|---|
| 189 | + return MODE_NO_INTERLACE; |
|---|
| 190 | + |
|---|
| 191 | + if (mode->flags & (DRM_MODE_FLAG_BCAST | DRM_MODE_FLAG_PIXMUX | |
|---|
| 192 | + DRM_MODE_FLAG_CLKDIV2)) |
|---|
| 193 | + return MODE_BAD; |
|---|
| 194 | + |
|---|
| 195 | + return MODE_OK; |
|---|
| 196 | +} |
|---|
| 197 | + |
|---|
| 133 | 198 | /* The mode_config.mutex will be held for this call */ |
|---|
| 134 | 199 | static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, |
|---|
| 135 | 200 | const struct drm_display_mode *mode, struct drm_display_mode *adj) |
|---|
| .. | .. |
|---|
| 137 | 202 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
|---|
| 138 | 203 | int ret; |
|---|
| 139 | 204 | |
|---|
| 140 | | - /* We can't do interlaced modes if we don't have the SPU_ADV_REG */ |
|---|
| 141 | | - if (!dcrtc->variant->has_spu_adv_reg && |
|---|
| 142 | | - adj->flags & DRM_MODE_FLAG_INTERLACE) |
|---|
| 205 | + /* |
|---|
| 206 | + * Set CRTC modesetting parameters for the adjusted mode. This is |
|---|
| 207 | + * applied after the connectors, bridges, and encoders have fixed up |
|---|
| 208 | + * this mode, as described above drm_atomic_helper_check_modeset(). |
|---|
| 209 | + */ |
|---|
| 210 | + drm_mode_set_crtcinfo(adj, CRTC_INTERLACE_HALVE_V); |
|---|
| 211 | + |
|---|
| 212 | + /* |
|---|
| 213 | + * Validate the adjusted mode in case an encoder/bridge has set |
|---|
| 214 | + * something we don't support. |
|---|
| 215 | + */ |
|---|
| 216 | + if (armada_drm_crtc_mode_valid(crtc, adj) != MODE_OK) |
|---|
| 143 | 217 | return false; |
|---|
| 144 | 218 | |
|---|
| 145 | 219 | /* Check whether the display mode is possible */ |
|---|
| .. | .. |
|---|
| 270 | 344 | tm = adj->crtc_vtotal - adj->crtc_vsync_end; |
|---|
| 271 | 345 | |
|---|
| 272 | 346 | DRM_DEBUG_KMS("[CRTC:%d:%s] mode " DRM_MODE_FMT "\n", |
|---|
| 273 | | - crtc->base.id, crtc->name, |
|---|
| 274 | | - adj->base.id, adj->name, adj->vrefresh, adj->clock, |
|---|
| 275 | | - adj->crtc_hdisplay, adj->crtc_hsync_start, |
|---|
| 276 | | - adj->crtc_hsync_end, adj->crtc_htotal, |
|---|
| 277 | | - adj->crtc_vdisplay, adj->crtc_vsync_start, |
|---|
| 278 | | - adj->crtc_vsync_end, adj->crtc_vtotal, |
|---|
| 279 | | - adj->type, adj->flags); |
|---|
| 347 | + crtc->base.id, crtc->name, DRM_MODE_ARG(adj)); |
|---|
| 280 | 348 | DRM_DEBUG_KMS("lm %d rm %d tm %d bm %d\n", lm, rm, tm, bm); |
|---|
| 281 | 349 | |
|---|
| 282 | 350 | /* Now compute the divider for real */ |
|---|
| .. | .. |
|---|
| 284 | 352 | |
|---|
| 285 | 353 | armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV); |
|---|
| 286 | 354 | |
|---|
| 287 | | - if (interlaced ^ dcrtc->interlaced) { |
|---|
| 288 | | - if (adj->flags & DRM_MODE_FLAG_INTERLACE) |
|---|
| 289 | | - drm_crtc_vblank_get(&dcrtc->crtc); |
|---|
| 290 | | - else |
|---|
| 291 | | - drm_crtc_vblank_put(&dcrtc->crtc); |
|---|
| 292 | | - dcrtc->interlaced = interlaced; |
|---|
| 293 | | - } |
|---|
| 294 | | - |
|---|
| 295 | 355 | spin_lock_irqsave(&dcrtc->irq_lock, flags); |
|---|
| 296 | 356 | |
|---|
| 357 | + dcrtc->interlaced = interlaced; |
|---|
| 297 | 358 | /* Even interlaced/progressive frame */ |
|---|
| 298 | 359 | dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 | |
|---|
| 299 | 360 | adj->crtc_htotal; |
|---|
| .. | .. |
|---|
| 351 | 412 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); |
|---|
| 352 | 413 | } |
|---|
| 353 | 414 | |
|---|
| 415 | +static int armada_drm_crtc_atomic_check(struct drm_crtc *crtc, |
|---|
| 416 | + struct drm_crtc_state *state) |
|---|
| 417 | +{ |
|---|
| 418 | + DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
|---|
| 419 | + |
|---|
| 420 | + if (state->gamma_lut && drm_color_lut_size(state->gamma_lut) != 256) |
|---|
| 421 | + return -EINVAL; |
|---|
| 422 | + |
|---|
| 423 | + if (state->color_mgmt_changed) |
|---|
| 424 | + state->planes_changed = true; |
|---|
| 425 | + |
|---|
| 426 | + return 0; |
|---|
| 427 | +} |
|---|
| 428 | + |
|---|
| 354 | 429 | static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc, |
|---|
| 355 | 430 | struct drm_crtc_state *old_crtc_state) |
|---|
| 356 | 431 | { |
|---|
| 357 | 432 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
|---|
| 358 | 433 | |
|---|
| 359 | 434 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
|---|
| 435 | + |
|---|
| 436 | + if (crtc->state->color_mgmt_changed) |
|---|
| 437 | + armada_drm_update_gamma(crtc); |
|---|
| 360 | 438 | |
|---|
| 361 | 439 | dcrtc->regs_idx = 0; |
|---|
| 362 | 440 | dcrtc->regs = dcrtc->atomic_regs; |
|---|
| .. | .. |
|---|
| 395 | 473 | struct drm_pending_vblank_event *event; |
|---|
| 396 | 474 | |
|---|
| 397 | 475 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
|---|
| 476 | + |
|---|
| 477 | + if (old_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) |
|---|
| 478 | + drm_crtc_vblank_put(crtc); |
|---|
| 398 | 479 | |
|---|
| 399 | 480 | drm_crtc_vblank_off(crtc); |
|---|
| 400 | 481 | armada_drm_crtc_update(dcrtc, false); |
|---|
| .. | .. |
|---|
| 440 | 521 | armada_drm_crtc_update(dcrtc, true); |
|---|
| 441 | 522 | drm_crtc_vblank_on(crtc); |
|---|
| 442 | 523 | |
|---|
| 524 | + if (crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) |
|---|
| 525 | + WARN_ON(drm_crtc_vblank_get(crtc)); |
|---|
| 526 | + |
|---|
| 443 | 527 | armada_drm_crtc_queue_state_event(crtc); |
|---|
| 444 | 528 | } |
|---|
| 445 | 529 | |
|---|
| 446 | 530 | static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { |
|---|
| 531 | + .mode_valid = armada_drm_crtc_mode_valid, |
|---|
| 447 | 532 | .mode_fixup = armada_drm_crtc_mode_fixup, |
|---|
| 448 | 533 | .mode_set_nofb = armada_drm_crtc_mode_set_nofb, |
|---|
| 534 | + .atomic_check = armada_drm_crtc_atomic_check, |
|---|
| 449 | 535 | .atomic_begin = armada_drm_crtc_atomic_begin, |
|---|
| 450 | 536 | .atomic_flush = armada_drm_crtc_atomic_flush, |
|---|
| 451 | 537 | .atomic_disable = armada_drm_crtc_atomic_disable, |
|---|
| .. | .. |
|---|
| 466 | 552 | for (x = 0; x < width; x++, p++) { |
|---|
| 467 | 553 | uint32_t val = *p; |
|---|
| 468 | 554 | |
|---|
| 555 | + /* |
|---|
| 556 | + * In "ARGB888" (HWC32) mode, writing to the SRAM |
|---|
| 557 | + * requires these bits to contain: |
|---|
| 558 | + * 31:24 = alpha 23:16 = blue 15:8 = green 7:0 = red |
|---|
| 559 | + * So, it's actually ABGR8888. This is independent |
|---|
| 560 | + * of the SWAPRB bits in DMA control register 0. |
|---|
| 561 | + */ |
|---|
| 469 | 562 | val = (val & 0xff00ff00) | |
|---|
| 470 | 563 | (val & 0x000000ff) << 16 | |
|---|
| 471 | 564 | (val & 0x00ff0000) >> 16; |
|---|
| .. | .. |
|---|
| 617 | 710 | |
|---|
| 618 | 711 | /* Must be a kernel-mapped object */ |
|---|
| 619 | 712 | if (!obj->addr) { |
|---|
| 620 | | - drm_gem_object_put_unlocked(&obj->obj); |
|---|
| 713 | + drm_gem_object_put(&obj->obj); |
|---|
| 621 | 714 | return -EINVAL; |
|---|
| 622 | 715 | } |
|---|
| 623 | 716 | |
|---|
| 624 | 717 | if (obj->obj.size < w * h * 4) { |
|---|
| 625 | 718 | DRM_ERROR("buffer is too small\n"); |
|---|
| 626 | | - drm_gem_object_put_unlocked(&obj->obj); |
|---|
| 719 | + drm_gem_object_put(&obj->obj); |
|---|
| 627 | 720 | return -ENOMEM; |
|---|
| 628 | 721 | } |
|---|
| 629 | 722 | } |
|---|
| .. | .. |
|---|
| 631 | 724 | if (dcrtc->cursor_obj) { |
|---|
| 632 | 725 | dcrtc->cursor_obj->update = NULL; |
|---|
| 633 | 726 | dcrtc->cursor_obj->update_data = NULL; |
|---|
| 634 | | - drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj); |
|---|
| 727 | + drm_gem_object_put(&dcrtc->cursor_obj->obj); |
|---|
| 635 | 728 | } |
|---|
| 636 | 729 | dcrtc->cursor_obj = obj; |
|---|
| 637 | 730 | dcrtc->cursor_w = w; |
|---|
| .. | .. |
|---|
| 664 | 757 | static void armada_drm_crtc_destroy(struct drm_crtc *crtc) |
|---|
| 665 | 758 | { |
|---|
| 666 | 759 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
|---|
| 667 | | - struct armada_private *priv = crtc->dev->dev_private; |
|---|
| 760 | + struct armada_private *priv = drm_to_armada_dev(crtc->dev); |
|---|
| 668 | 761 | |
|---|
| 669 | 762 | if (dcrtc->cursor_obj) |
|---|
| 670 | | - drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj); |
|---|
| 763 | + drm_gem_object_put(&dcrtc->cursor_obj->obj); |
|---|
| 671 | 764 | |
|---|
| 672 | 765 | priv->dcrtc[dcrtc->num] = NULL; |
|---|
| 673 | 766 | drm_crtc_cleanup(&dcrtc->crtc); |
|---|
| .. | .. |
|---|
| 680 | 773 | of_node_put(dcrtc->crtc.port); |
|---|
| 681 | 774 | |
|---|
| 682 | 775 | kfree(dcrtc); |
|---|
| 776 | +} |
|---|
| 777 | + |
|---|
| 778 | +static int armada_drm_crtc_late_register(struct drm_crtc *crtc) |
|---|
| 779 | +{ |
|---|
| 780 | + if (IS_ENABLED(CONFIG_DEBUG_FS)) |
|---|
| 781 | + armada_drm_crtc_debugfs_init(drm_to_armada_crtc(crtc)); |
|---|
| 782 | + |
|---|
| 783 | + return 0; |
|---|
| 683 | 784 | } |
|---|
| 684 | 785 | |
|---|
| 685 | 786 | /* These are called under the vbl_lock. */ |
|---|
| .. | .. |
|---|
| 709 | 810 | .cursor_set = armada_drm_crtc_cursor_set, |
|---|
| 710 | 811 | .cursor_move = armada_drm_crtc_cursor_move, |
|---|
| 711 | 812 | .destroy = armada_drm_crtc_destroy, |
|---|
| 813 | + .gamma_set = drm_atomic_helper_legacy_gamma_set, |
|---|
| 712 | 814 | .set_config = drm_atomic_helper_set_config, |
|---|
| 713 | 815 | .page_flip = drm_atomic_helper_page_flip, |
|---|
| 714 | 816 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, |
|---|
| 715 | 817 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, |
|---|
| 818 | + .late_register = armada_drm_crtc_late_register, |
|---|
| 716 | 819 | .enable_vblank = armada_drm_crtc_enable_vblank, |
|---|
| 717 | 820 | .disable_vblank = armada_drm_crtc_disable_vblank, |
|---|
| 718 | 821 | }; |
|---|
| 822 | + |
|---|
| 823 | +int armada_crtc_select_clock(struct armada_crtc *dcrtc, |
|---|
| 824 | + struct armada_clk_result *res, |
|---|
| 825 | + const struct armada_clocking_params *params, |
|---|
| 826 | + struct clk *clks[], size_t num_clks, |
|---|
| 827 | + unsigned long desired_khz) |
|---|
| 828 | +{ |
|---|
| 829 | + unsigned long desired_hz = desired_khz * 1000; |
|---|
| 830 | + unsigned long desired_clk_hz; // requested clk input |
|---|
| 831 | + unsigned long real_clk_hz; // actual clk input |
|---|
| 832 | + unsigned long real_hz; // actual pixel clk |
|---|
| 833 | + unsigned long permillage; |
|---|
| 834 | + struct clk *clk; |
|---|
| 835 | + u32 div; |
|---|
| 836 | + int i; |
|---|
| 837 | + |
|---|
| 838 | + DRM_DEBUG_KMS("[CRTC:%u:%s] desired clock=%luHz\n", |
|---|
| 839 | + dcrtc->crtc.base.id, dcrtc->crtc.name, desired_hz); |
|---|
| 840 | + |
|---|
| 841 | + for (i = 0; i < num_clks; i++) { |
|---|
| 842 | + clk = clks[i]; |
|---|
| 843 | + if (!clk) |
|---|
| 844 | + continue; |
|---|
| 845 | + |
|---|
| 846 | + if (params->settable & BIT(i)) { |
|---|
| 847 | + real_clk_hz = clk_round_rate(clk, desired_hz); |
|---|
| 848 | + desired_clk_hz = desired_hz; |
|---|
| 849 | + } else { |
|---|
| 850 | + real_clk_hz = clk_get_rate(clk); |
|---|
| 851 | + desired_clk_hz = real_clk_hz; |
|---|
| 852 | + } |
|---|
| 853 | + |
|---|
| 854 | + /* If the clock can do exactly the desired rate, we're done */ |
|---|
| 855 | + if (real_clk_hz == desired_hz) { |
|---|
| 856 | + real_hz = real_clk_hz; |
|---|
| 857 | + div = 1; |
|---|
| 858 | + goto found; |
|---|
| 859 | + } |
|---|
| 860 | + |
|---|
| 861 | + /* Calculate the divider - if invalid, we can't do this rate */ |
|---|
| 862 | + div = DIV_ROUND_CLOSEST(real_clk_hz, desired_hz); |
|---|
| 863 | + if (div == 0 || div > params->div_max) |
|---|
| 864 | + continue; |
|---|
| 865 | + |
|---|
| 866 | + /* Calculate the actual rate - HDMI requires -0.6%..+0.5% */ |
|---|
| 867 | + real_hz = DIV_ROUND_CLOSEST(real_clk_hz, div); |
|---|
| 868 | + |
|---|
| 869 | + DRM_DEBUG_KMS("[CRTC:%u:%s] clk=%u %luHz div=%u real=%luHz\n", |
|---|
| 870 | + dcrtc->crtc.base.id, dcrtc->crtc.name, |
|---|
| 871 | + i, real_clk_hz, div, real_hz); |
|---|
| 872 | + |
|---|
| 873 | + /* Avoid repeated division */ |
|---|
| 874 | + if (real_hz < desired_hz) { |
|---|
| 875 | + permillage = real_hz / desired_khz; |
|---|
| 876 | + if (permillage < params->permillage_min) |
|---|
| 877 | + continue; |
|---|
| 878 | + } else { |
|---|
| 879 | + permillage = DIV_ROUND_UP(real_hz, desired_khz); |
|---|
| 880 | + if (permillage > params->permillage_max) |
|---|
| 881 | + continue; |
|---|
| 882 | + } |
|---|
| 883 | + goto found; |
|---|
| 884 | + } |
|---|
| 885 | + |
|---|
| 886 | + return -ERANGE; |
|---|
| 887 | + |
|---|
| 888 | +found: |
|---|
| 889 | + DRM_DEBUG_KMS("[CRTC:%u:%s] selected clk=%u %luHz div=%u real=%luHz\n", |
|---|
| 890 | + dcrtc->crtc.base.id, dcrtc->crtc.name, |
|---|
| 891 | + i, real_clk_hz, div, real_hz); |
|---|
| 892 | + |
|---|
| 893 | + res->desired_clk_hz = desired_clk_hz; |
|---|
| 894 | + res->clk = clk; |
|---|
| 895 | + res->div = div; |
|---|
| 896 | + |
|---|
| 897 | + return i; |
|---|
| 898 | +} |
|---|
| 719 | 899 | |
|---|
| 720 | 900 | static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, |
|---|
| 721 | 901 | struct resource *res, int irq, const struct armada_variant *variant, |
|---|
| 722 | 902 | struct device_node *port) |
|---|
| 723 | 903 | { |
|---|
| 724 | | - struct armada_private *priv = drm->dev_private; |
|---|
| 904 | + struct armada_private *priv = drm_to_armada_dev(drm); |
|---|
| 725 | 905 | struct armada_crtc *dcrtc; |
|---|
| 726 | 906 | struct drm_plane *primary; |
|---|
| 727 | 907 | void __iomem *base; |
|---|
| .. | .. |
|---|
| 743 | 923 | dcrtc->variant = variant; |
|---|
| 744 | 924 | dcrtc->base = base; |
|---|
| 745 | 925 | dcrtc->num = drm->mode_config.num_crtc; |
|---|
| 746 | | - dcrtc->clk = ERR_PTR(-EINVAL); |
|---|
| 747 | 926 | dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0; |
|---|
| 748 | 927 | dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24; |
|---|
| 749 | 928 | spin_lock_init(&dcrtc->irq_lock); |
|---|
| .. | .. |
|---|
| 800 | 979 | |
|---|
| 801 | 980 | drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); |
|---|
| 802 | 981 | |
|---|
| 982 | + ret = drm_mode_crtc_set_gamma_size(&dcrtc->crtc, 256); |
|---|
| 983 | + if (ret) |
|---|
| 984 | + return ret; |
|---|
| 985 | + |
|---|
| 986 | + drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256); |
|---|
| 987 | + |
|---|
| 803 | 988 | return armada_overlay_plane_create(drm, 1 << dcrtc->num); |
|---|
| 804 | 989 | |
|---|
| 805 | 990 | err_crtc_init: |
|---|