drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
Extension
.c
Size
15491 bytes
Lines
529
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 */

#include <linux/delay.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_edid.h>
#include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_hdmi_state_helper.h>

#include "msm_kms.h"
#include "hdmi.h"

static void msm_hdmi_power_on(struct drm_bridge *bridge)
{
	struct drm_device *dev = bridge->dev;
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	int ret;

	pm_runtime_resume_and_get(&hdmi->pdev->dev);

	if (hdmi->extp_clk) {
		DBG("pixclock: %lu", hdmi->pixclock);
		ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock);
		if (ret)
			DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret);

		ret = clk_prepare_enable(hdmi->extp_clk);
		if (ret)
			DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret);
	}
}

static void power_off(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;

	/* TODO do we need to wait for final vblank somewhere before
	 * cutting the clocks?
	 */
	mdelay(16 + 4);

	if (hdmi->extp_clk)
		clk_disable_unprepare(hdmi->extp_clk);

	pm_runtime_put(&hdmi->pdev->dev);
}

#define AVI_IFRAME_LINE_NUMBER 1
#define SPD_IFRAME_LINE_NUMBER 1
#define VENSPEC_IFRAME_LINE_NUMBER 3

static int msm_hdmi_bridge_clear_avi_infoframe(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	u32 val;

	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
	val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND |
		 HDMI_INFOFRAME_CTRL0_AVI_CONT);
	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);

	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
	val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);

	return 0;
}

static int msm_hdmi_bridge_clear_audio_infoframe(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	u32 val;

	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
	val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND |
		 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT |
		 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE |
		 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE);
	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);

	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
	val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK;
	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);

Annotation

Implementation Notes