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

Commit f1427016 authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Rob Clark
Browse files

drm: msm: Add ASoC generic hdmi audio codec support.



This patch adds support to generic audio codec via
ASoC hdmi-codec infrastucture which is merged recently.

Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
[rebased on efc9194b]
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 79c21187
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@ config DRM_MSM
	select SHMEM
	select SHMEM
	select TMPFS
	select TMPFS
	select QCOM_SCM
	select QCOM_SCM
	select SND_SOC_HDMI_CODEC if SND_SOC
	default y
	default y
	help
	help
	  DRM/KMS driver for MSM/snapdragon.
	  DRM/KMS driver for MSM/snapdragon.
+119 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/of_irq.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_gpio.h>


#include <sound/hdmi-codec.h>
#include "hdmi.h"
#include "hdmi.h"


void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
@@ -434,6 +435,114 @@ static int msm_hdmi_get_gpio(struct device_node *of_node, const char *name)
	return gpio;
	return gpio;
}
}


/*
 * HDMI audio codec callbacks
 */
static int msm_hdmi_audio_hw_params(struct device *dev, void *data,
				    struct hdmi_codec_daifmt *daifmt,
				    struct hdmi_codec_params *params)
{
	struct hdmi *hdmi = dev_get_drvdata(dev);
	unsigned int chan;
	unsigned int channel_allocation = 0;
	unsigned int rate;
	unsigned int level_shift  = 0; /* 0dB */
	bool down_mix = false;

	dev_dbg(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
		 params->sample_width, params->cea.channels);

	switch (params->cea.channels) {
	case 2:
		/* FR and FL speakers */
		channel_allocation  = 0;
		chan = MSM_HDMI_AUDIO_CHANNEL_2;
		break;
	case 4:
		/* FC, LFE, FR and FL speakers */
		channel_allocation  = 0x3;
		chan = MSM_HDMI_AUDIO_CHANNEL_4;
		break;
	case 6:
		/* RR, RL, FC, LFE, FR and FL speakers */
		channel_allocation  = 0x0B;
		chan = MSM_HDMI_AUDIO_CHANNEL_6;
		break;
	case 8:
		/* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
		channel_allocation  = 0x1F;
		chan = MSM_HDMI_AUDIO_CHANNEL_8;
		break;
	default:
		return -EINVAL;
	}

	switch (params->sample_rate) {
	case 32000:
		rate = HDMI_SAMPLE_RATE_32KHZ;
		break;
	case 44100:
		rate = HDMI_SAMPLE_RATE_44_1KHZ;
		break;
	case 48000:
		rate = HDMI_SAMPLE_RATE_48KHZ;
		break;
	case 88200:
		rate = HDMI_SAMPLE_RATE_88_2KHZ;
		break;
	case 96000:
		rate = HDMI_SAMPLE_RATE_96KHZ;
		break;
	case 176400:
		rate = HDMI_SAMPLE_RATE_176_4KHZ;
		break;
	case 192000:
		rate = HDMI_SAMPLE_RATE_192KHZ;
		break;
	default:
		dev_err(dev, "rate[%d] not supported!\n",
			params->sample_rate);
		return -EINVAL;
	}

	msm_hdmi_audio_set_sample_rate(hdmi, rate);
	msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation,
			      level_shift, down_mix);

	return 0;
}

static void msm_hdmi_audio_shutdown(struct device *dev, void *data)
{
	struct hdmi *hdmi = dev_get_drvdata(dev);

	msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
}

static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
	.hw_params = msm_hdmi_audio_hw_params,
	.audio_shutdown = msm_hdmi_audio_shutdown,
};

static struct hdmi_codec_pdata codec_data = {
	.ops = &msm_hdmi_audio_codec_ops,
	.max_i2s_channels = 8,
	.i2s = 1,
};

static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
{
	hdmi->audio_pdev = platform_device_register_data(dev,
							 HDMI_CODEC_DRV_NAME,
							 PLATFORM_DEVID_AUTO,
							 &codec_data,
							 sizeof(codec_data));
	if (IS_ERR(hdmi->audio_pdev))
		return PTR_ERR(hdmi->audio_pdev);

	return 0;
}

static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
{
{
	struct drm_device *drm = dev_get_drvdata(master);
	struct drm_device *drm = dev_get_drvdata(master);
@@ -441,7 +550,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
	static struct hdmi_platform_config *hdmi_cfg;
	static struct hdmi_platform_config *hdmi_cfg;
	struct hdmi *hdmi;
	struct hdmi *hdmi;
	struct device_node *of_node = dev->of_node;
	struct device_node *of_node = dev->of_node;
	int i;
	int i, err;


	hdmi_cfg = (struct hdmi_platform_config *)
	hdmi_cfg = (struct hdmi_platform_config *)
			of_device_get_match_data(dev);
			of_device_get_match_data(dev);
@@ -468,6 +577,12 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
		return PTR_ERR(hdmi);
		return PTR_ERR(hdmi);
	priv->hdmi = hdmi;
	priv->hdmi = hdmi;


	err = msm_hdmi_register_audio_driver(hdmi, dev);
	if (err) {
		DRM_ERROR("Failed to attach an audio codec %d\n", err);
		hdmi->audio_pdev = NULL;
	}

	return 0;
	return 0;
}
}


@@ -477,6 +592,9 @@ static void msm_hdmi_unbind(struct device *dev, struct device *master,
	struct drm_device *drm = dev_get_drvdata(master);
	struct drm_device *drm = dev_get_drvdata(master);
	struct msm_drm_private *priv = drm->dev_private;
	struct msm_drm_private *priv = drm->dev_private;
	if (priv->hdmi) {
	if (priv->hdmi) {
		if (priv->hdmi->audio_pdev)
			platform_device_unregister(priv->hdmi->audio_pdev);

		msm_hdmi_destroy(priv->hdmi);
		msm_hdmi_destroy(priv->hdmi);
		priv->hdmi = NULL;
		priv->hdmi = NULL;
	}
	}
+14 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,7 @@ struct hdmi_hdcp_ctrl;
struct hdmi {
struct hdmi {
	struct drm_device *dev;
	struct drm_device *dev;
	struct platform_device *pdev;
	struct platform_device *pdev;
	struct platform_device *audio_pdev;


	const struct hdmi_platform_config *config;
	const struct hdmi_platform_config *config;


@@ -210,6 +211,19 @@ static inline int msm_hdmi_pll_8996_init(struct platform_device *pdev)
/*
/*
 * audio:
 * audio:
 */
 */
/* Supported HDMI Audio channels and rates */
#define	MSM_HDMI_AUDIO_CHANNEL_2	0
#define	MSM_HDMI_AUDIO_CHANNEL_4	1
#define	MSM_HDMI_AUDIO_CHANNEL_6	2
#define	MSM_HDMI_AUDIO_CHANNEL_8	3

#define	HDMI_SAMPLE_RATE_32KHZ		0
#define	HDMI_SAMPLE_RATE_44_1KHZ	1
#define	HDMI_SAMPLE_RATE_48KHZ		2
#define	HDMI_SAMPLE_RATE_88_2KHZ	3
#define	HDMI_SAMPLE_RATE_96KHZ		4
#define	HDMI_SAMPLE_RATE_176_4KHZ	5
#define	HDMI_SAMPLE_RATE_192KHZ		6


int msm_hdmi_audio_update(struct hdmi *hdmi);
int msm_hdmi_audio_update(struct hdmi *hdmi);
int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,