Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a626b68 authored by Slava Grigorev's avatar Slava Grigorev Committed by Alex Deucher
Browse files

radeon/audio: defined initial audio interface that gets initialized via detect() call

parent bfc1f97d
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -23,9 +23,10 @@
#include <linux/hdmi.h>
#include <drm/drmP.h>
#include "radeon.h"
#include "radeon_audio.h"
#include "sid.h"

static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
u32 dce6_endpoint_rreg(struct radeon_device *rdev,
			      u32 block_offset, u32 reg)
{
	unsigned long flags;
@@ -39,7 +40,7 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
	return r;
}

static void dce6_endpoint_wreg(struct radeon_device *rdev,
void dce6_endpoint_wreg(struct radeon_device *rdev,
			       u32 block_offset, u32 reg, u32 v)
{
	unsigned long flags;
@@ -54,10 +55,6 @@ static void dce6_endpoint_wreg(struct radeon_device *rdev,
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
}

#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
#define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v))


static void dce6_afmt_get_connected_pins(struct radeon_device *rdev)
{
	int i;
+3 −0
Original line number Diff line number Diff line
@@ -1757,6 +1757,9 @@ struct r600_audio {
	bool enabled;
	struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS];
	int num_pins;
	struct radeon_audio_funcs *hdmi_funcs;
	struct radeon_audio_funcs *dp_funcs;
	struct radeon_audio_basic_funcs *funcs;
};

/*
+95 −1
Original line number Diff line number Diff line
@@ -23,12 +23,18 @@
 */

#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include "radeon.h"
#include "atom.h"
#include "radeon_audio.h"

void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
		u8 enable_mask);
void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
		u8 enable_mask);
u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg);
void dce6_endpoint_wreg(struct radeon_device *rdev,
		u32 offset, u32 reg, u32 v);

static const u32 pin_offsets[7] =
{
@@ -41,6 +47,43 @@ static const u32 pin_offsets[7] =
	(0x5e90 - 0x5e00),
};

static u32 radeon_audio_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
{
	return RREG32(reg);
}

static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset,
		u32 reg, u32 v)
{
	WREG32(reg, v);
}

static struct radeon_audio_basic_funcs dce32_funcs = {
	.endpoint_rreg = radeon_audio_rreg,
	.endpoint_wreg = radeon_audio_wreg,
};

static struct radeon_audio_basic_funcs dce4_funcs = {
	.endpoint_rreg = radeon_audio_rreg,
	.endpoint_wreg = radeon_audio_wreg,
};

static struct radeon_audio_basic_funcs dce6_funcs = {
	.endpoint_rreg = dce6_endpoint_rreg,
	.endpoint_wreg = dce6_endpoint_wreg,
};

static void radeon_audio_interface_init(struct radeon_device *rdev)
{
	if (ASIC_IS_DCE6(rdev)) {
		rdev->audio.funcs = &dce6_funcs;
	} else if (ASIC_IS_DCE4(rdev)) {
		rdev->audio.funcs = &dce4_funcs;
	} else {
		rdev->audio.funcs = &dce32_funcs;
	}
}

static int radeon_audio_chipset_supported(struct radeon_device *rdev)
{
	return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
@@ -79,12 +122,63 @@ int radeon_audio_init(struct radeon_device *rdev)
		rdev->audio.pin[i].connected = false;
		rdev->audio.pin[i].offset = pin_offsets[i];
		rdev->audio.pin[i].id = i;
	}

	radeon_audio_interface_init(rdev);

	/* disable audio.  it will be set up later */
	for (i = 0; i < rdev->audio.num_pins; i++)
		if (ASIC_IS_DCE6(rdev))
			dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
		else
			r600_audio_enable(rdev, &rdev->audio.pin[i], false);

	return 0;
}

void radeon_audio_detect(struct drm_connector *connector,
	enum drm_connector_status status)
{
	if (!connector || !connector->encoder)
		return;

	if (status == connector_status_connected) {
		int sink_type;
		struct radeon_device *rdev = connector->encoder->dev->dev_private;
		struct radeon_connector *radeon_connector;
		struct radeon_encoder *radeon_encoder =
			to_radeon_encoder(connector->encoder);

		if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
			radeon_encoder->audio = 0;
			return;
		}

		radeon_connector = to_radeon_connector(connector);
		sink_type = radeon_dp_getsinktype(radeon_connector);

		if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
			sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
			radeon_encoder->audio = rdev->audio.dp_funcs;
		else
			radeon_encoder->audio = rdev->audio.hdmi_funcs;
		/* TODO: set up the sads, etc. and set the audio enable_mask */
	} else {
		/* TODO: reset the audio enable_mask */
	}
}

u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
{
	if (rdev->audio.funcs->endpoint_rreg)
		return rdev->audio.funcs->endpoint_rreg(rdev, offset, reg);

	return 0;
}

void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
	u32 reg, u32 v)
{
	if (rdev->audio.funcs->endpoint_wreg)
		rdev->audio.funcs->endpoint_wreg(rdev, offset, reg, v);
}
+26 −0
Original line number Diff line number Diff line
@@ -21,9 +21,35 @@
 *
 * Authors: Slava Grigorev <slava.grigorev@amd.com>
 */

#ifndef __RADEON_AUDIO_H__
#define __RADEON_AUDIO_H__

#include <linux/types.h>

#define RREG32_ENDPOINT(block, reg)		\
	radeon_audio_endpoint_rreg(rdev, (block), (reg))
#define WREG32_ENDPOINT(block, reg, v)	\
	radeon_audio_endpoint_wreg(rdev, (block), (reg), (v))

struct radeon_audio_basic_funcs
{
	u32  (*endpoint_rreg)(struct radeon_device *rdev, u32 offset, u32 reg);
	void (*endpoint_wreg)(struct radeon_device *rdev,
		u32 offset, u32 reg, u32 v);
};

struct radeon_audio_funcs
{
	/* TODO: add mode depended audio interface */
};

int radeon_audio_init(struct radeon_device *rdev);
void radeon_audio_detect(struct drm_connector *connector,
	enum drm_connector_status status);
u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
	u32 offset, u32 reg);
void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
	u32 offset,	u32 reg, u32 v);

#endif
+8 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <drm/drm_fb_helper.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
#include "radeon_audio.h"
#include "atom.h"

#include <linux/pm_runtime.h>
@@ -1332,6 +1333,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
	/* updated in get modes as well since we need to know if it's analog or digital */
	radeon_connector_update_scratch_regs(connector, ret);

	if (radeon_audio != 0)
		radeon_audio_detect(connector, ret);

exit:
	pm_runtime_mark_last_busy(connector->dev->dev);
	pm_runtime_put_autosuspend(connector->dev->dev);
@@ -1654,6 +1658,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
	}

	radeon_connector_update_scratch_regs(connector, ret);

	if (radeon_audio != 0)
		radeon_audio_detect(connector, ret);

out:
	pm_runtime_mark_last_busy(connector->dev->dev);
	pm_runtime_put_autosuspend(connector->dev->dev);
Loading