Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2023 Loongson Technology Corporation Limited
   4 */
   5
   6#include <linux/debugfs.h>
   7#include <linux/delay.h>
   8
   9#include <drm/drm_atomic.h>
  10#include <drm/drm_atomic_helper.h>
  11#include <drm/drm_debugfs.h>
  12#include <drm/drm_vblank.h>
  13
  14#include "lsdc_drv.h"
  15
  16/*
  17 * After the CRTC soft reset, the vblank counter would be reset to zero.
  18 * But the address and other settings in the CRTC register remain the same
  19 * as before.
  20 */
  21
  22static void lsdc_crtc0_soft_reset(struct lsdc_crtc *lcrtc)
  23{
  24	struct lsdc_device *ldev = lcrtc->ldev;
  25	u32 val;
  26
  27	val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
  28
  29	val &= CFG_VALID_BITS_MASK;
  30
  31	/* Soft reset bit, active low */
  32	val &= ~CFG_RESET_N;
  33
  34	val &= ~CFG_PIX_FMT_MASK;
  35
  36	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
  37
  38	udelay(1);
  39
  40	val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
  41
  42	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
  43
  44	/* Wait about a vblank time */
  45	mdelay(20);
  46}
  47
  48static void lsdc_crtc1_soft_reset(struct lsdc_crtc *lcrtc)
  49{
  50	struct lsdc_device *ldev = lcrtc->ldev;
  51	u32 val;
  52
  53	val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
  54
  55	val &= CFG_VALID_BITS_MASK;
  56
  57	/* Soft reset bit, active low */
  58	val &= ~CFG_RESET_N;
  59
  60	val &= ~CFG_PIX_FMT_MASK;
  61
  62	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
  63
  64	udelay(1);
  65
  66	val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
  67
  68	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
  69
  70	/* Wait about a vblank time */
  71	msleep(20);
  72}
  73
  74static void lsdc_crtc0_enable(struct lsdc_crtc *lcrtc)
  75{
  76	struct lsdc_device *ldev = lcrtc->ldev;
  77	u32 val;
  78
  79	val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
  80
  81	/*
  82	 * This may happen in extremely rare cases, but a soft reset can
  83	 * bring it back to normal. We add a warning here, hoping to catch
  84	 * something if it happens.
  85	 */
  86	if (val & CRTC_ANCHORED) {
  87		drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
  88		return lsdc_crtc0_soft_reset(lcrtc);
  89	}
  90
  91	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val | CFG_OUTPUT_ENABLE);
  92}
  93
  94static void lsdc_crtc0_disable(struct lsdc_crtc *lcrtc)
  95{
  96	struct lsdc_device *ldev = lcrtc->ldev;
  97
  98	lsdc_ureg32_clr(ldev, LSDC_CRTC0_CFG_REG, CFG_OUTPUT_ENABLE);
  99
 100	udelay(9);
 101}
 102
 103static void lsdc_crtc1_enable(struct lsdc_crtc *lcrtc)
 104{
 105	struct lsdc_device *ldev = lcrtc->ldev;
 106	u32 val;
 107
 108	/*
 109	 * This may happen in extremely rare cases, but a soft reset can
 110	 * bring it back to normal. We add a warning here, hoping to catch
 111	 * something if it happens.
 112	 */
 113	val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
 114	if (val & CRTC_ANCHORED) {
 115		drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
 116		return lsdc_crtc1_soft_reset(lcrtc);
 117	}
 118
 119	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val | CFG_OUTPUT_ENABLE);
 120}
 121
 122static void lsdc_crtc1_disable(struct lsdc_crtc *lcrtc)
 123{
 124	struct lsdc_device *ldev = lcrtc->ldev;
 125
 126	lsdc_ureg32_clr(ldev, LSDC_CRTC1_CFG_REG, CFG_OUTPUT_ENABLE);
 127
 128	udelay(9);
 129}
 130
 131/* All Loongson display controllers have hardware scanout position recoders */
 132
 133static void lsdc_crtc0_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
 134{
 135	struct lsdc_device *ldev = lcrtc->ldev;
 136	u32 val;
 137
 138	val = lsdc_rreg32(ldev, LSDC_CRTC0_SCAN_POS_REG);
 139
 140	*hpos = val >> 16;
 141	*vpos = val & 0xffff;
 142}
 143
 144static void lsdc_crtc1_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
 145{
 146	struct lsdc_device *ldev = lcrtc->ldev;
 147	u32 val;
 148
 149	val = lsdc_rreg32(ldev, LSDC_CRTC1_SCAN_POS_REG);
 150
 151	*hpos = val >> 16;
 152	*vpos = val & 0xffff;
 153}
 154
 155static void lsdc_crtc0_enable_vblank(struct lsdc_crtc *lcrtc)
 156{
 157	struct lsdc_device *ldev = lcrtc->ldev;
 158
 159	lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
 160}
 161
 162static void lsdc_crtc0_disable_vblank(struct lsdc_crtc *lcrtc)
 163{
 164	struct lsdc_device *ldev = lcrtc->ldev;
 165
 166	lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
 167}
 168
 169static void lsdc_crtc1_enable_vblank(struct lsdc_crtc *lcrtc)
 170{
 171	struct lsdc_device *ldev = lcrtc->ldev;
 172
 173	lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
 174}
 175
 176static void lsdc_crtc1_disable_vblank(struct lsdc_crtc *lcrtc)
 177{
 178	struct lsdc_device *ldev = lcrtc->ldev;
 179
 180	lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
 181}
 182
 183static void lsdc_crtc0_flip(struct lsdc_crtc *lcrtc)
 184{
 185	struct lsdc_device *ldev = lcrtc->ldev;
 186
 187	lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_PAGE_FLIP);
 188}
 189
 190static void lsdc_crtc1_flip(struct lsdc_crtc *lcrtc)
 191{
 192	struct lsdc_device *ldev = lcrtc->ldev;
 193
 194	lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_PAGE_FLIP);
 195}
 196
 197/*
 198 * CRTC0 clone from CRTC1 or CRTC1 clone from CRTC0 using hardware logic
 199 * This may be useful for custom cloning (TWIN) applications. Saving the
 200 * bandwidth compared with the clone (mirroring) display mode provided by
 201 * drm core.
 202 */
 203
 204static void lsdc_crtc0_clone(struct lsdc_crtc *lcrtc)
 205{
 206	struct lsdc_device *ldev = lcrtc->ldev;
 207
 208	lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_HW_CLONE);
 209}
 210
 211static void lsdc_crtc1_clone(struct lsdc_crtc *lcrtc)
 212{
 213	struct lsdc_device *ldev = lcrtc->ldev;
 214
 215	lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_HW_CLONE);
 216}
 217
 218static void lsdc_crtc0_set_mode(struct lsdc_crtc *lcrtc,
 219				const struct drm_display_mode *mode)
 220{
 221	struct lsdc_device *ldev = lcrtc->ldev;
 222
 223	lsdc_wreg32(ldev, LSDC_CRTC0_HDISPLAY_REG,
 224		    (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
 225
 226	lsdc_wreg32(ldev, LSDC_CRTC0_VDISPLAY_REG,
 227		    (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
 228
 229	lsdc_wreg32(ldev, LSDC_CRTC0_HSYNC_REG,
 230		    (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
 231
 232	lsdc_wreg32(ldev, LSDC_CRTC0_VSYNC_REG,
 233		    (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
 234}
 235
 236static void lsdc_crtc1_set_mode(struct lsdc_crtc *lcrtc,
 237				const struct drm_display_mode *mode)
 238{
 239	struct lsdc_device *ldev = lcrtc->ldev;
 240
 241	lsdc_wreg32(ldev, LSDC_CRTC1_HDISPLAY_REG,
 242		    (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
 243
 244	lsdc_wreg32(ldev, LSDC_CRTC1_VDISPLAY_REG,
 245		    (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
 246
 247	lsdc_wreg32(ldev, LSDC_CRTC1_HSYNC_REG,
 248		    (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
 249
 250	lsdc_wreg32(ldev, LSDC_CRTC1_VSYNC_REG,
 251		    (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
 252}
 253
 254/*
 255 * This is required for S3 support.
 256 * After resuming from suspend, LSDC_CRTCx_CFG_REG (x = 0 or 1) is filled
 257 * with garbage value, which causes the CRTC hang there.
 258 *
 259 * This function provides minimal settings for the affected registers.
 260 * This overrides the firmware's settings on startup, making the CRTC work
 261 * on our own, similar to the functional of GPU POST (Power On Self Test).
 262 * Only touch CRTC hardware-related parts.
 263 */
 264
 265static void lsdc_crtc0_reset(struct lsdc_crtc *lcrtc)
 266{
 267	struct lsdc_device *ldev = lcrtc->ldev;
 268
 269	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
 270}
 271
 272static void lsdc_crtc1_reset(struct lsdc_crtc *lcrtc)
 273{
 274	struct lsdc_device *ldev = lcrtc->ldev;
 275
 276	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
 277}
 278
 279static const struct lsdc_crtc_hw_ops ls7a1000_crtc_hw_ops[2] = {
 280	{
 281		.enable = lsdc_crtc0_enable,
 282		.disable = lsdc_crtc0_disable,
 283		.enable_vblank = lsdc_crtc0_enable_vblank,
 284		.disable_vblank = lsdc_crtc0_disable_vblank,
 285		.flip = lsdc_crtc0_flip,
 286		.clone = lsdc_crtc0_clone,
 287		.set_mode = lsdc_crtc0_set_mode,
 288		.get_scan_pos = lsdc_crtc0_scan_pos,
 289		.soft_reset = lsdc_crtc0_soft_reset,
 290		.reset = lsdc_crtc0_reset,
 291	},
 292	{
 293		.enable = lsdc_crtc1_enable,
 294		.disable = lsdc_crtc1_disable,
 295		.enable_vblank = lsdc_crtc1_enable_vblank,
 296		.disable_vblank = lsdc_crtc1_disable_vblank,
 297		.flip = lsdc_crtc1_flip,
 298		.clone = lsdc_crtc1_clone,
 299		.set_mode = lsdc_crtc1_set_mode,
 300		.get_scan_pos = lsdc_crtc1_scan_pos,
 301		.soft_reset = lsdc_crtc1_soft_reset,
 302		.reset = lsdc_crtc1_reset,
 303	},
 304};
 305
 306/*
 307 * The 32-bit hardware vblank counter has been available since LS7A2000
 308 * and LS2K2000. The counter increases even though the CRTC is disabled,
 309 * it will be reset only if the CRTC is being soft reset.
 310 * Those registers are also readable for ls7a1000, but its value does not
 311 * change.
 312 */
 313
 314static u32 lsdc_crtc0_get_vblank_count(struct lsdc_crtc *lcrtc)
 315{
 316	struct lsdc_device *ldev = lcrtc->ldev;
 317
 318	return lsdc_rreg32(ldev, LSDC_CRTC0_VSYNC_COUNTER_REG);
 319}
 320
 321static u32 lsdc_crtc1_get_vblank_count(struct lsdc_crtc *lcrtc)
 322{
 323	struct lsdc_device *ldev = lcrtc->ldev;
 324
 325	return lsdc_rreg32(ldev, LSDC_CRTC1_VSYNC_COUNTER_REG);
 326}
 327
 328/*
 329 * The DMA step bit fields are available since LS7A2000/LS2K2000, for
 330 * supporting odd resolutions. But a large DMA step save the bandwidth.
 331 * The larger, the better. Behavior of writing those bits on LS7A1000
 332 * or LS2K1000 is underfined.
 333 */
 334
 335static void lsdc_crtc0_set_dma_step(struct lsdc_crtc *lcrtc,
 336				    enum lsdc_dma_steps dma_step)
 337{
 338	struct lsdc_device *ldev = lcrtc->ldev;
 339	u32 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
 340
 341	val &= ~CFG_DMA_STEP_MASK;
 342	val |= dma_step << CFG_DMA_STEP_SHIFT;
 343
 344	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
 345}
 346
 347static void lsdc_crtc1_set_dma_step(struct lsdc_crtc *lcrtc,
 348				    enum lsdc_dma_steps dma_step)
 349{
 350	struct lsdc_device *ldev = lcrtc->ldev;
 351	u32 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
 352
 353	val &= ~CFG_DMA_STEP_MASK;
 354	val |= dma_step << CFG_DMA_STEP_SHIFT;
 355
 356	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
 357}
 358
 359static const struct lsdc_crtc_hw_ops ls7a2000_crtc_hw_ops[2] = {
 360	{
 361		.enable = lsdc_crtc0_enable,
 362		.disable = lsdc_crtc0_disable,
 363		.enable_vblank = lsdc_crtc0_enable_vblank,
 364		.disable_vblank = lsdc_crtc0_disable_vblank,
 365		.flip = lsdc_crtc0_flip,
 366		.clone = lsdc_crtc0_clone,
 367		.set_mode = lsdc_crtc0_set_mode,
 368		.soft_reset = lsdc_crtc0_soft_reset,
 369		.get_scan_pos = lsdc_crtc0_scan_pos,
 370		.set_dma_step = lsdc_crtc0_set_dma_step,
 371		.get_vblank_counter = lsdc_crtc0_get_vblank_count,
 372		.reset = lsdc_crtc0_reset,
 373	},
 374	{
 375		.enable = lsdc_crtc1_enable,
 376		.disable = lsdc_crtc1_disable,
 377		.enable_vblank = lsdc_crtc1_enable_vblank,
 378		.disable_vblank = lsdc_crtc1_disable_vblank,
 379		.flip = lsdc_crtc1_flip,
 380		.clone = lsdc_crtc1_clone,
 381		.set_mode = lsdc_crtc1_set_mode,
 382		.get_scan_pos = lsdc_crtc1_scan_pos,
 383		.soft_reset = lsdc_crtc1_soft_reset,
 384		.set_dma_step = lsdc_crtc1_set_dma_step,
 385		.get_vblank_counter = lsdc_crtc1_get_vblank_count,
 386		.reset = lsdc_crtc1_reset,
 387	},
 388};
 389
 390static void lsdc_crtc_reset(struct drm_crtc *crtc)
 391{
 392	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 393	const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
 394	struct lsdc_crtc_state *priv_crtc_state;
 395
 396	if (crtc->state)
 397		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
 398
 399	priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
 400
 401	if (!priv_crtc_state)
 402		__drm_atomic_helper_crtc_reset(crtc, NULL);
 403	else
 404		__drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
 405
 406	/* Reset the CRTC hardware, this is required for S3 support */
 407	ops->reset(lcrtc);
 408}
 409
 410static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 411					   struct drm_crtc_state *state)
 412{
 413	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
 414
 415	__drm_atomic_helper_crtc_destroy_state(&priv_state->base);
 416
 417	kfree(priv_state);
 418}
 419
 420static struct drm_crtc_state *
 421lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 422{
 423	struct lsdc_crtc_state *new_priv_state;
 424	struct lsdc_crtc_state *old_priv_state;
 425
 426	new_priv_state = kzalloc(sizeof(*new_priv_state), GFP_KERNEL);
 427	if (!new_priv_state)
 428		return NULL;
 429
 430	__drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
 431
 432	old_priv_state = to_lsdc_crtc_state(crtc->state);
 433
 434	memcpy(&new_priv_state->pparms, &old_priv_state->pparms,
 435	       sizeof(new_priv_state->pparms));
 436
 437	return &new_priv_state->base;
 438}
 439
 440static u32 lsdc_crtc_get_vblank_counter(struct drm_crtc *crtc)
 441{
 442	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 443
 444	/* 32-bit hardware vblank counter */
 445	return lcrtc->hw_ops->get_vblank_counter(lcrtc);
 446}
 447
 448static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
 449{
 450	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 451
 452	if (!lcrtc->has_vblank)
 453		return -EINVAL;
 454
 455	lcrtc->hw_ops->enable_vblank(lcrtc);
 456
 457	return 0;
 458}
 459
 460static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
 461{
 462	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 463
 464	if (!lcrtc->has_vblank)
 465		return;
 466
 467	lcrtc->hw_ops->disable_vblank(lcrtc);
 468}
 469
 470/*
 471 * CRTC related debugfs
 472 * Primary planes and cursor planes belong to the CRTC as well.
 473 * For the sake of convenience, plane-related registers are also add here.
 474 */
 475
 476#define REG_DEF(reg) { \
 477	.name = __stringify_1(LSDC_##reg##_REG), \
 478	.offset = LSDC_##reg##_REG, \
 479}
 480
 481static const struct lsdc_reg32 lsdc_crtc_regs_array[2][21] = {
 482	[0] = {
 483		REG_DEF(CRTC0_CFG),
 484		REG_DEF(CRTC0_FB_ORIGIN),
 485		REG_DEF(CRTC0_DVO_CONF),
 486		REG_DEF(CRTC0_HDISPLAY),
 487		REG_DEF(CRTC0_HSYNC),
 488		REG_DEF(CRTC0_VDISPLAY),
 489		REG_DEF(CRTC0_VSYNC),
 490		REG_DEF(CRTC0_GAMMA_INDEX),
 491		REG_DEF(CRTC0_GAMMA_DATA),
 492		REG_DEF(CRTC0_SYNC_DEVIATION),
 493		REG_DEF(CRTC0_VSYNC_COUNTER),
 494		REG_DEF(CRTC0_SCAN_POS),
 495		REG_DEF(CRTC0_STRIDE),
 496		REG_DEF(CRTC0_FB1_ADDR_HI),
 497		REG_DEF(CRTC0_FB1_ADDR_LO),
 498		REG_DEF(CRTC0_FB0_ADDR_HI),
 499		REG_DEF(CRTC0_FB0_ADDR_LO),
 500		REG_DEF(CURSOR0_CFG),
 501		REG_DEF(CURSOR0_POSITION),
 502		REG_DEF(CURSOR0_BG_COLOR),
 503		REG_DEF(CURSOR0_FG_COLOR),
 504	},
 505	[1] = {
 506		REG_DEF(CRTC1_CFG),
 507		REG_DEF(CRTC1_FB_ORIGIN),
 508		REG_DEF(CRTC1_DVO_CONF),
 509		REG_DEF(CRTC1_HDISPLAY),
 510		REG_DEF(CRTC1_HSYNC),
 511		REG_DEF(CRTC1_VDISPLAY),
 512		REG_DEF(CRTC1_VSYNC),
 513		REG_DEF(CRTC1_GAMMA_INDEX),
 514		REG_DEF(CRTC1_GAMMA_DATA),
 515		REG_DEF(CRTC1_SYNC_DEVIATION),
 516		REG_DEF(CRTC1_VSYNC_COUNTER),
 517		REG_DEF(CRTC1_SCAN_POS),
 518		REG_DEF(CRTC1_STRIDE),
 519		REG_DEF(CRTC1_FB1_ADDR_HI),
 520		REG_DEF(CRTC1_FB1_ADDR_LO),
 521		REG_DEF(CRTC1_FB0_ADDR_HI),
 522		REG_DEF(CRTC1_FB0_ADDR_LO),
 523		REG_DEF(CURSOR1_CFG),
 524		REG_DEF(CURSOR1_POSITION),
 525		REG_DEF(CURSOR1_BG_COLOR),
 526		REG_DEF(CURSOR1_FG_COLOR),
 527	},
 528};
 529
 530static int lsdc_crtc_show_regs(struct seq_file *m, void *arg)
 531{
 532	struct drm_info_node *node = (struct drm_info_node *)m->private;
 533	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
 534	struct lsdc_device *ldev = lcrtc->ldev;
 535	unsigned int i;
 536
 537	for (i = 0; i < lcrtc->nreg; i++) {
 538		const struct lsdc_reg32 *preg = &lcrtc->preg[i];
 539		u32 offset = preg->offset;
 540
 541		seq_printf(m, "%s (0x%04x): 0x%08x\n",
 542			   preg->name, offset, lsdc_rreg32(ldev, offset));
 543	}
 544
 545	return 0;
 546}
 547
 548static int lsdc_crtc_show_scan_position(struct seq_file *m, void *arg)
 549{
 550	struct drm_info_node *node = (struct drm_info_node *)m->private;
 551	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
 552	int x, y;
 553
 554	lcrtc->hw_ops->get_scan_pos(lcrtc, &x, &y);
 555	seq_printf(m, "Scanout position: x: %08u, y: %08u\n", x, y);
 556
 557	return 0;
 558}
 559
 560static int lsdc_crtc_show_vblank_counter(struct seq_file *m, void *arg)
 561{
 562	struct drm_info_node *node = (struct drm_info_node *)m->private;
 563	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
 564
 565	if (lcrtc->hw_ops->get_vblank_counter)
 566		seq_printf(m, "%s vblank counter: %08u\n\n", lcrtc->base.name,
 567			   lcrtc->hw_ops->get_vblank_counter(lcrtc));
 568
 569	return 0;
 570}
 571
 572static int lsdc_pixpll_show_clock(struct seq_file *m, void *arg)
 573{
 574	struct drm_info_node *node = (struct drm_info_node *)m->private;
 575	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
 576	struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
 577	const struct lsdc_pixpll_funcs *funcs = pixpll->funcs;
 578	struct drm_crtc *crtc = &lcrtc->base;
 579	struct drm_display_mode *mode = &crtc->state->mode;
 580	struct drm_printer printer = drm_seq_file_printer(m);
 581	unsigned int out_khz;
 582
 583	out_khz = funcs->get_rate(pixpll);
 584
 585	seq_printf(m, "%s: %dx%d@%d\n", crtc->name,
 586		   mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode));
 587
 588	seq_printf(m, "Pixel clock required: %d kHz\n", mode->clock);
 589	seq_printf(m, "Actual frequency output: %u kHz\n", out_khz);
 590	seq_printf(m, "Diff: %d kHz\n", out_khz - mode->clock);
 591
 592	funcs->print(pixpll, &printer);
 593
 594	return 0;
 595}
 596
 597static struct drm_info_list lsdc_crtc_debugfs_list[2][4] = {
 598	[0] = {
 599		{ "regs", lsdc_crtc_show_regs, 0, NULL },
 600		{ "pixclk", lsdc_pixpll_show_clock, 0, NULL },
 601		{ "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
 602		{ "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
 603	},
 604	[1] = {
 605		{ "regs", lsdc_crtc_show_regs, 0, NULL },
 606		{ "pixclk", lsdc_pixpll_show_clock, 0, NULL },
 607		{ "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
 608		{ "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
 609	},
 610};
 611
 612/* operate manually */
 613
 614static int lsdc_crtc_man_op_show(struct seq_file *m, void *data)
 615{
 616	seq_puts(m, "soft_reset: soft reset this CRTC\n");
 617	seq_puts(m, "enable: enable this CRTC\n");
 618	seq_puts(m, "disable: disable this CRTC\n");
 619	seq_puts(m, "flip: trigger the page flip\n");
 620	seq_puts(m, "clone: clone the another crtc with hardware logic\n");
 621
 622	return 0;
 623}
 624
 625static int lsdc_crtc_man_op_open(struct inode *inode, struct file *file)
 626{
 627	struct drm_crtc *crtc = inode->i_private;
 628
 629	return single_open(file, lsdc_crtc_man_op_show, crtc);
 630}
 631
 632static ssize_t lsdc_crtc_man_op_write(struct file *file,
 633				      const char __user *ubuf,
 634				      size_t len,
 635				      loff_t *offp)
 636{
 637	struct seq_file *m = file->private_data;
 638	struct lsdc_crtc *lcrtc = m->private;
 639	const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
 640	char buf[16];
 641
 642	if (len > sizeof(buf) - 1)
 643		return -EINVAL;
 644
 645	if (copy_from_user(buf, ubuf, len))
 646		return -EFAULT;
 647
 648	buf[len] = '\0';
 649
 650	if (sysfs_streq(buf, "soft_reset"))
 651		ops->soft_reset(lcrtc);
 652	else if (sysfs_streq(buf, "enable"))
 653		ops->enable(lcrtc);
 654	else if (sysfs_streq(buf, "disable"))
 655		ops->disable(lcrtc);
 656	else if (sysfs_streq(buf, "flip"))
 657		ops->flip(lcrtc);
 658	else if (sysfs_streq(buf, "clone"))
 659		ops->clone(lcrtc);
 660
 661	return len;
 662}
 663
 664static const struct file_operations lsdc_crtc_man_op_fops = {
 665	.owner = THIS_MODULE,
 666	.open = lsdc_crtc_man_op_open,
 667	.read = seq_read,
 668	.llseek = seq_lseek,
 669	.release = single_release,
 670	.write = lsdc_crtc_man_op_write,
 671};
 672
 673static int lsdc_crtc_late_register(struct drm_crtc *crtc)
 674{
 675	struct lsdc_display_pipe *dispipe = crtc_to_display_pipe(crtc);
 676	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 677	struct drm_minor *minor = crtc->dev->primary;
 678	unsigned int index = dispipe->index;
 679	unsigned int i;
 680
 681	lcrtc->preg = lsdc_crtc_regs_array[index];
 682	lcrtc->nreg = ARRAY_SIZE(lsdc_crtc_regs_array[index]);
 683	lcrtc->p_info_list = lsdc_crtc_debugfs_list[index];
 684	lcrtc->n_info_list = ARRAY_SIZE(lsdc_crtc_debugfs_list[index]);
 685
 686	for (i = 0; i < lcrtc->n_info_list; ++i)
 687		lcrtc->p_info_list[i].data = lcrtc;
 688
 689	drm_debugfs_create_files(lcrtc->p_info_list, lcrtc->n_info_list,
 690				 crtc->debugfs_entry, minor);
 691
 692	/* Manual operations supported */
 693	debugfs_create_file("ops", 0644, crtc->debugfs_entry, lcrtc,
 694			    &lsdc_crtc_man_op_fops);
 695
 696	return 0;
 697}
 698
 699static void lsdc_crtc_atomic_print_state(struct drm_printer *p,
 700					 const struct drm_crtc_state *state)
 701{
 702	const struct lsdc_crtc_state *priv_state;
 703	const struct lsdc_pixpll_parms *pparms;
 704
 705	priv_state = container_of_const(state, struct lsdc_crtc_state, base);
 706	pparms = &priv_state->pparms;
 707
 708	drm_printf(p, "\tInput clock divider = %u\n", pparms->div_ref);
 709	drm_printf(p, "\tMedium clock multiplier = %u\n", pparms->loopc);
 710	drm_printf(p, "\tOutput clock divider = %u\n", pparms->div_out);
 711}
 712
 713static const struct drm_crtc_funcs ls7a1000_crtc_funcs = {
 714	.reset = lsdc_crtc_reset,
 715	.destroy = drm_crtc_cleanup,
 716	.set_config = drm_atomic_helper_set_config,
 717	.page_flip = drm_atomic_helper_page_flip,
 718	.atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
 719	.atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
 720	.late_register = lsdc_crtc_late_register,
 721	.enable_vblank = lsdc_crtc_enable_vblank,
 722	.disable_vblank = lsdc_crtc_disable_vblank,
 723	.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
 724	.atomic_print_state = lsdc_crtc_atomic_print_state,
 725};
 726
 727static const struct drm_crtc_funcs ls7a2000_crtc_funcs = {
 728	.reset = lsdc_crtc_reset,
 729	.destroy = drm_crtc_cleanup,
 730	.set_config = drm_atomic_helper_set_config,
 731	.page_flip = drm_atomic_helper_page_flip,
 732	.atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
 733	.atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
 734	.late_register = lsdc_crtc_late_register,
 735	.get_vblank_counter = lsdc_crtc_get_vblank_counter,
 736	.enable_vblank = lsdc_crtc_enable_vblank,
 737	.disable_vblank = lsdc_crtc_disable_vblank,
 738	.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
 739	.atomic_print_state = lsdc_crtc_atomic_print_state,
 740};
 741
 742static enum drm_mode_status
 743lsdc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
 744{
 745	struct drm_device *ddev = crtc->dev;
 746	struct lsdc_device *ldev = to_lsdc(ddev);
 747	const struct lsdc_desc *descp = ldev->descp;
 748	unsigned int pitch;
 749
 750	if (mode->hdisplay > descp->max_width)
 751		return MODE_BAD_HVALUE;
 752
 753	if (mode->vdisplay > descp->max_height)
 754		return MODE_BAD_VVALUE;
 755
 756	if (mode->clock > descp->max_pixel_clk) {
 757		drm_dbg_kms(ddev, "mode %dx%d, pixel clock=%d is too high\n",
 758			    mode->hdisplay, mode->vdisplay, mode->clock);
 759		return MODE_CLOCK_HIGH;
 760	}
 761
 762	/* 4 for DRM_FORMAT_XRGB8888 */
 763	pitch = mode->hdisplay * 4;
 764
 765	if (pitch % descp->pitch_align) {
 766		drm_dbg_kms(ddev, "align to %u bytes is required: %u\n",
 767			    descp->pitch_align, pitch);
 768		return MODE_BAD_WIDTH;
 769	}
 770
 771	return MODE_OK;
 772}
 773
 774static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
 775				    struct drm_crtc_state *state)
 776{
 777	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 778	struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
 779	const struct lsdc_pixpll_funcs *pfuncs = pixpll->funcs;
 780	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
 781	unsigned int clock = state->mode.clock;
 782	int ret;
 783
 784	ret = pfuncs->compute(pixpll, clock, &priv_state->pparms);
 785	if (ret) {
 786		drm_warn(crtc->dev, "Failed to find PLL params for %ukHz\n",
 787			 clock);
 788		return -EINVAL;
 789	}
 790
 791	return 0;
 792}
 793
 794static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
 795					 struct drm_atomic_state *state)
 796{
 797	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 798
 799	if (!crtc_state->enable)
 800		return 0;
 801
 802	return lsdc_pixpll_atomic_check(crtc, crtc_state);
 803}
 804
 805static void lsdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
 806{
 807	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 808	const struct lsdc_crtc_hw_ops *crtc_hw_ops = lcrtc->hw_ops;
 809	struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
 810	const struct lsdc_pixpll_funcs *pixpll_funcs = pixpll->funcs;
 811	struct drm_crtc_state *state = crtc->state;
 812	struct drm_display_mode *mode = &state->mode;
 813	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
 814
 815	pixpll_funcs->update(pixpll, &priv_state->pparms);
 816
 817	if (crtc_hw_ops->set_dma_step) {
 818		unsigned int width_in_bytes = mode->hdisplay * 4;
 819		enum lsdc_dma_steps dma_step;
 820
 821		/*
 822		 * Using DMA step as large as possible, for improving
 823		 * hardware DMA efficiency.
 824		 */
 825		if (width_in_bytes % 256 == 0)
 826			dma_step = LSDC_DMA_STEP_256_BYTES;
 827		else if (width_in_bytes % 128 == 0)
 828			dma_step = LSDC_DMA_STEP_128_BYTES;
 829		else if (width_in_bytes % 64 == 0)
 830			dma_step = LSDC_DMA_STEP_64_BYTES;
 831		else  /* width_in_bytes % 32 == 0 */
 832			dma_step = LSDC_DMA_STEP_32_BYTES;
 833
 834		crtc_hw_ops->set_dma_step(lcrtc, dma_step);
 835	}
 836
 837	crtc_hw_ops->set_mode(lcrtc, mode);
 838}
 839
 840static void lsdc_crtc_send_vblank(struct drm_crtc *crtc)
 841{
 842	struct drm_device *ddev = crtc->dev;
 843	unsigned long flags;
 844
 845	if (!crtc->state || !crtc->state->event)
 846		return;
 847
 848	drm_dbg(ddev, "Send vblank manually\n");
 849
 850	spin_lock_irqsave(&ddev->event_lock, flags);
 851	drm_crtc_send_vblank_event(crtc, crtc->state->event);
 852	crtc->state->event = NULL;
 853	spin_unlock_irqrestore(&ddev->event_lock, flags);
 854}
 855
 856static void lsdc_crtc_atomic_enable(struct drm_crtc *crtc,
 857				    struct drm_atomic_state *state)
 858{
 859	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 860
 861	if (lcrtc->has_vblank)
 862		drm_crtc_vblank_on(crtc);
 863
 864	lcrtc->hw_ops->enable(lcrtc);
 865}
 866
 867static void lsdc_crtc_atomic_disable(struct drm_crtc *crtc,
 868				     struct drm_atomic_state *state)
 869{
 870	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 871
 872	if (lcrtc->has_vblank)
 873		drm_crtc_vblank_off(crtc);
 874
 875	lcrtc->hw_ops->disable(lcrtc);
 876
 877	/*
 878	 * Make sure we issue a vblank event after disabling the CRTC if
 879	 * someone was waiting it.
 880	 */
 881	lsdc_crtc_send_vblank(crtc);
 882}
 883
 884static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
 885				   struct drm_atomic_state *state)
 886{
 887	spin_lock_irq(&crtc->dev->event_lock);
 888	if (crtc->state->event) {
 889		if (drm_crtc_vblank_get(crtc) == 0)
 890			drm_crtc_arm_vblank_event(crtc, crtc->state->event);
 891		else
 892			drm_crtc_send_vblank_event(crtc, crtc->state->event);
 893		crtc->state->event = NULL;
 894	}
 895	spin_unlock_irq(&crtc->dev->event_lock);
 896}
 897
 898static bool lsdc_crtc_get_scanout_position(struct drm_crtc *crtc,
 899					   bool in_vblank_irq,
 900					   int *vpos,
 901					   int *hpos,
 902					   ktime_t *stime,
 903					   ktime_t *etime,
 904					   const struct drm_display_mode *mode)
 905{
 906	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 907	const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
 908	int vsw, vbp, vactive_start, vactive_end, vfp_end;
 909	int x, y;
 910
 911	vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
 912	vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
 913
 914	vactive_start = vsw + vbp + 1;
 915	vactive_end = vactive_start + mode->crtc_vdisplay;
 916
 917	/* last scan line before VSYNC */
 918	vfp_end = mode->crtc_vtotal;
 919
 920	if (stime)
 921		*stime = ktime_get();
 922
 923	ops->get_scan_pos(lcrtc, &x, &y);
 924
 925	if (y > vactive_end)
 926		y = y - vfp_end - vactive_start;
 927	else
 928		y -= vactive_start;
 929
 930	*vpos = y;
 931	*hpos = 0;
 932
 933	if (etime)
 934		*etime = ktime_get();
 935
 936	return true;
 937}
 938
 939static const struct drm_crtc_helper_funcs lsdc_crtc_helper_funcs = {
 940	.mode_valid = lsdc_crtc_mode_valid,
 941	.mode_set_nofb = lsdc_crtc_mode_set_nofb,
 942	.atomic_enable = lsdc_crtc_atomic_enable,
 943	.atomic_disable = lsdc_crtc_atomic_disable,
 944	.atomic_check = lsdc_crtc_helper_atomic_check,
 945	.atomic_flush = lsdc_crtc_atomic_flush,
 946	.get_scanout_position = lsdc_crtc_get_scanout_position,
 947};
 948
 949int ls7a1000_crtc_init(struct drm_device *ddev,
 950		       struct drm_crtc *crtc,
 951		       struct drm_plane *primary,
 952		       struct drm_plane *cursor,
 953		       unsigned int index,
 954		       bool has_vblank)
 955{
 956	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 957	int ret;
 958
 959	ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
 960	if (ret) {
 961		drm_err(ddev, "pixel pll init failed: %d\n", ret);
 962		return ret;
 963	}
 964
 965	lcrtc->ldev = to_lsdc(ddev);
 966	lcrtc->has_vblank = has_vblank;
 967	lcrtc->hw_ops = &ls7a1000_crtc_hw_ops[index];
 968
 969	ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
 970					&ls7a1000_crtc_funcs,
 971					"LS-CRTC-%d", index);
 972	if (ret) {
 973		drm_err(ddev, "crtc init with planes failed: %d\n", ret);
 974		return ret;
 975	}
 976
 977	drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
 978
 979	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
 980	if (ret)
 981		return ret;
 982
 983	drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
 984
 985	return 0;
 986}
 987
 988int ls7a2000_crtc_init(struct drm_device *ddev,
 989		       struct drm_crtc *crtc,
 990		       struct drm_plane *primary,
 991		       struct drm_plane *cursor,
 992		       unsigned int index,
 993		       bool has_vblank)
 994{
 995	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
 996	int ret;
 997
 998	ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
 999	if (ret) {
1000		drm_err(ddev, "crtc init with pll failed: %d\n", ret);
1001		return ret;
1002	}
1003
1004	lcrtc->ldev = to_lsdc(ddev);
1005	lcrtc->has_vblank = has_vblank;
1006	lcrtc->hw_ops = &ls7a2000_crtc_hw_ops[index];
1007
1008	ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
1009					&ls7a2000_crtc_funcs,
1010					"LS-CRTC-%u", index);
1011	if (ret) {
1012		drm_err(ddev, "crtc init with planes failed: %d\n", ret);
1013		return ret;
1014	}
1015
1016	drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
1017
1018	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
1019	if (ret)
1020		return ret;
1021
1022	drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
1023
1024	return 0;
1025}