^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2012 Avionic Design GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/iommu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <soc/tegra/pmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <drm/drm_atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <drm/drm_atomic_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <drm/drm_debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <drm/drm_fourcc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <drm/drm_plane_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <drm/drm_vblank.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "dc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "drm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "gem.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "hub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "plane.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct drm_crtc_state *state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) stats->frames = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) stats->vblank = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) stats->underflow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) stats->overflow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Reads the active copy of a register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) value = tegra_dc_readl(dc, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static inline unsigned int tegra_plane_offset(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (offset >= 0x500 && offset <= 0x638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) offset = 0x000 + (offset - 0x500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return plane->offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (offset >= 0x700 && offset <= 0x719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) offset = 0x180 + (offset - 0x700);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return plane->offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (offset >= 0x800 && offset <= 0x839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) offset = 0x1c0 + (offset - 0x800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return plane->offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return plane->offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static inline u32 tegra_plane_readl(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct device_node *np = dc->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct of_phandle_iterator it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) of_for_each_phandle(&it, err, np, "nvidia,outputs", NULL, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (it.node == dev->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Latching happens mmediately if the display controller is in STOP mode or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * on the next frame boundary otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Triple-buffered registers have three copies: ASSEMBLY, ARM and ACTIVE. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * ASSEMBLY copy is latched into the ARM copy immediately after *_UPDATE bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * are written. When the *_ACT_REQ bits are written, the ARM copy is latched
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * into the ACTIVE copy, either immediately if the display controller is in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * STOP mode, or at the next frame boundary otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void tegra_dc_commit(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned int bpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fixed20_12 outf = dfixed_init(out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fixed20_12 inf = dfixed_init(in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u32 dda_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) max = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) max = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) max = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) inf.full -= dfixed_const(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dda_inc = dfixed_div(inf, outf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dda_inc = min_t(u32, dda_inc, dfixed_const(max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return dda_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static inline u32 compute_initial_dda(unsigned int in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) fixed20_12 inf = dfixed_init(in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return dfixed_frac(inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u32 background[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) BLEND_COLOR_KEY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct tegra_plane_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 blending[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* disable blending for non-overlapping case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) state = to_tegra_plane_state(plane->base.state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (state->opaque) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * Since custom fix-weight blending isn't utilized and weight
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * of top window is set to max, we can enforce dependent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * blending which in this case results in transparent bottom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * window if top window is opaque and if top window enables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * alpha blending, then bottom window is getting alpha value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * of 1 minus the sum of alpha components of the overlapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * plane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) background[0] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) background[1] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * The region where three windows overlap is the intersection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * of the two regions where two windows overlap. It contributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * to the area if all of the windows on top of it have an alpha
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * component.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) switch (state->base.normalized_zpos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (state->blending[0].alpha &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) state->blending[1].alpha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) background[2] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) background[2] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Enable alpha blending if pixel format has an alpha
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * component.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) foreground |= BLEND_CONTROL_ALPHA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * If any of the windows on top of this window is opaque, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * will completely conceal this window within that area. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * top window has an alpha component, it is blended over the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * bottom window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (state->blending[i].alpha &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) state->blending[i].top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) background[i] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) switch (state->base.normalized_zpos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (state->blending[0].alpha &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) state->blending[1].alpha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) background[2] |= BLEND_CONTROL_DEPENDENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * When both middle and topmost windows have an alpha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * these windows a mixed together and then the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * is blended over the bottom window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (state->blending[0].alpha &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) state->blending[0].top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) background[2] |= BLEND_CONTROL_ALPHA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (state->blending[1].alpha &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) state->blending[1].top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) background[2] |= BLEND_CONTROL_ALPHA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) switch (state->base.normalized_zpos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * If window B / C is topmost, then X / Y registers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * matching the order of blending[...] state indices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * otherwise a swap is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!state->blending[0].top && state->blending[1].top) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) blending[0] = foreground;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) blending[1] = background[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) blending[0] = background[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) blending[1] = foreground;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) tegra_plane_writel(plane, blending[0], DC_WIN_BLEND_2WIN_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) tegra_plane_writel(plane, blending[1], DC_WIN_BLEND_2WIN_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) tegra_plane_writel(plane, foreground, DC_WIN_BLEND_3WIN_XY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static void tegra_plane_setup_blending(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) const struct tegra_dc_window *window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tegra_plane_writel(plane, value, DC_WIN_BLEND_MATCH_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) tegra_plane_writel(plane, value, DC_WIN_BLEND_NOMATCH_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - window->zpos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) tegra_plane_use_horizontal_filtering(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) const struct tegra_dc_window *window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct tegra_dc *dc = plane->dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (window->src.w == window->dst.w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (plane->index == 0 && dc->soc->has_win_a_without_filters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) tegra_plane_use_vertical_filtering(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) const struct tegra_dc_window *window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct tegra_dc *dc = plane->dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (window->src.h == window->dst.h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (plane->index == 0 && dc->soc->has_win_a_without_filters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (plane->index == 2 && dc->soc->has_win_c_without_vert_filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void tegra_dc_setup_window(struct tegra_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) const struct tegra_dc_window *window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct tegra_dc *dc = plane->dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) bool yuv, planar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * For YUV planar modes, the number of bytes per pixel takes into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * account only the luma component and therefore is 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) yuv = tegra_plane_format_is_yuv(window->format, &planar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!yuv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bpp = window->bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) bpp = planar ? 1 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) tegra_plane_writel(plane, window->format, DC_WIN_COLOR_DEPTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) tegra_plane_writel(plane, value, DC_WIN_POSITION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) tegra_plane_writel(plane, value, DC_WIN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) h_offset = window->src.x * bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) v_offset = window->src.y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) h_size = window->src.w * bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) v_size = window->src.h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (window->reflect_x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) h_offset += (window->src.w - 1) * bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (window->reflect_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) v_offset += window->src.h - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * For DDA computations the number of bytes per pixel for YUV planar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * modes needs to take into account all Y, U and V components.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (yuv && planar)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) bpp = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tegra_plane_writel(plane, value, DC_WIN_DDA_INC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) h_dda = compute_initial_dda(window->src.x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) v_dda = compute_initial_dda(window->src.y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) tegra_plane_writel(plane, h_dda, DC_WIN_H_INITIAL_DDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tegra_plane_writel(plane, v_dda, DC_WIN_V_INITIAL_DDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) tegra_plane_writel(plane, 0, DC_WIN_UV_BUF_STRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) tegra_plane_writel(plane, 0, DC_WIN_BUF_STRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) tegra_plane_writel(plane, window->base[0], DC_WINBUF_START_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (yuv && planar) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) tegra_plane_writel(plane, window->base[1], DC_WINBUF_START_ADDR_U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) value = window->stride[1] << 16 | window->stride[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (dc->soc->supports_block_linear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) unsigned long height = window->tiling.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) switch (window->tiling.mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) case TEGRA_BO_TILING_MODE_PITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) value = DC_WINBUF_SURFACE_KIND_PITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case TEGRA_BO_TILING_MODE_TILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) value = DC_WINBUF_SURFACE_KIND_TILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case TEGRA_BO_TILING_MODE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) DC_WINBUF_SURFACE_KIND_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) tegra_plane_writel(plane, value, DC_WINBUF_SURFACE_KIND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) switch (window->tiling.mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case TEGRA_BO_TILING_MODE_PITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) DC_WIN_BUFFER_ADDR_MODE_LINEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case TEGRA_BO_TILING_MODE_TILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) DC_WIN_BUFFER_ADDR_MODE_TILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) case TEGRA_BO_TILING_MODE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * No need to handle this here because ->atomic_check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * will already have filtered it out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) tegra_plane_writel(plane, value, DC_WIN_BUFFER_ADDR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) value = WIN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (yuv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* setup default colorspace conversion coefficients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) value |= CSC_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) } else if (window->bits_per_pixel < 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) value |= COLOR_EXPAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (window->reflect_x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) value |= H_DIRECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (window->reflect_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) value |= V_DIRECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (tegra_plane_use_horizontal_filtering(plane, window)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * Enable horizontal 6-tap filter and set filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * coefficients to the default values defined in TRM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) tegra_plane_writel(plane, 0x00008000, DC_WIN_H_FILTER_P(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) tegra_plane_writel(plane, 0x3e087ce1, DC_WIN_H_FILTER_P(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) tegra_plane_writel(plane, 0x3b117ac1, DC_WIN_H_FILTER_P(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) tegra_plane_writel(plane, 0x591b73aa, DC_WIN_H_FILTER_P(3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tegra_plane_writel(plane, 0x57256d9a, DC_WIN_H_FILTER_P(4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) tegra_plane_writel(plane, 0x552f668b, DC_WIN_H_FILTER_P(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) tegra_plane_writel(plane, 0x73385e8b, DC_WIN_H_FILTER_P(6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) tegra_plane_writel(plane, 0x72435583, DC_WIN_H_FILTER_P(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) tegra_plane_writel(plane, 0x714c4c8b, DC_WIN_H_FILTER_P(8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) tegra_plane_writel(plane, 0x70554393, DC_WIN_H_FILTER_P(9));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) tegra_plane_writel(plane, 0x715e389b, DC_WIN_H_FILTER_P(10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) tegra_plane_writel(plane, 0x71662faa, DC_WIN_H_FILTER_P(11));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) tegra_plane_writel(plane, 0x536d25ba, DC_WIN_H_FILTER_P(12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) tegra_plane_writel(plane, 0x55731bca, DC_WIN_H_FILTER_P(13));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) tegra_plane_writel(plane, 0x387a11d9, DC_WIN_H_FILTER_P(14));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) tegra_plane_writel(plane, 0x3c7c08f1, DC_WIN_H_FILTER_P(15));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) value |= H_FILTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (tegra_plane_use_vertical_filtering(plane, window)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) unsigned int i, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * Enable vertical 2-tap filter and set filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * coefficients to the default values defined in TRM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) for (i = 0, k = 128; i < 16; i++, k -= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) tegra_plane_writel(plane, k, DC_WIN_V_FILTER_P(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) value |= V_FILTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (dc->soc->has_legacy_blending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) tegra_plane_setup_blending_legacy(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) tegra_plane_setup_blending(plane, window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static const u32 tegra20_primary_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* non-native formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static const u64 tegra20_modifiers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) DRM_FORMAT_MOD_LINEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) DRM_FORMAT_MOD_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static const u32 tegra114_primary_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* new on Tegra114 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) DRM_FORMAT_ABGR4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) DRM_FORMAT_ABGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) DRM_FORMAT_BGRA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) DRM_FORMAT_XBGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) DRM_FORMAT_BGRX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) DRM_FORMAT_BGR565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) DRM_FORMAT_BGRA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) DRM_FORMAT_RGBA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static const u32 tegra124_primary_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* new on Tegra114 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) DRM_FORMAT_ABGR4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) DRM_FORMAT_ABGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) DRM_FORMAT_BGRA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) DRM_FORMAT_XBGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) DRM_FORMAT_BGRX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) DRM_FORMAT_BGR565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) DRM_FORMAT_BGRA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) DRM_FORMAT_RGBA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* new on Tegra124 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) DRM_FORMAT_RGBX8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) DRM_FORMAT_BGRX8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static const u64 tegra124_modifiers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) DRM_FORMAT_MOD_LINEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) DRM_FORMAT_MOD_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static int tegra_plane_atomic_check(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct drm_plane_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) DRM_MODE_REFLECT_X |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) DRM_MODE_REFLECT_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) unsigned int rotation = state->rotation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct tegra_bo_tiling *tiling = &plane_state->tiling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct tegra_plane *tegra = to_tegra_plane(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct tegra_dc *dc = to_tegra_dc(state->crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* no need for further checks if the plane is being disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!state->crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) err = tegra_plane_format(state->fb->format->format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) &plane_state->format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) &plane_state->swap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * Tegra20 and Tegra30 are special cases here because they support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * only variants of specific formats with an alpha component, but not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * the corresponding opaque formats. However, the opaque formats can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * be emulated by disabling alpha blending for the plane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (dc->soc->has_legacy_blending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) err = tegra_plane_setup_legacy_state(tegra, plane_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) err = tegra_fb_get_tiling(state->fb, tiling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) !dc->soc->supports_block_linear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) DRM_ERROR("hardware doesn't support block linear mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * Older userspace used custom BO flag in order to specify the Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * reflection, while modern userspace uses the generic DRM rotation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * property in order to achieve the same result. The legacy BO flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * duplicates the DRM rotation property when both are set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (tegra_fb_is_bottom_up(state->fb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) rotation |= DRM_MODE_REFLECT_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) rotation = drm_rotation_simplify(rotation, supported_rotation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (rotation & DRM_MODE_REFLECT_X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) plane_state->reflect_x = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) plane_state->reflect_x = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (rotation & DRM_MODE_REFLECT_Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) plane_state->reflect_y = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) plane_state->reflect_y = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * Tegra doesn't support different strides for U and V planes so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * error out if the user tries to display a framebuffer with such a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (state->fb->format->num_planes > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (state->fb->pitches[2] != state->fb->pitches[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) DRM_ERROR("unsupported UV-plane configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) err = tegra_plane_state_add(tegra, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static void tegra_plane_atomic_disable(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct drm_plane_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct tegra_plane *p = to_tegra_plane(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* rien ne va plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (!old_state || !old_state->crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) value &= ~WIN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static void tegra_plane_atomic_update(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct drm_plane_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct drm_framebuffer *fb = plane->state->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct tegra_plane *p = to_tegra_plane(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct tegra_dc_window window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* rien ne va plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (!plane->state->crtc || !plane->state->fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!plane->state->visible)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return tegra_plane_atomic_disable(plane, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) memset(&window, 0, sizeof(window));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) window.src.x = plane->state->src.x1 >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) window.src.y = plane->state->src.y1 >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) window.src.w = drm_rect_width(&plane->state->src) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) window.src.h = drm_rect_height(&plane->state->src) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) window.dst.x = plane->state->dst.x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) window.dst.y = plane->state->dst.y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) window.dst.w = drm_rect_width(&plane->state->dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) window.dst.h = drm_rect_height(&plane->state->dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) window.bits_per_pixel = fb->format->cpp[0] * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) window.reflect_x = state->reflect_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) window.reflect_y = state->reflect_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* copy from state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) window.zpos = plane->state->normalized_zpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) window.tiling = state->tiling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) window.format = state->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) window.swap = state->swap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) for (i = 0; i < fb->format->num_planes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) window.base[i] = state->iova[i] + fb->offsets[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * Tegra uses a shared stride for UV planes. Framebuffers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * already checked for this in the tegra_plane_atomic_check()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * function, so it's safe to ignore the V-plane pitch here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (i < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) window.stride[i] = fb->pitches[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) tegra_dc_setup_window(p, &window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .prepare_fb = tegra_plane_prepare_fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .cleanup_fb = tegra_plane_cleanup_fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .atomic_check = tegra_plane_atomic_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .atomic_disable = tegra_plane_atomic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .atomic_update = tegra_plane_atomic_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static unsigned long tegra_plane_get_possible_crtcs(struct drm_device *drm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * Ideally this would use drm_crtc_mask(), but that would require the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * CRTC to already be in the mode_config's list of CRTCs. However, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * will only be added to that list in the drm_crtc_init_with_planes()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * (in tegra_dc_init()), which in turn requires registration of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * planes. So we have ourselves a nice little chicken and egg problem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * We work around this by manually creating the mask from the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * of CRTCs that have been registered, and should therefore always be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * the same as drm_crtc_index() after registration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 1 << drm->mode_config.num_crtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct tegra_plane *plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) unsigned int num_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) const u64 *modifiers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) const u32 *formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) plane = kzalloc(sizeof(*plane), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (!plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* Always use window A as primary window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) plane->offset = 0xa00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) plane->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) plane->dc = dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) num_formats = dc->soc->num_primary_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) formats = dc->soc->primary_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) modifiers = dc->soc->modifiers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) &tegra_plane_funcs, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) num_formats, modifiers, type, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) kfree(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) err = drm_plane_create_rotation_property(&plane->base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) DRM_MODE_ROTATE_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) DRM_MODE_ROTATE_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) DRM_MODE_ROTATE_180 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) DRM_MODE_REFLECT_X |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) DRM_MODE_REFLECT_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev_err(dc->dev, "failed to create rotation property: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return &plane->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static const u32 tegra_cursor_plane_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) DRM_FORMAT_RGBA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int tegra_cursor_atomic_check(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct drm_plane_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct tegra_plane *tegra = to_tegra_plane(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* no need for further checks if the plane is being disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (!state->crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* scaling not supported for cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if ((state->src_w >> 16 != state->crtc_w) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) (state->src_h >> 16 != state->crtc_h))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* only square cursors supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (state->src_w != state->src_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (state->crtc_w != 32 && state->crtc_w != 64 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) state->crtc_w != 128 && state->crtc_w != 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) err = tegra_plane_state_add(tegra, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static void tegra_cursor_atomic_update(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct drm_plane_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) u32 value = CURSOR_CLIP_DISPLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /* rien ne va plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (!plane->state->crtc || !plane->state->fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) switch (plane->state->crtc_w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) value |= CURSOR_SIZE_32x32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) case 64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) value |= CURSOR_SIZE_64x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case 128:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) value |= CURSOR_SIZE_128x128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) case 256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) value |= CURSOR_SIZE_256x256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) WARN(1, "cursor size %ux%u not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) plane->state->crtc_w, plane->state->crtc_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) value |= (state->iova[0] >> 10) & 0x3fffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) value = (state->iova[0] >> 32) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /* enable cursor and set blend mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) value |= CURSOR_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) value &= ~CURSOR_DST_BLEND_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) value &= ~CURSOR_SRC_BLEND_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) value |= CURSOR_MODE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) value |= CURSOR_ALPHA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* position the cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) value = (plane->state->crtc_y & 0x3fff) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) (plane->state->crtc_x & 0x3fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static void tegra_cursor_atomic_disable(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct drm_plane_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct tegra_dc *dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* rien ne va plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (!old_state || !old_state->crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) dc = to_tegra_dc(old_state->crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) value &= ~CURSOR_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .prepare_fb = tegra_plane_prepare_fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .cleanup_fb = tegra_plane_cleanup_fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) .atomic_check = tegra_cursor_atomic_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .atomic_update = tegra_cursor_atomic_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .atomic_disable = tegra_cursor_atomic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static const uint64_t linear_modifiers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) DRM_FORMAT_MOD_LINEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) DRM_FORMAT_MOD_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct tegra_plane *plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) unsigned int num_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) const u32 *formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) plane = kzalloc(sizeof(*plane), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (!plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * This index is kind of fake. The cursor isn't a regular plane, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * its update and activation request bits in DC_CMD_STATE_CONTROL do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * use the same programming. Setting this fake index here allows the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * code in tegra_add_plane_state() to do the right thing without the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * need to special-casing the cursor plane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) plane->index = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) plane->dc = dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) formats = tegra_cursor_plane_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) &tegra_plane_funcs, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) num_formats, linear_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) DRM_PLANE_TYPE_CURSOR, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) kfree(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) drm_plane_create_zpos_immutable_property(&plane->base, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return &plane->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) static const u32 tegra20_overlay_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* non-native formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /* planar formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) DRM_FORMAT_UYVY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) DRM_FORMAT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) DRM_FORMAT_YUV420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) DRM_FORMAT_YUV422,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static const u32 tegra114_overlay_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* new on Tegra114 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) DRM_FORMAT_ABGR4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) DRM_FORMAT_ABGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) DRM_FORMAT_BGRA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) DRM_FORMAT_XBGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) DRM_FORMAT_BGRX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) DRM_FORMAT_BGR565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) DRM_FORMAT_BGRA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) DRM_FORMAT_RGBA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /* planar formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) DRM_FORMAT_UYVY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) DRM_FORMAT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) DRM_FORMAT_YUV420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) DRM_FORMAT_YUV422,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) static const u32 tegra124_overlay_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) DRM_FORMAT_ARGB4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) DRM_FORMAT_ARGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) DRM_FORMAT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) DRM_FORMAT_RGBA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) DRM_FORMAT_ABGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) DRM_FORMAT_ARGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) /* new on Tegra114 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) DRM_FORMAT_ABGR4444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) DRM_FORMAT_ABGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) DRM_FORMAT_BGRA5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) DRM_FORMAT_XRGB1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) DRM_FORMAT_RGBX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) DRM_FORMAT_XBGR1555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) DRM_FORMAT_BGRX5551,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) DRM_FORMAT_BGR565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) DRM_FORMAT_BGRA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) DRM_FORMAT_RGBA8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) DRM_FORMAT_XRGB8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) DRM_FORMAT_XBGR8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* new on Tegra124 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) DRM_FORMAT_RGBX8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) DRM_FORMAT_BGRX8888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* planar formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) DRM_FORMAT_UYVY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) DRM_FORMAT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) DRM_FORMAT_YUV420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) DRM_FORMAT_YUV422,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct tegra_dc *dc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) bool cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct tegra_plane *plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) unsigned int num_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) enum drm_plane_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) const u32 *formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) plane = kzalloc(sizeof(*plane), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (!plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) plane->offset = 0xa00 + 0x200 * index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) plane->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) plane->dc = dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) num_formats = dc->soc->num_overlay_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) formats = dc->soc->overlay_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (!cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) type = DRM_PLANE_TYPE_OVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) type = DRM_PLANE_TYPE_CURSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) &tegra_plane_funcs, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) num_formats, linear_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) type, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) kfree(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) err = drm_plane_create_rotation_property(&plane->base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) DRM_MODE_ROTATE_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) DRM_MODE_ROTATE_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) DRM_MODE_ROTATE_180 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) DRM_MODE_REFLECT_X |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) DRM_MODE_REFLECT_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) dev_err(dc->dev, "failed to create rotation property: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return &plane->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) static struct drm_plane *tegra_dc_add_shared_planes(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct drm_plane *plane, *primary = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) for (i = 0; i < dc->soc->num_wgrps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (wgrp->dc == dc->pipe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) for (j = 0; j < wgrp->num_windows; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) unsigned int index = wgrp->windows[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) plane = tegra_shared_plane_create(drm, dc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) wgrp->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (IS_ERR(plane))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * Choose the first shared plane owned by this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) * head as the primary plane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (!primary) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) plane->type = DRM_PLANE_TYPE_PRIMARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) primary = plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) struct drm_plane *planes[2], *primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) unsigned int planes_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) primary = tegra_primary_plane_create(drm, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (IS_ERR(primary))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) return primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (dc->soc->supports_cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) planes_num = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) planes_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) for (i = 0; i < planes_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (IS_ERR(planes[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err = PTR_ERR(planes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) tegra_plane_funcs.destroy(planes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) tegra_plane_funcs.destroy(primary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static void tegra_dc_destroy(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) drm_crtc_cleanup(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static void tegra_crtc_reset(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct tegra_dc_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (crtc->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) tegra_crtc_atomic_destroy_state(crtc, crtc->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) __drm_atomic_helper_crtc_reset(crtc, &state->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) static struct drm_crtc_state *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct tegra_dc_state *state = to_dc_state(crtc->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct tegra_dc_state *copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) copy = kmalloc(sizeof(*copy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (!copy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) __drm_atomic_helper_crtc_duplicate_state(crtc, ©->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) copy->clk = state->clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) copy->pclk = state->pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) copy->div = state->div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) copy->planes = state->planes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return ©->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct drm_crtc_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) __drm_atomic_helper_crtc_destroy_state(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) #define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) static const struct debugfs_reg32 tegra_dc_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) DEBUGFS_REG32(DC_CMD_INT_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) DEBUGFS_REG32(DC_CMD_INT_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) DEBUGFS_REG32(DC_CMD_INT_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) DEBUGFS_REG32(DC_CMD_INT_TYPE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) DEBUGFS_REG32(DC_CMD_INT_POLARITY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) DEBUGFS_REG32(DC_COM_CRC_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) DEBUGFS_REG32(DC_COM_SPI_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) DEBUGFS_REG32(DC_COM_GPIO_CTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) DEBUGFS_REG32(DC_DISP_BACK_PORCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) DEBUGFS_REG32(DC_DISP_ACTIVE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) DEBUGFS_REG32(DC_DISP_M0_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) DEBUGFS_REG32(DC_DISP_M1_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) DEBUGFS_REG32(DC_DISP_DI_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) DEBUGFS_REG32(DC_DISP_PP_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) DEBUGFS_REG32(DC_DISP_SD_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) DEBUGFS_REG32(DC_WIN_POSITION),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) DEBUGFS_REG32(DC_WIN_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) DEBUGFS_REG32(DC_WIN_DDA_INC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) DEBUGFS_REG32(DC_WIN_DV_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) DEBUGFS_REG32(DC_WINBUF_START_ADDR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) static int tegra_dc_show_regs(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) struct drm_info_node *node = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) struct tegra_dc *dc = node->info_ent->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) drm_modeset_lock(&dc->base.mutex, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (!dc->base.state->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) unsigned int offset = tegra_dc_regs[i].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) offset, tegra_dc_readl(dc, offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) drm_modeset_unlock(&dc->base.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) static int tegra_dc_show_crc(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) struct drm_info_node *node = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) struct tegra_dc *dc = node->info_ent->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) drm_modeset_lock(&dc->base.mutex, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (!dc->base.state->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) tegra_dc_commit(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) drm_crtc_wait_one_vblank(&dc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) drm_crtc_wait_one_vblank(&dc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) seq_printf(s, "%08x\n", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) drm_modeset_unlock(&dc->base.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) static int tegra_dc_show_stats(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct drm_info_node *node = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) struct tegra_dc *dc = node->info_ent->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) seq_printf(s, "frames: %lu\n", dc->stats.frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) static struct drm_info_list debugfs_files[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) { "regs", tegra_dc_show_regs, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) { "crc", tegra_dc_show_crc, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) { "stats", tegra_dc_show_stats, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static int tegra_dc_late_register(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) unsigned int i, count = ARRAY_SIZE(debugfs_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct drm_minor *minor = crtc->dev->primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) root = crtc->debugfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) root = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (!dc->debugfs_files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) for (i = 0; i < count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) dc->debugfs_files[i].data = dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) static void tegra_dc_early_unregister(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) unsigned int count = ARRAY_SIZE(debugfs_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct drm_minor *minor = crtc->dev->primary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) drm_debugfs_remove_files(dc->debugfs_files, count, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) kfree(dc->debugfs_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) dc->debugfs_files = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) /* XXX vblank syncpoints don't work with nvdisplay yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (dc->syncpt && !dc->soc->has_nvdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return host1x_syncpt_read(dc->syncpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) /* fallback to software emulated VBLANK counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) return (u32)drm_crtc_vblank_count(&dc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static int tegra_dc_enable_vblank(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) value |= VBLANK_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) value &= ~VBLANK_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) static const struct drm_crtc_funcs tegra_crtc_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) .page_flip = drm_atomic_helper_page_flip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .set_config = drm_atomic_helper_set_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .destroy = tegra_dc_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) .reset = tegra_crtc_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) .late_register = tegra_dc_late_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) .early_unregister = tegra_dc_early_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) .get_vblank_counter = tegra_dc_get_vblank_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) .enable_vblank = tegra_dc_enable_vblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) .disable_vblank = tegra_dc_disable_vblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) static int tegra_dc_set_timings(struct tegra_dc *dc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) unsigned int h_ref_to_sync = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) unsigned int v_ref_to_sync = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (!dc->soc->has_nvdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) value = (v_ref_to_sync << 16) | h_ref_to_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) value = ((mode->vsync_end - mode->vsync_start) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) ((mode->hsync_end - mode->hsync_start) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) value = ((mode->vtotal - mode->vsync_end) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) ((mode->htotal - mode->hsync_end) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) value = ((mode->vsync_start - mode->vdisplay) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) ((mode->hsync_start - mode->hdisplay) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) value = (mode->vdisplay << 16) | mode->hdisplay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) * tegra_dc_state_setup_clock - check clock settings and store them in atomic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) * state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) * @dc: display controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) * @crtc_state: CRTC atomic state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) * @clk: parent clock for display controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * @pclk: pixel clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * @div: shift clock divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * 0 on success or a negative error-code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) int tegra_dc_state_setup_clock(struct tegra_dc *dc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) struct drm_crtc_state *crtc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) struct clk *clk, unsigned long pclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) unsigned int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) struct tegra_dc_state *state = to_dc_state(crtc_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) if (!clk_has_parent(dc->clk, clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) state->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) state->pclk = pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) state->div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) static void tegra_dc_commit_state(struct tegra_dc *dc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) struct tegra_dc_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) err = clk_set_parent(dc->clk, state->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) dev_err(dc->dev, "failed to set parent clock: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) * Outputs may not want to change the parent clock rate. This is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * relevant to Tegra20 where only a single display PLL is available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * Since that PLL would typically be used for HDMI, an internal LVDS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) * panel would need to be driven by some other clock such as PLL_P
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) * which is shared with other peripherals. Changing the clock rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * should therefore be avoided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (state->pclk > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) err = clk_set_rate(state->clk, state->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) dev_err(dc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) "failed to set clock rate to %lu Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) state->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) err = clk_set_rate(dc->clk, state->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) dc->clk, state->pclk, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) state->div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (!dc->soc->has_nvdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) static void tegra_dc_stop(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) /* stop the display controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) value &= ~DISP_CTRL_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) tegra_dc_commit(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) static bool tegra_dc_idle(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) return (value & DISP_CTRL_MODE_MASK) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) timeout = jiffies + msecs_to_jiffies(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) while (time_before(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (tegra_dc_idle(dc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) struct drm_crtc_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (!tegra_dc_idle(dc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) tegra_dc_stop(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * Ignore the return value, there isn't anything useful to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * in case this fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) tegra_dc_wait_idle(dc, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) * This should really be part of the RGB encoder driver, but clearing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * these bits has the side-effect of stopping the display controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) * When that happens no VBLANK interrupts will be raised. At the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) * time the encoder is disabled before the display controller, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) * above code is always going to timeout waiting for the controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) * to go idle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) * Given the close coupling between the RGB encoder and the display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) * controller doing it here is still kind of okay. None of the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) * encoder drivers require these bits to be cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * XXX: Perhaps given that the display controller is switched off at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * this point anyway maybe clearing these bits isn't even useful for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * the RGB encoder?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (dc->rgb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) tegra_dc_stats_reset(&dc->stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) drm_crtc_vblank_off(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) spin_lock_irq(&crtc->dev->event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (crtc->state->event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) drm_crtc_send_vblank_event(crtc, crtc->state->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) crtc->state->event = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) spin_unlock_irq(&crtc->dev->event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) err = host1x_client_suspend(&dc->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) dev_err(dc->dev, "failed to suspend: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) struct drm_crtc_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) struct drm_display_mode *mode = &crtc->state->adjusted_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) struct tegra_dc_state *state = to_dc_state(crtc->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) err = host1x_client_resume(&dc->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) dev_err(dc->dev, "failed to resume: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) /* initialize display controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (dc->syncpt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) u32 syncpt = host1x_syncpt_id(dc->syncpt), enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) if (dc->soc->has_nvdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) enable = 1 << 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) enable = 1 << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) value = SYNCPT_CNTRL_NO_STALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) value = enable | syncpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) if (dc->soc->has_nvdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) DSC_OBUF_UF_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) DSC_OBUF_UF_INT | SD3_BUCKET_WALK_DONE_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) HEAD_UF_INT | MSF_INT | REG_TMOUT_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) REGION_CRC_INT | V_PULSE2_INT | V_PULSE3_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) VBLANK_INT | FRAME_END_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) value = SD3_BUCKET_WALK_DONE_INT | HEAD_UF_INT | VBLANK_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) FRAME_END_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) value = HEAD_UF_INT | REG_TMOUT_INT | FRAME_END_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) /* initialize timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) if (dc->soc->supports_background_color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) /* apply PLL and pixel clock changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) tegra_dc_commit_state(dc, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) /* program display mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) tegra_dc_set_timings(dc, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) /* interlacing isn't supported yet, so disable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (dc->soc->supports_interlacing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) value &= ~INTERLACE_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) value &= ~DISP_CTRL_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) value |= DISP_CTRL_MODE_C_DISPLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) if (!dc->soc->has_nvdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) /* enable underflow reporting and display red for missing pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) if (dc->soc->has_nvdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) value = UNDERFLOW_MODE_RED | UNDERFLOW_REPORT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) tegra_dc_writel(dc, value, DC_COM_RG_UNDERFLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) tegra_dc_commit(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) drm_crtc_vblank_on(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) struct drm_crtc_state *old_crtc_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) if (crtc->state->event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) spin_lock_irqsave(&crtc->dev->event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (drm_crtc_vblank_get(crtc) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) drm_crtc_send_vblank_event(crtc, crtc->state->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) drm_crtc_arm_vblank_event(crtc, crtc->state->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) crtc->state->event = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) struct drm_crtc_state *old_crtc_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) struct tegra_dc_state *state = to_dc_state(crtc->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) struct tegra_dc *dc = to_tegra_dc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) value = state->planes << 8 | GENERAL_UPDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) value = state->planes | GENERAL_ACT_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) .atomic_begin = tegra_crtc_atomic_begin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) .atomic_flush = tegra_crtc_atomic_flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) .atomic_enable = tegra_crtc_atomic_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) .atomic_disable = tegra_crtc_atomic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) static irqreturn_t tegra_dc_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) struct tegra_dc *dc = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) if (status & FRAME_END_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) dev_dbg(dc->dev, "%s(): frame end\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) dc->stats.frames++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (status & VBLANK_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) drm_crtc_handle_vblank(&dc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) dc->stats.vblank++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) dev_dbg(dc->dev, "%s(): underflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) dc->stats.underflow++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) dev_dbg(dc->dev, "%s(): overflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) dc->stats.overflow++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) if (status & HEAD_UF_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) dev_dbg_ratelimited(dc->dev, "%s(): head underflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) dc->stats.underflow++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) static bool tegra_dc_has_window_groups(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if (!dc->soc->wgrps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) for (i = 0; i < dc->soc->num_wgrps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) if (wgrp->dc == dc->pipe && wgrp->num_windows > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) static int tegra_dc_init(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) struct drm_device *drm = dev_get_drvdata(client->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) struct tegra_dc *dc = host1x_client_to_dc(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) struct drm_plane *primary = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) struct drm_plane *cursor = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) * XXX do not register DCs with no window groups because we cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) * assign a primary plane to them, which in turn will cause KMS to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) * crash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) if (!tegra_dc_has_window_groups(dc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) * Set the display hub as the host1x client parent for the display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) * controller. This is needed for the runtime reference counting that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) * ensures the display hub is always powered when any of the display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) * controllers are.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (dc->soc->has_nvdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) client->parent = &tegra->hub->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) dc->syncpt = host1x_syncpt_request(client, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (!dc->syncpt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) dev_warn(dc->dev, "failed to allocate syncpoint\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) err = host1x_client_iommu_attach(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) if (err < 0 && err != -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) dev_err(client->dev, "failed to attach to domain: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) if (dc->soc->wgrps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) primary = tegra_dc_add_shared_planes(drm, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) primary = tegra_dc_add_planes(drm, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (IS_ERR(primary)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) err = PTR_ERR(primary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) if (dc->soc->supports_cursor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) cursor = tegra_dc_cursor_plane_create(drm, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) if (IS_ERR(cursor)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) err = PTR_ERR(cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) /* dedicate one overlay to mouse cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) cursor = tegra_dc_overlay_plane_create(drm, dc, 2, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) if (IS_ERR(cursor)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) err = PTR_ERR(cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) &tegra_crtc_funcs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * Keep track of the minimum pitch alignment across all display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) * controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) if (dc->soc->pitch_align > tegra->pitch_align)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) tegra->pitch_align = dc->soc->pitch_align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) err = tegra_dc_rgb_init(drm, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) if (err < 0 && err != -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) dev_name(dc->dev), dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) * Inherit the DMA parameters (such as maximum segment size) from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) * parent host1x device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) client->dev->dma_parms = client->host->dma_parms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) if (!IS_ERR_OR_NULL(cursor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) drm_plane_cleanup(cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) if (!IS_ERR(primary))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) drm_plane_cleanup(primary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) host1x_client_iommu_detach(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) host1x_syncpt_free(dc->syncpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) static int tegra_dc_exit(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) struct tegra_dc *dc = host1x_client_to_dc(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) if (!tegra_dc_has_window_groups(dc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) /* avoid a dangling pointer just in case this disappears */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) client->dev->dma_parms = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) devm_free_irq(dc->dev, dc->irq, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) err = tegra_dc_rgb_exit(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) host1x_client_iommu_detach(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) host1x_syncpt_free(dc->syncpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) static int tegra_dc_runtime_suspend(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) struct tegra_dc *dc = host1x_client_to_dc(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) struct device *dev = client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) err = reset_control_assert(dc->rst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) dev_err(dev, "failed to assert reset: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (dc->soc->has_powergate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) tegra_powergate_power_off(dc->powergate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) clk_disable_unprepare(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) pm_runtime_put_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) static int tegra_dc_runtime_resume(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) struct tegra_dc *dc = host1x_client_to_dc(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) struct device *dev = client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) err = pm_runtime_resume_and_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) dev_err(dev, "failed to get runtime PM: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (dc->soc->has_powergate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) dc->rst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) dev_err(dev, "failed to power partition: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) goto put_rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) err = clk_prepare_enable(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) dev_err(dev, "failed to enable clock: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) goto put_rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) err = reset_control_deassert(dc->rst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) dev_err(dev, "failed to deassert reset: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) goto disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) clk_disable_unprepare(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) put_rpm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) pm_runtime_put_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) static const struct host1x_client_ops dc_client_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) .init = tegra_dc_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) .exit = tegra_dc_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) .suspend = tegra_dc_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) .resume = tegra_dc_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) .supports_background_color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) .supports_interlacing = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) .supports_cursor = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) .supports_block_linear = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) .has_legacy_blending = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) .pitch_align = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) .has_powergate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) .coupled_pm = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) .has_nvdisplay = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) .num_primary_formats = ARRAY_SIZE(tegra20_primary_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) .primary_formats = tegra20_primary_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) .overlay_formats = tegra20_overlay_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) .modifiers = tegra20_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) .has_win_a_without_filters = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) .has_win_c_without_vert_filter = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) .supports_background_color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) .supports_interlacing = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) .supports_cursor = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) .supports_block_linear = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) .has_legacy_blending = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) .pitch_align = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) .has_powergate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) .has_nvdisplay = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) .num_primary_formats = ARRAY_SIZE(tegra20_primary_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) .primary_formats = tegra20_primary_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) .overlay_formats = tegra20_overlay_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) .modifiers = tegra20_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) .has_win_a_without_filters = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) .has_win_c_without_vert_filter = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) .supports_background_color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) .supports_interlacing = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) .supports_cursor = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) .supports_block_linear = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) .has_legacy_blending = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) .pitch_align = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) .has_powergate = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) .has_nvdisplay = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) .num_primary_formats = ARRAY_SIZE(tegra114_primary_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) .primary_formats = tegra114_primary_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) .overlay_formats = tegra114_overlay_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) .modifiers = tegra20_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) .has_win_a_without_filters = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) .has_win_c_without_vert_filter = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) .supports_background_color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) .supports_interlacing = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) .supports_cursor = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) .supports_block_linear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) .has_legacy_blending = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) .pitch_align = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) .has_powergate = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) .has_nvdisplay = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) .num_primary_formats = ARRAY_SIZE(tegra124_primary_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) .primary_formats = tegra124_primary_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) .num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) .overlay_formats = tegra124_overlay_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) .modifiers = tegra124_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) .has_win_a_without_filters = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) .has_win_c_without_vert_filter = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) .supports_background_color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) .supports_interlacing = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) .supports_cursor = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) .supports_block_linear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) .has_legacy_blending = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) .pitch_align = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) .has_powergate = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) .has_nvdisplay = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) .num_primary_formats = ARRAY_SIZE(tegra114_primary_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) .primary_formats = tegra114_primary_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) .overlay_formats = tegra114_overlay_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) .modifiers = tegra124_modifiers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) .has_win_a_without_filters = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) .has_win_c_without_vert_filter = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) .index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) .dc = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) .windows = (const unsigned int[]) { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) .index = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) .dc = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) .windows = (const unsigned int[]) { 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) .index = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) .dc = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) .windows = (const unsigned int[]) { 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) .index = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) .windows = (const unsigned int[]) { 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) .index = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) .windows = (const unsigned int[]) { 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) .index = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) .windows = (const unsigned int[]) { 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) .supports_background_color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) .supports_interlacing = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) .supports_cursor = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) .supports_block_linear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) .has_legacy_blending = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) .pitch_align = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) .has_powergate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) .has_nvdisplay = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) .wgrps = tegra186_dc_wgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) .num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) .index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) .dc = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) .windows = (const unsigned int[]) { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) .index = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) .dc = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) .windows = (const unsigned int[]) { 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) .index = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) .dc = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) .windows = (const unsigned int[]) { 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) .index = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) .windows = (const unsigned int[]) { 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) .index = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) .windows = (const unsigned int[]) { 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) .index = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) .dc = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) .windows = (const unsigned int[]) { 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) .num_windows = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) .supports_background_color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) .supports_interlacing = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) .supports_cursor = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) .supports_block_linear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) .has_legacy_blending = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) .pitch_align = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) .has_powergate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) .coupled_pm = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) .has_nvdisplay = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) .wgrps = tegra194_dc_wgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) .num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) static const struct of_device_id tegra_dc_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) .compatible = "nvidia,tegra194-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) .data = &tegra194_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) .compatible = "nvidia,tegra186-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) .data = &tegra186_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) .compatible = "nvidia,tegra210-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) .data = &tegra210_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) .compatible = "nvidia,tegra124-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) .data = &tegra124_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) .compatible = "nvidia,tegra114-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) .data = &tegra114_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) .compatible = "nvidia,tegra30-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) .data = &tegra30_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) .compatible = "nvidia,tegra20-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) .data = &tegra20_dc_soc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) /* sentinel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) static int tegra_dc_parse_dt(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) u32 value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) dev_err(dc->dev, "missing \"nvidia,head\" property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) * If the nvidia,head property isn't present, try to find the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) * correct head number by looking up the position of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) * display controller's node within the device tree. Assuming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) * that the nodes are ordered properly in the DTS file and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) * that the translation into a flattened device tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) * preserves that ordering this will actually yield the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) * head number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) * If those assumptions don't hold, this will still work for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) * cases where only a single display controller is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) for_each_matching_node(np, tegra_dc_of_match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) if (np == dc->dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) value++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) dc->pipe = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) static int tegra_dc_match_by_pipe(struct device *dev, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) struct tegra_dc *dc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) unsigned int pipe = (unsigned long)(void *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) return dc->pipe == pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) static int tegra_dc_couple(struct tegra_dc *dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) * On Tegra20, DC1 requires DC0 to be taken out of reset in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) * be enabled, otherwise CPU hangs on writing to CMD_DISPLAY_COMMAND /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) * POWER_CONTROL registers during CRTC enabling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) if (dc->soc->coupled_pm && dc->pipe == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) struct device *companion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) struct tegra_dc *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) companion = driver_find_device(dc->dev->driver, NULL, (const void *)0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) tegra_dc_match_by_pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) if (!companion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) parent = dev_get_drvdata(companion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) dc->client.parent = &parent->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) static int tegra_dc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) struct tegra_dc *dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) if (!dc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) dc->soc = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) INIT_LIST_HEAD(&dc->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) dc->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) err = tegra_dc_parse_dt(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) err = tegra_dc_couple(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) dc->clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) if (IS_ERR(dc->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) dev_err(&pdev->dev, "failed to get clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) return PTR_ERR(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) dc->rst = devm_reset_control_get(&pdev->dev, "dc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) if (IS_ERR(dc->rst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) dev_err(&pdev->dev, "failed to get reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) return PTR_ERR(dc->rst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) /* assert reset and disable clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) err = clk_prepare_enable(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) usleep_range(2000, 4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) err = reset_control_assert(dc->rst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) usleep_range(2000, 4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) clk_disable_unprepare(dc->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) if (dc->soc->has_powergate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) if (dc->pipe == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) dc->powergate = TEGRA_POWERGATE_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) dc->powergate = TEGRA_POWERGATE_DISB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) tegra_powergate_power_off(dc->powergate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) dc->regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) if (IS_ERR(dc->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) return PTR_ERR(dc->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) dc->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) if (dc->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) err = tegra_dc_rgb_probe(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) if (err < 0 && err != -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) const char *level = KERN_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) if (err == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) level = KERN_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) platform_set_drvdata(pdev, dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) pm_runtime_enable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) INIT_LIST_HEAD(&dc->client.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) dc->client.ops = &dc_client_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) dc->client.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) err = host1x_client_register(&dc->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) dev_err(&pdev->dev, "failed to register host1x client: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) disable_pm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) tegra_dc_rgb_remove(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) static int tegra_dc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) struct tegra_dc *dc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) err = host1x_client_unregister(&dc->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) err = tegra_dc_rgb_remove(dc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) struct platform_driver tegra_dc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) .name = "tegra-dc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) .of_match_table = tegra_dc_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) .probe = tegra_dc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) .remove = tegra_dc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) };