diff options
Diffstat (limited to 'sound/soc/s3c24xx/s3c64xx-i2s-v4.c')
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s-v4.c | 135 |
1 files changed, 78 insertions, 57 deletions
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 06db130030a1..a9628472ebfe 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | #include <sound/pcm_params.h> | 17 | #include <sound/pcm_params.h> |
18 | 18 | ||
19 | #include <mach/gpio-bank-c.h> | 19 | #include <plat/audio.h> |
20 | #include <mach/gpio-bank-h.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | 20 | ||
23 | #include <mach/map.h> | 21 | #include <mach/map.h> |
24 | #include <mach/dma.h> | 22 | #include <mach/dma.h> |
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out; | |||
39 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; | 37 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; |
40 | static struct s3c_i2sv2_info s3c64xx_i2sv4; | 38 | static struct s3c_i2sv2_info s3c64xx_i2sv4; |
41 | 39 | ||
42 | struct snd_soc_dai s3c64xx_i2s_v4_dai; | 40 | static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai) |
43 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); | ||
44 | |||
45 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
46 | { | 41 | { |
47 | return cpu_dai->private_data; | 42 | struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; |
48 | } | 43 | int ret = 0; |
49 | 44 | ||
50 | static int s3c64xx_i2sv4_probe(struct platform_device *pdev, | 45 | snd_soc_dai_set_drvdata(dai, i2s); |
51 | struct snd_soc_dai *dai) | ||
52 | { | ||
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); | ||
61 | 46 | ||
62 | return 0; | 47 | ret = s3c_i2sv2_probe(dai, i2s, i2s->base); |
48 | |||
49 | return ret; | ||
63 | } | 50 | } |
64 | 51 | ||
65 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, | 52 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, |
66 | struct snd_pcm_hw_params *params, | 53 | struct snd_pcm_hw_params *params, |
67 | struct snd_soc_dai *cpu_dai) | 54 | struct snd_soc_dai *cpu_dai) |
68 | { | 55 | { |
69 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | 56 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
70 | struct s3c_dma_params *dma_data; | 57 | struct s3c_dma_params *dma_data; |
71 | u32 iismod; | 58 | u32 iismod; |
72 | 59 | ||
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = { | |||
104 | .hw_params = s3c_i2sv4_hw_params, | 91 | .hw_params = s3c_i2sv4_hw_params, |
105 | }; | 92 | }; |
106 | 93 | ||
94 | static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = { | ||
95 | .symmetric_rates = 1, | ||
96 | .playback = { | ||
97 | .channels_min = 2, | ||
98 | .channels_max = 2, | ||
99 | .rates = S3C64XX_I2S_RATES, | ||
100 | .formats = S3C64XX_I2S_FMTS, | ||
101 | }, | ||
102 | .capture = { | ||
103 | .channels_min = 2, | ||
104 | .channels_max = 2, | ||
105 | .rates = S3C64XX_I2S_RATES, | ||
106 | .formats = S3C64XX_I2S_FMTS, | ||
107 | }, | ||
108 | .probe = s3c64xx_i2sv4_probe, | ||
109 | .ops = &s3c64xx_i2sv4_dai_ops, | ||
110 | }; | ||
111 | |||
107 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | 112 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) |
108 | { | 113 | { |
114 | struct s3c_audio_pdata *i2s_pdata; | ||
109 | struct s3c_i2sv2_info *i2s; | 115 | struct s3c_i2sv2_info *i2s; |
110 | struct snd_soc_dai *dai; | 116 | struct resource *res; |
111 | int ret; | 117 | int ret; |
112 | 118 | ||
113 | i2s = &s3c64xx_i2sv4; | 119 | i2s = &s3c64xx_i2sv4; |
114 | dai = &s3c64xx_i2s_v4_dai; | ||
115 | |||
116 | if (dai->dev) { | ||
117 | dev_dbg(dai->dev, "%s: \ | ||
118 | I2Sv4 instance already registered!\n", __func__); | ||
119 | return -EBUSY; | ||
120 | } | ||
121 | |||
122 | dai->dev = &pdev->dev; | ||
123 | dai->name = "s3c64xx-i2s-v4"; | ||
124 | dai->id = 0; | ||
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; | ||
136 | 120 | ||
137 | i2s->feature |= S3C_FEATURE_CDCLKCON; | 121 | i2s->feature |= S3C_FEATURE_CDCLKCON; |
138 | 122 | ||
139 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; | 123 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; |
140 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; | 124 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; |
141 | 125 | ||
142 | i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; | 126 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
143 | i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; | 127 | if (!res) { |
144 | i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; | 128 | dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); |
145 | i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; | 129 | return -ENXIO; |
130 | } | ||
131 | i2s->dma_playback->channel = res->start; | ||
132 | |||
133 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
134 | if (!res) { | ||
135 | dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); | ||
136 | return -ENXIO; | ||
137 | } | ||
138 | i2s->dma_capture->channel = res->start; | ||
139 | |||
140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
141 | if (!res) { | ||
142 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
143 | return -ENXIO; | ||
144 | } | ||
145 | |||
146 | if (!request_mem_region(res->start, resource_size(res), | ||
147 | "s3c64xx-i2s-v4")) { | ||
148 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
149 | return -EBUSY; | ||
150 | } | ||
151 | i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; | ||
152 | i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; | ||
146 | 153 | ||
147 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | 154 | i2s->dma_capture->client = &s3c64xx_dma_client_in; |
148 | i2s->dma_capture->dma_size = 4; | 155 | i2s->dma_capture->dma_size = 4; |
149 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | 156 | i2s->dma_playback->client = &s3c64xx_dma_client_out; |
150 | i2s->dma_playback->dma_size = 4; | 157 | i2s->dma_playback->dma_size = 4; |
151 | 158 | ||
159 | i2s->base = res->start; | ||
160 | |||
161 | i2s_pdata = pdev->dev.platform_data; | ||
162 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | ||
163 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
152 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | 167 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); |
153 | if (IS_ERR(i2s->iis_cclk)) { | 168 | if (IS_ERR(i2s->iis_cclk)) { |
154 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 169 | dev_err(&pdev->dev, "failed to get audio-bus\n"); |
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | |||
158 | 173 | ||
159 | clk_enable(i2s->iis_cclk); | 174 | clk_enable(i2s->iis_cclk); |
160 | 175 | ||
161 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | 176 | ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai); |
162 | if (ret) | ||
163 | goto err_clk; | ||
164 | |||
165 | ret = s3c_i2sv2_register_dai(dai); | ||
166 | if (ret != 0) | 177 | if (ret != 0) |
167 | goto err_i2sv2; | 178 | goto err_i2sv2; |
168 | 179 | ||
169 | return 0; | 180 | return 0; |
170 | 181 | ||
171 | err_i2sv2: | 182 | err_i2sv2: |
172 | /* Not implemented for I2Sv2 core yet */ | ||
173 | err_clk: | ||
174 | clk_put(i2s->iis_cclk); | 183 | clk_put(i2s->iis_cclk); |
175 | err: | 184 | err: |
176 | return ret; | 185 | return ret; |
@@ -178,7 +187,18 @@ err: | |||
178 | 187 | ||
179 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) | 188 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) |
180 | { | 189 | { |
181 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | 190 | struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; |
191 | struct resource *res; | ||
192 | |||
193 | snd_soc_unregister_dai(&pdev->dev); | ||
194 | clk_put(i2s->iis_cclk); | ||
195 | |||
196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
197 | if (res) | ||
198 | release_mem_region(res->start, resource_size(res)); | ||
199 | else | ||
200 | dev_warn(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
201 | |||
182 | return 0; | 202 | return 0; |
183 | } | 203 | } |
184 | 204 | ||
@@ -207,3 +227,4 @@ module_exit(s3c64xx_i2sv4_exit); | |||
207 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 227 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
208 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); | 228 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); |
209 | MODULE_LICENSE("GPL"); | 229 | MODULE_LICENSE("GPL"); |
230 | MODULE_ALIAS("platform:s3c64xx-iis-v4"); | ||