diff options
-rw-r--r-- | sound/soc/sh/fsi.c | 115 |
1 files changed, 62 insertions, 53 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9c49c11c43c..7506ef6d287 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -92,6 +92,7 @@ | |||
92 | struct fsi_priv { | 92 | struct fsi_priv { |
93 | void __iomem *base; | 93 | void __iomem *base; |
94 | struct snd_pcm_substream *substream; | 94 | struct snd_pcm_substream *substream; |
95 | struct fsi_master *master; | ||
95 | 96 | ||
96 | int fifo_max; | 97 | int fifo_max; |
97 | int chan; | 98 | int chan; |
@@ -110,8 +111,6 @@ struct fsi_master { | |||
110 | struct sh_fsi_platform_info *info; | 111 | struct sh_fsi_platform_info *info; |
111 | }; | 112 | }; |
112 | 113 | ||
113 | static struct fsi_master *master; | ||
114 | |||
115 | /************************************************************************ | 114 | /************************************************************************ |
116 | 115 | ||
117 | 116 | ||
@@ -166,7 +165,7 @@ static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) | |||
166 | return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); | 165 | return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); |
167 | } | 166 | } |
168 | 167 | ||
169 | static int fsi_master_write(u32 reg, u32 data) | 168 | static int fsi_master_write(struct fsi_master *master, u32 reg, u32 data) |
170 | { | 169 | { |
171 | if ((reg < MREG_START) || | 170 | if ((reg < MREG_START) || |
172 | (reg > MREG_END)) | 171 | (reg > MREG_END)) |
@@ -175,7 +174,7 @@ static int fsi_master_write(u32 reg, u32 data) | |||
175 | return __fsi_reg_write((u32)(master->base + reg), data); | 174 | return __fsi_reg_write((u32)(master->base + reg), data); |
176 | } | 175 | } |
177 | 176 | ||
178 | static u32 fsi_master_read(u32 reg) | 177 | static u32 fsi_master_read(struct fsi_master *master, u32 reg) |
179 | { | 178 | { |
180 | if ((reg < MREG_START) || | 179 | if ((reg < MREG_START) || |
181 | (reg > MREG_END)) | 180 | (reg > MREG_END)) |
@@ -184,7 +183,8 @@ static u32 fsi_master_read(u32 reg) | |||
184 | return __fsi_reg_read((u32)(master->base + reg)); | 183 | return __fsi_reg_read((u32)(master->base + reg)); |
185 | } | 184 | } |
186 | 185 | ||
187 | static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) | 186 | static int fsi_master_mask_set(struct fsi_master *master, |
187 | u32 reg, u32 mask, u32 data) | ||
188 | { | 188 | { |
189 | if ((reg < MREG_START) || | 189 | if ((reg < MREG_START) || |
190 | (reg > MREG_END)) | 190 | (reg > MREG_END)) |
@@ -200,43 +200,29 @@ static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) | |||
200 | 200 | ||
201 | 201 | ||
202 | ************************************************************************/ | 202 | ************************************************************************/ |
203 | static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream) | 203 | static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) |
204 | { | 204 | { |
205 | struct snd_soc_pcm_runtime *rtd; | 205 | return fsi->master; |
206 | struct fsi_priv *fsi = NULL; | ||
207 | |||
208 | if (!substream || !master) | ||
209 | return NULL; | ||
210 | |||
211 | rtd = substream->private_data; | ||
212 | switch (rtd->dai->cpu_dai->id) { | ||
213 | case 0: | ||
214 | fsi = &master->fsia; | ||
215 | break; | ||
216 | case 1: | ||
217 | fsi = &master->fsib; | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | return fsi; | ||
222 | } | 206 | } |
223 | 207 | ||
224 | static int fsi_is_port_a(struct fsi_priv *fsi) | 208 | static int fsi_is_port_a(struct fsi_priv *fsi) |
225 | { | 209 | { |
226 | /* return | 210 | return fsi->master->base == fsi->base; |
227 | * 1 : port a | 211 | } |
228 | * 0 : port b | ||
229 | */ | ||
230 | 212 | ||
231 | if (fsi == &master->fsia) | 213 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) |
232 | return 1; | 214 | { |
215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
216 | struct snd_soc_dai_link *machine = rtd->dai; | ||
217 | struct snd_soc_dai *dai = machine->cpu_dai; | ||
233 | 218 | ||
234 | return 0; | 219 | return dai->private_data; |
235 | } | 220 | } |
236 | 221 | ||
237 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 222 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
238 | { | 223 | { |
239 | int is_porta = fsi_is_port_a(fsi); | 224 | int is_porta = fsi_is_port_a(fsi); |
225 | struct fsi_master *master = fsi_get_master(fsi); | ||
240 | 226 | ||
241 | return is_porta ? master->info->porta_flags : | 227 | return is_porta ? master->info->porta_flags : |
242 | master->info->portb_flags; | 228 | master->info->portb_flags; |
@@ -314,27 +300,30 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) | |||
314 | static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) | 300 | static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) |
315 | { | 301 | { |
316 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 302 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
303 | struct fsi_master *master = fsi_get_master(fsi); | ||
317 | 304 | ||
318 | fsi_master_mask_set(IMSK, data, data); | 305 | fsi_master_mask_set(master, IMSK, data, data); |
319 | fsi_master_mask_set(IEMSK, data, data); | 306 | fsi_master_mask_set(master, IEMSK, data, data); |
320 | } | 307 | } |
321 | 308 | ||
322 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) | 309 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) |
323 | { | 310 | { |
324 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 311 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
312 | struct fsi_master *master = fsi_get_master(fsi); | ||
325 | 313 | ||
326 | fsi_master_mask_set(IMSK, data, 0); | 314 | fsi_master_mask_set(master, IMSK, data, 0); |
327 | fsi_master_mask_set(IEMSK, data, 0); | 315 | fsi_master_mask_set(master, IEMSK, data, 0); |
328 | } | 316 | } |
329 | 317 | ||
330 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) | 318 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) |
331 | { | 319 | { |
332 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); | 320 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); |
321 | struct fsi_master *master = fsi_get_master(fsi); | ||
333 | 322 | ||
334 | if (enable) | 323 | if (enable) |
335 | fsi_master_mask_set(CLK_RST, val, val); | 324 | fsi_master_mask_set(master, CLK_RST, val, val); |
336 | else | 325 | else |
337 | fsi_master_mask_set(CLK_RST, val, 0); | 326 | fsi_master_mask_set(master, CLK_RST, val, 0); |
338 | } | 327 | } |
339 | 328 | ||
340 | static void fsi_irq_init(struct fsi_priv *fsi, int is_play) | 329 | static void fsi_irq_init(struct fsi_priv *fsi, int is_play) |
@@ -355,23 +344,23 @@ static void fsi_irq_init(struct fsi_priv *fsi, int is_play) | |||
355 | fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); | 344 | fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); |
356 | 345 | ||
357 | /* clear interrupt factor */ | 346 | /* clear interrupt factor */ |
358 | fsi_master_mask_set(INT_ST, data, 0); | 347 | fsi_master_mask_set(fsi_get_master(fsi), INT_ST, data, 0); |
359 | } | 348 | } |
360 | 349 | ||
361 | static void fsi_soft_all_reset(void) | 350 | static void fsi_soft_all_reset(struct fsi_master *master) |
362 | { | 351 | { |
363 | u32 status = fsi_master_read(SOFT_RST); | 352 | u32 status = fsi_master_read(master, SOFT_RST); |
364 | 353 | ||
365 | /* port AB reset */ | 354 | /* port AB reset */ |
366 | status &= 0x000000ff; | 355 | status &= 0x000000ff; |
367 | fsi_master_write(SOFT_RST, status); | 356 | fsi_master_write(master, SOFT_RST, status); |
368 | mdelay(10); | 357 | mdelay(10); |
369 | 358 | ||
370 | /* soft reset */ | 359 | /* soft reset */ |
371 | status &= 0x000000f0; | 360 | status &= 0x000000f0; |
372 | fsi_master_write(SOFT_RST, status); | 361 | fsi_master_write(master, SOFT_RST, status); |
373 | status |= 0x00000001; | 362 | status |= 0x00000001; |
374 | fsi_master_write(SOFT_RST, status); | 363 | fsi_master_write(master, SOFT_RST, status); |
375 | mdelay(10); | 364 | mdelay(10); |
376 | } | 365 | } |
377 | 366 | ||
@@ -517,12 +506,13 @@ static int fsi_data_pop(struct fsi_priv *fsi) | |||
517 | 506 | ||
518 | static irqreturn_t fsi_interrupt(int irq, void *data) | 507 | static irqreturn_t fsi_interrupt(int irq, void *data) |
519 | { | 508 | { |
520 | u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; | 509 | struct fsi_master *master = data; |
521 | u32 int_st = fsi_master_read(INT_ST); | 510 | u32 status = fsi_master_read(master, SOFT_RST) & ~0x00000010; |
511 | u32 int_st = fsi_master_read(master, INT_ST); | ||
522 | 512 | ||
523 | /* clear irq status */ | 513 | /* clear irq status */ |
524 | fsi_master_write(SOFT_RST, status); | 514 | fsi_master_write(master, SOFT_RST, status); |
525 | fsi_master_write(SOFT_RST, status | 0x00000010); | 515 | fsi_master_write(master, SOFT_RST, status | 0x00000010); |
526 | 516 | ||
527 | if (int_st & INT_A_OUT) | 517 | if (int_st & INT_A_OUT) |
528 | fsi_data_push(&master->fsia); | 518 | fsi_data_push(&master->fsia); |
@@ -533,7 +523,7 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
533 | if (int_st & INT_B_IN) | 523 | if (int_st & INT_B_IN) |
534 | fsi_data_pop(&master->fsib); | 524 | fsi_data_pop(&master->fsib); |
535 | 525 | ||
536 | fsi_master_write(INT_ST, 0x0000000); | 526 | fsi_master_write(master, INT_ST, 0x0000000); |
537 | 527 | ||
538 | return IRQ_HANDLED; | 528 | return IRQ_HANDLED; |
539 | } | 529 | } |
@@ -548,7 +538,7 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
548 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | 538 | static int fsi_dai_startup(struct snd_pcm_substream *substream, |
549 | struct snd_soc_dai *dai) | 539 | struct snd_soc_dai *dai) |
550 | { | 540 | { |
551 | struct fsi_priv *fsi = fsi_get(substream); | 541 | struct fsi_priv *fsi = fsi_get_priv(substream); |
552 | const char *msg; | 542 | const char *msg; |
553 | u32 flags = fsi_get_info_flags(fsi); | 543 | u32 flags = fsi_get_info_flags(fsi); |
554 | u32 fmt; | 544 | u32 fmt; |
@@ -667,7 +657,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
667 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | 657 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, |
668 | struct snd_soc_dai *dai) | 658 | struct snd_soc_dai *dai) |
669 | { | 659 | { |
670 | struct fsi_priv *fsi = fsi_get(substream); | 660 | struct fsi_priv *fsi = fsi_get_priv(substream); |
671 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 661 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
672 | 662 | ||
673 | fsi_irq_disable(fsi, is_play); | 663 | fsi_irq_disable(fsi, is_play); |
@@ -679,7 +669,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
679 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 669 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
680 | struct snd_soc_dai *dai) | 670 | struct snd_soc_dai *dai) |
681 | { | 671 | { |
682 | struct fsi_priv *fsi = fsi_get(substream); | 672 | struct fsi_priv *fsi = fsi_get_priv(substream); |
683 | struct snd_pcm_runtime *runtime = substream->runtime; | 673 | struct snd_pcm_runtime *runtime = substream->runtime; |
684 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 674 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
685 | int ret = 0; | 675 | int ret = 0; |
@@ -760,7 +750,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) | |||
760 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | 750 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) |
761 | { | 751 | { |
762 | struct snd_pcm_runtime *runtime = substream->runtime; | 752 | struct snd_pcm_runtime *runtime = substream->runtime; |
763 | struct fsi_priv *fsi = fsi_get(substream); | 753 | struct fsi_priv *fsi = fsi_get_priv(substream); |
764 | long location; | 754 | long location; |
765 | 755 | ||
766 | location = (fsi->byte_offset - 1); | 756 | location = (fsi->byte_offset - 1); |
@@ -870,10 +860,16 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform); | |||
870 | ************************************************************************/ | 860 | ************************************************************************/ |
871 | static int fsi_probe(struct platform_device *pdev) | 861 | static int fsi_probe(struct platform_device *pdev) |
872 | { | 862 | { |
863 | struct fsi_master *master; | ||
873 | struct resource *res; | 864 | struct resource *res; |
874 | unsigned int irq; | 865 | unsigned int irq; |
875 | int ret; | 866 | int ret; |
876 | 867 | ||
868 | if (0 != pdev->id) { | ||
869 | dev_err(&pdev->dev, "current fsi support id 0 only now\n"); | ||
870 | return -ENODEV; | ||
871 | } | ||
872 | |||
877 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 873 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
878 | irq = platform_get_irq(pdev, 0); | 874 | irq = platform_get_irq(pdev, 0); |
879 | if (!res || !irq) { | 875 | if (!res || !irq) { |
@@ -899,15 +895,19 @@ static int fsi_probe(struct platform_device *pdev) | |||
899 | master->irq = irq; | 895 | master->irq = irq; |
900 | master->info = pdev->dev.platform_data; | 896 | master->info = pdev->dev.platform_data; |
901 | master->fsia.base = master->base; | 897 | master->fsia.base = master->base; |
898 | master->fsia.master = master; | ||
902 | master->fsib.base = master->base + 0x40; | 899 | master->fsib.base = master->base + 0x40; |
900 | master->fsib.master = master; | ||
903 | 901 | ||
904 | pm_runtime_enable(&pdev->dev); | 902 | pm_runtime_enable(&pdev->dev); |
905 | pm_runtime_resume(&pdev->dev); | 903 | pm_runtime_resume(&pdev->dev); |
906 | 904 | ||
907 | fsi_soc_dai[0].dev = &pdev->dev; | 905 | fsi_soc_dai[0].dev = &pdev->dev; |
906 | fsi_soc_dai[0].private_data = &master->fsia; | ||
908 | fsi_soc_dai[1].dev = &pdev->dev; | 907 | fsi_soc_dai[1].dev = &pdev->dev; |
908 | fsi_soc_dai[1].private_data = &master->fsib; | ||
909 | 909 | ||
910 | fsi_soft_all_reset(); | 910 | fsi_soft_all_reset(master); |
911 | 911 | ||
912 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); | 912 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); |
913 | if (ret) { | 913 | if (ret) { |
@@ -937,6 +937,10 @@ exit: | |||
937 | 937 | ||
938 | static int fsi_remove(struct platform_device *pdev) | 938 | static int fsi_remove(struct platform_device *pdev) |
939 | { | 939 | { |
940 | struct fsi_master *master; | ||
941 | |||
942 | master = fsi_get_master(fsi_soc_dai[0].private_data); | ||
943 | |||
940 | snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); | 944 | snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); |
941 | snd_soc_unregister_platform(&fsi_soc_platform); | 945 | snd_soc_unregister_platform(&fsi_soc_platform); |
942 | 946 | ||
@@ -946,7 +950,12 @@ static int fsi_remove(struct platform_device *pdev) | |||
946 | 950 | ||
947 | iounmap(master->base); | 951 | iounmap(master->base); |
948 | kfree(master); | 952 | kfree(master); |
949 | master = NULL; | 953 | |
954 | fsi_soc_dai[0].dev = NULL; | ||
955 | fsi_soc_dai[0].private_data = NULL; | ||
956 | fsi_soc_dai[1].dev = NULL; | ||
957 | fsi_soc_dai[1].private_data = NULL; | ||
958 | |||
950 | return 0; | 959 | return 0; |
951 | } | 960 | } |
952 | 961 | ||