From: Philipp Zabel <p.zabel@pengutronix.de>
To: alsa-devel@alsa-project.org
Cc: Jean-Francois Moine <moinejf@free.fr>,
Koro Chen <koro.chen@mediatek.com>,
Lars-Peter Clausen <lars@metafoo.de>,
Russell King - ARM Linux <linux@arm.linux.org.uk>,
Philipp Zabel <p.zabel@pengutronix.de>,
Arnaud Pouliquen <arnaud.pouliquen@st.com>,
Liam Girdwood <lgirdwood@gmail.com>, Jyri Sarha <jsarha@ti.com>,
Cawa Cheng <cawa.cheng@mediatek.com>,
Mark Brown <broonie@kernel.org>,
linux-mediatek@lists.infradead.org,
Daniel Kurtz <djkurtz@chromium.org>,
kernel@pengutronix.de, Matthias Brugger <matthias.bgg@gmail.com>
Subject: [RFC v2 1/6] drm/mediatek: hdmi: Add audio interface to the hdmi-codec driver
Date: Mon, 4 Jan 2016 20:09:06 +0100 [thread overview]
Message-ID: <1451934551-21333-2-git-send-email-p.zabel@pengutronix.de> (raw)
In-Reply-To: <1451934551-21333-1-git-send-email-p.zabel@pengutronix.de>
Add the interface needed by Jyri's generic hdmi-codec driver [1] to start
or stop audio playback and to retrieve ELD (EDID like data) to limit the
supported audio formats to the HDMI sink capabilities.
[1] https://patchwork.kernel.org/patch/7215271/ ("ASoC: hdmi-codec: Add
hdmi-codec for external HDMI-encoders")
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
drivers/gpu/drm/mediatek/Kconfig | 1 +
drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c | 189 ++++++++++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_hdmi.c | 26 ++++
drivers/gpu/drm/mediatek/mtk_hdmi.h | 4 +
4 files changed, 220 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 829ab66..93b7ca9 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -17,6 +17,7 @@ config DRM_MEDIATEK
config DRM_MEDIATEK_HDMI
tristate "DRM HDMI Support for Mediatek SoCs"
depends on DRM_MEDIATEK
+ select SND_SOC_HDMI_CODEC if SND_SOC
select GENERIC_PHY
help
DRM/KMS HDMI driver for Mediatek SoCs
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c
index 5c1ec96..1a07ef3 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c
@@ -26,6 +26,7 @@
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <sound/hdmi-codec.h>
#include "mtk_cec.h"
#include "mtk_hdmi.h"
#include "mtk_hdmi_hw.h"
@@ -437,6 +438,192 @@ static irqreturn_t hdmi_flt_n_5v_irq_thread(int irq, void *arg)
return IRQ_HANDLED;
}
+/*
+ * HDMI audio codec callbacks
+ */
+
+static int mtk_hdmi_audio_hw_params(struct device *dev,
+ struct hdmi_codec_daifmt *daifmt,
+ struct hdmi_codec_params *params)
+{
+ struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
+ struct hdmi_audio_param hdmi_params;
+ unsigned int chan = params->cea.channels;
+
+ dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
+ params->sample_rate, params->sample_width, chan);
+
+ if (!hdmi->bridge.encoder || !hdmi->bridge.encoder->crtc)
+ return -ENODEV;
+
+ switch (chan) {
+ case 2:
+ hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0;
+ break;
+ case 4:
+ hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_4_0;
+ break;
+ case 6:
+ hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_5_1;
+ break;
+ case 8:
+ hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_7_1;
+ break;
+ default:
+ dev_err(hdmi->dev, "channel[%d] not supported!\n", chan);
+ return -EINVAL;
+ }
+
+ switch (params->sample_rate) {
+ case 32000:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_32000;
+ hdmi_params.iec_frame_fs = HDMI_IEC_32K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0x3;
+ break;
+ case 44100:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_44100;
+ hdmi_params.iec_frame_fs = HDMI_IEC_44K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0;
+ break;
+ case 48000:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
+ hdmi_params.iec_frame_fs = HDMI_IEC_48K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0x2;
+ break;
+ case 88200:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_88200;
+ hdmi_params.iec_frame_fs = HDMI_IEC_88K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0x8;
+ break;
+ case 96000:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_96000;
+ hdmi_params.iec_frame_fs = HDMI_IEC_96K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0xa;
+ break;
+ case 176400:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_176400;
+ hdmi_params.iec_frame_fs = HDMI_IEC_176K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0xc;
+ break;
+ case 192000:
+ hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_192000;
+ hdmi_params.iec_frame_fs = HDMI_IEC_192K;
+ /* channel status byte 3: fs and clock accuracy */
+ hdmi_params.hdmi_l_channel_state[3] = 0xe;
+ break;
+ default:
+ dev_err(hdmi->dev, "rate[%d] not supported!\n",
+ params->sample_rate);
+ return -EINVAL;
+ }
+
+ switch (daifmt->fmt) {
+ case HDMI_I2S:
+ hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
+ hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+ hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S;
+ hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
+ hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
+ break;
+ default:
+ dev_err(hdmi->dev, "%s: Invalid format %d\n", __func__,
+ daifmt->fmt);
+ return -EINVAL;
+ }
+
+ /* channel status */
+ /* byte 0: no copyright is asserted, mode 0 */
+ hdmi_params.hdmi_l_channel_state[0] = 1 << 2;
+ /* byte 1: category code */
+ hdmi_params.hdmi_l_channel_state[1] = 0;
+ /* byte 2: source/channel number don't take into account */
+ hdmi_params.hdmi_l_channel_state[2] = 0;
+ /* byte 4: word length 16bits */
+ hdmi_params.hdmi_l_channel_state[4] = 0x2;
+ memcpy(hdmi_params.hdmi_r_channel_state,
+ hdmi_params.hdmi_l_channel_state,
+ sizeof(hdmi_params.hdmi_l_channel_state));
+
+ mtk_hdmi_audio_set_param(hdmi, &hdmi_params);
+
+ return 0;
+}
+
+static int mtk_hdmi_audio_startup(struct device *dev,
+ void (*abort_cb)(struct device *dev))
+{
+ struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ mtk_hdmi_audio_enable(hdmi);
+
+ return 0;
+}
+
+static void mtk_hdmi_audio_shutdown(struct device *dev)
+{
+ struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ mtk_hdmi_audio_disable(hdmi);
+}
+
+int mtk_hdmi_audio_digital_mute(struct device *dev, bool enable)
+{
+ struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s(%d)\n", __func__, enable);
+
+ mtk_hdmi_hw_aud_mute(hdmi, enable);
+
+ return 0;
+}
+
+static int mtk_hdmi_audio_get_eld(struct device *dev, uint8_t *buf, size_t len)
+{
+ struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ memcpy(buf, hdmi->conn.eld, min(sizeof(hdmi->conn.eld), len));
+
+ return 0;
+}
+
+static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = {
+ .hw_params = mtk_hdmi_audio_hw_params,
+ .audio_startup = mtk_hdmi_audio_startup,
+ .audio_shutdown = mtk_hdmi_audio_shutdown,
+ .digital_mute = mtk_hdmi_audio_digital_mute,
+ .get_eld = mtk_hdmi_audio_get_eld,
+};
+
+static void mtk_hdmi_register_audio_driver(struct device *dev)
+{
+ struct hdmi_codec_pdata codec_data = {
+ .ops = &mtk_hdmi_audio_codec_ops,
+ .max_i2s_channels = 2,
+ .i2s = 1,
+ };
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
+ PLATFORM_DEVID_AUTO, &codec_data,
+ sizeof(codec_data));
+ if (IS_ERR(pdev))
+ return;
+
+ DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
+}
+
static int mtk_drm_hdmi_probe(struct platform_device *pdev)
{
struct mtk_hdmi *hdmi;
@@ -485,6 +672,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
return ret;
}
+ mtk_hdmi_register_audio_driver(dev);
+
hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
hdmi->bridge.of_node = pdev->dev.of_node;
ret = drm_bridge_add(&hdmi->bridge);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 342beab..535a4d7 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -441,6 +441,32 @@ void mtk_hdmi_power_off(struct mtk_hdmi *hdmi)
mtk_hdmi_hw_make_reg_writable(hdmi, false);
}
+void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi)
+{
+ mtk_hdmi_aud_enable_packet(hdmi, true);
+ hdmi->audio_enable = true;
+}
+
+void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi)
+{
+ mtk_hdmi_aud_enable_packet(hdmi, false);
+ hdmi->audio_enable = false;
+}
+
+int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi,
+ struct hdmi_audio_param *param)
+{
+ if (!hdmi->audio_enable) {
+ dev_err(hdmi->dev, "hdmi audio is in disable state!\n");
+ return -EINVAL;
+ }
+ dev_info(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n",
+ param->aud_codec, param->aud_input_type,
+ param->aud_input_chan_type, param->aud_hdmi_fs);
+ memcpy(&hdmi->aud_param, param, sizeof(*param));
+ return mtk_hdmi_aud_output_config(hdmi, &hdmi->mode);
+}
+
int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
struct drm_display_mode *mode)
{
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h
index c072bcc..12e5614 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.h
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h
@@ -211,6 +211,10 @@ int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
struct drm_display_mode *mode);
void mtk_hdmi_power_on(struct mtk_hdmi *hdmi);
void mtk_hdmi_power_off(struct mtk_hdmi *hdmi);
+void mtk_hdmi_audio_enable(struct mtk_hdmi *hctx);
+void mtk_hdmi_audio_disable(struct mtk_hdmi *hctx);
+int mtk_hdmi_audio_set_param(struct mtk_hdmi *hctx,
+ struct hdmi_audio_param *param);
#if defined(CONFIG_DEBUG_FS)
int mtk_drm_hdmi_debugfs_init(struct mtk_hdmi *hdmi);
void mtk_drm_hdmi_debugfs_exit(struct mtk_hdmi *hdmi);
--
2.6.2
next prev parent reply other threads:[~2016-01-04 19:09 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-04 19:09 [RFC v2 0/6] ASoC: Add mediatek HDMI codec support Philipp Zabel
2016-01-04 19:09 ` Philipp Zabel [this message]
2016-01-04 22:29 ` [RFC v2 1/6] drm/mediatek: hdmi: Add audio interface to the hdmi-codec driver Russell King - ARM Linux
2016-01-05 14:56 ` Philipp Zabel
2016-01-04 19:11 ` [RFC v2 0/6] ASoC: Add mediatek HDMI codec support Russell King - ARM Linux
2016-01-04 19:18 ` [RFC v2 4/6] video: rmk's HDMI notification prototype Philipp Zabel
2016-01-04 19:18 ` [RFC v2 5/6] drm/mediatek: hdmi: issue notifications Philipp Zabel
[not found] ` <1451934551-21333-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2016-01-04 19:09 ` [RFC v2 2/6] ASoC: mediatek: address dai link array entries by enum Philipp Zabel
2016-01-04 19:15 ` [RFC v2 3/6] ASoC: mediatek: Add HDMI dai-links in the machine driver Philipp Zabel
2016-01-05 12:46 ` Mark Brown
2016-01-07 10:06 ` Philipp Zabel
2016-03-05 12:24 ` Applied "ASoC: mediatek: address dai link array entries by enum" to the asoc tree Mark Brown
2016-01-04 19:19 ` [RFC v2 6/6] ASoC: hdmi-codec: Use HDMI notifications to add jack support Philipp Zabel
2016-01-07 17:09 ` Jyri Sarha
2016-01-08 8:43 ` Philipp Zabel
2016-01-08 9:57 ` Jyri Sarha
2016-01-08 10:46 ` Russell King - ARM Linux
2016-01-08 10:52 ` Takashi Iwai
2016-01-08 12:55 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1451934551-21333-2-git-send-email-p.zabel@pengutronix.de \
--to=p.zabel@pengutronix.de \
--cc=alsa-devel@alsa-project.org \
--cc=arnaud.pouliquen@st.com \
--cc=broonie@kernel.org \
--cc=cawa.cheng@mediatek.com \
--cc=djkurtz@chromium.org \
--cc=jsarha@ti.com \
--cc=kernel@pengutronix.de \
--cc=koro.chen@mediatek.com \
--cc=lars@metafoo.de \
--cc=lgirdwood@gmail.com \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux@arm.linux.org.uk \
--cc=matthias.bgg@gmail.com \
--cc=moinejf@free.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).