diff options
author | Kuninori Morimoto <morimoto.kuninori@renesas.com> | 2010-03-25 06:15:53 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-26 07:17:45 -0400 |
commit | cc780d380a004b58c139570b037d0e3b897bb2be (patch) | |
tree | c03cc0911f99e3232899c2920d52a0ed4e044635 /sound/soc | |
parent | 4a942b457ee239eab04db8dd4d4c12ef6dc4a152 (diff) |
ASoC: fsi: Add FSI2 device support
ARM-SHMOBILE series have FIFO-buffered serial interface 2 (FSI2)
device which is advanced version of FSI.
This patch add simple support for it.
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/sh/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 56 |
2 files changed, 48 insertions, 11 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index f07f6d8b93e1..a1d14bc3c76f 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menu "SoC Audio support for SuperH" | 1 | menu "SoC Audio support for SuperH" |
2 | depends on SUPERH | 2 | depends on SUPERH || ARCH_SHMOBILE |
3 | 3 | ||
4 | config SND_SOC_PCM_SH7760 | 4 | config SND_SOC_PCM_SH7760 |
5 | tristate "SoC Audio support for Renesas SH7760" | 5 | tristate "SoC Audio support for Renesas SH7760" |
@@ -22,7 +22,6 @@ config SND_SOC_SH4_SSI | |||
22 | 22 | ||
23 | config SND_SOC_SH4_FSI | 23 | config SND_SOC_SH4_FSI |
24 | tristate "SH4 FSI support" | 24 | tristate "SH4 FSI support" |
25 | depends on CPU_SUBTYPE_SH7724 | ||
26 | help | 25 | help |
27 | This option enables FSI sound support | 26 | This option enables FSI sound support |
28 | 27 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index ae888651a77a..f14bbb0410c1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -40,6 +40,10 @@ | |||
40 | #define MUTE_ST 0x0028 | 40 | #define MUTE_ST 0x0028 |
41 | #define REG_END MUTE_ST | 41 | #define REG_END MUTE_ST |
42 | 42 | ||
43 | |||
44 | #define CPU_INT_ST 0x01F4 | ||
45 | #define CPU_IEMSK 0x01F8 | ||
46 | #define CPU_IMSK 0x01FC | ||
43 | #define INT_ST 0x0200 | 47 | #define INT_ST 0x0200 |
44 | #define IEMSK 0x0204 | 48 | #define IEMSK 0x0204 |
45 | #define IMSK 0x0208 | 49 | #define IMSK 0x0208 |
@@ -47,7 +51,7 @@ | |||
47 | #define CLK_RST 0x0210 | 51 | #define CLK_RST 0x0210 |
48 | #define SOFT_RST 0x0214 | 52 | #define SOFT_RST 0x0214 |
49 | #define FIFO_SZ 0x0218 | 53 | #define FIFO_SZ 0x0218 |
50 | #define MREG_START INT_ST | 54 | #define MREG_START CPU_INT_ST |
51 | #define MREG_END FIFO_SZ | 55 | #define MREG_END FIFO_SZ |
52 | 56 | ||
53 | /* DO_FMT */ | 57 | /* DO_FMT */ |
@@ -116,11 +120,18 @@ struct fsi_priv { | |||
116 | int periods; | 120 | int periods; |
117 | }; | 121 | }; |
118 | 122 | ||
123 | struct fsi_regs { | ||
124 | u32 int_st; | ||
125 | u32 iemsk; | ||
126 | u32 imsk; | ||
127 | }; | ||
128 | |||
119 | struct fsi_master { | 129 | struct fsi_master { |
120 | void __iomem *base; | 130 | void __iomem *base; |
121 | int irq; | 131 | int irq; |
122 | struct fsi_priv fsia; | 132 | struct fsi_priv fsia; |
123 | struct fsi_priv fsib; | 133 | struct fsi_priv fsib; |
134 | struct fsi_regs *regs; | ||
124 | struct sh_fsi_platform_info *info; | 135 | struct sh_fsi_platform_info *info; |
125 | spinlock_t lock; | 136 | spinlock_t lock; |
126 | }; | 137 | }; |
@@ -337,8 +348,8 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) | |||
337 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 348 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
338 | struct fsi_master *master = fsi_get_master(fsi); | 349 | struct fsi_master *master = fsi_get_master(fsi); |
339 | 350 | ||
340 | fsi_master_mask_set(master, IMSK, data, data); | 351 | fsi_master_mask_set(master, master->regs->imsk, data, data); |
341 | fsi_master_mask_set(master, IEMSK, data, data); | 352 | fsi_master_mask_set(master, master->regs->iemsk, data, data); |
342 | } | 353 | } |
343 | 354 | ||
344 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) | 355 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) |
@@ -346,18 +357,18 @@ static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) | |||
346 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 357 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
347 | struct fsi_master *master = fsi_get_master(fsi); | 358 | struct fsi_master *master = fsi_get_master(fsi); |
348 | 359 | ||
349 | fsi_master_mask_set(master, IMSK, data, 0); | 360 | fsi_master_mask_set(master, master->regs->imsk, data, 0); |
350 | fsi_master_mask_set(master, IEMSK, data, 0); | 361 | fsi_master_mask_set(master, master->regs->iemsk, data, 0); |
351 | } | 362 | } |
352 | 363 | ||
353 | static u32 fsi_irq_get_status(struct fsi_master *master) | 364 | static u32 fsi_irq_get_status(struct fsi_master *master) |
354 | { | 365 | { |
355 | return fsi_master_read(master, INT_ST); | 366 | return fsi_master_read(master, master->regs->int_st); |
356 | } | 367 | } |
357 | 368 | ||
358 | static void fsi_irq_clear_all_status(struct fsi_master *master) | 369 | static void fsi_irq_clear_all_status(struct fsi_master *master) |
359 | { | 370 | { |
360 | fsi_master_write(master, INT_ST, 0x0000000); | 371 | fsi_master_write(master, master->regs->int_st, 0x0000000); |
361 | } | 372 | } |
362 | 373 | ||
363 | static void fsi_irq_clear_status(struct fsi_priv *fsi) | 374 | static void fsi_irq_clear_status(struct fsi_priv *fsi) |
@@ -369,7 +380,7 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) | |||
369 | data |= fsi_port_ab_io_bit(fsi, 1); | 380 | data |= fsi_port_ab_io_bit(fsi, 1); |
370 | 381 | ||
371 | /* clear interrupt factor */ | 382 | /* clear interrupt factor */ |
372 | fsi_master_mask_set(master, INT_ST, data, 0); | 383 | fsi_master_mask_set(master, master->regs->int_st, data, 0); |
373 | } | 384 | } |
374 | 385 | ||
375 | /************************************************************************ | 386 | /************************************************************************ |
@@ -953,6 +964,7 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform); | |||
953 | static int fsi_probe(struct platform_device *pdev) | 964 | static int fsi_probe(struct platform_device *pdev) |
954 | { | 965 | { |
955 | struct fsi_master *master; | 966 | struct fsi_master *master; |
967 | const struct platform_device_id *id_entry; | ||
956 | struct resource *res; | 968 | struct resource *res; |
957 | unsigned int irq; | 969 | unsigned int irq; |
958 | int ret; | 970 | int ret; |
@@ -962,6 +974,12 @@ static int fsi_probe(struct platform_device *pdev) | |||
962 | return -ENODEV; | 974 | return -ENODEV; |
963 | } | 975 | } |
964 | 976 | ||
977 | id_entry = pdev->id_entry; | ||
978 | if (!id_entry) { | ||
979 | dev_err(&pdev->dev, "unknown fsi device\n"); | ||
980 | return -ENODEV; | ||
981 | } | ||
982 | |||
965 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 983 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
966 | irq = platform_get_irq(pdev, 0); | 984 | irq = platform_get_irq(pdev, 0); |
967 | if (!res || (int)irq <= 0) { | 985 | if (!res || (int)irq <= 0) { |
@@ -990,6 +1008,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
990 | master->fsia.master = master; | 1008 | master->fsia.master = master; |
991 | master->fsib.base = master->base + 0x40; | 1009 | master->fsib.base = master->base + 0x40; |
992 | master->fsib.master = master; | 1010 | master->fsib.master = master; |
1011 | master->regs = (struct fsi_regs *)id_entry->driver_data; | ||
993 | spin_lock_init(&master->lock); | 1012 | spin_lock_init(&master->lock); |
994 | 1013 | ||
995 | pm_runtime_enable(&pdev->dev); | 1014 | pm_runtime_enable(&pdev->dev); |
@@ -1002,7 +1021,8 @@ static int fsi_probe(struct platform_device *pdev) | |||
1002 | 1021 | ||
1003 | fsi_soft_all_reset(master); | 1022 | fsi_soft_all_reset(master); |
1004 | 1023 | ||
1005 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); | 1024 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, |
1025 | id_entry->name, master); | ||
1006 | if (ret) { | 1026 | if (ret) { |
1007 | dev_err(&pdev->dev, "irq request err\n"); | 1027 | dev_err(&pdev->dev, "irq request err\n"); |
1008 | goto exit_iounmap; | 1028 | goto exit_iounmap; |
@@ -1069,6 +1089,23 @@ static struct dev_pm_ops fsi_pm_ops = { | |||
1069 | .runtime_resume = fsi_runtime_nop, | 1089 | .runtime_resume = fsi_runtime_nop, |
1070 | }; | 1090 | }; |
1071 | 1091 | ||
1092 | static struct fsi_regs fsi_regs = { | ||
1093 | .int_st = INT_ST, | ||
1094 | .iemsk = IEMSK, | ||
1095 | .imsk = IMSK, | ||
1096 | }; | ||
1097 | |||
1098 | static struct fsi_regs fsi2_regs = { | ||
1099 | .int_st = CPU_INT_ST, | ||
1100 | .iemsk = CPU_IEMSK, | ||
1101 | .imsk = CPU_IMSK, | ||
1102 | }; | ||
1103 | |||
1104 | static struct platform_device_id fsi_id_table[] = { | ||
1105 | { "sh_fsi", (kernel_ulong_t)&fsi_regs }, | ||
1106 | { "sh_fsi2", (kernel_ulong_t)&fsi2_regs }, | ||
1107 | }; | ||
1108 | |||
1072 | static struct platform_driver fsi_driver = { | 1109 | static struct platform_driver fsi_driver = { |
1073 | .driver = { | 1110 | .driver = { |
1074 | .name = "sh_fsi", | 1111 | .name = "sh_fsi", |
@@ -1076,6 +1113,7 @@ static struct platform_driver fsi_driver = { | |||
1076 | }, | 1113 | }, |
1077 | .probe = fsi_probe, | 1114 | .probe = fsi_probe, |
1078 | .remove = fsi_remove, | 1115 | .remove = fsi_remove, |
1116 | .id_table = fsi_id_table, | ||
1079 | }; | 1117 | }; |
1080 | 1118 | ||
1081 | static int __init fsi_mobile_init(void) | 1119 | static int __init fsi_mobile_init(void) |