1095 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2012 Russell King4 * Rewritten from the dovefb driver, and Armada510 manuals.5 */6 7#include <linux/clk.h>8#include <linux/component.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/platform_device.h>12#include <linux/property.h>13 14#include <drm/drm_atomic.h>15#include <drm/drm_atomic_helper.h>16#include <drm/drm_probe_helper.h>17#include <drm/drm_vblank.h>18 19#include "armada_crtc.h"20#include "armada_drm.h"21#include "armada_fb.h"22#include "armada_gem.h"23#include "armada_hw.h"24#include "armada_plane.h"25#include "armada_trace.h"26 27/*28 * A note about interlacing. Let's consider HDMI 1920x1080i.29 * The timing parameters we have from X are:30 * Hact HsyA HsyI Htot Vact VsyA VsyI Vtot31 * 1920 2448 2492 2640 1080 1084 1094 112532 * Which get translated to:33 * Hact HsyA HsyI Htot Vact VsyA VsyI Vtot34 * 1920 2448 2492 2640 540 542 547 56235 *36 * This is how it is defined by CEA-861-D - line and pixel numbers are37 * referenced to the rising edge of VSYNC and HSYNC. Total clocks per38 * line: 2640. The odd frame, the first active line is at line 21, and39 * the even frame, the first active line is 584.40 *41 * LN: 560 561 562 563 567 568 56942 * DE: ~~~|____________________________//__________________________43 * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____44 * VSYNC: _________________________|~~~~~~//~~~~~~~~~~~~~~~|__________45 * 22 blanking lines. VSYNC at 1320 (referenced to the HSYNC rising edge).46 *47 * LN: 1123 1124 1125 1 5 6 748 * DE: ~~~|____________________________//__________________________49 * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____50 * VSYNC: ____________________|~~~~~~~~~~~//~~~~~~~~~~|_______________51 * 23 blanking lines52 *53 * The Armada LCD Controller line and pixel numbers are, like X timings,54 * referenced to the top left of the active frame.55 *56 * So, translating these to our LCD controller:57 * Odd frame, 563 total lines, VSYNC at line 543-548, pixel 1128.58 * Even frame, 562 total lines, VSYNC at line 542-547, pixel 2448.59 * Note: Vsync front porch remains constant!60 *61 * if (odd_frame) {62 * vtotal = mode->crtc_vtotal + 1;63 * vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay + 1;64 * vhorizpos = mode->crtc_hsync_start - mode->crtc_htotal / 265 * } else {66 * vtotal = mode->crtc_vtotal;67 * vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay;68 * vhorizpos = mode->crtc_hsync_start;69 * }70 * vfrontporch = mode->crtc_vtotal - mode->crtc_vsync_end;71 *72 * So, we need to reprogram these registers on each vsync event:73 * LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL74 *75 * Note: we do not use the frame done interrupts because these appear76 * to happen too early, and lead to jitter on the display (presumably77 * they occur at the end of the last active line, before the vsync back78 * porch, which we're reprogramming.)79 */80 81void82armada_drm_crtc_update_regs(struct armada_crtc *dcrtc, struct armada_regs *regs)83{84 while (regs->offset != ~0) {85 void __iomem *reg = dcrtc->base + regs->offset;86 uint32_t val;87 88 val = regs->mask;89 if (val != 0)90 val &= readl_relaxed(reg);91 writel_relaxed(val | regs->val, reg);92 ++regs;93 }94}95 96static void armada_drm_crtc_update(struct armada_crtc *dcrtc, bool enable)97{98 uint32_t dumb_ctrl;99 100 dumb_ctrl = dcrtc->cfg_dumb_ctrl;101 102 if (enable)103 dumb_ctrl |= CFG_DUMB_ENA;104 105 /*106 * When the dumb interface isn't in DUMB24_RGB888_0 mode, it might107 * be using SPI or GPIO. If we set this to DUMB_BLANK, we will108 * force LCD_D[23:0] to output blank color, overriding the GPIO or109 * SPI usage. So leave it as-is unless in DUMB24_RGB888_0 mode.110 */111 if (!enable && (dumb_ctrl & DUMB_MASK) == DUMB24_RGB888_0) {112 dumb_ctrl &= ~DUMB_MASK;113 dumb_ctrl |= DUMB_BLANK;114 }115 116 armada_updatel(dumb_ctrl,117 ~(CFG_INV_CSYNC | CFG_INV_HSYNC | CFG_INV_VSYNC),118 dcrtc->base + LCD_SPU_DUMB_CTRL);119}120 121static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc)122{123 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);124 struct drm_pending_vblank_event *event;125 126 /* If we have an event, we need vblank events enabled */127 event = xchg(&crtc->state->event, NULL);128 if (event) {129 WARN_ON(drm_crtc_vblank_get(crtc) != 0);130 dcrtc->event = event;131 }132}133 134static 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 172static 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 198/* The mode_config.mutex will be held for this call */199static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,200 const struct drm_display_mode *mode, struct drm_display_mode *adj)201{202 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);203 int ret;204 205 /*206 * Set CRTC modesetting parameters for the adjusted mode. This is207 * applied after the connectors, bridges, and encoders have fixed up208 * 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 set214 * something we don't support.215 */216 if (armada_drm_crtc_mode_valid(crtc, adj) != MODE_OK)217 return false;218 219 /* Check whether the display mode is possible */220 ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);221 if (ret)222 return false;223 224 return true;225}226 227/* These are locked by dev->vbl_lock */228static void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)229{230 if (dcrtc->irq_ena & mask) {231 dcrtc->irq_ena &= ~mask;232 writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);233 }234}235 236static void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)237{238 if ((dcrtc->irq_ena & mask) != mask) {239 dcrtc->irq_ena |= mask;240 writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);241 if (readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR) & mask)242 writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);243 }244}245 246static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)247{248 struct drm_pending_vblank_event *event;249 void __iomem *base = dcrtc->base;250 251 if (stat & DMA_FF_UNDERFLOW)252 DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);253 if (stat & GRA_FF_UNDERFLOW)254 DRM_ERROR("graphics underflow on crtc %u\n", dcrtc->num);255 256 if (stat & VSYNC_IRQ)257 drm_crtc_handle_vblank(&dcrtc->crtc);258 259 spin_lock(&dcrtc->irq_lock);260 if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {261 int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;262 uint32_t val;263 264 writel_relaxed(dcrtc->v[i].spu_v_porch, base + LCD_SPU_V_PORCH);265 writel_relaxed(dcrtc->v[i].spu_v_h_total,266 base + LCD_SPUT_V_H_TOTAL);267 268 val = readl_relaxed(base + LCD_SPU_ADV_REG);269 val &= ~(ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNCOFFEN);270 val |= dcrtc->v[i].spu_adv_reg;271 writel_relaxed(val, base + LCD_SPU_ADV_REG);272 }273 274 if (stat & dcrtc->irq_ena & DUMB_FRAMEDONE) {275 if (dcrtc->update_pending) {276 armada_drm_crtc_update_regs(dcrtc, dcrtc->regs);277 dcrtc->update_pending = false;278 }279 if (dcrtc->cursor_update) {280 writel_relaxed(dcrtc->cursor_hw_pos,281 base + LCD_SPU_HWC_OVSA_HPXL_VLN);282 writel_relaxed(dcrtc->cursor_hw_sz,283 base + LCD_SPU_HWC_HPXL_VLN);284 armada_updatel(CFG_HWC_ENA,285 CFG_HWC_ENA | CFG_HWC_1BITMOD |286 CFG_HWC_1BITENA,287 base + LCD_SPU_DMA_CTRL0);288 dcrtc->cursor_update = false;289 }290 armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);291 }292 spin_unlock(&dcrtc->irq_lock);293 294 if (stat & VSYNC_IRQ && !dcrtc->update_pending) {295 event = xchg(&dcrtc->event, NULL);296 if (event) {297 spin_lock(&dcrtc->crtc.dev->event_lock);298 drm_crtc_send_vblank_event(&dcrtc->crtc, event);299 spin_unlock(&dcrtc->crtc.dev->event_lock);300 drm_crtc_vblank_put(&dcrtc->crtc);301 }302 }303}304 305static irqreturn_t armada_drm_irq(int irq, void *arg)306{307 struct armada_crtc *dcrtc = arg;308 u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);309 310 /*311 * Reading the ISR appears to clear bits provided CLEAN_SPU_IRQ_ISR312 * is set. Writing has some other effect to acknowledge the IRQ -313 * without this, we only get a single IRQ.314 */315 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);316 317 trace_armada_drm_irq(&dcrtc->crtc, stat);318 319 /* Mask out those interrupts we haven't enabled */320 v = stat & dcrtc->irq_ena;321 322 if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {323 armada_drm_crtc_irq(dcrtc, stat);324 return IRQ_HANDLED;325 }326 return IRQ_NONE;327}328 329/* The mode_config.mutex will be held for this call */330static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)331{332 struct drm_display_mode *adj = &crtc->state->adjusted_mode;333 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);334 struct armada_regs regs[17];335 uint32_t lm, rm, tm, bm, val, sclk;336 unsigned long flags;337 unsigned i;338 bool interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);339 340 i = 0;341 rm = adj->crtc_hsync_start - adj->crtc_hdisplay;342 lm = adj->crtc_htotal - adj->crtc_hsync_end;343 bm = adj->crtc_vsync_start - adj->crtc_vdisplay;344 tm = adj->crtc_vtotal - adj->crtc_vsync_end;345 346 DRM_DEBUG_KMS("[CRTC:%d:%s] mode " DRM_MODE_FMT "\n",347 crtc->base.id, crtc->name, DRM_MODE_ARG(adj));348 DRM_DEBUG_KMS("lm %d rm %d tm %d bm %d\n", lm, rm, tm, bm);349 350 /* Now compute the divider for real */351 dcrtc->variant->compute_clock(dcrtc, adj, &sclk);352 353 armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);354 355 spin_lock_irqsave(&dcrtc->irq_lock, flags);356 357 dcrtc->interlaced = interlaced;358 /* Even interlaced/progressive frame */359 dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |360 adj->crtc_htotal;361 dcrtc->v[1].spu_v_porch = tm << 16 | bm;362 val = adj->crtc_hsync_start;363 dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;364 365 if (interlaced) {366 /* Odd interlaced frame */367 val -= adj->crtc_htotal / 2;368 dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;369 dcrtc->v[0].spu_v_h_total = dcrtc->v[1].spu_v_h_total +370 (1 << 16);371 dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;372 } else {373 dcrtc->v[0] = dcrtc->v[1];374 }375 376 val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;377 378 armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE);379 armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH);380 armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH);381 armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,382 LCD_SPUT_V_H_TOTAL);383 384 if (dcrtc->variant->has_spu_adv_reg)385 armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,386 ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |387 ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);388 389 val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0;390 armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1);391 392 /*393 * The documentation doesn't indicate what the normal state of394 * the sync signals are. Sebastian Hesselbart kindly probed395 * these signals on his board to determine their state.396 *397 * The non-inverted state of the sync signals is active high.398 * Setting these bits makes the appropriate signal active low.399 */400 val = 0;401 if (adj->flags & DRM_MODE_FLAG_NCSYNC)402 val |= CFG_INV_CSYNC;403 if (adj->flags & DRM_MODE_FLAG_NHSYNC)404 val |= CFG_INV_HSYNC;405 if (adj->flags & DRM_MODE_FLAG_NVSYNC)406 val |= CFG_INV_VSYNC;407 armada_reg_queue_mod(regs, i, val, CFG_INV_CSYNC | CFG_INV_HSYNC |408 CFG_INV_VSYNC, LCD_SPU_DUMB_CTRL);409 armada_reg_queue_end(regs, i);410 411 armada_drm_crtc_update_regs(dcrtc, regs);412 spin_unlock_irqrestore(&dcrtc->irq_lock, flags);413}414 415static int armada_drm_crtc_atomic_check(struct drm_crtc *crtc,416 struct drm_atomic_state *state)417{418 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,419 crtc);420 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);421 422 if (crtc_state->gamma_lut && drm_color_lut_size(crtc_state->gamma_lut) != 256)423 return -EINVAL;424 425 if (crtc_state->color_mgmt_changed)426 crtc_state->planes_changed = true;427 428 return 0;429}430 431static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,432 struct drm_atomic_state *state)433{434 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,435 crtc);436 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);437 438 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);439 440 if (crtc_state->color_mgmt_changed)441 armada_drm_update_gamma(crtc);442 443 dcrtc->regs_idx = 0;444 dcrtc->regs = dcrtc->atomic_regs;445}446 447static void armada_drm_crtc_atomic_flush(struct drm_crtc *crtc,448 struct drm_atomic_state *state)449{450 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,451 crtc);452 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);453 454 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);455 456 armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx);457 458 /*459 * If we aren't doing a full modeset, then we need to queue460 * the event here.461 */462 if (!drm_atomic_crtc_needs_modeset(crtc_state)) {463 dcrtc->update_pending = true;464 armada_drm_crtc_queue_state_event(crtc);465 spin_lock_irq(&dcrtc->irq_lock);466 armada_drm_crtc_enable_irq(dcrtc, DUMB_FRAMEDONE_ENA);467 spin_unlock_irq(&dcrtc->irq_lock);468 } else {469 spin_lock_irq(&dcrtc->irq_lock);470 armada_drm_crtc_update_regs(dcrtc, dcrtc->regs);471 spin_unlock_irq(&dcrtc->irq_lock);472 }473}474 475static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc,476 struct drm_atomic_state *state)477{478 struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,479 crtc);480 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);481 struct drm_pending_vblank_event *event;482 483 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);484 485 if (old_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)486 drm_crtc_vblank_put(crtc);487 488 drm_crtc_vblank_off(crtc);489 armada_drm_crtc_update(dcrtc, false);490 491 if (!crtc->state->active) {492 /*493 * This modeset will be leaving the CRTC disabled, so494 * call the backend to disable upstream clocks etc.495 */496 if (dcrtc->variant->disable)497 dcrtc->variant->disable(dcrtc);498 499 /*500 * We will not receive any further vblank events.501 * Send the flip_done event manually.502 */503 event = crtc->state->event;504 crtc->state->event = NULL;505 if (event) {506 spin_lock_irq(&crtc->dev->event_lock);507 drm_crtc_send_vblank_event(crtc, event);508 spin_unlock_irq(&crtc->dev->event_lock);509 }510 }511}512 513static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc,514 struct drm_atomic_state *state)515{516 struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,517 crtc);518 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);519 520 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);521 522 if (!old_state->active) {523 /*524 * This modeset is enabling the CRTC after it having525 * been disabled. Reverse the call to ->disable in526 * the atomic_disable().527 */528 if (dcrtc->variant->enable)529 dcrtc->variant->enable(dcrtc, &crtc->state->adjusted_mode);530 }531 armada_drm_crtc_update(dcrtc, true);532 drm_crtc_vblank_on(crtc);533 534 if (crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)535 WARN_ON(drm_crtc_vblank_get(crtc));536 537 armada_drm_crtc_queue_state_event(crtc);538}539 540static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {541 .mode_valid = armada_drm_crtc_mode_valid,542 .mode_fixup = armada_drm_crtc_mode_fixup,543 .mode_set_nofb = armada_drm_crtc_mode_set_nofb,544 .atomic_check = armada_drm_crtc_atomic_check,545 .atomic_begin = armada_drm_crtc_atomic_begin,546 .atomic_flush = armada_drm_crtc_atomic_flush,547 .atomic_disable = armada_drm_crtc_atomic_disable,548 .atomic_enable = armada_drm_crtc_atomic_enable,549};550 551static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix,552 unsigned stride, unsigned width, unsigned height)553{554 uint32_t addr;555 unsigned y;556 557 addr = SRAM_HWC32_RAM1;558 for (y = 0; y < height; y++) {559 uint32_t *p = &pix[y * stride];560 unsigned x;561 562 for (x = 0; x < width; x++, p++) {563 uint32_t val = *p;564 565 /*566 * In "ARGB888" (HWC32) mode, writing to the SRAM567 * requires these bits to contain:568 * 31:24 = alpha 23:16 = blue 15:8 = green 7:0 = red569 * So, it's actually ABGR8888. This is independent570 * of the SWAPRB bits in DMA control register 0.571 */572 val = (val & 0xff00ff00) |573 (val & 0x000000ff) << 16 |574 (val & 0x00ff0000) >> 16;575 576 writel_relaxed(val,577 base + LCD_SPU_SRAM_WRDAT);578 writel_relaxed(addr | SRAM_WRITE,579 base + LCD_SPU_SRAM_CTRL);580 readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);581 addr += 1;582 if ((addr & 0x00ff) == 0)583 addr += 0xf00;584 if ((addr & 0x30ff) == 0)585 addr = SRAM_HWC32_RAM2;586 }587 }588}589 590static void armada_drm_crtc_cursor_tran(void __iomem *base)591{592 unsigned addr;593 594 for (addr = 0; addr < 256; addr++) {595 /* write the default value */596 writel_relaxed(0x55555555, base + LCD_SPU_SRAM_WRDAT);597 writel_relaxed(addr | SRAM_WRITE | SRAM_HWC32_TRAN,598 base + LCD_SPU_SRAM_CTRL);599 }600}601 602static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool reload)603{604 uint32_t xoff, xscr, w = dcrtc->cursor_w, s;605 uint32_t yoff, yscr, h = dcrtc->cursor_h;606 uint32_t para1;607 608 /*609 * Calculate the visible width and height of the cursor,610 * screen position, and the position in the cursor bitmap.611 */612 if (dcrtc->cursor_x < 0) {613 xoff = -dcrtc->cursor_x;614 xscr = 0;615 w -= min(xoff, w);616 } else if (dcrtc->cursor_x + w > dcrtc->crtc.mode.hdisplay) {617 xoff = 0;618 xscr = dcrtc->cursor_x;619 w = max_t(int, dcrtc->crtc.mode.hdisplay - dcrtc->cursor_x, 0);620 } else {621 xoff = 0;622 xscr = dcrtc->cursor_x;623 }624 625 if (dcrtc->cursor_y < 0) {626 yoff = -dcrtc->cursor_y;627 yscr = 0;628 h -= min(yoff, h);629 } else if (dcrtc->cursor_y + h > dcrtc->crtc.mode.vdisplay) {630 yoff = 0;631 yscr = dcrtc->cursor_y;632 h = max_t(int, dcrtc->crtc.mode.vdisplay - dcrtc->cursor_y, 0);633 } else {634 yoff = 0;635 yscr = dcrtc->cursor_y;636 }637 638 /* On interlaced modes, the vertical cursor size must be halved */639 s = dcrtc->cursor_w;640 if (dcrtc->interlaced) {641 s *= 2;642 yscr /= 2;643 h /= 2;644 }645 646 if (!dcrtc->cursor_obj || !h || !w) {647 spin_lock_irq(&dcrtc->irq_lock);648 dcrtc->cursor_update = false;649 armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);650 spin_unlock_irq(&dcrtc->irq_lock);651 return 0;652 }653 654 spin_lock_irq(&dcrtc->irq_lock);655 para1 = readl_relaxed(dcrtc->base + LCD_SPU_SRAM_PARA1);656 armada_updatel(CFG_CSB_256x32, CFG_CSB_256x32 | CFG_PDWN256x32,657 dcrtc->base + LCD_SPU_SRAM_PARA1);658 spin_unlock_irq(&dcrtc->irq_lock);659 660 /*661 * Initialize the transparency if the SRAM was powered down.662 * We must also reload the cursor data as well.663 */664 if (!(para1 & CFG_CSB_256x32)) {665 armada_drm_crtc_cursor_tran(dcrtc->base);666 reload = true;667 }668 669 if (dcrtc->cursor_hw_sz != (h << 16 | w)) {670 spin_lock_irq(&dcrtc->irq_lock);671 dcrtc->cursor_update = false;672 armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);673 spin_unlock_irq(&dcrtc->irq_lock);674 reload = true;675 }676 if (reload) {677 struct armada_gem_object *obj = dcrtc->cursor_obj;678 uint32_t *pix;679 /* Set the top-left corner of the cursor image */680 pix = obj->addr;681 pix += yoff * s + xoff;682 armada_load_cursor_argb(dcrtc->base, pix, s, w, h);683 }684 685 /* Reload the cursor position, size and enable in the IRQ handler */686 spin_lock_irq(&dcrtc->irq_lock);687 dcrtc->cursor_hw_pos = yscr << 16 | xscr;688 dcrtc->cursor_hw_sz = h << 16 | w;689 dcrtc->cursor_update = true;690 armada_drm_crtc_enable_irq(dcrtc, DUMB_FRAMEDONE_ENA);691 spin_unlock_irq(&dcrtc->irq_lock);692 693 return 0;694}695 696static void cursor_update(void *data)697{698 armada_drm_crtc_cursor_update(data, true);699}700 701static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,702 struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)703{704 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);705 struct armada_gem_object *obj = NULL;706 int ret;707 708 /* If no cursor support, replicate drm's return value */709 if (!dcrtc->variant->has_spu_adv_reg)710 return -ENXIO;711 712 if (handle && w > 0 && h > 0) {713 /* maximum size is 64x32 or 32x64 */714 if (w > 64 || h > 64 || (w > 32 && h > 32))715 return -ENOMEM;716 717 obj = armada_gem_object_lookup(file, handle);718 if (!obj)719 return -ENOENT;720 721 /* Must be a kernel-mapped object */722 if (!obj->addr) {723 drm_gem_object_put(&obj->obj);724 return -EINVAL;725 }726 727 if (obj->obj.size < w * h * 4) {728 DRM_ERROR("buffer is too small\n");729 drm_gem_object_put(&obj->obj);730 return -ENOMEM;731 }732 }733 734 if (dcrtc->cursor_obj) {735 dcrtc->cursor_obj->update = NULL;736 dcrtc->cursor_obj->update_data = NULL;737 drm_gem_object_put(&dcrtc->cursor_obj->obj);738 }739 dcrtc->cursor_obj = obj;740 dcrtc->cursor_w = w;741 dcrtc->cursor_h = h;742 ret = armada_drm_crtc_cursor_update(dcrtc, true);743 if (obj) {744 obj->update_data = dcrtc;745 obj->update = cursor_update;746 }747 748 return ret;749}750 751static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)752{753 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);754 int ret;755 756 /* If no cursor support, replicate drm's return value */757 if (!dcrtc->variant->has_spu_adv_reg)758 return -EFAULT;759 760 dcrtc->cursor_x = x;761 dcrtc->cursor_y = y;762 ret = armada_drm_crtc_cursor_update(dcrtc, false);763 764 return ret;765}766 767static void armada_drm_crtc_destroy(struct drm_crtc *crtc)768{769 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);770 struct armada_private *priv = drm_to_armada_dev(crtc->dev);771 772 if (dcrtc->cursor_obj)773 drm_gem_object_put(&dcrtc->cursor_obj->obj);774 775 priv->dcrtc[dcrtc->num] = NULL;776 drm_crtc_cleanup(&dcrtc->crtc);777 778 if (dcrtc->variant->disable)779 dcrtc->variant->disable(dcrtc);780 781 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);782 783 of_node_put(dcrtc->crtc.port);784 785 kfree(dcrtc);786}787 788static int armada_drm_crtc_late_register(struct drm_crtc *crtc)789{790 if (IS_ENABLED(CONFIG_DEBUG_FS))791 armada_drm_crtc_debugfs_init(drm_to_armada_crtc(crtc));792 793 return 0;794}795 796/* These are called under the vbl_lock. */797static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc)798{799 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);800 unsigned long flags;801 802 spin_lock_irqsave(&dcrtc->irq_lock, flags);803 armada_drm_crtc_enable_irq(dcrtc, VSYNC_IRQ_ENA);804 spin_unlock_irqrestore(&dcrtc->irq_lock, flags);805 return 0;806}807 808static void armada_drm_crtc_disable_vblank(struct drm_crtc *crtc)809{810 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);811 unsigned long flags;812 813 spin_lock_irqsave(&dcrtc->irq_lock, flags);814 armada_drm_crtc_disable_irq(dcrtc, VSYNC_IRQ_ENA);815 spin_unlock_irqrestore(&dcrtc->irq_lock, flags);816}817 818static const struct drm_crtc_funcs armada_crtc_funcs = {819 .reset = drm_atomic_helper_crtc_reset,820 .cursor_set = armada_drm_crtc_cursor_set,821 .cursor_move = armada_drm_crtc_cursor_move,822 .destroy = armada_drm_crtc_destroy,823 .set_config = drm_atomic_helper_set_config,824 .page_flip = drm_atomic_helper_page_flip,825 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,826 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,827 .late_register = armada_drm_crtc_late_register,828 .enable_vblank = armada_drm_crtc_enable_vblank,829 .disable_vblank = armada_drm_crtc_disable_vblank,830};831 832int armada_crtc_select_clock(struct armada_crtc *dcrtc,833 struct armada_clk_result *res,834 const struct armada_clocking_params *params,835 struct clk *clks[], size_t num_clks,836 unsigned long desired_khz)837{838 unsigned long desired_hz = desired_khz * 1000;839 unsigned long desired_clk_hz; // requested clk input840 unsigned long real_clk_hz; // actual clk input841 unsigned long real_hz; // actual pixel clk842 unsigned long permillage;843 struct clk *clk;844 u32 div;845 int i;846 847 DRM_DEBUG_KMS("[CRTC:%u:%s] desired clock=%luHz\n",848 dcrtc->crtc.base.id, dcrtc->crtc.name, desired_hz);849 850 for (i = 0; i < num_clks; i++) {851 clk = clks[i];852 if (!clk)853 continue;854 855 if (params->settable & BIT(i)) {856 real_clk_hz = clk_round_rate(clk, desired_hz);857 desired_clk_hz = desired_hz;858 } else {859 real_clk_hz = clk_get_rate(clk);860 desired_clk_hz = real_clk_hz;861 }862 863 /* If the clock can do exactly the desired rate, we're done */864 if (real_clk_hz == desired_hz) {865 real_hz = real_clk_hz;866 div = 1;867 goto found;868 }869 870 /* Calculate the divider - if invalid, we can't do this rate */871 div = DIV_ROUND_CLOSEST(real_clk_hz, desired_hz);872 if (div == 0 || div > params->div_max)873 continue;874 875 /* Calculate the actual rate - HDMI requires -0.6%..+0.5% */876 real_hz = DIV_ROUND_CLOSEST(real_clk_hz, div);877 878 DRM_DEBUG_KMS("[CRTC:%u:%s] clk=%u %luHz div=%u real=%luHz\n",879 dcrtc->crtc.base.id, dcrtc->crtc.name,880 i, real_clk_hz, div, real_hz);881 882 /* Avoid repeated division */883 if (real_hz < desired_hz) {884 permillage = real_hz / desired_khz;885 if (permillage < params->permillage_min)886 continue;887 } else {888 permillage = DIV_ROUND_UP(real_hz, desired_khz);889 if (permillage > params->permillage_max)890 continue;891 }892 goto found;893 }894 895 return -ERANGE;896 897found:898 DRM_DEBUG_KMS("[CRTC:%u:%s] selected clk=%u %luHz div=%u real=%luHz\n",899 dcrtc->crtc.base.id, dcrtc->crtc.name,900 i, real_clk_hz, div, real_hz);901 902 res->desired_clk_hz = desired_clk_hz;903 res->clk = clk;904 res->div = div;905 906 return i;907}908 909static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,910 struct resource *res, int irq, const struct armada_variant *variant,911 struct device_node *port)912{913 struct armada_private *priv = drm_to_armada_dev(drm);914 struct armada_crtc *dcrtc;915 struct drm_plane *primary;916 void __iomem *base;917 int ret;918 919 base = devm_ioremap_resource(dev, res);920 if (IS_ERR(base))921 return PTR_ERR(base);922 923 dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);924 if (!dcrtc) {925 DRM_ERROR("failed to allocate Armada crtc\n");926 return -ENOMEM;927 }928 929 if (dev != drm->dev)930 dev_set_drvdata(dev, dcrtc);931 932 dcrtc->variant = variant;933 dcrtc->base = base;934 dcrtc->num = drm->mode_config.num_crtc;935 dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;936 dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;937 spin_lock_init(&dcrtc->irq_lock);938 dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;939 940 /* Initialize some registers which we don't otherwise set */941 writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);942 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_BLANKCOLOR);943 writel_relaxed(dcrtc->spu_iopad_ctrl,944 dcrtc->base + LCD_SPU_IOPAD_CONTROL);945 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_SRAM_PARA0);946 writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |947 CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |948 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);949 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);950 writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);951 readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);952 writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);953 954 ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",955 dcrtc);956 if (ret < 0)957 goto err_crtc;958 959 if (dcrtc->variant->init) {960 ret = dcrtc->variant->init(dcrtc, dev);961 if (ret)962 goto err_crtc;963 }964 965 /* Ensure AXI pipeline is enabled */966 armada_updatel(CFG_ARBFAST_ENA, 0, dcrtc->base + LCD_SPU_DMA_CTRL0);967 968 priv->dcrtc[dcrtc->num] = dcrtc;969 970 dcrtc->crtc.port = port;971 972 primary = kzalloc(sizeof(*primary), GFP_KERNEL);973 if (!primary) {974 ret = -ENOMEM;975 goto err_crtc;976 }977 978 ret = armada_drm_primary_plane_init(drm, primary);979 if (ret) {980 kfree(primary);981 goto err_crtc;982 }983 984 ret = drm_crtc_init_with_planes(drm, &dcrtc->crtc, primary, NULL,985 &armada_crtc_funcs, NULL);986 if (ret)987 goto err_crtc_init;988 989 drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);990 991 ret = drm_mode_crtc_set_gamma_size(&dcrtc->crtc, 256);992 if (ret)993 return ret;994 995 drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);996 997 return armada_overlay_plane_create(drm, 1 << dcrtc->num);998 999err_crtc_init:1000 primary->funcs->destroy(primary);1001err_crtc:1002 kfree(dcrtc);1003 1004 return ret;1005}1006 1007static int1008armada_lcd_bind(struct device *dev, struct device *master, void *data)1009{1010 struct platform_device *pdev = to_platform_device(dev);1011 struct drm_device *drm = data;1012 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1013 int irq = platform_get_irq(pdev, 0);1014 const struct armada_variant *variant;1015 struct device_node *port = NULL;1016 struct device_node *np, *parent = dev->of_node;1017 1018 if (irq < 0)1019 return irq;1020 1021 1022 variant = device_get_match_data(dev);1023 if (!variant)1024 return -ENXIO;1025 1026 if (parent) {1027 np = of_get_child_by_name(parent, "ports");1028 if (np)1029 parent = np;1030 port = of_get_child_by_name(parent, "port");1031 of_node_put(np);1032 if (!port) {1033 dev_err(dev, "no port node found in %pOF\n", parent);1034 return -ENXIO;1035 }1036 }1037 1038 return armada_drm_crtc_create(drm, dev, res, irq, variant, port);1039}1040 1041static void1042armada_lcd_unbind(struct device *dev, struct device *master, void *data)1043{1044 struct armada_crtc *dcrtc = dev_get_drvdata(dev);1045 1046 armada_drm_crtc_destroy(&dcrtc->crtc);1047}1048 1049static const struct component_ops armada_lcd_ops = {1050 .bind = armada_lcd_bind,1051 .unbind = armada_lcd_unbind,1052};1053 1054static int armada_lcd_probe(struct platform_device *pdev)1055{1056 return component_add(&pdev->dev, &armada_lcd_ops);1057}1058 1059static void armada_lcd_remove(struct platform_device *pdev)1060{1061 component_del(&pdev->dev, &armada_lcd_ops);1062}1063 1064static const struct of_device_id armada_lcd_of_match[] = {1065 {1066 .compatible = "marvell,dove-lcd",1067 .data = &armada510_ops,1068 },1069 {}1070};1071MODULE_DEVICE_TABLE(of, armada_lcd_of_match);1072 1073static const struct platform_device_id armada_lcd_platform_ids[] = {1074 {1075 .name = "armada-lcd",1076 .driver_data = (unsigned long)&armada510_ops,1077 }, {1078 .name = "armada-510-lcd",1079 .driver_data = (unsigned long)&armada510_ops,1080 },1081 { },1082};1083MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);1084 1085struct platform_driver armada_lcd_platform_driver = {1086 .probe = armada_lcd_probe,1087 .remove_new = armada_lcd_remove,1088 .driver = {1089 .name = "armada-lcd",1090 .owner = THIS_MODULE,1091 .of_match_table = armada_lcd_of_match,1092 },1093 .id_table = armada_lcd_platform_ids,1094};1095