1 /* sound/soc/s3c24xx/s3c64xx-i2s-v4.c
3 * ALSA SoC Audio Layer - S3C64XX I2Sv4 driver
4 * Copyright (c) 2010 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/clk.h>
13 #include <linux/gpio.h>
16 #include <sound/soc.h>
17 #include <sound/pcm_params.h>
19 #include <mach/gpio-bank-c.h>
20 #include <mach/gpio-bank-h.h>
21 #include <plat/gpio-cfg.h>
27 #include "regs-i2s-v2.h"
28 #include "s3c64xx-i2s.h"
30 static struct s3c2410_dma_client s3c64xx_dma_client_out
= {
31 .name
= "I2Sv4 PCM Stereo out"
34 static struct s3c2410_dma_client s3c64xx_dma_client_in
= {
35 .name
= "I2Sv4 PCM Stereo in"
38 static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out
;
39 static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in
;
40 static struct s3c_i2sv2_info s3c64xx_i2sv4
;
42 struct snd_soc_dai s3c64xx_i2s_v4_dai
;
43 EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai
);
45 static inline struct s3c_i2sv2_info
*to_info(struct snd_soc_dai
*cpu_dai
)
47 return cpu_dai
->private_data
;
50 static int s3c64xx_i2sv4_probe(struct platform_device
*pdev
,
51 struct snd_soc_dai
*dai
)
53 /* configure GPIO for i2s port */
54 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0
);
55 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1
);
56 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2
);
57 s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK
);
58 s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK
);
59 s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK
);
60 s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI
);
65 static int s3c_i2sv4_hw_params(struct snd_pcm_substream
*substream
,
66 struct snd_pcm_hw_params
*params
,
67 struct snd_soc_dai
*cpu_dai
)
69 struct s3c_i2sv2_info
*i2s
= to_info(cpu_dai
);
70 struct s3c_dma_params
*dma_data
;
73 dev_dbg(cpu_dai
->dev
, "Entered %s\n", __func__
);
75 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
76 dma_data
= i2s
->dma_playback
;
78 dma_data
= i2s
->dma_capture
;
80 snd_soc_dai_set_dma_data(cpu_dai
, substream
, dma_data
);
82 iismod
= readl(i2s
->regs
+ S3C2412_IISMOD
);
83 dev_dbg(cpu_dai
->dev
, "%s: r: IISMOD: %x\n", __func__
, iismod
);
85 iismod
&= ~S3C64XX_IISMOD_BLC_MASK
;
86 switch (params_format(params
)) {
87 case SNDRV_PCM_FORMAT_S8
:
88 iismod
|= S3C64XX_IISMOD_BLC_8BIT
;
90 case SNDRV_PCM_FORMAT_S16_LE
:
92 case SNDRV_PCM_FORMAT_S24_LE
:
93 iismod
|= S3C64XX_IISMOD_BLC_24BIT
;
97 writel(iismod
, i2s
->regs
+ S3C2412_IISMOD
);
98 dev_dbg(cpu_dai
->dev
, "%s: w: IISMOD: %x\n", __func__
, iismod
);
103 static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops
= {
104 .hw_params
= s3c_i2sv4_hw_params
,
107 static __devinit
int s3c64xx_i2sv4_dev_probe(struct platform_device
*pdev
)
109 struct s3c_i2sv2_info
*i2s
;
110 struct snd_soc_dai
*dai
;
113 i2s
= &s3c64xx_i2sv4
;
114 dai
= &s3c64xx_i2s_v4_dai
;
117 dev_dbg(dai
->dev
, "%s: \
118 I2Sv4 instance already registered!\n", __func__
);
122 dai
->dev
= &pdev
->dev
;
123 dai
->name
= "s3c64xx-i2s-v4";
125 dai
->symmetric_rates
= 1;
126 dai
->playback
.channels_min
= 2;
127 dai
->playback
.channels_max
= 2;
128 dai
->playback
.rates
= S3C64XX_I2S_RATES
;
129 dai
->playback
.formats
= S3C64XX_I2S_FMTS
;
130 dai
->capture
.channels_min
= 2;
131 dai
->capture
.channels_max
= 2;
132 dai
->capture
.rates
= S3C64XX_I2S_RATES
;
133 dai
->capture
.formats
= S3C64XX_I2S_FMTS
;
134 dai
->probe
= s3c64xx_i2sv4_probe
;
135 dai
->ops
= &s3c64xx_i2sv4_dai_ops
;
137 i2s
->feature
|= S3C_FEATURE_CDCLKCON
;
139 i2s
->dma_capture
= &s3c64xx_i2sv4_pcm_stereo_in
;
140 i2s
->dma_playback
= &s3c64xx_i2sv4_pcm_stereo_out
;
142 i2s
->dma_capture
->channel
= DMACH_HSI_I2SV40_RX
;
143 i2s
->dma_capture
->dma_addr
= S3C64XX_PA_IISV4
+ S3C2412_IISRXD
;
144 i2s
->dma_playback
->channel
= DMACH_HSI_I2SV40_TX
;
145 i2s
->dma_playback
->dma_addr
= S3C64XX_PA_IISV4
+ S3C2412_IISTXD
;
147 i2s
->dma_capture
->client
= &s3c64xx_dma_client_in
;
148 i2s
->dma_capture
->dma_size
= 4;
149 i2s
->dma_playback
->client
= &s3c64xx_dma_client_out
;
150 i2s
->dma_playback
->dma_size
= 4;
152 i2s
->iis_cclk
= clk_get(&pdev
->dev
, "audio-bus");
153 if (IS_ERR(i2s
->iis_cclk
)) {
154 dev_err(&pdev
->dev
, "failed to get audio-bus\n");
155 ret
= PTR_ERR(i2s
->iis_cclk
);
159 clk_enable(i2s
->iis_cclk
);
161 ret
= s3c_i2sv2_probe(pdev
, dai
, i2s
, 0);
165 ret
= s3c_i2sv2_register_dai(dai
);
172 /* Not implemented for I2Sv2 core yet */
174 clk_put(i2s
->iis_cclk
);
179 static __devexit
int s3c64xx_i2sv4_dev_remove(struct platform_device
*pdev
)
181 dev_err(&pdev
->dev
, "Device removal not yet supported\n");
185 static struct platform_driver s3c64xx_i2sv4_driver
= {
186 .probe
= s3c64xx_i2sv4_dev_probe
,
187 .remove
= s3c64xx_i2sv4_dev_remove
,
189 .name
= "s3c64xx-iis-v4",
190 .owner
= THIS_MODULE
,
194 static int __init
s3c64xx_i2sv4_init(void)
196 return platform_driver_register(&s3c64xx_i2sv4_driver
);
198 module_init(s3c64xx_i2sv4_init
);
200 static void __exit
s3c64xx_i2sv4_exit(void)
202 platform_driver_unregister(&s3c64xx_i2sv4_driver
);
204 module_exit(s3c64xx_i2sv4_exit
);
206 /* Module information */
207 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
208 MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface");
209 MODULE_LICENSE("GPL");