Linux Tegra architecture development
 help / color / mirror / Atom feed
* Re: [PATCH v4 3/4] PCI: tegra: Add Tegra264 support
From: Thierry Reding @ 2026-04-07  9:38 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Karthikeyan Mitran, Hou Zhiqiang,
	Thomas Petazzoni, Pali Rohár, Michal Simek, Kevin Xie,
	linux-pci, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Thierry Reding, Manikanta Maddireddy
In-Reply-To: <iaoee5r5e2w52fap7ex23wdikbuvpjpesinedgjkehsedszhzo@64yoo2avmxle>

[-- Attachment #1: Type: text/plain, Size: 12894 bytes --]

On Thu, Apr 02, 2026 at 11:02:02PM +0530, Manivannan Sadhasivam wrote:
> On Thu, Apr 02, 2026 at 04:27:37PM +0200, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > Add a driver for the PCIe controller found on NVIDIA Tegra264 SoCs. The
> > driver is very small, with its main purpose being to set up the address
> > translation registers and then creating a standard PCI host using ECAM.
> > 
> > Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> 
> What is the rationale for adding a new driver? Can't you reuse the existing one?
> If so, that should be mentioned in the description.

Which existing one? Tegra PCI controllers for previou generations
(Tegra194 and Tegra234) were DesignWare IP, but Tegra264 is an internal
IP, so the programming is entirely different. I'll add something to that
effect to the commit message.

> > diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> > index 5aaed8ac6e44..6ead04f7bd6e 100644
> > --- a/drivers/pci/controller/Kconfig
> > +++ b/drivers/pci/controller/Kconfig
> > @@ -254,7 +254,15 @@ config PCI_TEGRA
> >  	select IRQ_MSI_LIB
> >  	help
> >  	  Say Y here if you want support for the PCIe host controller found
> > -	  on NVIDIA Tegra SoCs.
> > +	  on NVIDIA Tegra SoCs (Tegra20 through Tegra186).
> > +
> > +config PCIE_TEGRA264
> > +	bool "NVIDIA Tegra264 PCIe controller"
> 
> This driver seems to be using external MSI controller. So it can be built as a
> module. Also, you have the remove() callback for some reason.

Okay, I can turn this into a tristate symbol.

> > +	depends on ARCH_TEGRA || COMPILE_TEST
> > +	depends on PCI_MSI
> 
> Why?

I suppose it's not necessary in the sense of it being a build
dependency. At runtime, however, the root complex is not useful if PCI
MSI is not enabled. We can drop this dependency and rely on .config to
have it enabled as needed.

> > diff --git a/drivers/pci/controller/pcie-tegra264.c b/drivers/pci/controller/pcie-tegra264.c
> > new file mode 100644
> > index 000000000000..3ce1ad971bdb
> > --- /dev/null
> > +++ b/drivers/pci/controller/pcie-tegra264.c
[...]
> > +struct tegra264_pcie {
> > +	struct device *dev;
> > +	bool link_up;
> 
> Keep bool types at the end to avoid holes.

Done.

> > +static int tegra264_pcie_parse_dt(struct tegra264_pcie *pcie)
> > +{
> > +	int err;
> > +
> > +	pcie->wake_gpio = devm_gpiod_get_optional(pcie->dev, "nvidia,pex-wake",
> 
> You should switch to standard 'wake-gpios' property.

Will do.

> > +						  GPIOD_IN);
> > +	if (IS_ERR(pcie->wake_gpio))
> > +		return PTR_ERR(pcie->wake_gpio);
> > +
> > +	if (pcie->wake_gpio) {
> 
> Since you are bailing out above, you don't need this check.

I think we still want to have this check to handle the case of optional
wake GPIOs. Not all controllers may have this wired up and
devm_gpiod_get_optional() will return NULL (not an ERR_PTR()-encoded
error) if the wake-gpios property is missing.

> > +static void tegra264_pcie_bpmp_set_rp_state(struct tegra264_pcie *pcie)
> 
> I don't think this function name is self explanatory. Looks like it is turning
> off the PCIe controller, so how about tegra264_pcie_power_off()?

Agreed. The name is a relic from when this was potentially being used to
toggle on and off the controller. But it's only used for disabling, so
tegra264_pcie__power_off() sounds much better.

> > +{
> > +	struct tegra_bpmp_message msg = {};
> > +	struct mrq_pcie_request req = {};
> > +	int err;
> > +
> > +	req.cmd = CMD_PCIE_RP_CONTROLLER_OFF;
> > +	req.rp_ctrlr_off.rp_controller = pcie->ctl_id;
> > +
> > +	msg.mrq = MRQ_PCIE;
> > +	msg.tx.data = &req;
> > +	msg.tx.size = sizeof(req);
> > +
> > +	err = tegra_bpmp_transfer(pcie->bpmp, &msg);
> > +	if (err)
> > +		dev_info(pcie->dev, "failed to turn off PCIe #%u: %pe\n",
> 
> Why not dev_err()?
> 
> > +			 pcie->ctl_id, ERR_PTR(err));
> > +
> > +	if (msg.rx.ret)
> > +		dev_info(pcie->dev, "failed to turn off PCIe #%u: %d\n",
> 
> Same here.

These are not fatal errors and are safe to ignore. dev_err() seemed too
strong for this. They also really shouldn't happen. Though I now realize
that's a bad argument, or rather, actually an argument for making them
dev_err() so that they do stand out if they really should happen.

> 
> > +			 pcie->ctl_id, msg.rx.ret);
> > +}
> > +
> > +static void tegra264_pcie_icc_set(struct tegra264_pcie *pcie)
> > +{
> > +	u32 value, speed, width, bw;
> > +	int err;
> > +
> > +	value = readw(pcie->ecam + XTL_RC_PCIE_CFG_LINK_STATUS);
> > +	speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, value);
> > +	width = FIELD_GET(PCI_EXP_LNKSTA_NLW, value);
> > +
> > +	bw = width * (PCIE_SPEED2MBS_ENC(speed) / BITS_PER_BYTE);
> > +	value = MBps_to_icc(bw);
> 
> So this becomes, 'width * (PCIE_SPEED2MBS_ENC(speed) / 8) * 1000 / 8'. But don't
> you want, 'width * (PCIE_SPEED2MBS_ENC(speed)) * 1000 / 8'?

This is M*B*ps_to_icc(), not M*b*ps_to_icc(), so we do in fact get the
latter. I almost fell for this as well because I got confused by some of
these macros being all-caps and other times the case actually mattering.

> > +	err = icc_set_bw(pcie->icc_path, bw, bw);
> > +	if (err < 0)
> > +		dev_err(pcie->dev,
> > +			"failed to request bandwidth (%u MBps): %pe\n",
> > +			bw, ERR_PTR(err));
> 
> So you don't want to error out if this fails?

No. This is not a fatal error and the system will continue to work,
albeit perhaps at suboptimal performance. Given that Ethernet and mass
storage are connected to these, a failure to set the bandwidth and
erroring out here may leave the system unusable, but continuing on would
let the system boot and update firmware, kernel or whatever to recover.

I'll add a comment explaining this.

[...]
> > +static void tegra264_pcie_init(struct tegra264_pcie *pcie)
> > +{
> > +	enum pci_bus_speed speed;
> > +	unsigned int i;
> > +	u32 value;
> > +
> > +	/* bring the link out of reset */
> 
> s/link/controller or endpoint?

This controls the PERST# signal, so I guess "endpoint" would be more
correct.

> > +	value = readl(pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
> > +	value |= XTL_RC_MGMT_PERST_CONTROL_PERST_O_N;
> > +	writel(value, pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
> > +
> > +	if (!tegra_is_silicon()) {
> 
> This looks like some pre-silicon validation thing. Do you really want it to be
> present in the upstream driver?

At this point there is silicon for this chip, but we've been trying to
get some of the pre-silicon code merged upstream as well because
occasionally people will want to run upstream on simulation, even after
silicon is available. At other times we may want to reuse these drivers
on future chips during pre-silicon validation.

Obviously there needs to be a balance. We don't want to have excessive
amounts of code specifically for pre-silicon validation, but in
relatively simple cases like this it is useful.

> 
> > +		dev_info(pcie->dev,
> > +			 "skipping link state for PCIe #%u in simulation\n",
> > +			 pcie->ctl_id);
> > +		pcie->link_up = true;
> > +		return;
> > +	}
> > +
> > +	for (i = 0; i < PCIE_LINK_WAIT_MAX_RETRIES; i++) {
> > +		if (tegra264_pcie_link_up(pcie, NULL))
> > +			break;
> > +
> > +		usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
> > +	}
> > +
> > +	if (tegra264_pcie_link_up(pcie, &speed)) {
> 
> Why are you doing it for the second time?

It's just a last-resort check to see if it's really not come up after
the retries. Also, in this call we're actually interested in retrieving
the detected link speed.

> 
> > +		/* Per PCIe r5.0, 6.6.1 wait for 100ms after DLL up */
> 
> No need of this comment.

Fair enough. This was perhaps more useful in earlier versions of the
patch before the line below used the standardize wait time.

[...]
> > +static int tegra264_pcie_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct pci_host_bridge *bridge;
> > +	struct tegra264_pcie *pcie;
> > +	struct resource_entry *bus;
> > +	struct resource *res;
> > +	int err;
> > +
> > +	bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct tegra264_pcie));
> > +	if (!bridge)
> > +		return dev_err_probe(dev, -ENOMEM,
> > +				     "failed to allocate host bridge\n");
> > +
> > +	pcie = pci_host_bridge_priv(bridge);
> > +	platform_set_drvdata(pdev, pcie);
> > +	pcie->bridge = bridge;
> > +	pcie->dev = dev;
> > +
> > +	err = pinctrl_pm_select_default_state(dev);
> 
> I questioned this before:
> https://lore.kernel.org/linux-pci/o5sxxdikdjwd76zsedvkpsl54nw6wrhopwsflt43y5st67mrub@uuw3yfjfqthd/

I'll remove this. Looks like we should be fine with just relying on the
default state being set by the pinctrl core. We might need to move it
into the resume callback.

> > +	if (err < 0)
> > +		return dev_err_probe(dev, err,
> > +				     "failed to configure sideband pins\n");
> > +
> > +	err = tegra264_pcie_parse_dt(pcie);
> > +	if (err < 0)
> > +		return dev_err_probe(dev, err, "failed to parse device tree");
> > +
> > +	pcie->xal = devm_platform_ioremap_resource_byname(pdev, "xal");
> > +	if (IS_ERR(pcie->xal))
> > +		return dev_err_probe(dev, PTR_ERR(pcie->xal),
> > +				     "failed to map XAL memory\n");
> > +
> > +	pcie->xtl = devm_platform_ioremap_resource_byname(pdev, "xtl-pri");
> > +	if (IS_ERR(pcie->xtl))
> > +		return dev_err_probe(dev, PTR_ERR(pcie->xtl),
> > +				     "failed to map XTL-PRI memory\n");
> > +
> > +	bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
> > +	if (!bus)
> > +		return dev_err_probe(dev, -ENODEV,
> > +				     "failed to get bus resources\n");
> > +
> > +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam");
> > +	if (!res)
> > +		return dev_err_probe(dev, -ENXIO,
> > +				     "failed to get ECAM resource\n");
> > +
> > +	pcie->icc_path = devm_of_icc_get(&pdev->dev, "write");
> > +	if (IS_ERR(pcie->icc_path))
> > +		return dev_err_probe(&pdev->dev, PTR_ERR(pcie->icc_path),
> > +				     "failed to get ICC");
> > +
> > +	/*
> > +	 * Parse BPMP property only for silicon, as interaction with BPMP is
> > +	 * not needed for other platforms.
> > +	 */
> > +	if (tegra_is_silicon()) {
> > +		pcie->bpmp = tegra_bpmp_get_with_id(dev, &pcie->ctl_id);
> > +		if (IS_ERR(pcie->bpmp))
> > +			return dev_err_probe(dev, PTR_ERR(pcie->bpmp),
> > +					     "failed to get BPMP\n");
> > +	}
> > +
> 
> pm_runtime_set_active()
> 
> > +	pm_runtime_enable(dev);
> 
> devm_pm_runtime_enable()?

Looks like I can even use devm_pm_runtime_set_active_enabled() to
combine the two.

> 
> > +	pm_runtime_get_sync(dev);
> > +
> > +	/* sanity check that programmed ranges match what's in DT */
> > +	if (!tegra264_pcie_check_ranges(pdev)) {
> > +		err = -EINVAL;
> > +		goto put_pm;
> > +	}
> > +
> > +	pcie->cfg = pci_ecam_create(dev, res, bus->res, &pci_generic_ecam_ops);
> > +	if (IS_ERR(pcie->cfg)) {
> > +		err = dev_err_probe(dev, PTR_ERR(pcie->cfg),
> > +				    "failed to create ECAM\n");
> > +		goto put_pm;
> > +	}
> > +
> > +	bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
> > +	bridge->sysdata = pcie->cfg;
> > +	pcie->ecam = pcie->cfg->win;
> > +
> > +	tegra264_pcie_init(pcie);
> > +
> > +	if (!pcie->link_up)
> > +		goto free;
> 
> goto free_ecam;

It's not clear to me, but are you suggesting to rename the existing
"free" label to "free_ecam"? I can do that.

> > +	err = pci_host_probe(bridge);
> > +	if (err < 0) {
> > +		dev_err(dev, "failed to register host: %pe\n", ERR_PTR(err));
> 
> dev_err_probe()

Okay.

> 
> > +		goto free;
> > +	}
> > +
> > +	return err;
> 
> return 0;

Done.

[...]
> > +static int tegra264_pcie_resume_noirq(struct device *dev)
> > +{
> > +	struct tegra264_pcie *pcie = dev_get_drvdata(dev);
> > +	int err;
> > +
> > +	if (pcie->wake_gpio && device_may_wakeup(dev)) {
> > +		err = disable_irq_wake(pcie->wake_irq);
> > +		if (err < 0)
> > +			dev_err(dev, "failed to disable wake IRQ: %pe\n",
> > +				ERR_PTR(err));
> > +	}
> > +
> > +	if (pcie->link_up == false)
> > +		return 0;
> > +
> > +	tegra264_pcie_init(pcie);
> > +
> 
> Why do you need init() here without deinit() in tegra264_pcie_suspend_noirq()?

That's because when we come out of suspend the link may have gone down
again, so we need to take the endpoint out of reset to retrigger the
link training. I think we could possibly explicitly clear that PERST_O_N
bit in the PERST_CONTROL register in a new tegra264_pcie_deinit() to
mirror what tegra264_pcie_init() does, but it's automatically done by
firmware anyway, so not needed.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [PATCH] drm/tegra: rgb: Fix use-after-free and leak in tegra_dc_rgb_probe()
From: Wentao Liang @ 2026-04-07  8:46 UTC (permalink / raw)
  To: Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
	Jonathan Hunter
  Cc: dri-devel, linux-tegra, linux-kernel, Wentao Liang, stable

Move the of_device_is_available() check before devm_add_action_or_reset()
to avoid using np after it may have been freed (if the action registration
fails). Also release np immediately when the device is not available to
prevent a reference leak.

Fixes: 3c3642335065 ("drm/tegra: rgb: Fix the unbound reference count")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 drivers/gpu/drm/tegra/rgb.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index ff5a749710db..d7586fc820ce 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -215,13 +215,15 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
 	if (!np)
 		return -ENODEV;
 
+	if (!of_device_is_available(np)) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
 	err = devm_add_action_or_reset(dc->dev, tegra_dc_of_node_put, np);
 	if (err < 0)
 		return err;
 
-	if (!of_device_is_available(np))
-		return -ENODEV;
-
 	rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
 	if (!rgb)
 		return -ENOMEM;
-- 
2.34.1


^ permalink raw reply related

* Re: [GIT PULL] PCI: tegra: Changes for v7.1-rc1
From: Thierry Reding @ 2026-04-07  8:28 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, linux-pci, linux-tegra
In-Reply-To: <lduiidifejglrep2laxzk2hep5rxpm3ysz5cwhdsglf6ciyjp4@z2dmnlvi7nhi>

[-- Attachment #1: Type: text/plain, Size: 2130 bytes --]

On Thu, Apr 02, 2026 at 10:29:34PM +0530, Manivannan Sadhasivam wrote:
> On Thu, Apr 02, 2026 at 01:56:48PM +0200, Thierry Reding wrote:
> > On Sun, Mar 29, 2026 at 05:50:39PM +0200, Thierry Reding wrote:
> > > From: Thierry Reding <thierry.reding@gmail.com>
> > > 
> > > Hi Lorenzo, Bjorn,
> > > 
> > > The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
> > > 
> > >   Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
> > > 
> > > are available in the Git repository at:
> > > 
> > >   git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-7.1-pci
> > > 
> > > for you to fetch changes up to a0c0906bb09ee2f64690b3b8ffb458b4dbbcb26e:
> > > 
> > >   PCI: tegra: Add Tegra264 support (2026-03-28 15:00:05 +0100)
> > > 
> > > This is v3 of the Tegra264 PCI patches that can be found here:
> > > 
> > >   https://lore.kernel.org/linux-pci/20260326135855.2795149-1-thierry.reding@kernel.org/
> > > 
> > > This looks ready now, but if there's any more feedback, I will happily
> > > respin these driver patches.
> > > 
> > > Note that the shortlog and the diffstat below include the dependencies
> > > from the Tegra tree, and that subset will go in through the ARM SoC tree
> > > as well. Effectively what's new in this pull request is just the two PCI
> > > patches, the rest is only included here to resolve the build time
> > > dependencies.
> > 
> > I'm retracting this PR. DT maintainers aren't happy about how I handled
> > this, so it'll have to wait for another release cycle.
> > 
> 
> JFYI, We don't pull from PCI patches from other trees. We only merge them by
> ourselves.

To clarify this again: the build dependencies are non-trivial and they
can't all go through the PCI tree because there are dependencies with at
least the Tegra tree, hence why a shared branch seemed the best solution
in this case.

But I guess this is all too complicated for everyone involved, so we'll
just try to get in the build dependencies for 7.1 and then defer the PCI
driver until 7.2. That way everyone can follow their standard process.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH 1/2] Revert "arm64: tegra: Disable ISO SMMU for Tegra194"
From: Thierry Reding @ 2026-04-07  8:16 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: Aaron Kling, Thierry Reding, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Hunter, devicetree, linux-tegra,
	linux-kernel
In-Reply-To: <oPjOdaRsQES6O8jgrehMZw@nvidia.com>

[-- Attachment #1: Type: text/plain, Size: 9789 bytes --]

On Tue, Apr 07, 2026 at 01:09:10PM +0900, Mikko Perttunen wrote:
> On Monday, April 6, 2026 4:49 PM Aaron Kling wrote:
> > On Tue, Feb 17, 2026 at 4:13 AM Thierry Reding
> > <thierry.reding@kernel.org> wrote:
> > >
> > > On Tue, Feb 17, 2026 at 12:53:54PM +0900, Mikko Perttunen wrote:
> > > > On Thursday, January 22, 2026 7:22 PM Mikko Perttunen wrote:
> > > > > On Tuesday, December 9, 2025 1:21 PM Aaron Kling wrote:
> > > > > > On Mon, Nov 3, 2025 at 12:05 PM Aaron Kling <webgeek1234@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, Nov 3, 2025 at 5:07 AM Thierry Reding <thierry.reding@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Sat, Nov 01, 2025 at 06:13:26PM -0500, Aaron Kling wrote:
> > > > > > > > > On Sat, Nov 1, 2025 at 6:01 PM Aaron Kling via B4 Relay
> > > > > > > > > <devnull+webgeek1234.gmail.com@kernel.org> wrote:
> > > > > > > > > >
> > > > > > > > > > From: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > > > >
> > > > > > > > > > This reverts commit ebea268ea583ba4970df425dfef8c8e21d0a4e12.
> > > > > > > > > >
> > > > > > > > > > Mmu is now being enabled for the display controllers.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > > > > ---
> > > > > > > > > >  arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +-
> > > > > > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > > > > >
> > > > > > > > > > diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > > index 1399342f23e1c4f73b278adc66dfb948fc30d326..854ed6d46aa1d8eedcdfbae1fdde1374adf40337 100644
> > > > > > > > > > --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > > +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > > @@ -1807,7 +1807,7 @@ iommu@10000000 {
> > > > > > > > > >                         #iommu-cells = <1>;
> > > > > > > > > >
> > > > > > > > > >                         nvidia,memory-controller = <&mc>;
> > > > > > > > > > -                       status = "disabled";
> > > > > > > > > > +                       status = "okay";
> > > > > > > > > >                 };
> > > > > > > > > >
> > > > > > > > > >                 smmu: iommu@12000000 {
> > > > > > > > > >
> > > > > > > > > > --
> > > > > > > > > > 2.51.0
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > Question for Jon as the author of the commit being reverted. The
> > > > > > > > > commit message states "we do not have a way to pass frame-buffer
> > > > > > > > > memory from the bootloader to the kernel". If I understand this
> > > > > > > > > correctly, this is talking about seamless handoff. What does this have
> > > > > > > > > to do with enabling mmu on the display controllers? Seamless does not
> > > > > > > > > work on any tegra arch as far as I'm aware, but Tegra194 is the only
> > > > > > > > > one that doesn't have mmu enabled for the dc's. But enabling mmu
> > > > > > > > > allows for better and faster memory allocation. My initial attempts to
> > > > > > > > > enable this didn't work because I tried to attach them to the main mmu
> > > > > > > > > unit, see the related freedesktop issue [0]. After noticing in the
> > > > > > > > > downstream dt that the dc's are on a separate unit, I made it work.
> > > > > > > > > And so far, it seems to work just as well as Tegra186. Then when I was
> > > > > > > > > packaging up the change to submit, I found that this had been
> > > > > > > > > explicitly disabled. But I'm not seeing why. Am I missing some
> > > > > > > > > additional factors?
> > > > > > > >
> > > > > > > > This isn't seamless handoff to the Tegra DRM driver for display, but
> > > > > > > > rather to simple-framebuffer. While this does technically work, it also
> > > > > > > > causes a spew of SMMU faults during early boot because the firmware does
> > > > > > > > not properly pass the SMMU mapping information to the kernel.
> > > > > > > >
> > > > > > > > In a nutshell what happens is that the firmware sets up the display
> > > > > > > > controller to scan out from a reserved memory region, but it does so
> > > > > > > > without involving the SMMU, so it uses physical addresses directly. When
> > > > > > > > the kernel boots and the SMMU is enabled the continued accesses from
> > > > > > > > display hardware cause SMMU faults (because there is no mapping for the
> > > > > > > > framebuffer addresses).
> > > > > > > >
> > > > > > > > That said, we did solve these issues and this may not be happening
> > > > > > > > anymore with the most recent L4T releases, so it may be okay to revert
> > > > > > > > this now. We should find out exactly which release includes all the
> > > > > > > > needed changes so that it can be referenced in the commit message. I
> > > > > > > > want to avoid people running new kernels with an old L4T release and
> > > > > > > > then seeing these errors without any reference as to why that might
> > > > > > > > suddenly happen.
> > > > > > >
> > > > > > > For reference, I have rolled back my Android usecase to use the L4T
> > > > > > > r32.7.6 bootloaders on T194 for a variety of reasons. So I am using
> > > > > > > cboot as the final bootloader and not edk2 as in L4T r34/r35. I have a
> > > > > > > pending cboot patch to support simple-framebuffer handoff, but haven't
> > > > > > > fully verified it as tegra-drm is currently unable to takeover from
> > > > > > > simplefb like openrm does for t234. But all that to say that since I
> > > > > > > no longer use r35 for t194 I don't have the setup to easily verify
> > > > > > > which point release works here and what doesn't.
> > > > > >
> > > > > > Any further thoughts on this patch?
> > > > > >
> > > > > > Aaron
> > > > >
> > > > > FWIW,
> > > > >
> > > > > looks like the edk2 patch to update iommu-addresses --
> > > > >
> > > > > commit 6071946461389221d2314cbbae0377610b5b1f6a
> > > > > Author: Jan Bobek <jbobek@nvidia.com>
> > > > > Date:   Tue Mar 21 00:15:27 2023 +0000
> > > > >
> > > > >     feat(NvDisplayControllerDxe): update FDT with framebuffer info
> > > > >
> > > > >     On ready-to-boot and whenever FDT is installed, update FDT with
> > > > >     framebuffer mode information, base address and size.
> > > > >
> > > > >     Signed-off-by: Jan Bobek <jbobek@nvidia.com>
> > > > >     Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com>
> > > > >
> > > > > is in since r36.2
> > > > >
> > > > > $ git tag --contains 6071946461389221d2314cbbae0377610b5b1f6a | grep "^r"
> > > > > r36.2
> > > > > r36.3.0
> > > > > r36.4.0
> > > > > r36.4.3
> > > > > r36.4.4
> > > > > r36.4.5
> > > > > r38.2
> > > > > r38.4
> > > > >
> > > > > Not so good for T194 since r36 only supports Orin.
> > > > >
> > > > > I'll look into getting this cherry-picked to r35.
> > > > >
> > > > > Mikko
> > > > >
> > > > >
> > > >
> > > > I looked into this and it appears a version of this is in r35, but it
> > > > only supports T234. However, I also found that at one point, L4T
> > > > bootloader configuration has been modified to place the display
> > > > controllers into SMMU bypass until otherwise configured by the kernel
> > > > -- which the kernel does in tegra_mc_probe_device.
> > > >
> > > > I think that means there is still potential for an issue where the
> > > > display continues to be on between tegra_mc_probe_device and tegradrm
> > > > reconfiguring it. However, I cannot reproduce that happening -- most
> > > > likely the display is being turned off before that because of a clock
> > > > or power domain being turned off.
> > > >
> > > > In any case, this means that we no longer need to pass the
> > > > framebuffer's information to the kernel. I think it would be good to
> > > > have some clarity to ensure the issue described above cannot happen,
> > > > but otherwise we should be able to enable IOMMU.
> > >
> > > The problem would happen if you enable some sort of early framebuffer
> > > support, such as simple-drm or simple-framebuffer. Maybe even efifb. I
> > > think it'd still be worth getting the iommu-addresses code into r35 if
> > > for nothing else but to have a bit more of a safety buffer for the
> > > future.
> > >
> > > If we don't and for some reason decide that we want early framebuffer
> > > support, it might be too late to get UEFI updated for Tegra194. I recall
> > > that the UEFI code for Tegra194 is different from the one for Tegra234,
> > > so it is probably not as trivial as a simple cherry-pick, but I'll try
> > > to do some digging and find the code that does this for Xavier.
> > 
> > Any updates on this?
> 
> FWIW, in my testing with L4T versions with UEFI firmware, I'm not seeing 
> any issues even if efifb is enabled. My inclination would be to merge, 
> and we can work on issues related to early framebuffer separately.
> 
> Outside adding support to r35, one option is to make it so TegraDRM has 
> to explicitly call tegra_mc_probe_device (not necessarily directly) when 
> it has quiesced the hardware during probe. This would not allow seamless 
> early framebuffer transition, but otherwise it should work. Implementing 
> this for tegra-smmu would also allow us to get rid of the IOMMU API 
> paths in TegraDRM and Host1x, which would be a great boon.

I did most of this work a long time ago and L4T just wasn't ready yet to
make use of all this cleanup potential. We can probably go find most of
the code and it might still be largely applicable.

It's a bit disappointing that this didn't go anywhere for the longest
time and all of a sudden most of it just seems to be irrelevant.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v4] drm/tegra: Enable cmu for Tegra186 and Tegra194
From: Mikko Perttunen @ 2026-04-07  7:56 UTC (permalink / raw)
  To: Thierry Reding, David Airlie, Simona Vetter, Jonathan Hunter,
	Thierry Reding, webgeek1234
  Cc: dri-devel, linux-tegra, linux-kernel, Kurt Kiefer, Aaron Kling,
	Jasper Korten
In-Reply-To: <20260407-tegra-drm-cmu-v4-1-2fe95f305afd@gmail.com>

On Tuesday, April 7, 2026 4:09 PM Aaron Kling via B4 Relay wrote:
> From: Aaron Kling <webgeek1234@gmail.com>
> 
> Without the cmu, nvdisplay will display colors that are notably darker
> than intended. The vendor bootloader and the downstream display driver
> enable the cmu and sets a sRGB table. Loading that table here results in
> the intended colors.
> 
> Co-developed-by: Kurt Kiefer <kekiefer@gmail.com>
> Signed-off-by: Kurt Kiefer <kekiefer@gmail.com>
> Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> Tested-by: Jasper Korten <jja2000@gmail.com>
> ---
> Changes in v4:
> - Add missing signoff
> - Rename cmu phys var to be more clear
> - Remove redundant lut null check
> - Link to v3: https://lore.kernel.org/r/20260406-tegra-drm-cmu-v3-1-dfcb1dda4ad6@gmail.com
> 
> Changes in v3:
> - Remove improper IOVA null check
> - Use dmam_alloc_coherent instead of manually tracking memory
> - Address other review comments
> - Link to v2: https://lore.kernel.org/r/20260202-tegra-drm-cmu-v2-1-a1bcb37f3e85@gmail.com
> 
> Changes in v2:
> - Several formatting changes per v1 review
> - Move cmu alloc/free to dc, where it can be handled in probe/remove
> - Enable cmu for displayport as well
> - Link to v1: https://lore.kernel.org/r/20251101-tegra-drm-cmu-v1-1-211799755ab8@gmail.com
> ---
>  drivers/gpu/drm/tegra/dc.c  | 116 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/tegra/dc.h  |  13 +++++
>  drivers/gpu/drm/tegra/sor.c |  25 ++++++++++
>  3 files changed, 154 insertions(+)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index 06370b7e0e5678..0e74c4cd5dc4b1 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -36,6 +36,103 @@
>  #include "hub.h"
>  #include "plane.h"
>  
> +static const u16 default_srgb_lut[] = {
> +	0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
> +	0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
> +	0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
> +	0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
> +	0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
> +	0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
> +	0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
> +	0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
> +	0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
> +	0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
> +	0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
> +	0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
> +	0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
> +	0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
> +	0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
> +	0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
> +	0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
> +	0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
> +	0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
> +	0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
> +	0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
> +	0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
> +	0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
> +	0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
> +	0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
> +	0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
> +	0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
> +	0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
> +	0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
> +	0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
> +	0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
> +	0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
> +	0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
> +	0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
> +	0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
> +	0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
> +	0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
> +	0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
> +	0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
> +	0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
> +	0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
> +	0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
> +	0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
> +	0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
> +	0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
> +	0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
> +	0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
> +	0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
> +	0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
> +	0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
> +	0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
> +	0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
> +	0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
> +	0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
> +	0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
> +	0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
> +	0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
> +	0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
> +	0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
> +	0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
> +	0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
> +	0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
> +	0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
> +	0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
> +	0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
> +	0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
> +	0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
> +	0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
> +	0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
> +	0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
> +	0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
> +	0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
> +	0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
> +	0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
> +	0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
> +	0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
> +	0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
> +	0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
> +	0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
> +	0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
> +	0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
> +	0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
> +	0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
> +	0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
> +	0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
> +	0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
> +	0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
> +	0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
> +	0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
> +	0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
> +	0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
> +	0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
> +	0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
> +	0x9FF7, 0x9FFF,
> +};
> +
>  static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
>  					    struct drm_crtc_state *state);
>  
> @@ -3251,6 +3348,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
>  	if (dc->irq < 0)
>  		return -ENXIO;
>  
> +	if (dc->soc->has_nvdisplay) {
> +		unsigned int i;
> +		u64 r;
> +
> +		dc->cmu_output_lut =
> +			dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
> +					    &dc->cmu_output_lut_phys, GFP_KERNEL);
> +
> +		if (!dc->cmu_output_lut) {
> +			dev_err(dc->dev, "failed to allocate lut for cmu\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
> +			r = default_srgb_lut[i];
> +			dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
> +		}
> +	}
> +
>  	err = tegra_dc_rgb_probe(dc);
>  	if (err < 0 && err != -ENODEV)
>  		return dev_err_probe(&pdev->dev, err,
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 0559fa6b1bf704..e42c0b5a00b242 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -103,6 +103,9 @@ struct tegra_dc {
>  	const struct tegra_dc_soc_info *soc;
>  
>  	bool has_opp_table;
> +
> +	u64 *cmu_output_lut;
> +	dma_addr_t cmu_output_lut_phys;
>  };
>  
>  static inline struct tegra_dc *
> @@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
>  #define BASE_COLOR_SIZE_888    (  8 << 0)
>  #define BASE_COLOR_SIZE_101010 ( 10 << 0)
>  #define BASE_COLOR_SIZE_121212 ( 12 << 0)
> +#define CMU_ENABLE_ENABLE      (1 << 20)
>  
>  #define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431
>  #define  SC1_H_QUALIFIER_NONE	(1 << 16)
> @@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
>  #define PROTOCOL_MASK (0xf << 8)
>  #define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
>  
> +#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT	0x431
> +#define  OUTPUT_LUT_MODE_MASK        (3 << 5)
> +#define  OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
> +#define  OUTPUT_LUT_SIZE_MASK        (3 << 1)
> +#define  OUTPUT_LUT_SIZE_SIZE_1025   (2 << 1)
> +
> +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE	0x432
> +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI	0x433
> +
>  #define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR	0x442
>  #define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR	0x446
>  
> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> index de8b2dfc4984c4..98828c9e09f425 100644
> --- a/drivers/gpu/drm/tegra/sor.c
> +++ b/drivers/gpu/drm/tegra/sor.c
> @@ -2557,6 +2557,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
>  	value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
>  	value &= ~DITHER_CONTROL_MASK;
>  	value &= ~BASE_COLOR_SIZE_MASK;
> +	if (dc->soc->has_nvdisplay) {
> +		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
> +				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> +		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
> +				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
> +
> +		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
> +				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
> +
> +		value |= CMU_ENABLE_ENABLE;
> +	}
>  
>  	switch (state->bpc) {
>  	case 6:
> @@ -2921,6 +2932,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
>  	if (err < 0)
>  		dev_err(sor->dev, "failed to attach SOR: %d\n", err);
>  
> +	if (dc->soc->has_nvdisplay) {
> +		value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
> +		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
> +				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> +		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
> +				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
> +
> +		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
> +				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
> +
> +		value |= CMU_ENABLE_ENABLE;
> +		tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
> +	}
> +
>  	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
>  	value |= SOR_ENABLE(sor->index);
>  	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
> 
> ---
> base-commit: 2febe6e6ee6e34c7754eff3c4d81aa7b0dcb7979
> change-id: 20251031-tegra-drm-cmu-697e8e030978
> 
> Best regards,
> -- 
> Aaron Kling <webgeek1234@gmail.com>
> 
> 
> 

Thank you!

Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Tested-by: Mikko Perttunen <mperttunen@nvidia.com> # Jetson AGX Xavier




^ permalink raw reply

* [PATCH v4] drm/tegra: Enable cmu for Tegra186 and Tegra194
From: Aaron Kling via B4 Relay @ 2026-04-07  7:09 UTC (permalink / raw)
  To: Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
	Jonathan Hunter, Thierry Reding
  Cc: dri-devel, linux-tegra, linux-kernel, Kurt Kiefer, Aaron Kling,
	Jasper Korten

From: Aaron Kling <webgeek1234@gmail.com>

Without the cmu, nvdisplay will display colors that are notably darker
than intended. The vendor bootloader and the downstream display driver
enable the cmu and sets a sRGB table. Loading that table here results in
the intended colors.

Co-developed-by: Kurt Kiefer <kekiefer@gmail.com>
Signed-off-by: Kurt Kiefer <kekiefer@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
Tested-by: Jasper Korten <jja2000@gmail.com>
---
Changes in v4:
- Add missing signoff
- Rename cmu phys var to be more clear
- Remove redundant lut null check
- Link to v3: https://lore.kernel.org/r/20260406-tegra-drm-cmu-v3-1-dfcb1dda4ad6@gmail.com

Changes in v3:
- Remove improper IOVA null check
- Use dmam_alloc_coherent instead of manually tracking memory
- Address other review comments
- Link to v2: https://lore.kernel.org/r/20260202-tegra-drm-cmu-v2-1-a1bcb37f3e85@gmail.com

Changes in v2:
- Several formatting changes per v1 review
- Move cmu alloc/free to dc, where it can be handled in probe/remove
- Enable cmu for displayport as well
- Link to v1: https://lore.kernel.org/r/20251101-tegra-drm-cmu-v1-1-211799755ab8@gmail.com
---
 drivers/gpu/drm/tegra/dc.c  | 116 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/dc.h  |  13 +++++
 drivers/gpu/drm/tegra/sor.c |  25 ++++++++++
 3 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 06370b7e0e5678..0e74c4cd5dc4b1 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -36,6 +36,103 @@
 #include "hub.h"
 #include "plane.h"
 
+static const u16 default_srgb_lut[] = {
+	0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
+	0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
+	0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
+	0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
+	0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
+	0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
+	0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
+	0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
+	0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
+	0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
+	0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
+	0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
+	0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
+	0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
+	0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
+	0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
+	0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
+	0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
+	0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
+	0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
+	0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
+	0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
+	0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
+	0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
+	0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
+	0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
+	0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
+	0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
+	0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
+	0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
+	0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
+	0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
+	0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
+	0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
+	0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
+	0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
+	0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
+	0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
+	0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
+	0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
+	0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
+	0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
+	0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
+	0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
+	0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
+	0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
+	0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
+	0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
+	0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
+	0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
+	0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
+	0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
+	0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
+	0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
+	0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
+	0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
+	0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
+	0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
+	0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
+	0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
+	0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
+	0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
+	0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
+	0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
+	0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
+	0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
+	0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
+	0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
+	0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
+	0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
+	0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
+	0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
+	0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
+	0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
+	0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
+	0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
+	0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
+	0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
+	0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
+	0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
+	0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
+	0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
+	0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
+	0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
+	0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
+	0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
+	0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
+	0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
+	0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
+	0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
+	0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
+	0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
+	0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
+	0x9FF7, 0x9FFF,
+};
+
 static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 					    struct drm_crtc_state *state);
 
@@ -3251,6 +3348,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
 	if (dc->irq < 0)
 		return -ENXIO;
 
+	if (dc->soc->has_nvdisplay) {
+		unsigned int i;
+		u64 r;
+
+		dc->cmu_output_lut =
+			dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
+					    &dc->cmu_output_lut_phys, GFP_KERNEL);
+
+		if (!dc->cmu_output_lut) {
+			dev_err(dc->dev, "failed to allocate lut for cmu\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
+			r = default_srgb_lut[i];
+			dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
+		}
+	}
+
 	err = tegra_dc_rgb_probe(dc);
 	if (err < 0 && err != -ENODEV)
 		return dev_err_probe(&pdev->dev, err,
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 0559fa6b1bf704..e42c0b5a00b242 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -103,6 +103,9 @@ struct tegra_dc {
 	const struct tegra_dc_soc_info *soc;
 
 	bool has_opp_table;
+
+	u64 *cmu_output_lut;
+	dma_addr_t cmu_output_lut_phys;
 };
 
 static inline struct tegra_dc *
@@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
 #define BASE_COLOR_SIZE_888    (  8 << 0)
 #define BASE_COLOR_SIZE_101010 ( 10 << 0)
 #define BASE_COLOR_SIZE_121212 ( 12 << 0)
+#define CMU_ENABLE_ENABLE      (1 << 20)
 
 #define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431
 #define  SC1_H_QUALIFIER_NONE	(1 << 16)
@@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
 #define PROTOCOL_MASK (0xf << 8)
 #define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
 
+#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT	0x431
+#define  OUTPUT_LUT_MODE_MASK        (3 << 5)
+#define  OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
+#define  OUTPUT_LUT_SIZE_MASK        (3 << 1)
+#define  OUTPUT_LUT_SIZE_SIZE_1025   (2 << 1)
+
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE	0x432
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI	0x433
+
 #define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR	0x442
 #define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR	0x446
 
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index de8b2dfc4984c4..98828c9e09f425 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -2557,6 +2557,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
 	value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
 	value &= ~DITHER_CONTROL_MASK;
 	value &= ~BASE_COLOR_SIZE_MASK;
+	if (dc->soc->has_nvdisplay) {
+		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
+		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
+
+		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
+				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
+
+		value |= CMU_ENABLE_ENABLE;
+	}
 
 	switch (state->bpc) {
 	case 6:
@@ -2921,6 +2932,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
 	if (err < 0)
 		dev_err(sor->dev, "failed to attach SOR: %d\n", err);
 
+	if (dc->soc->has_nvdisplay) {
+		value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
+		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
+		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
+
+		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
+				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
+
+		value |= CMU_ENABLE_ENABLE;
+		tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
+	}
+
 	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
 	value |= SOR_ENABLE(sor->index);
 	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);

---
base-commit: 2febe6e6ee6e34c7754eff3c4d81aa7b0dcb7979
change-id: 20251031-tegra-drm-cmu-697e8e030978

Best regards,
-- 
Aaron Kling <webgeek1234@gmail.com>



^ permalink raw reply related

* Re: [PATCH v3] drm/tegra: Enable cmu for Tegra186 and Tegra194
From: Mikko Perttunen @ 2026-04-07  4:59 UTC (permalink / raw)
  To: Aaron Kling
  Cc: Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
	Jonathan Hunter, Thierry Reding, dri-devel, linux-tegra,
	linux-kernel, Kurt Kiefer, Jasper Korten
In-Reply-To: <20260406-tegra-drm-cmu-v3-1-dfcb1dda4ad6@gmail.com>

On Mon, 06 Apr 2026 02:47:31 -0500, Aaron Kling <webgeek1234@gmail.com> wrote:
> Without the cmu, nvdisplay will display colors that are notably darker
> than intended. The vendor bootloader and the downstream display driver
> enable the cmu and sets a sRGB table. Loading that table here results in
> the intended colors.
> 
> Co-developed-by: Kurt Kiefer <kekiefer@gmail.com>

You need to include a Signed-off-by with each Co-developed-by tag.
From submitting-patches.rst:

    Co-developed-by: states that the patch was co-created by multiple developers;
    it is used to give attribution to co-authors (in addition to the author
    attributed by the From: tag) when several people work on a single patch.  Since
    Co-developed-by: denotes authorship, every Co-developed-by: must be immediately
    followed by a Signed-off-by: of the associated co-author.

checkpatch.pl should also flag this.

>
>
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 0559fa6b1bf7..973ab0bb15c9 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -103,6 +103,9 @@ struct tegra_dc {
>  	const struct tegra_dc_soc_info *soc;
>  
>  	bool has_opp_table;
> +
> +	u64 *cmu_output_lut;
> +	dma_addr_t cmu_output_phys;

I think 'cmu_output_lut_phys' would be slightly clearer.

>
> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> index de8b2dfc4984..78e71a3ff026 100644
> --- a/drivers/gpu/drm/tegra/sor.c
> +++ b/drivers/gpu/drm/tegra/sor.c
> @@ -2557,6 +2557,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
>  	value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
>  	value &= ~DITHER_CONTROL_MASK;
>  	value &= ~BASE_COLOR_SIZE_MASK;
> +	if (dc->soc->has_nvdisplay && dc->cmu_output_lut) {

Checking for cmu_output_lut not being NULL shouldn't be necessary,
since we fail probe if it's NULL. (Checking here gives the impression
it might be NULL).

Otherwise looks good to me. Main thing is the trailers in the commit
message.

Thanks!
Mikko

-- 


^ permalink raw reply

* Re: [PATCH 1/2] Revert "arm64: tegra: Disable ISO SMMU for Tegra194"
From: Mikko Perttunen @ 2026-04-07  4:09 UTC (permalink / raw)
  To: Thierry Reding, Aaron Kling
  Cc: Thierry Reding, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Hunter, devicetree, linux-tegra, linux-kernel
In-Reply-To: <CALHNRZ8Zs2Zp80OgoU6R54=n76JgiYGbMvWD2iP9HpUFYO2big@mail.gmail.com>

On Monday, April 6, 2026 4:49 PM Aaron Kling wrote:
> On Tue, Feb 17, 2026 at 4:13 AM Thierry Reding
> <thierry.reding@kernel.org> wrote:
> >
> > On Tue, Feb 17, 2026 at 12:53:54PM +0900, Mikko Perttunen wrote:
> > > On Thursday, January 22, 2026 7:22 PM Mikko Perttunen wrote:
> > > > On Tuesday, December 9, 2025 1:21 PM Aaron Kling wrote:
> > > > > On Mon, Nov 3, 2025 at 12:05 PM Aaron Kling <webgeek1234@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, Nov 3, 2025 at 5:07 AM Thierry Reding <thierry.reding@gmail.com> wrote:
> > > > > > >
> > > > > > > On Sat, Nov 01, 2025 at 06:13:26PM -0500, Aaron Kling wrote:
> > > > > > > > On Sat, Nov 1, 2025 at 6:01 PM Aaron Kling via B4 Relay
> > > > > > > > <devnull+webgeek1234.gmail.com@kernel.org> wrote:
> > > > > > > > >
> > > > > > > > > From: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > > >
> > > > > > > > > This reverts commit ebea268ea583ba4970df425dfef8c8e21d0a4e12.
> > > > > > > > >
> > > > > > > > > Mmu is now being enabled for the display controllers.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > > > ---
> > > > > > > > >  arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +-
> > > > > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > > > >
> > > > > > > > > diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > index 1399342f23e1c4f73b278adc66dfb948fc30d326..854ed6d46aa1d8eedcdfbae1fdde1374adf40337 100644
> > > > > > > > > --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > > @@ -1807,7 +1807,7 @@ iommu@10000000 {
> > > > > > > > >                         #iommu-cells = <1>;
> > > > > > > > >
> > > > > > > > >                         nvidia,memory-controller = <&mc>;
> > > > > > > > > -                       status = "disabled";
> > > > > > > > > +                       status = "okay";
> > > > > > > > >                 };
> > > > > > > > >
> > > > > > > > >                 smmu: iommu@12000000 {
> > > > > > > > >
> > > > > > > > > --
> > > > > > > > > 2.51.0
> > > > > > > > >
> > > > > > > > >
> > > > > > > >
> > > > > > > > Question for Jon as the author of the commit being reverted. The
> > > > > > > > commit message states "we do not have a way to pass frame-buffer
> > > > > > > > memory from the bootloader to the kernel". If I understand this
> > > > > > > > correctly, this is talking about seamless handoff. What does this have
> > > > > > > > to do with enabling mmu on the display controllers? Seamless does not
> > > > > > > > work on any tegra arch as far as I'm aware, but Tegra194 is the only
> > > > > > > > one that doesn't have mmu enabled for the dc's. But enabling mmu
> > > > > > > > allows for better and faster memory allocation. My initial attempts to
> > > > > > > > enable this didn't work because I tried to attach them to the main mmu
> > > > > > > > unit, see the related freedesktop issue [0]. After noticing in the
> > > > > > > > downstream dt that the dc's are on a separate unit, I made it work.
> > > > > > > > And so far, it seems to work just as well as Tegra186. Then when I was
> > > > > > > > packaging up the change to submit, I found that this had been
> > > > > > > > explicitly disabled. But I'm not seeing why. Am I missing some
> > > > > > > > additional factors?
> > > > > > >
> > > > > > > This isn't seamless handoff to the Tegra DRM driver for display, but
> > > > > > > rather to simple-framebuffer. While this does technically work, it also
> > > > > > > causes a spew of SMMU faults during early boot because the firmware does
> > > > > > > not properly pass the SMMU mapping information to the kernel.
> > > > > > >
> > > > > > > In a nutshell what happens is that the firmware sets up the display
> > > > > > > controller to scan out from a reserved memory region, but it does so
> > > > > > > without involving the SMMU, so it uses physical addresses directly. When
> > > > > > > the kernel boots and the SMMU is enabled the continued accesses from
> > > > > > > display hardware cause SMMU faults (because there is no mapping for the
> > > > > > > framebuffer addresses).
> > > > > > >
> > > > > > > That said, we did solve these issues and this may not be happening
> > > > > > > anymore with the most recent L4T releases, so it may be okay to revert
> > > > > > > this now. We should find out exactly which release includes all the
> > > > > > > needed changes so that it can be referenced in the commit message. I
> > > > > > > want to avoid people running new kernels with an old L4T release and
> > > > > > > then seeing these errors without any reference as to why that might
> > > > > > > suddenly happen.
> > > > > >
> > > > > > For reference, I have rolled back my Android usecase to use the L4T
> > > > > > r32.7.6 bootloaders on T194 for a variety of reasons. So I am using
> > > > > > cboot as the final bootloader and not edk2 as in L4T r34/r35. I have a
> > > > > > pending cboot patch to support simple-framebuffer handoff, but haven't
> > > > > > fully verified it as tegra-drm is currently unable to takeover from
> > > > > > simplefb like openrm does for t234. But all that to say that since I
> > > > > > no longer use r35 for t194 I don't have the setup to easily verify
> > > > > > which point release works here and what doesn't.
> > > > >
> > > > > Any further thoughts on this patch?
> > > > >
> > > > > Aaron
> > > >
> > > > FWIW,
> > > >
> > > > looks like the edk2 patch to update iommu-addresses --
> > > >
> > > > commit 6071946461389221d2314cbbae0377610b5b1f6a
> > > > Author: Jan Bobek <jbobek@nvidia.com>
> > > > Date:   Tue Mar 21 00:15:27 2023 +0000
> > > >
> > > >     feat(NvDisplayControllerDxe): update FDT with framebuffer info
> > > >
> > > >     On ready-to-boot and whenever FDT is installed, update FDT with
> > > >     framebuffer mode information, base address and size.
> > > >
> > > >     Signed-off-by: Jan Bobek <jbobek@nvidia.com>
> > > >     Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com>
> > > >
> > > > is in since r36.2
> > > >
> > > > $ git tag --contains 6071946461389221d2314cbbae0377610b5b1f6a | grep "^r"
> > > > r36.2
> > > > r36.3.0
> > > > r36.4.0
> > > > r36.4.3
> > > > r36.4.4
> > > > r36.4.5
> > > > r38.2
> > > > r38.4
> > > >
> > > > Not so good for T194 since r36 only supports Orin.
> > > >
> > > > I'll look into getting this cherry-picked to r35.
> > > >
> > > > Mikko
> > > >
> > > >
> > >
> > > I looked into this and it appears a version of this is in r35, but it
> > > only supports T234. However, I also found that at one point, L4T
> > > bootloader configuration has been modified to place the display
> > > controllers into SMMU bypass until otherwise configured by the kernel
> > > -- which the kernel does in tegra_mc_probe_device.
> > >
> > > I think that means there is still potential for an issue where the
> > > display continues to be on between tegra_mc_probe_device and tegradrm
> > > reconfiguring it. However, I cannot reproduce that happening -- most
> > > likely the display is being turned off before that because of a clock
> > > or power domain being turned off.
> > >
> > > In any case, this means that we no longer need to pass the
> > > framebuffer's information to the kernel. I think it would be good to
> > > have some clarity to ensure the issue described above cannot happen,
> > > but otherwise we should be able to enable IOMMU.
> >
> > The problem would happen if you enable some sort of early framebuffer
> > support, such as simple-drm or simple-framebuffer. Maybe even efifb. I
> > think it'd still be worth getting the iommu-addresses code into r35 if
> > for nothing else but to have a bit more of a safety buffer for the
> > future.
> >
> > If we don't and for some reason decide that we want early framebuffer
> > support, it might be too late to get UEFI updated for Tegra194. I recall
> > that the UEFI code for Tegra194 is different from the one for Tegra234,
> > so it is probably not as trivial as a simple cherry-pick, but I'll try
> > to do some digging and find the code that does this for Xavier.
> 
> Any updates on this?

FWIW, in my testing with L4T versions with UEFI firmware, I'm not seeing 
any issues even if efifb is enabled. My inclination would be to merge, 
and we can work on issues related to early framebuffer separately.

Outside adding support to r35, one option is to make it so TegraDRM has 
to explicitly call tegra_mc_probe_device (not necessarily directly) when 
it has quiesced the hardware during probe. This would not allow seamless 
early framebuffer transition, but otherwise it should work. Implementing 
this for tegra-smmu would also allow us to get rid of the IOMMU API 
paths in TegraDRM and Host1x, which would be a great boon.

Cheers
Mikko

> 
> Aaron





^ permalink raw reply

* [PATCH] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: Besar Wicaksono @ 2026-04-06 23:20 UTC (permalink / raw)
  To: will, mark.rutland, james.clark
  Cc: linux-arm-kernel, linux-kernel, linux-tegra, treding, jonathanh,
	vsethi, rwiley, sdonthineni, mochs, nirmoyd, skelley,
	Besar Wicaksono

The PMCCNTR_EL0 in NVIDIA Olympus CPU may increment while
in WFI/WFE, which does not align with counting CPU_CYCLES
on a programmable counter. Add a MIDR range entry and
refuse PMCCNTR_EL0 for cycle events on affected parts so
perf does not mix the two behaviors.

Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
 drivers/perf/arm_pmuv3.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 8014ff766cff..b5d2f60af6f0 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -978,6 +978,29 @@ static int armv8pmu_get_chain_idx(struct pmu_hw_events *cpuc,
 	return -EAGAIN;
 }
 
+/*
+ * List of CPUs that should avoid using PMCCNTR_EL0.
+ */
+static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
+	/*
+	 * The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
+	 * This is an implementation specific behavior and not an erratum.
+	 *
+	 * From ARM DDI0487 D14.4:
+	 *   It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
+	 *   when the PE is in WFI or WFE state, even if the clocks are not stopped.
+	 *
+	 * From ARM DDI0487 D24.5.2:
+	 *   All counters are subject to any changes in clock frequency, including
+	 *   clock stopping caused by the WFI and WFE instructions.
+	 *   This means that it is CONSTRAINED UNPREDICTABLE whether or not
+	 *   PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
+	 *   WFE instructions.
+	 */
+	MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+	{}
+};
+
 static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
 				     struct perf_event *event)
 {
@@ -1011,6 +1034,14 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
 	if (cpu_pmu->has_smt)
 		return false;
 
+	/*
+	 * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
+	 * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
+	 * prevent inconsistency in the results.
+	 */
+	if (is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus))
+		return false;
+
 	return true;
 }
 
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] cpufreq: CPPC: add autonomous mode boot parameter support
From: Sumit Gupta @ 2026-04-06 18:08 UTC (permalink / raw)
  To: Pierre Gondois
  Cc: linux-tegra, linux-kernel, linux-doc, zhenglifeng1, treding,
	viresh.kumar, jonathanh, vsethi, ionela.voinescu, ksitaraman,
	sanjayc, zhanjie9, corbet, mochs, skhan, bbasu, rdunlap, linux-pm,
	mario.limonciello, rafael, sumitg
In-Reply-To: <4b1f100b-e699-43c1-a06b-5545056d174c@arm.com>

Hi Pierre,

Thank you for the comments.
Sorry for late reply as I was on vacation.


On 24/03/26 23:48, Pierre Gondois wrote:
> External email: Use caution opening links or attachments
>
>
> Hello Sumit,
>
> On 3/17/26 16:10, Sumit Gupta wrote:
>> Add kernel boot parameter 'cppc_cpufreq.auto_sel_mode' to enable CPPC
>> autonomous performance selection on all CPUs at system startup without
>> requiring runtime sysfs manipulation. When autonomous mode is enabled,
>> the hardware automatically adjusts CPU performance based on workload
>> demands using Energy Performance Preference (EPP) hints.
>>
>> When auto_sel_mode=1:
>> - Configure all CPUs for autonomous operation on first init
>> - Set EPP to performance preference (0x0)
>> - Use HW min/max when set; otherwise program from policy limits (caps)
>> - Clamp desired_perf to bounds before enabling autonomous mode
>> - Hardware controls frequency instead of the OS governor
>>
>> The boot parameter is applied only during first policy initialization.
>> On hotplug, skip applying it so that the user's runtime sysfs
>> configuration is preserved.
>>
>> Reviewed-by: Randy Dunlap <rdunlap@infradead.org> (Documentation)
>> Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
>> ---
>> Part 1 [1] of this series was applied for 7.1 and present in next.
>> Sending this patch as reworked version of 'patch 11' from [2] based
>> on next.
>>
>> [1] 
>> https://lore.kernel.org/lkml/20260206142658.72583-1-sumitg@nvidia.com/
>> [2] 
>> https://lore.kernel.org/lkml/20251223121307.711773-1-sumitg@nvidia.com/
>> ---
>>   .../admin-guide/kernel-parameters.txt         | 13 +++
>>   drivers/cpufreq/cppc_cpufreq.c                | 84 +++++++++++++++++--
>>   2 files changed, 92 insertions(+), 5 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
>> b/Documentation/admin-guide/kernel-parameters.txt
>> index fa6171b5fdd5..de4b4c89edfe 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -1060,6 +1060,19 @@ Kernel parameters
>>                       policy to use. This governor must be registered 
>> in the
>>                       kernel before the cpufreq driver probes.
>>
>> +     cppc_cpufreq.auto_sel_mode=
>> +                     [CPU_FREQ] Enable ACPI CPPC autonomous performance
>> +                     selection. When enabled, hardware automatically 
>> adjusts
>> +                     CPU frequency on all CPUs based on workload 
>> demands.
>> +                     In Autonomous mode, Energy Performance 
>> Preference (EPP)
>> +                     hints guide hardware toward performance (0x0) 
>> or energy
>> +                     efficiency (0xff).
>> +                     Requires ACPI CPPC autonomous selection 
>> register support.
>> +                     Format: <bool>
>> +                     Default: 0 (disabled)
>> +                     0: use cpufreq governors
>> +                     1: enable if supported by hardware
>> +
>>       cpu_init_udelay=N
>>                       [X86,EARLY] Delay for N microsec between assert 
>> and de-assert
>>                       of APIC INIT to start processors.  This delay 
>> occurs
>> diff --git a/drivers/cpufreq/cppc_cpufreq.c 
>> b/drivers/cpufreq/cppc_cpufreq.c
>> index 5dfb109cf1f4..49c148b2a0a4 100644
>> --- a/drivers/cpufreq/cppc_cpufreq.c
>> +++ b/drivers/cpufreq/cppc_cpufreq.c
>> @@ -28,6 +28,9 @@
>>
>>   static struct cpufreq_driver cppc_cpufreq_driver;
>>
>> +/* Autonomous Selection boot parameter */
>> +static bool auto_sel_mode;
>> +
>>   #ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
>>   static enum {
>>       FIE_UNSET = -1,
>> @@ -708,11 +711,74 @@ static int cppc_cpufreq_cpu_init(struct 
>> cpufreq_policy *policy)
>>       policy->cur = cppc_perf_to_khz(caps, caps->highest_perf);
>>       cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
>>
>> -     ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
>> -     if (ret) {
>> -             pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
>> -                      caps->highest_perf, cpu, ret);
>> -             goto out;
>> +     /*
>> +      * Enable autonomous mode on first init if boot param is set.
>> +      * Check last_governor to detect first init and skip if auto_sel
>> +      * is already enabled.
>> +      */
> If the goal is to set autosel only once at the driver init,
> shouldn't this be done in cppc_cpufreq_init() ?
> I understand that cpu_data doesn't exist yet in
> cppc_cpufreq_init(), but this seems more appropriate to do
> it there IMO.
>
> This means the cpudata should be updated accordingly
> in this cppc_cpufreq_cpu_init() function.

In an earlier version [1], the setup was in cppc_cpufreq_init() but
was moved to cppc_cpufreq_cpu_init() to improve per-CPU error handling.
Keeping the setup in cppc_cpufreq_init() helps to avoid the last_governor
check. We can warn for a CPU failing to enable and continue so other
CPUs keep autonomous mode.
cppc_cpufreq_cpu_init() would then just check the auto_sel state
from register and sync policy limits from min/max_perf registers when
autonomous mode is active.
Please let me know your thoughts.

[1] 
https://lore.kernel.org/lkml/5593d364-ca37-41c5-b33f-f7e245d6d626@nvidia.com/


>
>> +     if (auto_sel_mode && policy->last_governor[0] == '\0' &&
>> +         !cpu_data->perf_ctrls.auto_sel) {
>> +             /* Enable CPPC - optional register, some platforms need 
>> it */
> The documentation of the CPPC Enable Register is subject to
> interpretation, but IIUC the field should be set to use the CPPC
> controls, so I assume this should be set in cppc_cpufreq_init()
> instead ?

Agree that the CPPC Enable is about using the CPPC control path
in general and not only for autonomous selection.
Will move cppc_set_enable() into cppc_cpufreq_init() or outside the
autonomous mode block in cppc_cpufreq_cpu_init() as per conclusion
of previous comment.

>> +             ret = cppc_set_enable(cpu, true);
>> +             if (ret && ret != -EOPNOTSUPP)
>> +                     pr_warn("Failed to enable CPPC for CPU%d 
>> (%d)\n", cpu, ret);
>> +
>> +             /*
>> +              * Prefer HW min/max_perf when set; otherwise program from
>> +              * policy limits derived earlier from caps.
>> +              * Clamp desired_perf to bounds and sync policy->cur.
>> +              */
>> +             if (!cpu_data->perf_ctrls.min_perf || 
>> !cpu_data->perf_ctrls.max_perf)
>
> The function doesn't seem to exist.

It is newly added in [2].
Don't need to call it if we move the setup to cppc_cpufreq_init().

[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=ea3db45ae476889a1ba0ab3617e6afdeeefbda3d 



>
>> + cppc_cpufreq_update_perf_limits(cpu_data, policy);
>> +
>> +             cpu_data->perf_ctrls.desired_perf =
>> +                     clamp_t(u32, cpu_data->perf_ctrls.desired_perf,
>> +                             cpu_data->perf_ctrls.min_perf,
>> +                             cpu_data->perf_ctrls.max_perf);
>> +
>> +             policy->cur = cppc_perf_to_khz(caps,
>> + cpu_data->perf_ctrls.desired_perf);
>> +
>
> Maybe this should also be done in cppc_cpufreq_init()
> if the auto_sel_mode parameter is set ?

Yes.

>
>> +             /* EPP is optional - some platforms may not support it */
>> +             ret = cppc_set_epp(cpu, CPPC_EPP_PERFORMANCE_PREF);
>> +             if (ret && ret != -EOPNOTSUPP)
>> +                     pr_warn("Failed to set EPP for CPU%d (%d)\n", 
>> cpu, ret);
>> +             else if (!ret)
>> +                     cpu_data->perf_ctrls.energy_perf = 
>> CPPC_EPP_PERFORMANCE_PREF;
>> +
>> +             ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
>> +             if (ret) {
>> +                     pr_debug("Err setting perf for autonomous mode 
>> CPU:%d ret:%d\n",
>> +                              cpu, ret);
>> +                     goto out;
>> +             }
>> +
>> +             ret = cppc_set_auto_sel(cpu, true);
>> +             if (ret && ret != -EOPNOTSUPP) {
>> +                     pr_warn("Failed autonomous config for CPU%d 
>> (%d)\n",
>> +                             cpu, ret);
>> +                     goto out;
>> +             }
>> +             if (!ret)
>> +                     cpu_data->perf_ctrls.auto_sel = true;
>> +     }
>> +
>> +     if (cpu_data->perf_ctrls.auto_sel) {
>
> There is a patchset ongoing which tries to remove
> setting policy->min/max from driver initialization.
> Indeed, these values are only temporarily valid,
> until the governor override them.
> It is not sure yet the patch will be accepted though.
>
> https://lore.kernel.org/lkml/20260317101753.2284763-4-pierre.gondois@arm.com/ 
>


You are right that policy->min/max from .init() are temporary today
as cpufreq_set_policy() overwrites them before the governor starts.

On my test platform (highest == nominal, lowest_nonlinear == lowest),
this had no visible effect because the BIOS bounds and cpuinfo range
end up identical. But on platforms where they differ, the governor
would widen the range to full cpuinfo limits.

I think your patch [3] fixes this by giving these the right semantic as
initial QoS requests. With it, cpufreq_set_policy() preserves the policy
limits set from min/max_perf registers in .init(), which can either be
BIOS values on first boot or last user configured values before hotplug.

I will update the comment in v2 to reflect QoS seeding intent.

I see that the first two patches of your series [3] is applied for 7.1.
Do you plan to send the pending patch (3/4) from [3]?

[3] 
https://lore.kernel.org/lkml/20260317101753.2284763-4-pierre.gondois@arm.com/


>
>
>> +             /* Sync policy limits from HW when autonomous mode is 
>> active */
>> +             policy->min = cppc_perf_to_khz(caps,
>> + cpu_data->perf_ctrls.min_perf ?:
>> + caps->lowest_nonlinear_perf);
>> +             policy->max = cppc_perf_to_khz(caps,
>> + cpu_data->perf_ctrls.max_perf ?:
>> + caps->nominal_perf);
>> +     } else {
>> +             /* Normal mode: governors control frequency */
>> +             ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
>> +             if (ret) {
>> +                     pr_debug("Err setting perf value:%d on CPU:%d. 
>> ret:%d\n",
>> +                              caps->highest_perf, cpu, ret);
>> +                     goto out;
>> +             }
>>       }
>>
>>       cppc_cpufreq_cpu_fie_init(policy);
>> @@ -1038,10 +1104,18 @@ static int __init cppc_cpufreq_init(void)
>>
>>   static void __exit cppc_cpufreq_exit(void)
>>   {
>> +     unsigned int cpu;
>> +
>> +     for_each_present_cpu(cpu)
>> +             cppc_set_auto_sel(cpu, false);
>
> If the firmware has a default EPP value, it means that loading
> and the unloading the driver will reset this default EPP value.
> Maybe the initial EPP value and/or the auto_sel value should be
> cached somewhere and restored on exit ?
> I don't know if this is actually an issue, this is just to signal it.

The auto_sel_mode boot path programs EPP to performance preference(0),
not the firmware’s previous value. On unload we only call
cppc_set_auto_sel(false); we do not restore EPP, min/max perf,
or other CPPC fields to firmware defaults.

Thank you,
Sumit Gupta

....



^ permalink raw reply

* Re: [PATCH v3] dmaengine: tegra210-adma: Add error logging on failure paths
From: Sheetal . @ 2026-04-06 11:07 UTC (permalink / raw)
  To: Frank Li
  Cc: Jon Hunter, Vinod Koul, Thierry Reding, Laxman Dewangan, Frank Li,
	Mohan Kumar, dmaengine, linux-tegra, linux-kernel
In-Reply-To: <ac8uBTemDHCr4T6V@lizhi-Precision-Tower-5810>



On 03-04-2026 08:33, Frank Li wrote:
> External email: Use caution opening links or attachments
> 
> 
> On Mon, Mar 23, 2026 at 08:38:58AM +0000, Sheetal wrote:
>> Add dev_err/dev_err_probe logging across failure paths to improve
>> debuggability of DMA errors during runtime and probe.
>>
>> Signed-off-by: Sheetal <sheetal@nvidia.com>
>> ---
>> Changes in v3:
>> - Cast page_no to (unsigned long long) for %llu to fix -Wformat
>>    warning on 32-bit builds where resource_size_t is unsigned int
>> - Remove redundant dev_err for devm_ioremap_resource failures since
>>    the API already logs errors internally.
>>
>> Changes in v2:
>> - Fix format specifier for size_t: use %zu instead of %u for
>>    desc->num_periods to resolve -Wformat warning with W=1
>>
>>   drivers/dma/tegra210-adma.c | 37 +++++++++++++++++++++++++++-------
>>   1 file changed, 30 insertions(+), 7 deletions(-)
>>
> ...
>> @@ -1047,38 +1058,45 @@ static int tegra_adma_probe(struct platform_device *pdev)
>>        res_page = platform_get_resource_byname(pdev, IORESOURCE_MEM, "page");
>>        if (res_page) {
>>                tdma->ch_base_addr = devm_ioremap_resource(&pdev->dev, res_page);
>>                if (IS_ERR(tdma->ch_base_addr))
>>                        return PTR_ERR(tdma->ch_base_addr);
>>
>>                res_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "global");
>>                if (res_base) {
>>                        resource_size_t page_offset, page_no;
>>                        unsigned int ch_base_offset;
>>
>> -                     if (res_page->start < res_base->start)
>> +                     if (res_page->start < res_base->start) {
>> +                             dev_err(&pdev->dev, "invalid page/global resource order\n");
>>                                return -EINVAL;
> 
> It is in probe function, return dev_err_probe(, -EINVAL, ...);
> check other place

ACK

> 
>> +                     }
>> +
>>                        page_offset = res_page->start - res_base->start;
>>                        ch_base_offset = cdata->ch_base_offset;
>>                        if (!ch_base_offset)
>>                                return -EINVAL;
>>
>>                        page_no = div_u64(page_offset, ch_base_offset);
>> -                     if (!page_no || page_no > INT_MAX)
>> +                     if (!page_no || page_no > INT_MAX) {
>> +                             dev_err(&pdev->dev, "invalid page number %llu\n",
>> +                                     (unsigned long long)page_no);
>>                                return -EINVAL;
>> +                     }
>>
>>                        tdma->ch_page_no = page_no - 1;
>>                        tdma->base_addr = devm_ioremap_resource(&pdev->dev, res_base);
>>                        if (IS_ERR(tdma->base_addr))
>>                                return PTR_ERR(tdma->base_addr);
>>                }
>>        } else {
>>                /* If no 'page' property found, then reg DT binding would be legacy */
>>                res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>                if (res_base) {
>>                        tdma->base_addr = devm_ioremap_resource(&pdev->dev, res_base);
>>                        if (IS_ERR(tdma->base_addr))
>>                                return PTR_ERR(tdma->base_addr);
>>                } else {
>> +                     dev_err(&pdev->dev, "failed to get memory resource\n");
>>                        return -ENODEV;
>>                }
>>
>> @@ -1130,6 +1147,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
>>                tdc->irq = of_irq_get(pdev->dev.of_node, i);
>>                if (tdc->irq <= 0) {
>>                        ret = tdc->irq ?: -ENXIO;
>> +                     dev_err_probe(&pdev->dev, ret, "failed to get IRQ for channel %d\n", i);
>>                        goto irq_dispose;
>>                }
>>
>> @@ -1141,12 +1159,16 @@ static int tegra_adma_probe(struct platform_device *pdev)
>>        pm_runtime_enable(&pdev->dev);
>>
>>        ret = pm_runtime_resume_and_get(&pdev->dev);
>> -     if (ret < 0)
>> +     if (ret < 0) {
>> +             dev_err_probe(&pdev->dev, ret, "runtime PM resume failed\n");
>>                goto rpm_disable;
> 
> can you change to use devm_ firtly to elimiate goto first, then change to
> use
>          return dev_err_probe() pattern
> 


Thanks for the review, Frank.

For the devm_ conversion, it doesn't seem straightforward as the goto 
cleanup paths handle multiple resources. I'd like to send that as a 
separate follow-up patch.


> 
> Frank
> 
>> +     }
>>
>>        ret = tegra_adma_init(tdma);
>> -     if (ret)
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "failed to initialize ADMA: %d\n", ret);
>>                goto rpm_put;
>> +     }
>>
>>        dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
>>        dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask);
>> --
>> 2.17.1
>>


^ permalink raw reply

* [PATCH v1 9/9] ARM: tegra: tf600t: Invert accelerometer calibration matrix
From: Svyatoslav Ryhel @ 2026-04-06  8:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

IMU calibration matrix used in the device tree is inverted when testing on
the device which results in wrong screen orientation. Invert it to match
the matrix dumped from the device.

Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
index 0bebea0cb8c4..5c634b0f3f46 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
@@ -1091,9 +1091,9 @@ imu@69 {
 			vdd-supply   = <&vdd_3v3_sys>;
 			vddio-supply = <&vdd_1v8_vio>;
 
-			mount-matrix =	 "0", "-1",  "0",
-					"-1",  "0",  "0",
-					 "0",  "0", "-1";
+			mount-matrix =	 "0",  "1",  "0",
+					 "1",  "0",  "0",
+					 "0",  "0",  "1";
 
 			/* External I2C interface */
 			i2c-gate {
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 8/9] ARM: tegra: tf600t: Drop backlight regulator
From: Svyatoslav Ryhel @ 2026-04-06  8:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

Drop dedicated backlight regulator since the GPIO used in it is actually
SFIO controlling backlight and setting it as GPIO causes backlight to
freeze at maximum level.

Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
index 8b68bfef8dee..0bebea0cb8c4 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
@@ -2192,7 +2192,7 @@ backlight: backlight {
 		compatible = "pwm-backlight";
 
 		enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
-		power-supply = <&vdd_5v0_bl>;
+		power-supply = <&vdd_5v0_sys>;
 		pwms = <&pwm 0 71428>;
 
 		brightness-levels = <1 255>;
@@ -2422,17 +2422,6 @@ vdd_3v3_als: regulator-als {
 		vin-supply = <&vdd_3v3_sys>;
 	};
 
-	vdd_5v0_bl: regulator-bl {
-		compatible = "regulator-fixed";
-		regulator-name = "vdd_5v0_bl";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		regulator-boot-on;
-		gpio = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
-		enable-active-high;
-		vin-supply = <&vdd_5v0_bat>;
-	};
-
 	vdd_panel: regulator-panel {
 		compatible = "regulator-fixed";
 		regulator-name = "vdd_panel";
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 7/9] ARM: tegra: tf600t: Configure panel
From: Svyatoslav Ryhel @ 2026-04-06  8:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

Configure DSI panel used in ASUS VivoTab TF600T.

Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 .../boot/dts/nvidia/tegra30-asus-tf600t.dts   | 62 ++++++++++++++++++-
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
index 9296e7970ce4..8b68bfef8dee 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-tf600t.dts
@@ -23,6 +23,7 @@ aliases {
 		rtc0 = &pmic;
 		rtc1 = "/rtc@7000e000";
 
+		display0 = &lcd;
 		display1 = &hdmi;
 
 		serial1 = &uartc; /* Bluetooth */
@@ -55,6 +56,37 @@ linux,cma@80000000 {
 	};
 
 	host1x@50000000 {
+		vi@54080000 {
+			status = "okay";
+
+			csi@800 {
+				status = "okay";
+
+				avdd-dsi-csi-supply = <&avdd_dsi_csi>;
+			};
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+
+					vi_ppa_input: endpoint {
+						/* Link to the rear camera */
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					vi_ppb_input: endpoint {
+						/* Link to the front camera */
+					};
+				};
+			};
+		};
+
 		hdmi: hdmi@54280000 {
 			status = "okay";
 
@@ -68,6 +100,22 @@ hdmi_out: endpoint {
 				};
 			};
 		};
+
+		lcd: dsi@54300000 {
+			status = "okay";
+
+			avdd-dsi-csi-supply = <&avdd_dsi_csi>;
+
+			panel@0 {
+				compatible = "hydis,hv101hd1";
+				reg = <0>;
+
+				vdd-supply = <&vdd_panel>;
+				vio-supply = <&vio_panel>;
+
+				backlight = <&backlight>;
+			};
+		};
 	};
 
 	vde@6001a000 {
@@ -1123,11 +1171,10 @@ pmic-sleep-hog {
 			};
 
 			regulators {
-				vdd_lcd: vdd1 {
+				vio_panel: vdd1 {
 					regulator-name = "vddio_ddr_1v2";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
-					regulator-always-on;
 					regulator-boot-on;
 					ti,regulator-ext-sleep-control = <8>;
 				};
@@ -2386,6 +2433,17 @@ vdd_5v0_bl: regulator-bl {
 		vin-supply = <&vdd_5v0_bat>;
 	};
 
+	vdd_panel: regulator-panel {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_panel";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		gpio = <&gpio TEGRA_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&vdd_3v3_sys>;
+	};
+
 	hdmi_5v0_sys: regulator-hdmi {
 		compatible = "regulator-fixed";
 		regulator-name = "hdmi_5v0_sys";
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 6/9] ARM: tegra: transformers: Add connector node for common trees
From: Svyatoslav Ryhel @ 2026-04-06  8:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

All ASUS Transformers have micro-HDMI connector directly available. After
Tegra HDMI got bridge/connector support, we should use connector framework
for proper HW description.

Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com> # ASUS TF T30
Tested-by: Robert Eckelmann <longnoserob@gmail.com> # ASUS TF101 T20
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # ASUS TF201 T30
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 .../tegra20-asus-transformer-common.dtsi      | 22 ++++++++++++++++---
 .../tegra30-asus-transformer-common.dtsi      | 21 ++++++++++++++++--
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra20-asus-transformer-common.dtsi b/arch/arm/boot/dts/nvidia/tegra20-asus-transformer-common.dtsi
index 73c7ee378865..fe05cfd2312f 100644
--- a/arch/arm/boot/dts/nvidia/tegra20-asus-transformer-common.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20-asus-transformer-common.dtsi
@@ -79,9 +79,11 @@ hdmi@54280000 {
 			pll-supply = <&hdmi_pll_reg>;
 			hdmi-supply = <&vdd_hdmi_en>;
 
-			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
-			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7)
-				GPIO_ACTIVE_HIGH>;
+			port {
+				hdmi_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
 		};
 	};
 
@@ -1029,6 +1031,20 @@ key-volume-up {
 		};
 	};
 
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		type = "d";
+
+		hpd-gpios = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
+		ddc-i2c-bus = <&hdmi_ddc>;
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_out>;
+			};
+		};
+	};
+
 	i2cmux {
 		compatible = "i2c-mux-pinctrl";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
index d4a7bae51830..76db928b53bc 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
@@ -166,8 +166,11 @@ hdmi: hdmi@54280000 {
 			pll-supply = <&vdd_1v8_vio>;
 			vdd-supply = <&vdd_3v3_sys>;
 
-			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
-			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+			port {
+				hdmi_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
 		};
 	};
 
@@ -1701,6 +1704,20 @@ key-volume-up {
 		};
 	};
 
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		type = "d";
+
+		hpd-gpios = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
+		ddc-i2c-bus = <&hdmi_ddc>;
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_out>;
+			};
+		};
+	};
+
 	vdd_5v0_bat: regulator-bat {
 		compatible = "regulator-fixed";
 		regulator-name = "vdd_ac_bat";
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 5/9] ARM: tegra: transformer: Add support for front camera
From: Svyatoslav Ryhel @ 2026-04-06  8:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

Add front camera video path. Aptina MI1040 camera is used on all supported
ASUS Transformers, but only TF201 and TF700T will work since on
TF300T/TG/TL front camera is linked through an additional ISP.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 .../tegra30-asus-transformer-common.dtsi      | 138 +++++++++++++++++-
 1 file changed, 137 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
index 0e06136042a9..d4a7bae51830 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi
@@ -2,6 +2,7 @@
 
 #include <dt-bindings/input/gpio-keys.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/media/video-interfaces.h>
 #include <dt-bindings/thermal/thermal.h>
 
 #include "tegra30.dtsi"
@@ -73,6 +74,91 @@ trustzone@bfe00000 {
 	};
 
 	host1x@50000000 {
+		vi@54080000 {
+			status = "okay";
+
+			csi@800 {
+				status = "okay";
+
+				avdd-dsi-csi-supply = <&avdd_dsi_csi>;
+
+				/* CSI-A */
+				channel@0 {
+					reg = <0>;
+
+					nvidia,mipi-calibrate = <&csi 0>; /* CSIA pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csia_input: endpoint {
+							data-lanes = <1 2>;
+							/* Add rear camera */
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csia_output: endpoint {
+							remote-endpoint = <&vi_ppa_input>;
+						};
+					};
+				};
+
+				/* CSI-B */
+				channel@1 {
+					reg = <1>;
+
+					nvidia,mipi-calibrate = <&csi 1>; /* CSIB pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csib_input: endpoint {
+							data-lanes = <3>;
+							remote-endpoint = <&front_camera_output>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csib_output: endpoint {
+							remote-endpoint = <&vi_ppb_input>;
+						};
+					};
+				};
+			};
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+
+					vi_ppa_input: endpoint {
+						remote-endpoint = <&csia_output>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					vi_ppb_input: endpoint {
+						remote-endpoint = <&csib_output>;
+					};
+				};
+			};
+		};
+
 		hdmi: hdmi@54280000 {
 			status = "okay";
 
@@ -1173,6 +1259,36 @@ light-sensor@1c {
 			vdd-supply = <&vdd_3v3_sys>;
 		};
 
+		/* Aptina 1/6" HD SOC (MI1040) */
+		front-camera@48 {
+			compatible = "aptina,mi1040";
+			reg = <0x48>;
+
+			clocks = <&tegra_car TEGRA30_CLK_CSUS>;
+
+			reset-gpios = <&gpio TEGRA_GPIO(O, 0) GPIO_ACTIVE_LOW>;
+
+			vddio-supply = <&vdd_1v8_cam>;
+			vdd-supply = <&vdd_1v8_cam>;
+			vaa-supply = <&avdd_2v85_fcam>;
+
+			orientation = <0>; /* Front camera */
+
+			assigned-clocks = <&tegra_car TEGRA30_CLK_VI_SENSOR>,
+					  <&tegra_car TEGRA30_CLK_CSUS>;
+			assigned-clock-rates = <24000000>;
+			assigned-clock-parents = <&tegra_car TEGRA30_CLK_PLL_P>,
+						 <&tegra_car TEGRA30_CLK_VI_SENSOR>;
+
+			port {
+				front_camera_output: endpoint {
+					bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+					link-frequencies = /bits/ 64 <384000000>;
+					remote-endpoint = <&csib_input>;
+				};
+			};
+		};
+
 		gyroscope@68 {
 			compatible = "invensense,mpu3050";
 			reg = <0x68>;
@@ -1310,7 +1426,7 @@ ldo4 {
 
 				/* LDO5 is not used by Transformers */
 
-				ldo6 {
+				avdd_dsi_csi: ldo6 {
 					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
@@ -1685,6 +1801,26 @@ hdmi_5v0_sys: regulator-hdmi {
 		vin-supply = <&vdd_5v0_sys>;
 	};
 
+	vdd_1v8_cam: regulator-viocam {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_1v8_cam";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&vdd_1v8_vio>;
+	};
+
+	avdd_2v85_fcam: regulator-avcam-front {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_2v85_fcam";
+		regulator-min-microvolt = <2850000>;
+		regulator-max-microvolt = <2850000>;
+		gpio = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&vdd_3v3_sys>;
+	};
+
 	sound {
 		nvidia,i2s-controller = <&tegra_i2s1>;
 
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 4/9] ARM: tegra: grouper: Add support for front camera
From: Svyatoslav Ryhel @ 2026-04-06  8:33 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

Add front camera video path.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 .../tegra30-asus-nexus7-grouper-common.dtsi   | 128 ++++++++++++++++++
 ...egra30-asus-nexus7-grouper-maxim-pmic.dtsi |   4 +-
 .../tegra30-asus-nexus7-grouper-ti-pmic.dtsi  |   4 +-
 3 files changed, 132 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi
index 15f53babdc21..892d718294dd 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi
@@ -2,6 +2,7 @@
 
 #include <dt-bindings/input/gpio-keys.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/media/video-interfaces.h>
 #include <dt-bindings/power/summit,smb347-charger.h>
 #include <dt-bindings/thermal/thermal.h>
 
@@ -84,6 +85,93 @@ init-mode-hog {
 		};
 	};
 
+	host1x@50000000 {
+		vi@54080000 {
+			status = "okay";
+
+			csi@800 {
+				status = "okay";
+
+				avdd-dsi-csi-supply = <&avdd_dsi_csi>;
+
+				/* CSI-A */
+				channel@0 {
+					reg = <0>;
+
+					nvidia,mipi-calibrate = <&csi 0>; /* CSIA pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csia_input: endpoint {
+							data-lanes = <1 2>;
+							/* No rear camera */
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csia_output: endpoint {
+							remote-endpoint = <&vi_ppa_input>;
+						};
+					};
+				};
+
+				/* CSI-B */
+				channel@1 {
+					reg = <1>;
+
+					nvidia,mipi-calibrate = <&csi 1>; /* CSIB pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csib_input: endpoint {
+							data-lanes = <3>;
+							remote-endpoint = <&front_camera_output>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csib_output: endpoint {
+							remote-endpoint = <&vi_ppb_input>;
+						};
+					};
+				};
+			};
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+
+					vi_ppa_input: endpoint {
+						remote-endpoint = <&csia_output>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					vi_ppb_input: endpoint {
+						remote-endpoint = <&csib_output>;
+					};
+				};
+			};
+		};
+	};
+
 	pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -890,6 +978,36 @@ light-sensor@1c {
 			vdd-supply = <&vdd_3v3_sys>;
 		};
 
+		/* Aptina 1/6" HD SOC (MI1040) */
+		front-camera@48 {
+			compatible = "aptina,mi1040";
+			reg = <0x48>;
+
+			clocks = <&tegra_car TEGRA30_CLK_CSUS>;
+
+			reset-gpios = <&gpio TEGRA_GPIO(O, 0) GPIO_ACTIVE_LOW>;
+
+			vddio-supply = <&avdd_cam1>;
+			vdd-supply = <&vddio_cam>;
+			vaa-supply = <&avdd_cam1>;
+
+			orientation = <0>; /* Front camera */
+
+			assigned-clocks = <&tegra_car TEGRA30_CLK_VI_SENSOR>,
+					  <&tegra_car TEGRA30_CLK_CSUS>;
+			assigned-clock-rates = <24000000>;
+			assigned-clock-parents = <&tegra_car TEGRA30_CLK_PLL_P>,
+						 <&tegra_car TEGRA30_CLK_VI_SENSOR>;
+
+			port {
+				front_camera_output: endpoint {
+					bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+					link-frequencies = /bits/ 64 <384000000>;
+					remote-endpoint = <&csib_input>;
+				};
+			};
+		};
+
 		accelerometer@68 {
 			compatible = "invensense,mpu6050";
 			reg = <0x68>;
@@ -1203,6 +1321,16 @@ vcc_3v3_ts: regulator-ts {
 		vin-supply = <&vdd_5v0_sys>;
 	};
 
+	avdd_cam1: regulator-vcam1 {
+		compatible = "regulator-fixed";
+		regulator-name = "avdd_cam1";
+		regulator-min-microvolt = <2850000>;
+		regulator-max-microvolt = <2850000>;
+		gpio = <&gpio TEGRA_GPIO(R, 6) GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&vdd_5v0_sys>;
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-rt5640-grouper",
 			     "nvidia,tegra-audio-rt5640";
diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi
index 694c7fe37eb8..4bd98935031b 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi
@@ -135,7 +135,7 @@ ldo4 {
 					regulator-boot-on;
 				};
 
-				ldo5 {
+				vddio_cam: ldo5 {
 					regulator-name = "vdd_camera";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -149,7 +149,7 @@ ldo6 {
 					regulator-boot-on;
 				};
 
-				ldo7 {
+				avdd_dsi_csi: ldo7 {
 					regulator-name = "avdd_dsi_csi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi
index ee4a3f482769..8fe3c62c9052 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi
@@ -92,13 +92,13 @@ ldo4 {
 					regulator-always-on;
 				};
 
-				ldo5 {
+				vddio_cam: ldo5 {
 					regulator-name = "vddio_sdmmc,avdd_vdac";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				ldo6 {
+				avdd_dsi_csi: ldo6 {
 					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 3/9] ARM: tegra: p880: Lower CPU thermal limit
From: Svyatoslav Ryhel @ 2026-04-06  8:33 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

From: Ion Agorria <ion@agorria.com>

Lower the CPU thermal limit for the LG P880, since its chassis has less
thermal dissipation capability than the P895.

Signed-off-by: Ion Agorria <ion@agorria.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts b/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
index 1b21d7628c8c..6b30e17459ac 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
@@ -537,4 +537,17 @@ sound {
 
 		nvidia,int-mic-en-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
 	};
+
+	thermal-zones {
+		cpu-thermal {
+			trips {
+				cpu-alert {
+					/* throttle at 60C until temperature drops to 59.8C */
+					temperature = <60000>;
+					hysteresis = <200>;
+					type = "passive";
+				};
+			};
+		};
+	};
 };
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 2/9] ARM: tegra: lg-x3: Set PMIC's RTC address
From: Svyatoslav Ryhel @ 2026-04-06  8:33 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

LG X3 devices have the PMIC's RTC module located at a non-standard
address. Set the correct address.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi b/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
index d2a5904cebed..60e8a19aa70e 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
@@ -1297,7 +1297,8 @@ pwr_i2c: i2c@7000d000 {
 
 		pmic: max77663@1c {
 			compatible = "maxim,max77663";
-			reg = <0x1c>;
+			reg = <0x1c>, <0x48>;
+			reg-names = "pmic", "rtc";
 
 			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <2>;
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 1/9] ARM: tegra: lg-x3: Complete video device graph
From: Svyatoslav Ryhel @ 2026-04-06  8:33 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260406083404.31359-1-clamor95@gmail.com>

Add front and rear camera nodes and interlink them with Tegra CSI and VI.
Adjust camera PMIC voltages to better fit requirements and fix the focuser
node.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts |  28 ++++
 arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts |  46 ++++++
 arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi  | 154 +++++++++++++++++--
 3 files changed, 214 insertions(+), 14 deletions(-)

diff --git a/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts b/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
index cc14e6dca770..1b21d7628c8c 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts
@@ -12,6 +12,18 @@ aliases {
 		mmc2 = &sdmmc1; /* WiFi */
 	};
 
+	host1x@50000000 {
+		vi@54080000 {
+			csi@800 {
+				/delete-node/ channel@1;
+			};
+
+			ports {
+				/delete-node/ port@1;
+			};
+		};
+	};
+
 	pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -116,6 +128,22 @@ rmi4-f11@11 {
 		};
 	};
 
+	i2c@7000c500 {
+		camera-pmic@7d {
+			vt_1v2_front: ldo1 {
+				regulator-name = "vt_1v2_dig";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			vt_2v7_front: ldo2 {
+				regulator-name = "vt_2v7_vana";
+				regulator-min-microvolt = <2700000>;
+				regulator-max-microvolt = <2700000>;
+			};
+		};
+	};
+
 	spi@7000dc00 {
 		dsi@2 {
 			/*
diff --git a/arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts b/arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts
index 414117fd4382..896639599c12 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts
@@ -118,6 +118,52 @@ rmi4-f1a@1a {
 		};
 	};
 
+	i2c@7000c500 {
+		/* Aptina 1/6" HD SOC (MT9M114) */
+		front-camera@48 {
+			compatible = "onnn,mt9m114";
+			reg = <0x48>;
+
+			clocks = <&tegra_car TEGRA30_CLK_CSUS>;
+
+			reset-gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_LOW>;
+
+			vddio-supply = <&vio_1v8_front>;
+			vdd-supply = <&vt_1v8_front>;
+			vaa-supply = <&vt_2v8_front>;
+
+			orientation = <0>; /* Front camera */
+
+			assigned-clocks = <&tegra_car TEGRA30_CLK_VI_SENSOR>,
+					  <&tegra_car TEGRA30_CLK_CSUS>;
+			assigned-clock-rates = <24000000>;
+			assigned-clock-parents = <&tegra_car TEGRA30_CLK_PLL_P>,
+						 <&tegra_car TEGRA30_CLK_VI_SENSOR>;
+
+			port {
+				front_camera_output: endpoint {
+					bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+					link-frequencies = /bits/ 64 <384000000>;
+					remote-endpoint = <&csib_input>;
+				};
+			};
+		};
+
+		camera-pmic@7d {
+			vt_1v8_front: ldo1 {
+				regulator-name = "vt_1v8_dig";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			vt_2v8_front: ldo2 {
+				regulator-name = "vt_2v8_vana";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+		};
+	};
+
 	spi@7000dc00 {
 		dsi@2 {
 			/*
diff --git a/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi b/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
index 768e201456d8..d2a5904cebed 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/input/gpio-keys.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
+#include <dt-bindings/media/video-interfaces.h>
 #include <dt-bindings/mfd/max77620.h>
 #include <dt-bindings/thermal/thermal.h>
 
@@ -74,6 +75,91 @@ trustzone@bfe00000 {
 	};
 
 	host1x@50000000 {
+		vi@54080000 {
+			status = "okay";
+
+			csi@800 {
+				status = "okay";
+
+				avdd-dsi-csi-supply = <&avdd_dsi_csi>;
+
+				/* CSI-A */
+				channel@0 {
+					reg = <0>;
+
+					nvidia,mipi-calibrate = <&csi 0>; /* CSIA pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csia_input: endpoint {
+							data-lanes = <1 2>;
+							remote-endpoint = <&rear_camera_output>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csia_output: endpoint {
+							remote-endpoint = <&vi_ppa_input>;
+						};
+					};
+				};
+
+				/* CSI-B */
+				channel@1 {
+					reg = <1>;
+
+					nvidia,mipi-calibrate = <&csi 1>; /* CSIB pad */
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						csib_input: endpoint {
+							data-lanes = <3>;
+							remote-endpoint = <&front_camera_output>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						csib_output: endpoint {
+							remote-endpoint = <&vi_ppb_input>;
+						};
+					};
+				};
+			};
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+
+					vi_ppa_input: endpoint {
+						remote-endpoint = <&csia_output>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					vi_ppb_input: endpoint {
+						remote-endpoint = <&csib_output>;
+					};
+				};
+			};
+		};
+
 		lcd: dc@54200000 {
 			rgb {
 				status = "okay";
@@ -1112,29 +1198,68 @@ dw9714: coil@c {
 			compatible = "dongwoon,dw9714";
 			reg = <0x0c>;
 
-			enable-gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_HIGH>;
+			powerdown-gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>;
 
 			vcc-supply = <&vcc_focuser>;
 		};
 
+		/* SONY IMX111 1/4" BSI */
+		rear-camera@10 {
+			compatible = "sony,imx111";
+			reg = <0x10>;
+
+			clocks = <&tegra_car TEGRA30_CLK_CSUS>;
+
+			reset-gpios = <&gpio TEGRA_GPIO(K, 4) GPIO_ACTIVE_LOW>;
+
+			iovdd-supply = <&vio_1v8_rear>;
+			dvdd-supply = <&vdd_1v2_rear>;
+			avdd-supply = <&vdd_2v7_rear>;
+
+			orientation = <1>; /* Rear camera */
+			rotation = <90>;
+
+			nvmem = <&m24c08>;
+			lens-focus = <&dw9714>;
+
+			assigned-clocks = <&tegra_car TEGRA30_CLK_VI_SENSOR>,
+					  <&tegra_car TEGRA30_CLK_CSUS>;
+			assigned-clock-rates = <24000000>;
+			assigned-clock-parents = <&tegra_car TEGRA30_CLK_PLL_P>,
+						 <&tegra_car TEGRA30_CLK_VI_SENSOR>;
+
+			port {
+				rear_camera_output: endpoint {
+					data-lanes = <1 2>;
+					bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+					link-frequencies = /bits/ 64 <542400000>;
+					remote-endpoint = <&csia_input>;
+				};
+			};
+		};
+
+		/* rear camera sensor eeprom m24c08 from ST */
+		m24c08: eeprom@50 {
+			compatible = "atmel,24c08";
+			reg = <0x50>;
+
+			/* if high then WP is on, if low then off */
+			wp-gpios = <&gpio TEGRA_GPIO(K, 3) GPIO_ACTIVE_HIGH>;
+
+			/* it is not OTP but writing is unwanted */
+			read-only;
+			pagesize = <16>;
+			num-addresses = <1>;
+
+			vcc-supply = <&vio_1v8_rear>;
+		};
+
 		camera-pmic@7d {
 			compatible = "ti,lp8720";
 			reg = <0x7d>;
 
 			enable-gpios = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>;
 
-			vt_1v2_front: ldo1 {
-				regulator-name = "vt_1v2_dig";
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <1200000>;
-			};
-
-			vt_2v7_front: ldo2 {
-				regulator-name = "vt_2v7_vana";
-				regulator-min-microvolt = <2700000>;
-				regulator-max-microvolt = <2700000>;
-			};
-
 			vdd_2v7_rear: ldo3 {
 				regulator-name = "8m_2v7_vana";
 				regulator-min-microvolt = <2700000>;
@@ -1348,10 +1473,11 @@ vdd_1v2_mhl: ldo7 {
 					maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
 				};
 
-				ldo8 {
+				avdd_dsi_csi: ldo8 {
 					regulator-name = "avdd_dsi_csi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
+					regulator-boot-on;
 
 					maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
 				};
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 0/9] ARM: tegra: complete a few Tegra30 device trees
From: Svyatoslav Ryhel @ 2026-04-06  8:33 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Svyatoslav Ryhel, Ion Agorria,
	Jonas Schwöbel
  Cc: devicetree, linux-tegra, linux-kernel

Configure camera support for ASUS Transformers, Google Nexus 7 and
LG X3 devices. Fix RTC on LG X3 devices. Lower throttling temperature
for LG P880. Add panel support for TF600T.

Ion Agorria (1):
  ARM: tegra: p880: Lower CPU thermal limit

Svyatoslav Ryhel (8):
  ARM: tegra: lg-x3: Complete video device graph
  ARM: tegra: lg-x3: Set PMIC's RTC address
  ARM: tegra: grouper: Add support for front camera
  ARM: tegra: transformer: Add support for front camera
  ARM: tegra: transformers: Add connector node for common trees
  ARM: tegra: tf600t: Configure panel
  ARM: tegra: tf600t: Drop backlight regulator
  ARM: tegra: tf600t: Invert accelerometer calibration matrix

 .../tegra20-asus-transformer-common.dtsi      |  22 ++-
 .../tegra30-asus-nexus7-grouper-common.dtsi   | 128 ++++++++++++++
 ...egra30-asus-nexus7-grouper-maxim-pmic.dtsi |   4 +-
 .../tegra30-asus-nexus7-grouper-ti-pmic.dtsi  |   4 +-
 .../boot/dts/nvidia/tegra30-asus-tf600t.dts   |  71 ++++++--
 .../tegra30-asus-transformer-common.dtsi      | 159 +++++++++++++++++-
 arch/arm/boot/dts/nvidia/tegra30-lg-p880.dts  |  41 +++++
 arch/arm/boot/dts/nvidia/tegra30-lg-p895.dts  |  46 +++++
 arch/arm/boot/dts/nvidia/tegra30-lg-x3.dtsi   | 157 +++++++++++++++--
 9 files changed, 595 insertions(+), 37 deletions(-)

-- 
2.51.0


^ permalink raw reply

* Re: [PATCH 1/2] Revert "arm64: tegra: Disable ISO SMMU for Tegra194"
From: Aaron Kling @ 2026-04-06  7:49 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mikko Perttunen, Thierry Reding, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Hunter, devicetree, linux-tegra,
	linux-kernel
In-Reply-To: <aZQ-cMn-3vI7UH7t@orome>

On Tue, Feb 17, 2026 at 4:13 AM Thierry Reding
<thierry.reding@kernel.org> wrote:
>
> On Tue, Feb 17, 2026 at 12:53:54PM +0900, Mikko Perttunen wrote:
> > On Thursday, January 22, 2026 7:22 PM Mikko Perttunen wrote:
> > > On Tuesday, December 9, 2025 1:21 PM Aaron Kling wrote:
> > > > On Mon, Nov 3, 2025 at 12:05 PM Aaron Kling <webgeek1234@gmail.com> wrote:
> > > > >
> > > > > On Mon, Nov 3, 2025 at 5:07 AM Thierry Reding <thierry.reding@gmail.com> wrote:
> > > > > >
> > > > > > On Sat, Nov 01, 2025 at 06:13:26PM -0500, Aaron Kling wrote:
> > > > > > > On Sat, Nov 1, 2025 at 6:01 PM Aaron Kling via B4 Relay
> > > > > > > <devnull+webgeek1234.gmail.com@kernel.org> wrote:
> > > > > > > >
> > > > > > > > From: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > >
> > > > > > > > This reverts commit ebea268ea583ba4970df425dfef8c8e21d0a4e12.
> > > > > > > >
> > > > > > > > Mmu is now being enabled for the display controllers.
> > > > > > > >
> > > > > > > > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > > > > > > > ---
> > > > > > > >  arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +-
> > > > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > > >
> > > > > > > > diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > index 1399342f23e1c4f73b278adc66dfb948fc30d326..854ed6d46aa1d8eedcdfbae1fdde1374adf40337 100644
> > > > > > > > --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> > > > > > > > @@ -1807,7 +1807,7 @@ iommu@10000000 {
> > > > > > > >                         #iommu-cells = <1>;
> > > > > > > >
> > > > > > > >                         nvidia,memory-controller = <&mc>;
> > > > > > > > -                       status = "disabled";
> > > > > > > > +                       status = "okay";
> > > > > > > >                 };
> > > > > > > >
> > > > > > > >                 smmu: iommu@12000000 {
> > > > > > > >
> > > > > > > > --
> > > > > > > > 2.51.0
> > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > > Question for Jon as the author of the commit being reverted. The
> > > > > > > commit message states "we do not have a way to pass frame-buffer
> > > > > > > memory from the bootloader to the kernel". If I understand this
> > > > > > > correctly, this is talking about seamless handoff. What does this have
> > > > > > > to do with enabling mmu on the display controllers? Seamless does not
> > > > > > > work on any tegra arch as far as I'm aware, but Tegra194 is the only
> > > > > > > one that doesn't have mmu enabled for the dc's. But enabling mmu
> > > > > > > allows for better and faster memory allocation. My initial attempts to
> > > > > > > enable this didn't work because I tried to attach them to the main mmu
> > > > > > > unit, see the related freedesktop issue [0]. After noticing in the
> > > > > > > downstream dt that the dc's are on a separate unit, I made it work.
> > > > > > > And so far, it seems to work just as well as Tegra186. Then when I was
> > > > > > > packaging up the change to submit, I found that this had been
> > > > > > > explicitly disabled. But I'm not seeing why. Am I missing some
> > > > > > > additional factors?
> > > > > >
> > > > > > This isn't seamless handoff to the Tegra DRM driver for display, but
> > > > > > rather to simple-framebuffer. While this does technically work, it also
> > > > > > causes a spew of SMMU faults during early boot because the firmware does
> > > > > > not properly pass the SMMU mapping information to the kernel.
> > > > > >
> > > > > > In a nutshell what happens is that the firmware sets up the display
> > > > > > controller to scan out from a reserved memory region, but it does so
> > > > > > without involving the SMMU, so it uses physical addresses directly. When
> > > > > > the kernel boots and the SMMU is enabled the continued accesses from
> > > > > > display hardware cause SMMU faults (because there is no mapping for the
> > > > > > framebuffer addresses).
> > > > > >
> > > > > > That said, we did solve these issues and this may not be happening
> > > > > > anymore with the most recent L4T releases, so it may be okay to revert
> > > > > > this now. We should find out exactly which release includes all the
> > > > > > needed changes so that it can be referenced in the commit message. I
> > > > > > want to avoid people running new kernels with an old L4T release and
> > > > > > then seeing these errors without any reference as to why that might
> > > > > > suddenly happen.
> > > > >
> > > > > For reference, I have rolled back my Android usecase to use the L4T
> > > > > r32.7.6 bootloaders on T194 for a variety of reasons. So I am using
> > > > > cboot as the final bootloader and not edk2 as in L4T r34/r35. I have a
> > > > > pending cboot patch to support simple-framebuffer handoff, but haven't
> > > > > fully verified it as tegra-drm is currently unable to takeover from
> > > > > simplefb like openrm does for t234. But all that to say that since I
> > > > > no longer use r35 for t194 I don't have the setup to easily verify
> > > > > which point release works here and what doesn't.
> > > >
> > > > Any further thoughts on this patch?
> > > >
> > > > Aaron
> > >
> > > FWIW,
> > >
> > > looks like the edk2 patch to update iommu-addresses --
> > >
> > > commit 6071946461389221d2314cbbae0377610b5b1f6a
> > > Author: Jan Bobek <jbobek@nvidia.com>
> > > Date:   Tue Mar 21 00:15:27 2023 +0000
> > >
> > >     feat(NvDisplayControllerDxe): update FDT with framebuffer info
> > >
> > >     On ready-to-boot and whenever FDT is installed, update FDT with
> > >     framebuffer mode information, base address and size.
> > >
> > >     Signed-off-by: Jan Bobek <jbobek@nvidia.com>
> > >     Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com>
> > >
> > > is in since r36.2
> > >
> > > $ git tag --contains 6071946461389221d2314cbbae0377610b5b1f6a | grep "^r"
> > > r36.2
> > > r36.3.0
> > > r36.4.0
> > > r36.4.3
> > > r36.4.4
> > > r36.4.5
> > > r38.2
> > > r38.4
> > >
> > > Not so good for T194 since r36 only supports Orin.
> > >
> > > I'll look into getting this cherry-picked to r35.
> > >
> > > Mikko
> > >
> > >
> >
> > I looked into this and it appears a version of this is in r35, but it
> > only supports T234. However, I also found that at one point, L4T
> > bootloader configuration has been modified to place the display
> > controllers into SMMU bypass until otherwise configured by the kernel
> > -- which the kernel does in tegra_mc_probe_device.
> >
> > I think that means there is still potential for an issue where the
> > display continues to be on between tegra_mc_probe_device and tegradrm
> > reconfiguring it. However, I cannot reproduce that happening -- most
> > likely the display is being turned off before that because of a clock
> > or power domain being turned off.
> >
> > In any case, this means that we no longer need to pass the
> > framebuffer's information to the kernel. I think it would be good to
> > have some clarity to ensure the issue described above cannot happen,
> > but otherwise we should be able to enable IOMMU.
>
> The problem would happen if you enable some sort of early framebuffer
> support, such as simple-drm or simple-framebuffer. Maybe even efifb. I
> think it'd still be worth getting the iommu-addresses code into r35 if
> for nothing else but to have a bit more of a safety buffer for the
> future.
>
> If we don't and for some reason decide that we want early framebuffer
> support, it might be too late to get UEFI updated for Tegra194. I recall
> that the UEFI code for Tegra194 is different from the one for Tegra234,
> so it is probably not as trivial as a simple cherry-pick, but I'll try
> to do some digging and find the code that does this for Xavier.

Any updates on this?

Aaron

^ permalink raw reply

* [PATCH v3] drm/tegra: Enable cmu for Tegra186 and Tegra194
From: Aaron Kling via B4 Relay @ 2026-04-06  7:47 UTC (permalink / raw)
  To: Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
	Jonathan Hunter, Thierry Reding
  Cc: dri-devel, linux-tegra, linux-kernel, Kurt Kiefer, Aaron Kling,
	Jasper Korten

From: Aaron Kling <webgeek1234@gmail.com>

Without the cmu, nvdisplay will display colors that are notably darker
than intended. The vendor bootloader and the downstream display driver
enable the cmu and sets a sRGB table. Loading that table here results in
the intended colors.

Co-developed-by: Kurt Kiefer <kekiefer@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
Tested-by: Jasper Korten <jja2000@gmail.com>
---
Changes in v3:
- Remove improper IOVA null check
- Use dmam_alloc_coherent instead of manually tracking memory
- Address other review comments
- Link to v2: https://lore.kernel.org/r/20260202-tegra-drm-cmu-v2-1-a1bcb37f3e85@gmail.com

Changes in v2:
- Several formatting changes per v1 review
- Move cmu alloc/free to dc, where it can be handled in probe/remove
- Enable cmu for displayport as well
- Link to v1: https://lore.kernel.org/r/20251101-tegra-drm-cmu-v1-1-211799755ab8@gmail.com
---
 drivers/gpu/drm/tegra/dc.c  | 116 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/dc.h  |  13 +++++
 drivers/gpu/drm/tegra/sor.c |  25 ++++++++++
 3 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 06370b7e0e5678c7a91f288bc98599503fe9f049..4500b970f05d856a44533fd6c7daec9e81cc2be5 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -36,6 +36,103 @@
 #include "hub.h"
 #include "plane.h"
 
+static const u16 default_srgb_lut[] = {
+	0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
+	0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
+	0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
+	0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
+	0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
+	0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
+	0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
+	0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
+	0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
+	0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
+	0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
+	0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
+	0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
+	0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
+	0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
+	0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
+	0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
+	0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
+	0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
+	0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
+	0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
+	0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
+	0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
+	0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
+	0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
+	0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
+	0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
+	0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
+	0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
+	0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
+	0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
+	0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
+	0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
+	0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
+	0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
+	0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
+	0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
+	0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
+	0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
+	0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
+	0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
+	0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
+	0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
+	0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
+	0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
+	0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
+	0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
+	0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
+	0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
+	0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
+	0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
+	0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
+	0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
+	0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
+	0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
+	0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
+	0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
+	0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
+	0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
+	0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
+	0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
+	0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
+	0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
+	0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
+	0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
+	0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
+	0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
+	0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
+	0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
+	0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
+	0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
+	0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
+	0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
+	0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
+	0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
+	0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
+	0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
+	0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
+	0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
+	0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
+	0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
+	0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
+	0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
+	0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
+	0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
+	0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
+	0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
+	0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
+	0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
+	0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
+	0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
+	0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
+	0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
+	0x9FF7, 0x9FFF,
+};
+
 static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 					    struct drm_crtc_state *state);
 
@@ -3251,6 +3348,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
 	if (dc->irq < 0)
 		return -ENXIO;
 
+	if (dc->soc->has_nvdisplay) {
+		unsigned int i;
+		u64 r;
+
+		dc->cmu_output_lut =
+			dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
+					    &dc->cmu_output_phys, GFP_KERNEL);
+
+		if (!dc->cmu_output_lut) {
+			dev_err(dc->dev, "failed to allocate lut for cmu\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
+			r = default_srgb_lut[i];
+			dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
+		}
+	}
+
 	err = tegra_dc_rgb_probe(dc);
 	if (err < 0 && err != -ENODEV)
 		return dev_err_probe(&pdev->dev, err,
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 0559fa6b1bf70416e51d5067cc04a6ae6572de23..973ab0bb15c9260be6256b4459cd03c018d3dea5 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -103,6 +103,9 @@ struct tegra_dc {
 	const struct tegra_dc_soc_info *soc;
 
 	bool has_opp_table;
+
+	u64 *cmu_output_lut;
+	dma_addr_t cmu_output_phys;
 };
 
 static inline struct tegra_dc *
@@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
 #define BASE_COLOR_SIZE_888    (  8 << 0)
 #define BASE_COLOR_SIZE_101010 ( 10 << 0)
 #define BASE_COLOR_SIZE_121212 ( 12 << 0)
+#define CMU_ENABLE_ENABLE      (1 << 20)
 
 #define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431
 #define  SC1_H_QUALIFIER_NONE	(1 << 16)
@@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
 #define PROTOCOL_MASK (0xf << 8)
 #define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
 
+#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT	0x431
+#define  OUTPUT_LUT_MODE_MASK        (3 << 5)
+#define  OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
+#define  OUTPUT_LUT_SIZE_MASK        (3 << 1)
+#define  OUTPUT_LUT_SIZE_SIZE_1025   (2 << 1)
+
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE	0x432
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI	0x433
+
 #define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR	0x442
 #define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR	0x446
 
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index de8b2dfc4984c4534b723ebf043f2eb0f277157a..78e71a3ff02632e60872c442d4c2f7ab7bc0e2d2 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -2557,6 +2557,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
 	value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
 	value &= ~DITHER_CONTROL_MASK;
 	value &= ~BASE_COLOR_SIZE_MASK;
+	if (dc->soc->has_nvdisplay && dc->cmu_output_lut) {
+		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
+		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
+
+		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
+				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
+
+		value |= CMU_ENABLE_ENABLE;
+	}
 
 	switch (state->bpc) {
 	case 6:
@@ -2921,6 +2932,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
 	if (err < 0)
 		dev_err(sor->dev, "failed to attach SOR: %d\n", err);
 
+	if (dc->soc->has_nvdisplay && dc->cmu_output_lut) {
+		value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
+		tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
+		tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_phys),
+				DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
+
+		tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
+				DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
+
+		value |= CMU_ENABLE_ENABLE;
+		tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
+	}
+
 	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
 	value |= SOR_ENABLE(sor->index);
 	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);

---
base-commit: 2febe6e6ee6e34c7754eff3c4d81aa7b0dcb7979
change-id: 20251031-tegra-drm-cmu-697e8e030978

Best regards,
-- 
Aaron Kling <webgeek1234@gmail.com>



^ permalink raw reply related

* Re: [PATCH 1/2] memory: tegra: Add T238 MC support
From: Ashish Mhetre @ 2026-04-06  7:20 UTC (permalink / raw)
  To: Jon Hunter, krzk, robh, conor+dt, =thierry.reding, sumitg
  Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <1ec86de6-9282-46fb-bdba-521ac25b5fc8@nvidia.com>



On 3/31/2026 5:08 PM, Jon Hunter wrote:
>
>
> On 31/03/2026 12:23, Ashish Mhetre wrote:
>> Add Memory Controller driver support for Tegra238 SOC, including:
>> - MC client definitions with Tegra238-specific stream IDs
>> - Reuse of Tegra234 ICC operations for bandwidth management via BPMP-FW
>> - Device tree compatible string "nvidia,tegra238-mc"
>>
>> Export tegra234_mc_icc_ops so it can be shared with the Tegra238 MC
>> driver, as both SoCs use the same ICC aggregation and bandwidth
>> management logic.
>>
>> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
>> ---
>>   drivers/memory/tegra/Makefile   |   1 +
>>   drivers/memory/tegra/mc.c       |   3 +
>>   drivers/memory/tegra/mc.h       |   6 +
>>   drivers/memory/tegra/tegra234.c |   2 +-
>>   drivers/memory/tegra/tegra238.c | 395 ++++++++++++++++++++++++++++++++
>>   5 files changed, 406 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/memory/tegra/tegra238.c
>>
>> diff --git a/drivers/memory/tegra/Makefile 
>> b/drivers/memory/tegra/Makefile
>> index 6334601e6120..0d50e37d43af 100644
>> --- a/drivers/memory/tegra/Makefile
>> +++ b/drivers/memory/tegra/Makefile
>> @@ -10,6 +10,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
>>   tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
>>   tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o
>>   tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o
>> +tegra-mc-$(CONFIG_ARCH_TEGRA_238_SOC) += tegra186.o tegra238.o
>>   tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
>>     obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
>> diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
>> index d620660da331..10ef3c323e22 100644
>> --- a/drivers/memory/tegra/mc.c
>> +++ b/drivers/memory/tegra/mc.c
>> @@ -49,6 +49,9 @@ static const struct of_device_id 
>> tegra_mc_of_match[] = {
>>   #ifdef CONFIG_ARCH_TEGRA_234_SOC
>>       { .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc },
>>   #endif
>> +#ifdef CONFIG_ARCH_TEGRA_238_SOC
>> +    { .compatible = "nvidia,tegra238-mc", .data = &tegra238_mc_soc },
>> +#endif
>
> It is always better/preferred for the dt-binding patch to be 1st in 
> the series. The above does not exist until after patch 2 is applied.
>

Ack, I will resend with correct ordering.

>>   #ifdef CONFIG_ARCH_TEGRA_264_SOC
>>       { .compatible = "nvidia,tegra264-mc", .data = &tegra264_mc_soc },
>>   #endif
>> diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
>> index 649b54369263..d0da4a5f192d 100644
>> --- a/drivers/memory/tegra/mc.h
>> +++ b/drivers/memory/tegra/mc.h
>> @@ -238,6 +238,11 @@ extern const struct tegra_mc_soc tegra194_mc_soc;
>>     #ifdef CONFIG_ARCH_TEGRA_234_SOC
>>   extern const struct tegra_mc_soc tegra234_mc_soc;
>> +extern const struct tegra_mc_icc_ops tegra234_mc_icc_ops;
>> +#endif
>> +
>> +#ifdef CONFIG_ARCH_TEGRA_238_SOC
>> +extern const struct tegra_mc_soc tegra238_mc_soc;
>>   #endif
>
> Does this work? Tegra238 is dependent upon stuff in Tegra234, but 
> there is no guarantee that both of these CONFIG options are always 
> enabled?
>

Good point, thanks for catching this Jon. If CONFIG_ARCH_TEGRA_238_SOC
is enabled without CONFIG_ARCH_TEGRA_234_SOC, the build would fail
since tegra234_mc_icc_ops wouldn't be compiled or declared.
I'll fix this in V2 with combined Tegra234 and Tegra238 SOC guard for 
struct.

>>     #ifdef CONFIG_ARCH_TEGRA_264_SOC
>> @@ -256,6 +261,7 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
>>   #if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
>>       defined(CONFIG_ARCH_TEGRA_194_SOC) || \
>>       defined(CONFIG_ARCH_TEGRA_234_SOC) || \
>> +    defined(CONFIG_ARCH_TEGRA_238_SOC) || \
>>       defined(CONFIG_ARCH_TEGRA_264_SOC)
>>   extern const struct tegra_mc_ops tegra186_mc_ops;
>>   #endif
>> diff --git a/drivers/memory/tegra/tegra234.c 
>> b/drivers/memory/tegra/tegra234.c
>> index 87b22038a5fb..9fbd34d4abe0 100644
>> --- a/drivers/memory/tegra/tegra234.c
>> +++ b/drivers/memory/tegra/tegra234.c
>> @@ -1125,7 +1125,7 @@ static int tegra234_mc_icc_get_init_bw(struct 
>> icc_node *node, u32 *avg, u32 *pea
>>       return 0;
>>   }
>>   -static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
>> +const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
>>       .xlate = tegra_mc_icc_xlate,
>>       .aggregate = tegra234_mc_icc_aggregate,
>>       .get_bw = tegra234_mc_icc_get_init_bw,
>> diff --git a/drivers/memory/tegra/tegra238.c 
>> b/drivers/memory/tegra/tegra238.c
>> new file mode 100644
>> index 000000000000..5abdca16a275
>> --- /dev/null
>> +++ b/drivers/memory/tegra/tegra238.c
>> @@ -0,0 +1,395 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2026, NVIDIA CORPORATION.  All rights reserved.
>> + */
>
> ...
>
>> +const struct tegra_mc_soc tegra238_mc_soc = {
>> +    .num_clients = ARRAY_SIZE(tegra238_mc_clients),
>> +    .clients = tegra238_mc_clients,
>> +    .num_address_bits = 40,
>> +    .num_channels = 8,
>> +    .client_id_mask = 0x1ff,
>> +    .intmasks = tegra238_mc_intmasks,
>> +    .num_intmasks = ARRAY_SIZE(tegra238_mc_intmasks),
>> +    .has_addr_hi_reg = true,
>> +    .ops = &tegra186_mc_ops,
>> +    .icc_ops = &tegra234_mc_icc_ops,
>> +    .ch_intmask = 0x0000ff00,
>> +    .global_intstatus_channel_shift = 8,
>> +    /*
>> +     * Additionally, there are lite carveouts but those are not 
>> currently
>> +     * supported.
>> +     */
>
> I don't know what this means?
>

I have kept this comment similar to Tegra234. tegra_mc_get_carveout_info()
function uses num_carveouts variable as upper limit for supported carveouts.
On top of it, there are few lite carveouts which are supported by SOC 
but are
not used by the driver.
It's redundant info IMO and can be removed from both Tegra234 and Tegra238.
Jon, Can you please share your thoughts on this?

Thanks,
Ashish Mhetre

>> +    .num_carveouts = 32,
>> +    .regs = &tegra20_mc_regs,
>> +    .handle_irq = tegra30_mc_irq_handlers,
>> +    .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
>> +    .mc_addr_hi_mask = 0x3,
>> +    .mc_err_status_type_mask = (0x7 << 28),
>> +};
>
> Jon
>


^ permalink raw reply

* [PATCH 3/3] arm64: tegra: Correct Tegra234 p3740 interrupt flags
From: Krzysztof Kozlowski @ 2026-04-06  6:49 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
	Jonathan Hunter, devicetree, linux-tegra, linux-kernel
  Cc: Krzysztof Kozlowski
In-Reply-To: <20260406064935.27968-4-krzysztof.kozlowski@oss.qualcomm.com>

GPIO_ACTIVE_x flags are not correct in the context of interrupt flags.
These are simple defines so they could be used in DTS but they will not
have the same meaning:
1. GPIO_ACTIVE_HIGH = 0 => IRQ_TYPE_NONE
2. GPIO_ACTIVE_LOW  = 1 => IRQ_TYPE_EDGE_RISING

Realtek RT5540 codec driver requests interrupt on rising edge, so correct
the interrupt flags, assuming the author of the code wanted the similar
logical behavior behind the name "ACTIVE_xxx", this is:

  ACTIVE_HIGH  => IRQ_TYPE_EDGE_RISING

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
 arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
index 9ce55b4d2de8..97cede1fcb70 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
@@ -75,7 +75,7 @@ rt5640: audio-codec@1c {
 				compatible = "realtek,rt5640";
 				reg = <0x1c>;
 				interrupt-parent = <&gpio>;
-				interrupts = <TEGRA234_MAIN_GPIO(F, 3) GPIO_ACTIVE_HIGH>;
+				interrupts = <TEGRA234_MAIN_GPIO(F, 3) IRQ_TYPE_EDGE_RISING>;
 				clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>;
 				clock-names = "mclk";
 
-- 
2.51.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox