[alsa-devel] [PATCH 0/4] Add FSI - HDMI support
Dear Mark, Paul
These are FSI - HDMI prototype sound support
Kuninori Morimoto (4): fbdev: sh-mobile: Add HDMI sound type selection ASoC: Add sh_mobile_hdmi sound support ASoC: fsi-codec: Add FSI - HDMI support ARM: mach-shmobile: ap4evb: Add HDMI sound support
Paul
1st patch is depend on [PATCH] fbdev: sh-mobile_hdmi: remove un-necessity settings which I sent to LinuxSH ML in 2010/08/27
Best regards -- Kuninori Morimoto
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/video/sh_mobile_hdmi.c | 21 ++++++++++++++++++++- include/video/sh_mobile_hdmi.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletions(-)
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index afebe80..d25e348 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -318,6 +318,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi) */ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) { + u8 data; + struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; + /* * [7:4] L/R data swap control * [3:0] appropriate N[19:16] @@ -335,7 +338,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) * [6:5] set required down sampling rate if required * [4:3] set required audio source */ - hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); + switch (pdata->flags & HDMI_SRC_MASK) { + default: + /* FALL THROUGH */ + case HDMI_SRC_I2S: + data = (0x0 << 3); + break; + case HDMI_SRC_SPDIF: + data = (0x1 << 3); + break; + case HDMI_SRC_DSD: + data = (0x2 << 3); + break; + case HDMI_SRC_HBR: + data = (0x3 << 3); + break; + } + hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
/* [3:0] set sending channel number for channel status */ hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h index 577cf18..929c2d3 100644 --- a/include/video/sh_mobile_hdmi.h +++ b/include/video/sh_mobile_hdmi.h @@ -14,9 +14,25 @@ struct sh_mobile_lcdc_chan_cfg; struct device;
+/* + * flags format + * + * 0x0000000A + * + * A: Audio source select + */ + +/* Audio source select */ +#define HDMI_SRC_MASK (0xF << 0) +#define HDMI_SRC_I2S (0 << 0) /* default */ +#define HDMI_SRC_SPDIF (1 << 0) +#define HDMI_SRC_DSD (2 << 0) +#define HDMI_SRC_HBR (3 << 0) + struct sh_mobile_hdmi_info { struct sh_mobile_lcdc_chan_cfg *lcd_chan; struct device *lcd_dev; + unsigned int flags; };
#endif
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@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
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/Kconfig | 7 +++++ sound/soc/sh/Makefile | 2 + sound/soc/sh/fsi-hdmi.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 sound/soc/sh/fsi-hdmi.c
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 52d7e8e..6b224d2 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -62,6 +62,13 @@ config SND_FSI_DA7210 This option enables generic sound support for the FSI - DA7210 unit
+config SND_FSI_HDMI + bool "FSI-HDMI sound support" + depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI + help + This option enables generic sound support for the + FSI - HDMI unit + config SND_SIU_MIGOR tristate "SIU sound support on Migo-R" depends on SH_MIGOR diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 8a5a192..94476d4 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -16,9 +16,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o snd-soc-sh7760-ac97-objs := sh7760-ac97.o snd-soc-fsi-ak4642-objs := fsi-ak4642.o snd-soc-fsi-da7210-objs := fsi-da7210.o +snd-soc-fsi-hdmi-objs := fsi-hdmi.o snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o +obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c new file mode 100644 index 0000000..cb81b8c --- /dev/null +++ b/sound/soc/sh/fsi-hdmi.c @@ -0,0 +1,67 @@ +/* + * FSI - HDMI sound support + * + * Copyright (C) 2010 Renesas Solutions Corp. + * Kuninori Morimoto kuninori.morimoto.gx@renesas.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/platform_device.h> +#include <sound/sh_fsi.h> +#include <video/sh_mobile_hdmi.h> + +static struct snd_soc_dai_link fsi_dai_link = { + .name = "HDMI", + .stream_name = "HDMI", + .cpu_dai = &fsi_soc_dai[FSI_PORT_B], + .codec_dai = &sh_hdmi_dai, +}; + +static struct snd_soc_card fsi_soc_card = { + .name = "FSI", + .platform = &fsi_soc_platform, + .dai_link = &fsi_dai_link, + .num_links = 1, +}; + +static struct snd_soc_device fsi_snd_devdata = { + .card = &fsi_soc_card, + .codec_dev = &soc_codec_dev_sh_hdmi, +}; + +static struct platform_device *fsi_snd_device; + +static int __init fsi_hdmi_init(void) +{ + int ret = -ENOMEM; + + fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); + if (!fsi_snd_device) + goto out; + + platform_set_drvdata(fsi_snd_device, + &fsi_snd_devdata); + fsi_snd_devdata.dev = &fsi_snd_device->dev; + ret = platform_device_add(fsi_snd_device); + + if (ret) + platform_device_put(fsi_snd_device); + +out: + return ret; +} + +static void __exit fsi_hdmi_exit(void) +{ + platform_device_unregister(fsi_snd_device); +} + +module_init(fsi_hdmi_init); +module_exit(fsi_hdmi_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card"); +MODULE_AUTHOR("Kuninori Morimoto kuninori.morimoto.gx@renesas.com");
On Mon, 2010-08-30 at 14:05 +0900, Kuninori Morimoto wrote:
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
sound/soc/sh/Kconfig | 7 +++++ sound/soc/sh/Makefile | 2 + sound/soc/sh/fsi-hdmi.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 sound/soc/sh/fsi-hdmi.c
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 52d7e8e..6b224d2 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -62,6 +62,13 @@ config SND_FSI_DA7210 This option enables generic sound support for the FSI - DA7210 unit
+config SND_FSI_HDMI
- bool "FSI-HDMI sound support"
- depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
- help
This option enables generic sound support for the
FSI - HDMI unit
config SND_SIU_MIGOR tristate "SIU sound support on Migo-R" depends on SH_MIGOR diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 8a5a192..94476d4 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -16,9 +16,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o snd-soc-sh7760-ac97-objs := sh7760-ac97.o snd-soc-fsi-ak4642-objs := fsi-ak4642.o snd-soc-fsi-da7210-objs := fsi-da7210.o +snd-soc-fsi-hdmi-objs := fsi-hdmi.o snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o +obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c new file mode 100644 index 0000000..cb81b8c --- /dev/null +++ b/sound/soc/sh/fsi-hdmi.c @@ -0,0 +1,67 @@ +/*
- FSI - HDMI sound support
- Copyright (C) 2010 Renesas Solutions Corp.
- Kuninori Morimoto kuninori.morimoto.gx@renesas.com
- This file is subject to the terms and conditions of the GNU General Public
- License. See the file "COPYING" in the main directory of this archive
- for more details.
- */
+#include <linux/platform_device.h> +#include <sound/sh_fsi.h> +#include <video/sh_mobile_hdmi.h>
+static struct snd_soc_dai_link fsi_dai_link = {
- .name = "HDMI",
- .stream_name = "HDMI",
- .cpu_dai = &fsi_soc_dai[FSI_PORT_B],
- .codec_dai = &sh_hdmi_dai,
+};
+static struct snd_soc_card fsi_soc_card = {
- .name = "FSI",
- .platform = &fsi_soc_platform,
- .dai_link = &fsi_dai_link,
- .num_links = 1,
+};
+static struct snd_soc_device fsi_snd_devdata = {
- .card = &fsi_soc_card,
- .codec_dev = &soc_codec_dev_sh_hdmi,
+};
The DAI link construction has changed recently. Can you redo against Mark's for-2.6.37 branch.
Thanks
Liam
Dear Liam
Thank you for checking patch
The DAI link construction has changed recently. Can you redo against Mark's for-2.6.37 branch.
Thanks I will send v2 patch late this week.
Best regards -- Kuninori Morimoto
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- arch/arm/mach-shmobile/board-ap4evb.c | 56 ++++++++++++++++++++++++++++++++- 1 files changed, 55 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 1b95f12..a2489fe 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -516,6 +516,8 @@ static struct platform_device *qhd_devices[] __initdata = { /* FSI */ #define IRQ_FSI evt2irq(0x1840) #define FSIACKCR 0xE6150018 +#define FSIDIV 0xFE1F8000 +#define FSIDIV_SIZE 32 static void fsiackcr_init(struct clk *clk) { u32 status = __raw_readl(clk->enable_reg); @@ -536,12 +538,58 @@ static struct clk fsiackcr_clk = { .rate = 0, /* unknown */ };
+static int fsi_set_rate(int is_porta, int rate) +{ + struct clk *clk; + void __iomem *base; + int ret = 0; + + /* set_rate is not needed if port A */ + if (is_porta) + return 0; + + clk = clk_get(NULL, "fsib_clk"); + if (IS_ERR(clk)) + return -EINVAL; + + base = ioremap_nocache(FSIDIV, FSIDIV_SIZE); + if (!base) { + ret = -ENXIO; + goto fsi_set_rate_err; + } + + switch (rate) { + case 48000: + clk_set_rate(clk, clk_round_rate(clk, 85428000)); + __raw_writel(0x00070003, base + 0x8); + ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; + break; + default: + pr_err("unsupported rate in FSI2 port B\n"); + ret = -EINVAL; + break; + } + + iounmap(base); + +fsi_set_rate_err: + clk_put(clk); + + return ret; +} + static struct sh_fsi_platform_info fsi_info = { .porta_flags = SH_FSI_BRS_INV | SH_FSI_OUT_SLAVE_MODE | SH_FSI_IN_SLAVE_MODE | SH_FSI_OFMT(PCM) | SH_FSI_IFMT(PCM), + + .portb_flags = SH_FSI_BRS_INV | + SH_FSI_BRM_INV | + SH_FSI_LRS_INV | + SH_FSI_OFMT(SPDIF), + .set_rate = fsi_set_rate, };
static struct resource fsi_resources[] = { @@ -625,6 +673,7 @@ static struct platform_device lcdc1_device = { static struct sh_mobile_hdmi_info hdmi_info = { .lcd_chan = &sh_mobile_lcdc1_info.ch[0], .lcd_dev = &lcdc1_device.dev, + .flags = HDMI_SRC_SPDIF, };
static struct resource hdmi_resources[] = { @@ -863,6 +912,7 @@ static void __init ap4evb_map_io(void)
#define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define USCCR1 0xE6058144 static void __init ap4evb_init(void) { u32 srcr4; @@ -933,7 +983,7 @@ static void __init ap4evb_init(void) /* setup USB phy */ __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */
- /* enable FSI2 */ + /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); gpio_request(GPIO_FN_FSIAILR, NULL); gpio_request(GPIO_FN_FSIAISLD, NULL); @@ -946,6 +996,10 @@ static void __init ap4evb_init(void) gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */ gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */
+ /* setup FSI2 port B (HDMI) */ + gpio_request(GPIO_FN_FSIBCK, NULL); + __raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */ + /* set SPU2 clock to 119.6 MHz */ clk = clk_get(NULL, "spu_clk"); if (!IS_ERR(clk)) {
participants (2)
-
Kuninori Morimoto
-
Liam Girdwood