[alsa-devel] [PATCH 2/4] ASoC: Add sh_mobile_hdmi sound support

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Aug 30 07:05:26 CEST 2010


Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 drivers/video/sh_mobile_hdmi.c |  153 ++++++++++++++++++++++++++++++++++++++++
 include/video/sh_mobile_hdmi.h |    3 +
 2 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index d25e348..f31d570 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -22,6 +22,8 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
 
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
@@ -202,6 +204,8 @@ enum hotplug_state {
 	HDMI_HOTPLUG_EDID_DONE,
 };
 
+static struct snd_soc_codec *sh_hdmi_codec;
+
 struct sh_hdmi {
 	void __iomem *base;
 	enum hotplug_state hp_state;
@@ -210,6 +214,7 @@ struct sh_hdmi {
 	struct fb_info *info;
 	struct delayed_work edid_work;
 	struct fb_var_screeninfo var;
+	struct snd_soc_codec codec;
 };
 
 static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -222,6 +227,101 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
 	return ioread8(hdmi->base + reg);
 }
 
+/************************************************************************
+
+
+			HDMI sound
+
+
+************************************************************************/
+static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
+				     unsigned int reg)
+{
+	struct sh_hdmi *hdmi;
+
+	codec = sh_hdmi_codec;
+	hdmi = codec->control_data;
+
+	return hdmi_read(hdmi, reg);
+}
+
+static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
+			     unsigned int reg,
+			     unsigned int value)
+{
+	struct sh_hdmi *hdmi;
+
+	codec = sh_hdmi_codec;
+	hdmi = codec->control_data;
+
+	hdmi_write(hdmi, value, reg);
+	return 0;
+}
+
+struct snd_soc_dai sh_hdmi_dai = {
+	.name = "SH MOBILE HDMI",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+	},
+};
+EXPORT_SYMBOL_GPL(sh_hdmi_dai);
+
+/*
+ * initialise the driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int sh_hdmi_snd_init(struct sh_hdmi *hdmi)
+{
+	struct snd_soc_codec *codec = &hdmi->codec;
+	int ret = 0;
+
+	if (sh_hdmi_codec) {
+		dev_err(codec->dev, "Another hdmi is registered\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	snd_soc_codec_set_drvdata(codec, hdmi);
+	codec->name		= "SH MOBILE HDMI";
+	codec->owner		= THIS_MODULE;
+	codec->read		= sh_hdmi_snd_read;
+	codec->write		= sh_hdmi_snd_write;
+	codec->dai		= &sh_hdmi_dai;
+	codec->num_dai		= 1;
+
+	sh_hdmi_dai.dev	= codec->dev;
+	sh_hdmi_codec	= codec;
+
+	ret = snd_soc_register_codec(codec);
+	if (ret) {
+		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_register_dai(&sh_hdmi_dai);
+	if (ret) {
+		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+		snd_soc_unregister_codec(codec);
+		return ret;
+	}
+
+	return ret;
+}
+
+/************************************************************************
+
+
+			HDMI video
+
+
+************************************************************************/
 /* External video parameter settings */
 static void hdmi_external_video_param(struct sh_hdmi *hdmi)
 {
@@ -792,6 +892,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
 	struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int irq = platform_get_irq(pdev, 0), ret;
+	struct snd_soc_codec *codec;
 	struct sh_hdmi *hdmi;
 	long rate;
 
@@ -806,6 +907,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->dev = &pdev->dev;
 
+	codec			= &hdmi->codec;
+	codec->dev		= &pdev->dev;
+	codec->control_data	= hdmi;
+	ret = sh_hdmi_snd_init(hdmi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to sound initialise\n");
+		goto egetclk;
+	}
+
 	hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
 	if (IS_ERR(hdmi->hdmi_clk)) {
 		ret = PTR_ERR(hdmi->hdmi_clk);
@@ -901,6 +1011,10 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int irq = platform_get_irq(pdev, 0);
 
+	snd_soc_unregister_dai(&sh_hdmi_dai);
+	snd_soc_unregister_codec(&hdmi->codec);
+	sh_hdmi_codec = NULL;
+
 	pdata->lcd_chan->board_cfg.display_on = NULL;
 	pdata->lcd_chan->board_cfg.display_off = NULL;
 	pdata->lcd_chan->board_cfg.board_data = NULL;
@@ -917,6 +1031,45 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int sh_hdmi_snd_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	int ret;
+
+	if (!sh_hdmi_codec) {
+		dev_err(&pdev->dev, "Codec device not registered\n");
+		return -ENODEV;
+	}
+
+	socdev->card->codec = sh_hdmi_codec;
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to create pcms\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "sh_mobile_hdmi Audio Codec");
+	return ret;
+}
+
+static int sh_hdmi_snd_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_sh_hdmi = {
+	.probe =	sh_hdmi_snd_probe,
+	.remove =	sh_hdmi_snd_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_sh_hdmi);
+
 static struct platform_driver sh_hdmi_driver = {
 	.remove		= __exit_p(sh_hdmi_remove),
 	.driver = {
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index 929c2d3..7b9fe18 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -35,4 +35,7 @@ struct sh_mobile_hdmi_info {
 	unsigned int			 flags;
 };
 
+extern struct snd_soc_dai sh_hdmi_dai;
+extern struct snd_soc_codec_device soc_codec_dev_sh_hdmi;
+
 #endif
-- 
1.7.0.4



More information about the Alsa-devel mailing list