diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 11:34:25 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 11:34:25 -0800 |
commit | 460dc1eecf37263c8e3b17685ef236f0d236facb (patch) | |
tree | 1d20e367cefccddb969b48afaab140b8125cea4e /sound/soc/samsung | |
parent | 024e4ec1856d57bb78c06ec903d29dcf716f5f47 (diff) | |
parent | b531f81b0d70ffbe8d70500512483227cc532608 (diff) |
Merge tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"The biggest change in this update is the unification of HD-audio codec
parsers. Now the HD-audio codec is parsed in a generic parser code
which is invoked by each HD-audio codec driver.
Some background information is found in David Henningsson's blog
entry:
http://voices.canonical.com/david.henningsson/2013/01/18/upcoming-changes-to-the-intel-hda-drivers/
Other than that, some random updates/fixes like USB-audio and a bunch
of small AoC updates as usual.
Highlights:
- Unification of HD-audio parser code (aka generic parser)
- Support of new Intel HD-audio controller, new IDT codecs
- Fixes for HD-audio HDMI audio hotplug
- Haswell HDMI audio fixup
- Support of Creative CA0132 DSP code
- A few fixes of HDSP driver
- USB-audio fix for Roland A-PRO, M-Audio FT C600
- Support PM for aloop driver (and fixes Oops)
- Compress API updates for gapless playback support
For ASoC part:
- Support for a wider range of hardware in the compressed stream code
- The ability to mute capture streams as well as playback streams
while inactive
- DT support for AK4642, FSI, Samsung I2S and WM8962
- AC'97 support for Tegra
- New driver for max98090, replacing the stub which was there
- A new driver from Dialog
Note that due to dependencies, DTification of DMA support for Samsung
platforms (used only by the and I2S driver and SPI) is merged here as
well."
Fix up trivial conflict in drivers/spi/spi-s3c64xx.c due to removed code
being changed.
* tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (453 commits)
ALSA: usb: Fix Processing Unit Descriptor parsers
ALSA: hda - hdmi: Notify userspace when ELD control changes
ALSA: hda - hdmi: Protect ELD buffer
ALSA: hda - hdmi: Refactor hdmi_eld into parsed_hdmi_eld
ALSA: hda - hdmi: Do not expose eld data when eld is invalid
ALSA: hda - hdmi: ELD shouldn't be valid after unplug
ALSA: hda - Fix the silent speaker output on Fujitsu S7020 laptop
ALSA: hda - add quirks for mute LED on two HP machines
ALSA: usb/quirks, fix out-of-bounds access
ASoC: codecs: Add da7213 codec
ALSA: au88x0 - Define channel map for au88x0
ALSA: compress: add support for gapless playback
ALSA: hda - Remove speaker clicks on CX20549
ALSA: hda - Disable runtime PM for Intel 5 Series/3400
ALSA: hda - Increase badness for missing multi-io
ASoC: arizona: Automatically manage input mutes
ALSA: hda - Fix broken workaround for HDMI/SPDIF conflicts
ALSA: hda/ca0132 - Add missing \n to debug prints
ALSA: hda/ca0132 - Fix type of INVALID_CHIP_ADDRESS
ALSA: hda - update documentation for no-primary-hp fixup
...
Diffstat (limited to 'sound/soc/samsung')
-rw-r--r-- | sound/soc/samsung/Kconfig | 6 | ||||
-rw-r--r-- | sound/soc/samsung/dma.c | 3 | ||||
-rw-r--r-- | sound/soc/samsung/dma.h | 1 | ||||
-rw-r--r-- | sound/soc/samsung/i2s.c | 267 | ||||
-rw-r--r-- | sound/soc/samsung/i2s.h | 7 | ||||
-rw-r--r-- | sound/soc/samsung/s3c24xx-i2s.c | 2 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm8580.c | 7 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm8994.c | 30 |
8 files changed, 257 insertions, 66 deletions
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 3c7c3a59ed39..90e7e6653233 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -63,7 +63,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8580 config SND_SOC_SAMSUNG_SMDK_WM8994 tristate "SoC I2S Audio support for WM8994 on SMDK" - depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212) + depends on SND_SOC_SAMSUNG depends on I2C=y && GENERIC_HARDIRQS select MFD_WM8994 select SND_SOC_WM8994 @@ -162,7 +162,7 @@ config SND_SOC_GONI_AQUILA_WM8994 config SND_SOC_SAMSUNG_SMDK_SPDIF tristate "SoC S/PDIF Audio support for SMDK" - depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310 || MACH_SMDK4212) + depends on SND_SOC_SAMSUNG select SND_SAMSUNG_SPDIF help Say Y if you want to add support for SoC S/PDIF audio on the SMDK. @@ -177,7 +177,7 @@ config SND_SOC_SMDK_WM8580_PCM config SND_SOC_SMDK_WM8994_PCM tristate "SoC PCM Audio support for WM8994 on SMDK" - depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212) + depends on SND_SOC_SAMSUNG depends on I2C=y && GENERIC_HARDIRQS select MFD_WM8994 select SND_SOC_WM8994 diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index db87628d7630..21b79262010e 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -174,7 +174,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream, config.width = prtd->params->dma_size; config.fifo = prtd->params->dma_addr; prtd->params->ch = prtd->params->ops->request( - prtd->params->channel, &req); + prtd->params->channel, &req, rtd->cpu_dai->dev, + prtd->params->ch_name); prtd->params->ops->config(prtd->params->ch, &config); } diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 73d8c7c8a1e8..189a7a6d5020 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h @@ -19,6 +19,7 @@ struct s3c_dma_params { int dma_size; /* Size of the DMA transfer */ unsigned ch; struct samsung_dma_ops *ops; + char *ch_name; }; int asoc_dma_platform_register(struct device *dev); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index d2d124f1dd1b..d7231e336a7c 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -15,11 +15,15 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #include <linux/pm_runtime.h> #include <sound/soc.h> #include <sound/pcm_params.h> +#include <mach/dma.h> + #include <linux/platform_data/asoc-s3c.h> #include "dma.h" @@ -29,6 +33,15 @@ #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) +enum samsung_dai_type { + TYPE_PRI, + TYPE_SEC, +}; + +struct samsung_i2s_dai_data { + int dai_type; +}; + struct i2s_dai { /* Platform device for this DAI */ struct platform_device *pdev; @@ -66,6 +79,7 @@ struct i2s_dai { u32 suspend_i2smod; u32 suspend_i2scon; u32 suspend_i2spsr; + unsigned long gpios[7]; /* i2s gpio line numbers */ }; /* Lock for cross i/f checks */ @@ -651,6 +665,9 @@ static int i2s_startup(struct snd_pcm_substream *substream, /* Enforce set_sysclk in Master mode */ i2s->rclk_srcrate = 0; + if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR)) + writel(CON_RSTCLR, i2s->addr + I2SCON); + spin_unlock_irqrestore(&lock, flags); return 0; @@ -981,8 +998,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS; } else { /* Create a new platform_device for Secondary */ i2s->pdev = platform_device_register_resndata(NULL, - pdev->name, pdev->id + SAMSUNG_I2S_SECOFF, - NULL, 0, NULL, 0); + "samsung-i2s-sec", -1, NULL, 0, NULL, 0); if (IS_ERR(i2s->pdev)) return NULL; } @@ -993,18 +1009,103 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) return i2s; } +#ifdef CONFIG_OF +static int samsung_i2s_parse_dt_gpio(struct i2s_dai *i2s) +{ + struct device *dev = &i2s->pdev->dev; + int index, gpio, ret; + + for (index = 0; index < 7; index++) { + gpio = of_get_gpio(dev->of_node, index); + if (!gpio_is_valid(gpio)) { + dev_err(dev, "invalid gpio[%d]: %d\n", index, gpio); + goto free_gpio; + } + + ret = gpio_request(gpio, dev_name(dev)); + if (ret) { + dev_err(dev, "gpio [%d] request failed\n", gpio); + goto free_gpio; + } + i2s->gpios[index] = gpio; + } + return 0; + +free_gpio: + while (--index >= 0) + gpio_free(i2s->gpios[index]); + return -EINVAL; +} + +static void samsung_i2s_dt_gpio_free(struct i2s_dai *i2s) +{ + unsigned int index; + for (index = 0; index < 7; index++) + gpio_free(i2s->gpios[index]); +} +#else +static int samsung_i2s_parse_dt_gpio(struct i2s_dai *dai) +{ + return -EINVAL; +} + +static void samsung_i2s_dt_gpio_free(struct i2s_dai *dai) +{ +} + +#endif + +static const struct of_device_id exynos_i2s_match[]; + +static inline int samsung_i2s_get_driver_data(struct platform_device *pdev) +{ +#ifdef CONFIG_OF + struct samsung_i2s_dai_data *data; + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(exynos_i2s_match, pdev->dev.of_node); + data = (struct samsung_i2s_dai_data *) match->data; + return data->dai_type; + } else +#endif + return platform_get_device_id(pdev)->driver_data; +} + +#ifdef CONFIG_PM_RUNTIME +static int i2s_runtime_suspend(struct device *dev) +{ + struct i2s_dai *i2s = dev_get_drvdata(dev); + + clk_disable_unprepare(i2s->clk); + + return 0; +} + +static int i2s_runtime_resume(struct device *dev) +{ + struct i2s_dai *i2s = dev_get_drvdata(dev); + + clk_prepare_enable(i2s->clk); + + return 0; +} +#endif /* CONFIG_PM_RUNTIME */ + static int samsung_i2s_probe(struct platform_device *pdev) { - u32 dma_pl_chan, dma_cp_chan, dma_pl_sec_chan; struct i2s_dai *pri_dai, *sec_dai = NULL; - struct s3c_audio_pdata *i2s_pdata; - struct samsung_i2s *i2s_cfg; + struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; + struct samsung_i2s *i2s_cfg = NULL; struct resource *res; - u32 regs_base, quirks; + u32 regs_base, quirks = 0, idma_addr = 0; + struct device_node *np = pdev->dev.of_node; + enum samsung_dai_type samsung_dai_type; int ret = 0; /* Call during Seconday interface registration */ - if (pdev->id >= SAMSUNG_I2S_SECOFF) { + samsung_dai_type = samsung_i2s_get_driver_data(pdev); + + if (samsung_dai_type == TYPE_SEC) { sec_dai = dev_get_drvdata(&pdev->dev); snd_soc_register_dai(&sec_dai->pdev->dev, &sec_dai->i2s_dai_drv); @@ -1012,31 +1113,60 @@ static int samsung_i2s_probe(struct platform_device *pdev) return 0; } - i2s_pdata = pdev->dev.platform_data; - if (i2s_pdata == NULL) { - dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n"); - return -EINVAL; + pri_dai = i2s_alloc_dai(pdev, false); + if (!pri_dai) { + dev_err(&pdev->dev, "Unable to alloc I2S_pri\n"); + return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); - return -ENXIO; - } - dma_pl_chan = res->start; + if (!np) { + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!res) { + dev_err(&pdev->dev, + "Unable to get I2S-TX dma resource\n"); + return -ENXIO; + } + pri_dai->dma_playback.channel = res->start; - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); - return -ENXIO; - } - dma_cp_chan = res->start; + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!res) { + dev_err(&pdev->dev, + "Unable to get I2S-RX dma resource\n"); + return -ENXIO; + } + pri_dai->dma_capture.channel = res->start; - res = platform_get_resource(pdev, IORESOURCE_DMA, 2); - if (res) - dma_pl_sec_chan = res->start; - else - dma_pl_sec_chan = 0; + if (i2s_pdata == NULL) { + dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n"); + return -EINVAL; + } + + if (&i2s_pdata->type) + i2s_cfg = &i2s_pdata->type.i2s; + + if (i2s_cfg) { + quirks = i2s_cfg->quirks; + idma_addr = i2s_cfg->idma_addr; + } + } else { + if (of_find_property(np, "samsung,supports-6ch", NULL)) + quirks |= QUIRK_PRI_6CHAN; + + if (of_find_property(np, "samsung,supports-secdai", NULL)) + quirks |= QUIRK_SEC_DAI; + + if (of_find_property(np, "samsung,supports-rstclr", NULL)) + quirks |= QUIRK_NEED_RSTCLR; + + if (of_property_read_u32(np, "samsung,idma-addr", + &idma_addr)) { + if (quirks & QUIRK_SEC_DAI) { + dev_err(&pdev->dev, "idma address is not"\ + "specified"); + return -EINVAL; + } + } + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -1051,24 +1181,14 @@ static int samsung_i2s_probe(struct platform_device *pdev) } regs_base = res->start; - i2s_cfg = &i2s_pdata->type.i2s; - quirks = i2s_cfg->quirks; - - pri_dai = i2s_alloc_dai(pdev, false); - if (!pri_dai) { - dev_err(&pdev->dev, "Unable to alloc I2S_pri\n"); - ret = -ENOMEM; - goto err; - } - pri_dai->dma_playback.dma_addr = regs_base + I2STXD; pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; pri_dai->dma_playback.client = (struct s3c2410_dma_client *)&pri_dai->dma_playback; + pri_dai->dma_playback.ch_name = "tx"; pri_dai->dma_capture.client = (struct s3c2410_dma_client *)&pri_dai->dma_capture; - pri_dai->dma_playback.channel = dma_pl_chan; - pri_dai->dma_capture.channel = dma_cp_chan; + pri_dai->dma_capture.ch_name = "rx"; pri_dai->dma_playback.dma_size = 4; pri_dai->dma_capture.dma_size = 4; pri_dai->base = regs_base; @@ -1087,20 +1207,34 @@ static int samsung_i2s_probe(struct platform_device *pdev) sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; sec_dai->dma_playback.client = (struct s3c2410_dma_client *)&sec_dai->dma_playback; - /* Use iDMA always if SysDMA not provided */ - sec_dai->dma_playback.channel = dma_pl_sec_chan ? : -1; + sec_dai->dma_playback.ch_name = "tx-sec"; + + if (!np) { + res = platform_get_resource(pdev, IORESOURCE_DMA, 2); + if (res) + sec_dai->dma_playback.channel = res->start; + } + sec_dai->dma_playback.dma_size = 4; sec_dai->base = regs_base; sec_dai->quirks = quirks; - sec_dai->idma_playback.dma_addr = i2s_cfg->idma_addr; + sec_dai->idma_playback.dma_addr = idma_addr; sec_dai->pri_dai = pri_dai; pri_dai->sec_dai = sec_dai; } - if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { - dev_err(&pdev->dev, "Unable to configure gpio\n"); - ret = -EINVAL; - goto err; + if (np) { + if (samsung_i2s_parse_dt_gpio(pri_dai)) { + dev_err(&pdev->dev, "Unable to configure gpio\n"); + ret = -EINVAL; + goto err; + } + } else { + if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { + dev_err(&pdev->dev, "Unable to configure gpio\n"); + ret = -EINVAL; + goto err; + } } snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv); @@ -1120,10 +1254,14 @@ static int samsung_i2s_remove(struct platform_device *pdev) { struct i2s_dai *i2s, *other; struct resource *res; + struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; i2s = dev_get_drvdata(&pdev->dev); other = i2s->pri_dai ? : i2s->sec_dai; + if (!i2s_pdata->cfg_gpio && pdev->dev.of_node) + samsung_i2s_dt_gpio_free(i2s->pri_dai); + if (other) { other->pri_dai = NULL; other->sec_dai = NULL; @@ -1143,12 +1281,47 @@ static int samsung_i2s_remove(struct platform_device *pdev) return 0; } +static struct platform_device_id samsung_i2s_driver_ids[] = { + { + .name = "samsung-i2s", + .driver_data = TYPE_PRI, + }, { + .name = "samsung-i2s-sec", + .driver_data = TYPE_SEC, + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, samsung-i2s-driver-ids); + +#ifdef CONFIG_OF +static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = { + [TYPE_PRI] = { TYPE_PRI }, + [TYPE_SEC] = { TYPE_SEC }, +}; + +static const struct of_device_id exynos_i2s_match[] = { + { .compatible = "samsung,i2s-v5", + .data = &samsung_i2s_dai_data_array[TYPE_PRI], + }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_i2s_match); +#endif + +static const struct dev_pm_ops samsung_i2s_pm = { + SET_RUNTIME_PM_OPS(i2s_runtime_suspend, + i2s_runtime_resume, NULL) +}; + static struct platform_driver samsung_i2s_driver = { .probe = samsung_i2s_probe, .remove = samsung_i2s_remove, + .id_table = samsung_i2s_driver_ids, .driver = { .name = "samsung-i2s", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(exynos_i2s_match), + .pm = &samsung_i2s_pm, }, }; diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h index d420a7ca56ca..7966afc934db 100644 --- a/sound/soc/samsung/i2s.h +++ b/sound/soc/samsung/i2s.h @@ -13,13 +13,6 @@ #ifndef __SND_SOC_SAMSUNG_I2S_H #define __SND_SOC_SAMSUNG_I2S_H -/* - * Maximum number of I2S blocks that any SoC can have. - * The secondary interface of a CPU dai(if there exists any), - * is indexed at [cpu-dai's ID + SAMSUNG_I2S_SECOFF] - */ -#define SAMSUNG_I2S_SECOFF 4 - #define SAMSUNG_I2S_DIV_BCLK 1 #define SAMSUNG_I2S_RCLKSRC_0 0 diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index ee10e8704e97..13f6dd1ceb00 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -469,7 +469,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { int ret = 0; - ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai); + ret = snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); if (ret) { pr_err("failed to register the dai\n"); return ret; diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 7e2b710763be..7a16b32ed673 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -193,9 +193,9 @@ static struct snd_soc_dai_link smdk_dai[] = { [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */ .name = "Sec_FIFO TX", .stream_name = "Playback", - .cpu_dai_name = "samsung-i2s.x", + .cpu_dai_name = "samsung-i2s-sec", .codec_dai_name = "wm8580-hifi-playback", - .platform_name = "samsung-i2s.x", + .platform_name = "samsung-i2s-sec", .codec_name = "wm8580.0-001b", .ops = &smdk_ops, }, @@ -223,9 +223,6 @@ static int __init smdk_audio_init(void) if (machine_is_smdkc100() || machine_is_smdkv210() || machine_is_smdkc110()) { smdk.num_links = 3; - /* Secondary is at offset SAMSUNG_I2S_SECOFF from Primary */ - str = (char *)smdk_dai[SEC_PLAYBACK].cpu_dai_name; - str[strlen(str) - 1] = '0' + SAMSUNG_I2S_SECOFF; } else if (machine_is_smdk6410()) { str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name; str[strlen(str) - 1] = '2'; diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index b0d0ab8bff5a..581ea4a06fc6 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -10,6 +10,7 @@ #include "../codecs/wm8994.h" #include <sound/pcm_params.h> #include <linux/module.h> +#include <linux/of.h> /* * Default CFG switch settings to use this driver: @@ -134,9 +135,9 @@ static struct snd_soc_dai_link smdk_dai[] = { }, { /* Sec_Fifo Playback i/f */ .name = "Sec_FIFO TX", .stream_name = "Sec_Dai", - .cpu_dai_name = "samsung-i2s.4", + .cpu_dai_name = "samsung-i2s-sec", .codec_dai_name = "wm8994-aif1", - .platform_name = "samsung-i2s.4", + .platform_name = "samsung-i2s-sec", .codec_name = "wm8994-codec", .ops = &smdk_ops, }, @@ -153,9 +154,25 @@ static struct snd_soc_card smdk = { static int smdk_audio_probe(struct platform_device *pdev) { int ret; + struct device_node *np = pdev->dev.of_node; struct snd_soc_card *card = &smdk; card->dev = &pdev->dev; + + if (np) { + smdk_dai[0].cpu_dai_name = NULL; + smdk_dai[0].cpu_of_node = of_parse_phandle(np, + "samsung,i2s-controller", 0); + if (!smdk_dai[0].cpu_of_node) { + dev_err(&pdev->dev, + "Property 'samsung,i2s-controller' missing or invalid\n"); + ret = -EINVAL; + } + + smdk_dai[0].platform_name = NULL; + smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; + } + ret = snd_soc_register_card(card); if (ret) @@ -173,10 +190,19 @@ static int smdk_audio_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id samsung_wm8994_of_match[] = { + { .compatible = "samsung,smdk-wm8994", }, + {}, +}; +MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match); +#endif /* CONFIG_OF */ + static struct platform_driver smdk_audio_driver = { .driver = { .name = "smdk-audio", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(samsung_wm8994_of_match), }, .probe = smdk_audio_probe, .remove = smdk_audio_remove, |