From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/gpu/drm/omapdrm/dss/hdmi4.c | 687 +++++++++++++++++++++++++++------------------------------
1 files changed, 327 insertions(+), 360 deletions(-)
diff --git a/kernel/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/kernel/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 5879f45..a14fbf0 100644
--- a/kernel/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/kernel/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -1,21 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* HDMI interface DSS driver for TI's OMAP4 family of SoCs.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
* Authors: Yong Zhi
* Mythri pk <mythripk@ti.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "HDMI"
@@ -31,13 +20,15 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
-#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/component.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <sound/omap-hdmi-audio.h>
#include <media/cec.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_state_helper.h>
#include "omapdss.h"
#include "hdmi4_core.h"
@@ -108,26 +99,6 @@
return IRQ_HANDLED;
}
-static int hdmi_init_regulator(struct omap_hdmi *hdmi)
-{
- struct regulator *reg;
-
- if (hdmi->vdda_reg != NULL)
- return 0;
-
- reg = devm_regulator_get(&hdmi->pdev->dev, "vdda");
-
- if (IS_ERR(reg)) {
- if (PTR_ERR(reg) != -EPROBE_DEFER)
- DSSERR("can't get VDDA regulator\n");
- return PTR_ERR(reg);
- }
-
- hdmi->vdda_reg = reg;
-
- return 0;
-}
-
static int hdmi_power_on_core(struct omap_hdmi *hdmi)
{
int r;
@@ -174,7 +145,7 @@
static int hdmi_power_on_full(struct omap_hdmi *hdmi)
{
int r;
- struct videomode *vm;
+ const struct videomode *vm;
struct hdmi_wp_data *wp = &hdmi->wp;
struct dss_pll_clock_info hdmi_cinfo = { 0 };
unsigned int pc;
@@ -227,9 +198,6 @@
hdmi4_configure(&hdmi->core, &hdmi->wp, &hdmi->cfg);
- /* tv size */
- dss_mgr_set_timings(&hdmi->output, vm);
-
r = dss_mgr_enable(&hdmi->output);
if (r)
goto err_mgr_enable;
@@ -271,39 +239,6 @@
hdmi_power_off_core(hdmi);
}
-static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- if (!dispc_mgr_timings_ok(hdmi->dss->dispc, dssdev->dispc_channel, vm))
- return -EINVAL;
-
- return 0;
-}
-
-static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- mutex_lock(&hdmi->lock);
-
- hdmi->cfg.vm = *vm;
-
- dispc_set_tv_pclk(hdmi->dss->dispc, vm->pixelclock);
-
- mutex_unlock(&hdmi->lock);
-}
-
-static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- *vm = hdmi->cfg.vm;
-}
-
static int hdmi_dump_regs(struct seq_file *s, void *p)
{
struct omap_hdmi *hdmi = s->private;
@@ -325,23 +260,6 @@
return 0;
}
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
- int r;
-
- mutex_lock(&hdmi->lock);
-
- r = hdmi_runtime_get(hdmi);
- BUG_ON(r);
-
- r = hdmi4_read_edid(&hdmi->core, buf, len);
-
- hdmi_runtime_put(hdmi);
- mutex_unlock(&hdmi->lock);
-
- return r;
-}
-
static void hdmi_start_audio_stream(struct omap_hdmi *hd)
{
hdmi_wp_audio_enable(&hd->wp, true);
@@ -352,72 +270,6 @@
{
hdmi4_audio_stop(&hd->core, &hd->wp);
hdmi_wp_audio_enable(&hd->wp, false);
-}
-
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
- unsigned long flags;
- int r = 0;
-
- DSSDBG("ENTER hdmi_display_enable\n");
-
- mutex_lock(&hdmi->lock);
-
- if (!dssdev->dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- r = -ENODEV;
- goto err0;
- }
-
- r = hdmi_power_on_full(hdmi);
- if (r) {
- DSSERR("failed to power on device\n");
- goto err0;
- }
-
- if (hdmi->audio_configured) {
- r = hdmi4_audio_config(&hdmi->core, &hdmi->wp,
- &hdmi->audio_config,
- hdmi->cfg.vm.pixelclock);
- if (r) {
- DSSERR("Error restoring audio configuration: %d", r);
- hdmi->audio_abort_cb(&hdmi->pdev->dev);
- hdmi->audio_configured = false;
- }
- }
-
- spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
- if (hdmi->audio_configured && hdmi->audio_playing)
- hdmi_start_audio_stream(hdmi);
- hdmi->display_enabled = true;
- spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
- mutex_unlock(&hdmi->lock);
- return 0;
-
-err0:
- mutex_unlock(&hdmi->lock);
- return r;
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
- unsigned long flags;
-
- DSSDBG("Enter hdmi_display_disable\n");
-
- mutex_lock(&hdmi->lock);
-
- spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
- hdmi_stop_audio_stream(hdmi);
- hdmi->display_enabled = false;
- spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
- hdmi_power_off_full(hdmi);
-
- mutex_unlock(&hdmi->lock);
}
int hdmi4_core_enable(struct hdmi_core_data *core)
@@ -456,50 +308,139 @@
mutex_unlock(&hdmi->lock);
}
-static int hdmi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+/* -----------------------------------------------------------------------------
+ * DRM Bridge Operations
+ */
+
+static int hdmi4_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
- int r;
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
- r = hdmi_init_regulator(hdmi);
- if (r)
- return r;
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+ return -EINVAL;
- r = dss_mgr_connect(&hdmi->output, dssdev);
- if (r)
- return r;
-
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&hdmi->output, dssdev);
- return r;
- }
-
- return 0;
+ return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+ bridge, flags);
}
-static void hdmi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void hdmi4_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
- WARN_ON(dst != dssdev->dst);
+ mutex_lock(&hdmi->lock);
- if (dst != dssdev->dst)
+ drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm);
+
+ dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000);
+
+ mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi4_bridge_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
+{
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+ struct drm_atomic_state *state = bridge_state->base.state;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *connector;
+ struct drm_crtc_state *crtc_state;
+ unsigned long flags;
+ int ret;
+
+ /*
+ * None of these should fail, as the bridge can't be enabled without a
+ * valid CRTC to connector path with fully populated new states.
+ */
+ connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+ if (WARN_ON(!connector))
+ return;
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (WARN_ON(!conn_state))
+ return;
+ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ if (WARN_ON(!crtc_state))
return;
- omapdss_output_unset_device(dssdev);
+ hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi
+ ? HDMI_HDMI : HDMI_DVI;
- dss_mgr_disconnect(&hdmi->output, dssdev);
+ if (connector->display_info.is_hdmi) {
+ const struct drm_display_mode *mode;
+ struct hdmi_avi_infoframe avi;
+
+ mode = &crtc_state->adjusted_mode;
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
+ mode);
+ if (ret == 0)
+ hdmi->cfg.infoframe = avi;
+ }
+
+ mutex_lock(&hdmi->lock);
+
+ ret = hdmi_power_on_full(hdmi);
+ if (ret) {
+ DSSERR("failed to power on device\n");
+ goto done;
+ }
+
+ if (hdmi->audio_configured) {
+ ret = hdmi4_audio_config(&hdmi->core, &hdmi->wp,
+ &hdmi->audio_config,
+ hdmi->cfg.vm.pixelclock);
+ if (ret) {
+ DSSERR("Error restoring audio configuration: %d", ret);
+ hdmi->audio_abort_cb(&hdmi->pdev->dev);
+ hdmi->audio_configured = false;
+ }
+ }
+
+ spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+ if (hdmi->audio_configured && hdmi->audio_playing)
+ hdmi_start_audio_stream(hdmi);
+ hdmi->display_enabled = true;
+ spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+done:
+ mutex_unlock(&hdmi->lock);
}
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
- u8 *edid, int len)
+static void hdmi4_bridge_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+ unsigned long flags;
+
+ mutex_lock(&hdmi->lock);
+
+ spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+ hdmi_stop_audio_stream(hdmi);
+ hdmi->display_enabled = false;
+ spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+ hdmi_power_off_full(hdmi);
+
+ mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
+ enum drm_connector_status status)
+{
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+ if (status == connector_status_disconnected)
+ hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
+}
+
+static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+ struct edid *edid = NULL;
+ unsigned int cec_addr;
bool need_enable;
int r;
@@ -508,109 +449,70 @@
if (need_enable) {
r = hdmi4_core_enable(&hdmi->core);
if (r)
- return r;
+ return NULL;
}
- r = read_edid(hdmi, edid, len);
- if (r >= 256)
- hdmi4_cec_set_phys_addr(&hdmi->core,
- cec_get_edid_phys_addr(edid, r, NULL));
- else
- hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
+ mutex_lock(&hdmi->lock);
+ r = hdmi_runtime_get(hdmi);
+ BUG_ON(r);
+
+ r = hdmi4_core_ddc_init(&hdmi->core);
+ if (r)
+ goto done;
+
+ edid = drm_do_get_edid(connector, hdmi4_core_ddc_read, &hdmi->core);
+
+done:
+ hdmi_runtime_put(hdmi);
+ mutex_unlock(&hdmi->lock);
+
+ if (edid && edid->extensions) {
+ unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+ cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+ } else {
+ cec_addr = CEC_PHYS_ADDR_INVALID;
+ }
+
+ hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
+
if (need_enable)
hdmi4_core_disable(&hdmi->core);
- return r;
+ return edid;
}
-static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
-}
-
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
- const struct hdmi_avi_infoframe *avi)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- hdmi->cfg.infoframe = *avi;
- return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
- bool hdmi_mode)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
- return 0;
-}
-
-static const struct omapdss_hdmi_ops hdmi_ops = {
- .connect = hdmi_connect,
- .disconnect = hdmi_disconnect,
-
- .enable = hdmi_display_enable,
- .disable = hdmi_display_disable,
-
- .check_timings = hdmi_display_check_timing,
- .set_timings = hdmi_display_set_timing,
- .get_timings = hdmi_display_get_timings,
-
- .read_edid = hdmi_read_edid,
- .lost_hotplug = hdmi_lost_hotplug,
- .set_infoframe = hdmi_set_infoframe,
- .set_hdmi_mode = hdmi_set_hdmi_mode,
+static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
+ .attach = hdmi4_bridge_attach,
+ .mode_set = hdmi4_bridge_mode_set,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_enable = hdmi4_bridge_enable,
+ .atomic_disable = hdmi4_bridge_disable,
+ .hpd_notify = hdmi4_bridge_hpd_notify,
+ .get_edid = hdmi4_bridge_get_edid,
};
-static void hdmi_init_output(struct omap_hdmi *hdmi)
+static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
{
- struct omap_dss_device *out = &hdmi->output;
+ hdmi->bridge.funcs = &hdmi4_bridge_funcs;
+ hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+ hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+ hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
- out->dev = &hdmi->pdev->dev;
- out->id = OMAP_DSS_OUTPUT_HDMI;
- out->output_type = OMAP_DISPLAY_TYPE_HDMI;
- out->name = "hdmi.0";
- out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
- out->ops.hdmi = &hdmi_ops;
- out->owner = THIS_MODULE;
-
- omapdss_register_output(out);
+ drm_bridge_add(&hdmi->bridge);
}
-static void hdmi_uninit_output(struct omap_hdmi *hdmi)
+static void hdmi4_bridge_cleanup(struct omap_hdmi *hdmi)
{
- struct omap_dss_device *out = &hdmi->output;
-
- omapdss_unregister_output(out);
+ drm_bridge_remove(&hdmi->bridge);
}
-static int hdmi_probe_of(struct omap_hdmi *hdmi)
-{
- struct platform_device *pdev = hdmi->pdev;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *ep;
- int r;
+/* -----------------------------------------------------------------------------
+ * Audio Callbacks
+ */
- ep = of_graph_get_endpoint_by_regs(node, 0, 0);
- if (!ep)
- return 0;
-
- r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
- if (r)
- goto err;
-
- of_node_put(ep);
- return 0;
-
-err:
- of_node_put(ep);
- return r;
-}
-
-/* Audio callbacks */
static int hdmi_audio_startup(struct device *dev,
void (*abort_cb)(struct device *dev))
{
@@ -725,86 +627,49 @@
return 0;
}
-/* HDMI HW IP initialisation */
+/* -----------------------------------------------------------------------------
+ * Component Bind & Unbind
+ */
+
static int hdmi4_bind(struct device *dev, struct device *master, void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
struct dss_device *dss = dss_get_device(master);
- struct omap_hdmi *hdmi;
+ struct omap_hdmi *hdmi = dev_get_drvdata(dev);
int r;
- int irq;
- hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
- if (!hdmi)
- return -ENOMEM;
-
- hdmi->pdev = pdev;
hdmi->dss = dss;
- dev_set_drvdata(&pdev->dev, hdmi);
- mutex_init(&hdmi->lock);
- spin_lock_init(&hdmi->audio_playing_lock);
-
- r = hdmi_probe_of(hdmi);
+ r = hdmi_runtime_get(hdmi);
if (r)
- goto err_free;
+ return r;
- r = hdmi_wp_init(pdev, &hdmi->wp, 4);
+ r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);
if (r)
- goto err_free;
+ goto err_runtime_put;
- r = hdmi_pll_init(dss, pdev, &hdmi->pll, &hdmi->wp);
+ r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);
if (r)
- goto err_free;
-
- r = hdmi_phy_init(pdev, &hdmi->phy, 4);
- if (r)
- goto err_pll;
-
- r = hdmi4_core_init(pdev, &hdmi->core);
- if (r)
- goto err_pll;
-
- r = hdmi4_cec_init(pdev, &hdmi->core, &hdmi->wp);
- if (r)
- goto err_pll;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- DSSERR("platform_get_irq failed\n");
- r = -ENODEV;
- goto err_pll;
- }
-
- r = devm_request_threaded_irq(&pdev->dev, irq,
- NULL, hdmi_irq_handler,
- IRQF_ONESHOT, "OMAP HDMI", hdmi);
- if (r) {
- DSSERR("HDMI IRQ request failed\n");
- goto err_pll;
- }
-
- pm_runtime_enable(&pdev->dev);
-
- hdmi_init_output(hdmi);
+ goto err_pll_uninit;
r = hdmi_audio_register(hdmi);
if (r) {
DSSERR("Registering HDMI audio failed\n");
- hdmi_uninit_output(hdmi);
- pm_runtime_disable(&pdev->dev);
- return r;
+ goto err_cec_uninit;
}
hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
hdmi);
+ hdmi_runtime_put(hdmi);
+
return 0;
-err_pll:
+err_cec_uninit:
+ hdmi4_cec_uninit(&hdmi->core);
+err_pll_uninit:
hdmi_pll_uninit(&hdmi->pll);
-err_free:
- kfree(hdmi);
+err_runtime_put:
+ hdmi_runtime_put(hdmi);
return r;
}
@@ -817,15 +682,8 @@
if (hdmi->audio_pdev)
platform_device_unregister(hdmi->audio_pdev);
- hdmi_uninit_output(hdmi);
-
hdmi4_cec_uninit(&hdmi->core);
-
hdmi_pll_uninit(&hdmi->pll);
-
- pm_runtime_disable(dev);
-
- kfree(hdmi);
}
static const struct component_ops hdmi4_component_ops = {
@@ -833,42 +691,152 @@
.unbind = hdmi4_unbind,
};
+/* -----------------------------------------------------------------------------
+ * Probe & Remove, Suspend & Resume
+ */
+
+static int hdmi4_init_output(struct omap_hdmi *hdmi)
+{
+ struct omap_dss_device *out = &hdmi->output;
+ int r;
+
+ hdmi4_bridge_init(hdmi);
+
+ out->dev = &hdmi->pdev->dev;
+ out->id = OMAP_DSS_OUTPUT_HDMI;
+ out->type = OMAP_DISPLAY_TYPE_HDMI;
+ out->name = "hdmi.0";
+ out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
+ out->owner = THIS_MODULE;
+ out->of_port = 0;
+
+ r = omapdss_device_init_output(out, &hdmi->bridge);
+ if (r < 0) {
+ hdmi4_bridge_cleanup(hdmi);
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
+}
+
+static void hdmi4_uninit_output(struct omap_hdmi *hdmi)
+{
+ struct omap_dss_device *out = &hdmi->output;
+
+ omapdss_device_unregister(out);
+ omapdss_device_cleanup_output(out);
+
+ hdmi4_bridge_cleanup(hdmi);
+}
+
+static int hdmi4_probe_of(struct omap_hdmi *hdmi)
+{
+ struct platform_device *pdev = hdmi->pdev;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *ep;
+ int r;
+
+ ep = of_graph_get_endpoint_by_regs(node, 0, 0);
+ if (!ep)
+ return 0;
+
+ r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
+ of_node_put(ep);
+ return r;
+}
+
static int hdmi4_probe(struct platform_device *pdev)
{
- return component_add(&pdev->dev, &hdmi4_component_ops);
+ struct omap_hdmi *hdmi;
+ int irq;
+ int r;
+
+ hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ hdmi->pdev = pdev;
+
+ dev_set_drvdata(&pdev->dev, hdmi);
+
+ mutex_init(&hdmi->lock);
+ spin_lock_init(&hdmi->audio_playing_lock);
+
+ r = hdmi4_probe_of(hdmi);
+ if (r)
+ goto err_free;
+
+ r = hdmi_wp_init(pdev, &hdmi->wp, 4);
+ if (r)
+ goto err_free;
+
+ r = hdmi_phy_init(pdev, &hdmi->phy, 4);
+ if (r)
+ goto err_free;
+
+ r = hdmi4_core_init(pdev, &hdmi->core);
+ if (r)
+ goto err_free;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ DSSERR("platform_get_irq failed\n");
+ r = -ENODEV;
+ goto err_free;
+ }
+
+ r = devm_request_threaded_irq(&pdev->dev, irq,
+ NULL, hdmi_irq_handler,
+ IRQF_ONESHOT, "OMAP HDMI", hdmi);
+ if (r) {
+ DSSERR("HDMI IRQ request failed\n");
+ goto err_free;
+ }
+
+ hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda");
+ if (IS_ERR(hdmi->vdda_reg)) {
+ r = PTR_ERR(hdmi->vdda_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDA regulator\n");
+ goto err_free;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ r = hdmi4_init_output(hdmi);
+ if (r)
+ goto err_pm_disable;
+
+ r = component_add(&pdev->dev, &hdmi4_component_ops);
+ if (r)
+ goto err_uninit_output;
+
+ return 0;
+
+err_uninit_output:
+ hdmi4_uninit_output(hdmi);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_free:
+ kfree(hdmi);
+ return r;
}
static int hdmi4_remove(struct platform_device *pdev)
{
+ struct omap_hdmi *hdmi = platform_get_drvdata(pdev);
+
component_del(&pdev->dev, &hdmi4_component_ops);
+
+ hdmi4_uninit_output(hdmi);
+
+ pm_runtime_disable(&pdev->dev);
+
+ kfree(hdmi);
return 0;
}
-
-static int hdmi_runtime_suspend(struct device *dev)
-{
- struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-
- dispc_runtime_put(hdmi->dss->dispc);
-
- return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
- struct omap_hdmi *hdmi = dev_get_drvdata(dev);
- int r;
-
- r = dispc_runtime_get(hdmi->dss->dispc);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
- .runtime_suspend = hdmi_runtime_suspend,
- .runtime_resume = hdmi_runtime_resume,
-};
static const struct of_device_id hdmi_of_match[] = {
{ .compatible = "ti,omap4-hdmi", },
@@ -880,7 +848,6 @@
.remove = hdmi4_remove,
.driver = {
.name = "omapdss_hdmi",
- .pm = &hdmi_pm_ops,
.of_match_table = hdmi_of_match,
.suppress_bind_attrs = true,
},
--
Gitblit v1.6.2