mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 22:26:55 +00:00
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: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
[rebased on efc9194
]
Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
79c21187ca
commit
f14270161a
3 changed files with 134 additions and 1 deletions
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue