diff options
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r-- | sound/soc/sh/rcar/core.c | 243 |
1 files changed, 118 insertions, 125 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed76901f8202..19f78963e8b9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
138 | return mod->ops->name; | 138 | return mod->ops->name; |
139 | } | 139 | } |
140 | 140 | ||
141 | char *rsnd_mod_dma_name(struct rsnd_mod *mod) | ||
142 | { | ||
143 | if (!mod || !mod->ops) | ||
144 | return "unknown"; | ||
145 | |||
146 | if (!mod->ops->dma_name) | ||
147 | return mod->ops->name; | ||
148 | |||
149 | return mod->ops->dma_name(mod); | ||
150 | } | ||
151 | |||
141 | void rsnd_mod_init(struct rsnd_priv *priv, | 152 | void rsnd_mod_init(struct rsnd_priv *priv, |
142 | struct rsnd_mod *mod, | 153 | struct rsnd_mod *mod, |
143 | struct rsnd_mod_ops *ops, | 154 | struct rsnd_mod_ops *ops, |
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
153 | /* | 164 | /* |
154 | * rsnd_dma functions | 165 | * rsnd_dma functions |
155 | */ | 166 | */ |
156 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
157 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
158 | { | ||
159 | /* push next A or B plane */ | ||
160 | dma->submit_loop = 1; | ||
161 | schedule_work(&dma->work); | ||
162 | } | ||
163 | |||
164 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
165 | { | ||
166 | /* push both A and B plane*/ | ||
167 | dma->offset = 0; | ||
168 | dma->submit_loop = 2; | ||
169 | __rsnd_dma_start(dma); | ||
170 | } | ||
171 | |||
172 | void rsnd_dma_stop(struct rsnd_dma *dma) | 167 | void rsnd_dma_stop(struct rsnd_dma *dma) |
173 | { | 168 | { |
174 | dma->submit_loop = 0; | ||
175 | cancel_work_sync(&dma->work); | ||
176 | dmaengine_terminate_all(dma->chan); | 169 | dmaengine_terminate_all(dma->chan); |
177 | } | 170 | } |
178 | 171 | ||
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data) | |||
180 | { | 173 | { |
181 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 174 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
182 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 175 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
183 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
184 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 176 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
185 | unsigned long flags; | ||
186 | |||
187 | rsnd_lock(priv, flags); | ||
188 | 177 | ||
189 | /* | 178 | /* |
190 | * Renesas sound Gen1 needs 1 DMAC, | 179 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data) | |||
197 | * rsnd_dai_pointer_update() will be called twice, | 186 | * rsnd_dai_pointer_update() will be called twice, |
198 | * ant it will breaks io->byte_pos | 187 | * ant it will breaks io->byte_pos |
199 | */ | 188 | */ |
200 | if (dma->submit_loop) | ||
201 | rsnd_dma_continue(dma); | ||
202 | |||
203 | rsnd_unlock(priv, flags); | ||
204 | 189 | ||
205 | rsnd_dai_pointer_update(io, io->byte_per_period); | 190 | rsnd_dai_pointer_update(io, io->byte_per_period); |
206 | } | 191 | } |
207 | 192 | ||
208 | static void __rsnd_dma_start(struct rsnd_dma *dma) | 193 | void rsnd_dma_start(struct rsnd_dma *dma) |
209 | { | 194 | { |
210 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 195 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
211 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
212 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 197 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
213 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 198 | struct snd_pcm_substream *substream = io->substream; |
214 | struct device *dev = rsnd_priv_to_dev(priv); | 199 | struct device *dev = rsnd_priv_to_dev(priv); |
215 | struct dma_async_tx_descriptor *desc; | 200 | struct dma_async_tx_descriptor *desc; |
216 | dma_addr_t buf; | ||
217 | size_t len = io->byte_per_period; | ||
218 | int i; | ||
219 | 201 | ||
220 | for (i = 0; i < dma->submit_loop; i++) { | 202 | desc = dmaengine_prep_dma_cyclic(dma->chan, |
221 | 203 | (dma->addr) ? dma->addr : | |
222 | buf = runtime->dma_addr + | 204 | substream->runtime->dma_addr, |
223 | rsnd_dai_pointer_offset(io, dma->offset + len); | 205 | snd_pcm_lib_buffer_bytes(substream), |
224 | dma->offset = len; | 206 | snd_pcm_lib_period_bytes(substream), |
225 | 207 | dma->dir, | |
226 | desc = dmaengine_prep_slave_single( | 208 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
227 | dma->chan, buf, len, dma->dir, | ||
228 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
229 | if (!desc) { | ||
230 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
231 | return; | ||
232 | } | ||
233 | 209 | ||
234 | desc->callback = rsnd_dma_complete; | 210 | if (!desc) { |
235 | desc->callback_param = dma; | 211 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
212 | return; | ||
213 | } | ||
236 | 214 | ||
237 | if (dmaengine_submit(desc) < 0) { | 215 | desc->callback = rsnd_dma_complete; |
238 | dev_err(dev, "dmaengine_submit() fail\n"); | 216 | desc->callback_param = dma; |
239 | return; | ||
240 | } | ||
241 | 217 | ||
242 | dma_async_issue_pending(dma->chan); | 218 | if (dmaengine_submit(desc) < 0) { |
219 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
220 | return; | ||
243 | } | 221 | } |
244 | } | ||
245 | |||
246 | static void rsnd_dma_do_work(struct work_struct *work) | ||
247 | { | ||
248 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
249 | 222 | ||
250 | __rsnd_dma_start(dma); | 223 | dma_async_issue_pending(dma->chan); |
251 | } | 224 | } |
252 | 225 | ||
253 | int rsnd_dma_available(struct rsnd_dma *dma) | 226 | int rsnd_dma_available(struct rsnd_dma *dma) |
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) | |||
261 | { | 234 | { |
262 | if (mod) | 235 | if (mod) |
263 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", | 236 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", |
264 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 237 | rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); |
265 | else | 238 | else |
266 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); | 239 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); |
267 | 240 | ||
268 | } | 241 | } |
269 | 242 | ||
270 | static void rsnd_dma_of_name(struct rsnd_dma *dma, | 243 | static void rsnd_dma_of_name(struct rsnd_mod *mod_from, |
271 | int is_play, char *dma_name) | 244 | struct rsnd_mod *mod_to, |
245 | char *dma_name) | ||
246 | { | ||
247 | int index = 0; | ||
248 | |||
249 | index = _rsnd_dma_of_name(dma_name + index, mod_from); | ||
250 | *(dma_name + index++) = '_'; | ||
251 | index = _rsnd_dma_of_name(dma_name + index, mod_to); | ||
252 | } | ||
253 | |||
254 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | ||
255 | int is_play, | ||
256 | struct rsnd_mod **mod_from, | ||
257 | struct rsnd_mod **mod_to) | ||
272 | { | 258 | { |
273 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 259 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
274 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); | 260 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); |
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
276 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 262 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
277 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 263 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
278 | struct rsnd_mod *mod[MOD_MAX]; | 264 | struct rsnd_mod *mod[MOD_MAX]; |
279 | struct rsnd_mod *src_mod, *dst_mod; | ||
280 | int i, index; | 265 | int i, index; |
281 | 266 | ||
282 | 267 | ||
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
301 | mod[i] = src; | 286 | mod[i] = src; |
302 | src = NULL; | 287 | src = NULL; |
303 | } else { | 288 | } else { |
304 | mod[i] = dvc; | 289 | if ((!is_play) && (this == src)) |
290 | this = dvc; | ||
291 | |||
292 | mod[i] = (is_play) ? src : dvc; | ||
293 | i++; | ||
294 | mod[i] = (is_play) ? dvc : src; | ||
295 | src = NULL; | ||
305 | dvc = NULL; | 296 | dvc = NULL; |
306 | } | 297 | } |
307 | 298 | ||
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
313 | } | 304 | } |
314 | 305 | ||
315 | if (is_play) { | 306 | if (is_play) { |
316 | src_mod = mod[index - 1]; | 307 | *mod_from = mod[index - 1]; |
317 | dst_mod = mod[index]; | 308 | *mod_to = mod[index]; |
318 | } else { | 309 | } else { |
319 | src_mod = mod[index]; | 310 | *mod_from = mod[index]; |
320 | dst_mod = mod[index - 1]; | 311 | *mod_to = mod[index - 1]; |
321 | } | 312 | } |
322 | |||
323 | index = 0; | ||
324 | index = _rsnd_dma_of_name(dma_name + index, src_mod); | ||
325 | *(dma_name + index++) = '_'; | ||
326 | index = _rsnd_dma_of_name(dma_name + index, dst_mod); | ||
327 | } | 313 | } |
328 | 314 | ||
329 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 315 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
@@ -331,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
331 | { | 317 | { |
332 | struct device *dev = rsnd_priv_to_dev(priv); | 318 | struct device *dev = rsnd_priv_to_dev(priv); |
333 | struct dma_slave_config cfg; | 319 | struct dma_slave_config cfg; |
320 | struct rsnd_mod *mod_from; | ||
321 | struct rsnd_mod *mod_to; | ||
334 | char dma_name[DMA_NAME_SIZE]; | 322 | char dma_name[DMA_NAME_SIZE]; |
335 | dma_cap_mask_t mask; | 323 | dma_cap_mask_t mask; |
336 | int ret; | 324 | int ret; |
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
343 | dma_cap_zero(mask); | 331 | dma_cap_zero(mask); |
344 | dma_cap_set(DMA_SLAVE, mask); | 332 | dma_cap_set(DMA_SLAVE, mask); |
345 | 333 | ||
346 | if (dev->of_node) | 334 | rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); |
347 | rsnd_dma_of_name(dma, is_play, dma_name); | 335 | rsnd_dma_of_name(mod_from, mod_to, dma_name); |
348 | else | 336 | |
349 | snprintf(dma_name, DMA_NAME_SIZE, | 337 | cfg.slave_id = id; |
350 | is_play ? "tx" : "rx"); | 338 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
339 | cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); | ||
340 | cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); | ||
341 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
342 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
351 | 343 | ||
352 | dev_dbg(dev, "dma name : %s\n", dma_name); | 344 | dev_dbg(dev, "dma : %s %pad -> %pad\n", |
345 | dma_name, &cfg.src_addr, &cfg.dst_addr); | ||
353 | 346 | ||
354 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 347 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
355 | (void *)id, dev, | 348 | (void *)id, dev, |
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
359 | return -EIO; | 352 | return -EIO; |
360 | } | 353 | } |
361 | 354 | ||
362 | rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id); | ||
363 | |||
364 | ret = dmaengine_slave_config(dma->chan, &cfg); | 355 | ret = dmaengine_slave_config(dma->chan, &cfg); |
365 | if (ret < 0) | 356 | if (ret < 0) |
366 | goto rsnd_dma_init_err; | 357 | goto rsnd_dma_init_err; |
367 | 358 | ||
368 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 359 | dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; |
369 | INIT_WORK(&dma->work, rsnd_dma_do_work); | 360 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
370 | 361 | ||
371 | return 0; | 362 | return 0; |
372 | 363 | ||
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
633 | return -EINVAL; | 624 | return -EINVAL; |
634 | } | 625 | } |
635 | 626 | ||
636 | /* set clock inversion */ | ||
637 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
638 | case SND_SOC_DAIFMT_NB_IF: | ||
639 | rdai->bit_clk_inv = 0; | ||
640 | rdai->frm_clk_inv = 1; | ||
641 | break; | ||
642 | case SND_SOC_DAIFMT_IB_NF: | ||
643 | rdai->bit_clk_inv = 1; | ||
644 | rdai->frm_clk_inv = 0; | ||
645 | break; | ||
646 | case SND_SOC_DAIFMT_IB_IF: | ||
647 | rdai->bit_clk_inv = 1; | ||
648 | rdai->frm_clk_inv = 1; | ||
649 | break; | ||
650 | case SND_SOC_DAIFMT_NB_NF: | ||
651 | default: | ||
652 | rdai->bit_clk_inv = 0; | ||
653 | rdai->frm_clk_inv = 0; | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | /* set format */ | 627 | /* set format */ |
658 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 628 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
659 | case SND_SOC_DAIFMT_I2S: | 629 | case SND_SOC_DAIFMT_I2S: |
660 | rdai->sys_delay = 0; | 630 | rdai->sys_delay = 0; |
661 | rdai->data_alignment = 0; | 631 | rdai->data_alignment = 0; |
632 | rdai->frm_clk_inv = 0; | ||
662 | break; | 633 | break; |
663 | case SND_SOC_DAIFMT_LEFT_J: | 634 | case SND_SOC_DAIFMT_LEFT_J: |
664 | rdai->sys_delay = 1; | 635 | rdai->sys_delay = 1; |
665 | rdai->data_alignment = 0; | 636 | rdai->data_alignment = 0; |
637 | rdai->frm_clk_inv = 1; | ||
666 | break; | 638 | break; |
667 | case SND_SOC_DAIFMT_RIGHT_J: | 639 | case SND_SOC_DAIFMT_RIGHT_J: |
668 | rdai->sys_delay = 1; | 640 | rdai->sys_delay = 1; |
669 | rdai->data_alignment = 1; | 641 | rdai->data_alignment = 1; |
642 | rdai->frm_clk_inv = 1; | ||
643 | break; | ||
644 | } | ||
645 | |||
646 | /* set clock inversion */ | ||
647 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
648 | case SND_SOC_DAIFMT_NB_IF: | ||
649 | rdai->bit_clk_inv = rdai->bit_clk_inv; | ||
650 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_IB_NF: | ||
653 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
654 | rdai->frm_clk_inv = rdai->frm_clk_inv; | ||
655 | break; | ||
656 | case SND_SOC_DAIFMT_IB_IF: | ||
657 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
658 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
659 | break; | ||
660 | case SND_SOC_DAIFMT_NB_NF: | ||
661 | default: | ||
670 | break; | 662 | break; |
671 | } | 663 | } |
672 | 664 | ||
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
736 | struct device_node *dai_node, *dai_np; | 728 | struct device_node *dai_node, *dai_np; |
737 | struct device_node *ssi_node, *ssi_np; | 729 | struct device_node *ssi_node, *ssi_np; |
738 | struct device_node *src_node, *src_np; | 730 | struct device_node *src_node, *src_np; |
731 | struct device_node *dvc_node, *dvc_np; | ||
739 | struct device_node *playback, *capture; | 732 | struct device_node *playback, *capture; |
740 | struct rsnd_dai_platform_info *dai_info; | 733 | struct rsnd_dai_platform_info *dai_info; |
741 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 734 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
742 | struct device *dev = &pdev->dev; | 735 | struct device *dev = &pdev->dev; |
743 | int nr, i; | 736 | int nr, i; |
744 | int dai_i, ssi_i, src_i; | 737 | int dai_i, ssi_i, src_i, dvc_i; |
745 | 738 | ||
746 | if (!of_data) | 739 | if (!of_data) |
747 | return; | 740 | return; |
@@ -767,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
767 | 760 | ||
768 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); | 761 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); |
769 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); | 762 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); |
763 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
770 | 764 | ||
771 | #define mod_parse(name) \ | 765 | #define mod_parse(name) \ |
772 | if (name##_node) { \ | 766 | if (name##_node) { \ |
@@ -802,6 +796,7 @@ if (name##_node) { \ | |||
802 | 796 | ||
803 | mod_parse(ssi); | 797 | mod_parse(ssi); |
804 | mod_parse(src); | 798 | mod_parse(src); |
799 | mod_parse(dvc); | ||
805 | 800 | ||
806 | if (playback) | 801 | if (playback) |
807 | of_node_put(playback); | 802 | of_node_put(playback); |
@@ -950,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
950 | 945 | ||
951 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | 946 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
952 | { | 947 | { |
953 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 948 | struct snd_soc_dai *dai = rtd->cpu_dai; |
954 | struct rsnd_dai *rdai; | 949 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
955 | int i, ret; | 950 | int ret; |
956 | 951 | ||
957 | for_each_rsnd_dai(rdai, priv, i) { | 952 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); |
958 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | 953 | if (ret) |
959 | if (ret) | 954 | return ret; |
960 | return ret; | ||
961 | 955 | ||
962 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | 956 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); |
963 | if (ret) | 957 | if (ret) |
964 | return ret; | 958 | return ret; |
965 | } | ||
966 | 959 | ||
967 | return snd_pcm_lib_preallocate_pages_for_all( | 960 | return snd_pcm_lib_preallocate_pages_for_all( |
968 | rtd->pcm, | 961 | rtd->pcm, |
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1049 | for_each_rsnd_dai(rdai, priv, i) { | 1042 | for_each_rsnd_dai(rdai, priv, i) { |
1050 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); | 1043 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); |
1051 | if (ret) | 1044 | if (ret) |
1052 | return ret; | 1045 | goto exit_snd_probe; |
1053 | 1046 | ||
1054 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); | 1047 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); |
1055 | if (ret) | 1048 | if (ret) |
1056 | return ret; | 1049 | goto exit_snd_probe; |
1057 | } | 1050 | } |
1058 | 1051 | ||
1059 | /* | 1052 | /* |
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1081 | 1074 | ||
1082 | exit_snd_soc: | 1075 | exit_snd_soc: |
1083 | snd_soc_unregister_platform(dev); | 1076 | snd_soc_unregister_platform(dev); |
1077 | exit_snd_probe: | ||
1078 | for_each_rsnd_dai(rdai, priv, i) { | ||
1079 | rsnd_dai_call(remove, &rdai->playback, rdai); | ||
1080 | rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1081 | } | ||
1084 | 1082 | ||
1085 | return ret; | 1083 | return ret; |
1086 | } | 1084 | } |
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1089 | { | 1087 | { |
1090 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | 1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); |
1091 | struct rsnd_dai *rdai; | 1089 | struct rsnd_dai *rdai; |
1092 | int ret, i; | 1090 | int ret = 0, i; |
1093 | 1091 | ||
1094 | pm_runtime_disable(&pdev->dev); | 1092 | pm_runtime_disable(&pdev->dev); |
1095 | 1093 | ||
1096 | for_each_rsnd_dai(rdai, priv, i) { | 1094 | for_each_rsnd_dai(rdai, priv, i) { |
1097 | ret = rsnd_dai_call(remove, &rdai->playback, rdai); | 1095 | ret |= rsnd_dai_call(remove, &rdai->playback, rdai); |
1098 | if (ret) | 1096 | ret |= rsnd_dai_call(remove, &rdai->capture, rdai); |
1099 | return ret; | ||
1100 | |||
1101 | ret = rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1102 | if (ret) | ||
1103 | return ret; | ||
1104 | } | 1097 | } |
1105 | 1098 | ||
1106 | return 0; | 1099 | return ret; |
1107 | } | 1100 | } |
1108 | 1101 | ||
1109 | static struct platform_driver rsnd_driver = { | 1102 | static struct platform_driver rsnd_driver = { |