From 04dd17822334871b23ea2862f7798fb0e0007777 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 11 May 2024 08:53:19 +0000 Subject: [PATCH] change otg to host mode --- kernel/drivers/gpu/drm/tegra/output.c | 143 +++++++++++++++++++++++++++-------------------- 1 files changed, 82 insertions(+), 61 deletions(-) diff --git a/kernel/drivers/gpu/drm/tegra/output.c b/kernel/drivers/gpu/drm/tegra/output.c index c662efc..47d26b5 100644 --- a/kernel/drivers/gpu/drm/tegra/output.c +++ b/kernel/drivers/gpu/drm/tegra/output.c @@ -1,14 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2012 Avionic Design GmbH * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_simple_kms_helper.h> #include "drm.h" #include "dc.h" @@ -26,7 +25,7 @@ * ignore any other means of obtaining a mode. */ if (output->panel) { - err = output->panel->funcs->get_modes(output->panel); + err = drm_panel_get_modes(output->panel, connector); if (err > 0) return err; } @@ -36,7 +35,7 @@ else if (output->ddc) edid = drm_get_edid(connector, output->ddc); - cec_notifier_set_phys_addr_from_edid(output->notifier, edid); + cec_notifier_set_phys_addr_from_edid(output->cec, edid); drm_connector_update_edid_property(connector, edid); if (edid) { @@ -53,18 +52,11 @@ struct tegra_output *output = connector_to_output(connector); enum drm_connector_status status = connector_status_unknown; - if (gpio_is_valid(output->hpd_gpio)) { - if (output->hpd_gpio_flags & OF_GPIO_ACTIVE_LOW) { - if (gpio_get_value(output->hpd_gpio) != 0) - status = connector_status_disconnected; - else - status = connector_status_connected; - } else { - if (gpio_get_value(output->hpd_gpio) == 0) - status = connector_status_disconnected; - else - status = connector_status_connected; - } + if (output->hpd_gpio) { + if (gpiod_get_value(output->hpd_gpio) == 0) + status = connector_status_disconnected; + else + status = connector_status_connected; } else { if (!output->panel) status = connector_status_disconnected; @@ -73,20 +65,20 @@ } if (status != connector_status_connected) - cec_notifier_phys_addr_invalidate(output->notifier); + cec_notifier_phys_addr_invalidate(output->cec); return status; } void tegra_output_connector_destroy(struct drm_connector *connector) { + struct tegra_output *output = connector_to_output(connector); + + if (output->cec) + cec_notifier_conn_unregister(output->cec); + drm_connector_unregister(connector); drm_connector_cleanup(connector); -} - -void tegra_output_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); } static irqreturn_t hpd_irq(int irq, void *data) @@ -102,51 +94,61 @@ int tegra_output_probe(struct tegra_output *output) { struct device_node *ddc, *panel; + unsigned long flags; int err, size; if (!output->of_node) output->of_node = output->dev->of_node; + err = drm_of_find_panel_or_bridge(output->of_node, -1, -1, + &output->panel, &output->bridge); + if (err && err != -ENODEV) + return err; + panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); if (panel) { + /* + * Don't mix nvidia,panel phandle with the graph in a + * device-tree. + */ + WARN_ON(output->panel || output->bridge); + output->panel = of_drm_find_panel(panel); + of_node_put(panel); + if (IS_ERR(output->panel)) return PTR_ERR(output->panel); - - of_node_put(panel); } output->edid = of_get_property(output->of_node, "nvidia,edid", &size); ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); if (ddc) { - output->ddc = of_find_i2c_adapter_by_node(ddc); + output->ddc = of_get_i2c_adapter_by_node(ddc); + of_node_put(ddc); + if (!output->ddc) { err = -EPROBE_DEFER; - of_node_put(ddc); return err; } - - of_node_put(ddc); } - output->hpd_gpio = of_get_named_gpio_flags(output->of_node, - "nvidia,hpd-gpio", 0, - &output->hpd_gpio_flags); - if (gpio_is_valid(output->hpd_gpio)) { - unsigned long flags; + output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev, + output->of_node, + "nvidia,hpd-gpio", 0, + GPIOD_IN, + "HDMI hotplug detect"); + if (IS_ERR(output->hpd_gpio)) { + if (PTR_ERR(output->hpd_gpio) != -ENOENT) + return PTR_ERR(output->hpd_gpio); - err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN, - "HDMI hotplug detect"); - if (err < 0) { - dev_err(output->dev, "gpio_request_one(): %d\n", err); - return err; - } + output->hpd_gpio = NULL; + } - err = gpio_to_irq(output->hpd_gpio); + if (output->hpd_gpio) { + err = gpiod_to_irq(output->hpd_gpio); if (err < 0) { - dev_err(output->dev, "gpio_to_irq(): %d\n", err); - gpio_free(output->hpd_gpio); + dev_err(output->dev, "gpiod_to_irq(): %d\n", err); return err; } @@ -160,7 +162,6 @@ if (err < 0) { dev_err(output->dev, "failed to request IRQ#%u: %d\n", output->hpd_irq, err); - gpio_free(output->hpd_gpio); return err; } @@ -179,31 +180,38 @@ void tegra_output_remove(struct tegra_output *output) { - if (gpio_is_valid(output->hpd_gpio)) { + if (output->hpd_gpio) free_irq(output->hpd_irq, output); - gpio_free(output->hpd_gpio); - } if (output->ddc) - put_device(&output->ddc->dev); + i2c_put_adapter(output->ddc); } int tegra_output_init(struct drm_device *drm, struct tegra_output *output) { - int err; - - if (output->panel) { - err = drm_panel_attach(output->panel, &output->connector); - if (err < 0) - return err; - } + int connector_type; /* * The connector is now registered and ready to receive hotplug events * so the hotplug interrupt can be enabled. */ - if (gpio_is_valid(output->hpd_gpio)) + if (output->hpd_gpio) enable_irq(output->hpd_irq); + + connector_type = output->connector.connector_type; + /* + * Create a CEC notifier for HDMI connector. + */ + if (connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector_type == DRM_MODE_CONNECTOR_HDMIB) { + struct cec_connector_info conn_info; + + cec_fill_conn_info_from_drm(&conn_info, &output->connector); + output->cec = cec_notifier_conn_register(output->dev, NULL, + &conn_info); + if (!output->cec) + return -ENOMEM; + } return 0; } @@ -214,11 +222,8 @@ * The connector is going away, so the interrupt must be disabled to * prevent the hotplug interrupt handler from potentially crashing. */ - if (gpio_is_valid(output->hpd_gpio)) + if (output->hpd_gpio) disable_irq(output->hpd_irq); - - if (output->panel) - drm_panel_detach(output->panel); } void tegra_output_find_possible_crtcs(struct tegra_output *output, @@ -242,3 +247,19 @@ output->encoder.possible_crtcs = mask; } + +int tegra_output_suspend(struct tegra_output *output) +{ + if (output->hpd_irq) + disable_irq(output->hpd_irq); + + return 0; +} + +int tegra_output_resume(struct tegra_output *output) +{ + if (output->hpd_irq) + enable_irq(output->hpd_irq); + + return 0; +} -- Gitblit v1.6.2