diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2013-08-26 04:52:35 -0400 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2013-09-30 03:56:11 -0400 |
commit | 688e6a6df880ee70e76f6ec1991dd0f186c25329 (patch) | |
tree | caa139836ebdfcd041e44d00b751bd406b06ea04 /arch/arm/mach-shmobile/board-bockw.c | |
parent | 71d7472f63385f4f6fb7c8548450b2e4665dc542 (diff) |
ARM: shmobile: bockw: add R-Car sound support (PIO)
This patch enables R-Car sound,
AK4643 (CN19) and AK4554 (CN20/CN21) codec chip
on Bock-W.
But, it supports PIO transfer only at this point.
User can check sound settings (Dip-switch/PFC etc)
via this patch, but will get under/over flow error
when playback/capture.
Because PIO transfer via SSI will be interrupted
"sampling rate" times per 1 second.
DMA transfer will be supported when HPB-DMAC was
enabled on r8a7778.
You will notice strange ALSA sound card HW
numbering on Bock-W board.
This came from AK4554 strange format on playback/capture.
The format on playback/capture is same on "normal" codec chip,
but AK4554 was different.
Because of that, AK4554 playback/capture are
registered as a different sound card.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[horms+renesas@verge.net.au: squashed cleanup of SND_SOC_xxx in
Kconfig by Kuninori Morimoto]
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'arch/arm/mach-shmobile/board-bockw.c')
-rw-r--r-- | arch/arm/mach-shmobile/board-bockw.c | 274 |
1 files changed, 273 insertions, 1 deletions
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index b998c6b2a270..7ad868d0a047 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c | |||
@@ -37,9 +37,12 @@ | |||
37 | #include <mach/irqs.h> | 37 | #include <mach/irqs.h> |
38 | #include <mach/r8a7778.h> | 38 | #include <mach/r8a7778.h> |
39 | #include <asm/mach/arch.h> | 39 | #include <asm/mach/arch.h> |
40 | #include <sound/rcar_snd.h> | ||
41 | #include <sound/simple_card.h> | ||
40 | 42 | ||
41 | #define FPGA 0x18200000 | 43 | #define FPGA 0x18200000 |
42 | #define IRQ0MR 0x30 | 44 | #define IRQ0MR 0x30 |
45 | #define COMCTLR 0x101c | ||
43 | static void __iomem *fpga; | 46 | static void __iomem *fpga; |
44 | 47 | ||
45 | /* | 48 | /* |
@@ -67,6 +70,35 @@ static void __iomem *fpga; | |||
67 | * SW19 (MMC) 1 pin | 70 | * SW19 (MMC) 1 pin |
68 | */ | 71 | */ |
69 | 72 | ||
73 | /* | ||
74 | * SSI settings | ||
75 | * | ||
76 | * SW45: 1-4 side (SSI5 out, ROUT/LOUT CN19 Mid) | ||
77 | * SW46: 1101 (SSI6 Recorde) | ||
78 | * SW47: 1110 (SSI5 Playback) | ||
79 | * SW48: 11 (Recorde power) | ||
80 | * SW49: 1 (SSI slave mode) | ||
81 | * SW50: 1111 (SSI7, SSI8) | ||
82 | * SW51: 1111 (SSI3, SSI4) | ||
83 | * SW54: 1pin (ak4554 FPGA control) | ||
84 | * SW55: 1 (CLKB is 24.5760MHz) | ||
85 | * SW60: 1pin (ak4554 FPGA control) | ||
86 | * SW61: 3pin (use X11 clock) | ||
87 | * SW78: 3-6 (ak4642 connects I2C0) | ||
88 | * | ||
89 | * You can use sound as | ||
90 | * | ||
91 | * hw0: CN19: SSI56-AK4643 | ||
92 | * hw1: CN21: SSI3-AK4554(playback) | ||
93 | * hw2: CN21: SSI4-AK4554(capture) | ||
94 | * hw3: CN20: SSI7-AK4554(playback) | ||
95 | * hw4: CN20: SSI8-AK4554(capture) | ||
96 | * | ||
97 | * this command is required when playback on hw0. | ||
98 | * | ||
99 | * # amixer set "LINEOUT Mixer DACL" on | ||
100 | */ | ||
101 | |||
70 | /* Dummy supplies, where voltage doesn't matter */ | 102 | /* Dummy supplies, where voltage doesn't matter */ |
71 | static struct regulator_consumer_supply dummy_supplies[] = { | 103 | static struct regulator_consumer_supply dummy_supplies[] = { |
72 | REGULATOR_SUPPLY("vddvario", "smsc911x"), | 104 | REGULATOR_SUPPLY("vddvario", "smsc911x"), |
@@ -122,7 +154,9 @@ static struct sh_eth_plat_data ether_platform_data __initdata = { | |||
122 | static struct i2c_board_info i2c0_devices[] = { | 154 | static struct i2c_board_info i2c0_devices[] = { |
123 | { | 155 | { |
124 | I2C_BOARD_INFO("rx8581", 0x51), | 156 | I2C_BOARD_INFO("rx8581", 0x51), |
125 | }, | 157 | }, { |
158 | I2C_BOARD_INFO("ak4643", 0x12), | ||
159 | } | ||
126 | }; | 160 | }; |
127 | 161 | ||
128 | /* HSPI*/ | 162 | /* HSPI*/ |
@@ -185,7 +219,213 @@ static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \ | |||
185 | BOCKW_CAMERA(0); | 219 | BOCKW_CAMERA(0); |
186 | BOCKW_CAMERA(1); | 220 | BOCKW_CAMERA(1); |
187 | 221 | ||
222 | /* Sound */ | ||
223 | static struct resource rsnd_resources[] __initdata = { | ||
224 | [RSND_GEN1_SRU] = DEFINE_RES_MEM(0xffd90000, 0x1000), | ||
225 | [RSND_GEN1_SSI] = DEFINE_RES_MEM(0xffd91000, 0x1240), | ||
226 | [RSND_GEN1_ADG] = DEFINE_RES_MEM(0xfffe0000, 0x24), | ||
227 | }; | ||
228 | |||
229 | static struct rsnd_ssi_platform_info rsnd_ssi[] = { | ||
230 | RSND_SSI_UNUSED, /* SSI 0 */ | ||
231 | RSND_SSI_UNUSED, /* SSI 1 */ | ||
232 | RSND_SSI_UNUSED, /* SSI 2 */ | ||
233 | RSND_SSI_SET(1, 0, gic_iid(0x85), RSND_SSI_PLAY), | ||
234 | RSND_SSI_SET(2, 0, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG), | ||
235 | RSND_SSI_SET(0, 0, gic_iid(0x86), RSND_SSI_PLAY), | ||
236 | RSND_SSI_SET(0, 0, gic_iid(0x86), 0), | ||
237 | RSND_SSI_SET(3, 0, gic_iid(0x86), RSND_SSI_PLAY), | ||
238 | RSND_SSI_SET(4, 0, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG), | ||
239 | }; | ||
240 | |||
241 | static struct rsnd_scu_platform_info rsnd_scu[9] = { | ||
242 | /* no member at this point */ | ||
243 | }; | ||
244 | |||
245 | enum { | ||
246 | AK4554_34 = 0, | ||
247 | AK4643_56, | ||
248 | AK4554_78, | ||
249 | SOUND_MAX, | ||
250 | }; | ||
251 | |||
252 | static int rsnd_codec_power(int id, int enable) | ||
253 | { | ||
254 | static int sound_user[SOUND_MAX] = {0, 0, 0}; | ||
255 | int *usr = NULL; | ||
256 | u32 bit; | ||
257 | |||
258 | switch (id) { | ||
259 | case 3: | ||
260 | case 4: | ||
261 | usr = sound_user + AK4554_34; | ||
262 | bit = (1 << 10); | ||
263 | break; | ||
264 | case 5: | ||
265 | case 6: | ||
266 | usr = sound_user + AK4643_56; | ||
267 | bit = (1 << 6); | ||
268 | break; | ||
269 | case 7: | ||
270 | case 8: | ||
271 | usr = sound_user + AK4554_78; | ||
272 | bit = (1 << 7); | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | if (!usr) | ||
277 | return -EIO; | ||
278 | |||
279 | if (enable) { | ||
280 | if (*usr == 0) { | ||
281 | u32 val = ioread16(fpga + COMCTLR); | ||
282 | val &= ~bit; | ||
283 | iowrite16(val, fpga + COMCTLR); | ||
284 | } | ||
285 | |||
286 | (*usr)++; | ||
287 | } else { | ||
288 | if (*usr == 0) | ||
289 | return 0; | ||
290 | |||
291 | (*usr)--; | ||
292 | |||
293 | if (*usr == 0) { | ||
294 | u32 val = ioread16(fpga + COMCTLR); | ||
295 | val |= bit; | ||
296 | iowrite16(val, fpga + COMCTLR); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int rsnd_start(int id) | ||
304 | { | ||
305 | return rsnd_codec_power(id, 1); | ||
306 | } | ||
307 | |||
308 | static int rsnd_stop(int id) | ||
309 | { | ||
310 | return rsnd_codec_power(id, 0); | ||
311 | } | ||
312 | |||
313 | static struct rcar_snd_info rsnd_info = { | ||
314 | .flags = RSND_GEN1, | ||
315 | .ssi_info = rsnd_ssi, | ||
316 | .ssi_info_nr = ARRAY_SIZE(rsnd_ssi), | ||
317 | .scu_info = rsnd_scu, | ||
318 | .scu_info_nr = ARRAY_SIZE(rsnd_scu), | ||
319 | .start = rsnd_start, | ||
320 | .stop = rsnd_stop, | ||
321 | }; | ||
322 | |||
323 | static struct asoc_simple_card_info rsnd_card_info[] = { | ||
324 | /* SSI5, SSI6 */ | ||
325 | { | ||
326 | .name = "AK4643", | ||
327 | .card = "SSI56-AK4643", | ||
328 | .codec = "ak4642-codec.0-0012", | ||
329 | .platform = "rcar_sound", | ||
330 | .daifmt = SND_SOC_DAIFMT_LEFT_J, | ||
331 | .cpu_dai = { | ||
332 | .name = "rsnd-dai.0", | ||
333 | .fmt = SND_SOC_DAIFMT_CBS_CFS, | ||
334 | }, | ||
335 | .codec_dai = { | ||
336 | .name = "ak4642-hifi", | ||
337 | .fmt = SND_SOC_DAIFMT_CBM_CFM, | ||
338 | .sysclk = 11289600, | ||
339 | }, | ||
340 | }, | ||
341 | /* SSI3 */ | ||
342 | { | ||
343 | .name = "AK4554", | ||
344 | .card = "SSI3-AK4554(playback)", | ||
345 | .codec = "ak4554-adc-dac.0", | ||
346 | .platform = "rcar_sound", | ||
347 | .cpu_dai = { | ||
348 | .name = "rsnd-dai.1", | ||
349 | .fmt = SND_SOC_DAIFMT_CBM_CFM | | ||
350 | SND_SOC_DAIFMT_RIGHT_J, | ||
351 | }, | ||
352 | .codec_dai = { | ||
353 | .name = "ak4554-hifi", | ||
354 | }, | ||
355 | }, | ||
356 | /* SSI4 */ | ||
357 | { | ||
358 | .name = "AK4554", | ||
359 | .card = "SSI4-AK4554(capture)", | ||
360 | .codec = "ak4554-adc-dac.0", | ||
361 | .platform = "rcar_sound", | ||
362 | .cpu_dai = { | ||
363 | .name = "rsnd-dai.2", | ||
364 | .fmt = SND_SOC_DAIFMT_CBM_CFM | | ||
365 | SND_SOC_DAIFMT_LEFT_J, | ||
366 | }, | ||
367 | .codec_dai = { | ||
368 | .name = "ak4554-hifi", | ||
369 | }, | ||
370 | }, | ||
371 | /* SSI7 */ | ||
372 | { | ||
373 | .name = "AK4554", | ||
374 | .card = "SSI7-AK4554(playback)", | ||
375 | .codec = "ak4554-adc-dac.1", | ||
376 | .platform = "rcar_sound", | ||
377 | .cpu_dai = { | ||
378 | .name = "rsnd-dai.3", | ||
379 | .fmt = SND_SOC_DAIFMT_CBM_CFM | | ||
380 | SND_SOC_DAIFMT_RIGHT_J, | ||
381 | }, | ||
382 | .codec_dai = { | ||
383 | .name = "ak4554-hifi", | ||
384 | }, | ||
385 | }, | ||
386 | /* SSI8 */ | ||
387 | { | ||
388 | .name = "AK4554", | ||
389 | .card = "SSI8-AK4554(capture)", | ||
390 | .codec = "ak4554-adc-dac.1", | ||
391 | .platform = "rcar_sound", | ||
392 | .cpu_dai = { | ||
393 | .name = "rsnd-dai.4", | ||
394 | .fmt = SND_SOC_DAIFMT_CBM_CFM | | ||
395 | SND_SOC_DAIFMT_LEFT_J, | ||
396 | }, | ||
397 | .codec_dai = { | ||
398 | .name = "ak4554-hifi", | ||
399 | }, | ||
400 | } | ||
401 | }; | ||
402 | |||
188 | static const struct pinctrl_map bockw_pinctrl_map[] = { | 403 | static const struct pinctrl_map bockw_pinctrl_map[] = { |
404 | /* AUDIO */ | ||
405 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
406 | "audio_clk_a", "audio_clk"), | ||
407 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
408 | "audio_clk_b", "audio_clk"), | ||
409 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
410 | "ssi34_ctrl", "ssi"), | ||
411 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
412 | "ssi3_data", "ssi"), | ||
413 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
414 | "ssi4_data", "ssi"), | ||
415 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
416 | "ssi5_ctrl", "ssi"), | ||
417 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
418 | "ssi5_data", "ssi"), | ||
419 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
420 | "ssi6_ctrl", "ssi"), | ||
421 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
422 | "ssi6_data", "ssi"), | ||
423 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
424 | "ssi78_ctrl", "ssi"), | ||
425 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
426 | "ssi7_data", "ssi"), | ||
427 | PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", | ||
428 | "ssi8_data", "ssi"), | ||
189 | /* Ether */ | 429 | /* Ether */ |
190 | PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778", | 430 | PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778", |
191 | "ether_rmii", "ether"), | 431 | "ether_rmii", "ether"), |
@@ -233,6 +473,8 @@ static const struct pinctrl_map bockw_pinctrl_map[] = { | |||
233 | static void __init bockw_init(void) | 473 | static void __init bockw_init(void) |
234 | { | 474 | { |
235 | void __iomem *base; | 475 | void __iomem *base; |
476 | struct clk *clk; | ||
477 | int i; | ||
236 | 478 | ||
237 | r8a7778_clock_init(); | 479 | r8a7778_clock_init(); |
238 | r8a7778_init_irq_extpin(1); | 480 | r8a7778_init_irq_extpin(1); |
@@ -309,6 +551,36 @@ static void __init bockw_init(void) | |||
309 | sdhi0_resources, ARRAY_SIZE(sdhi0_resources), | 551 | sdhi0_resources, ARRAY_SIZE(sdhi0_resources), |
310 | &sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); | 552 | &sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); |
311 | } | 553 | } |
554 | |||
555 | /* for Audio */ | ||
556 | clk = clk_get(NULL, "audio_clk_b"); | ||
557 | clk_set_rate(clk, 24576000); | ||
558 | clk_put(clk); | ||
559 | rsnd_codec_power(5, 1); /* enable ak4642 */ | ||
560 | |||
561 | platform_device_register_simple( | ||
562 | "ak4554-adc-dac", 0, NULL, 0); | ||
563 | |||
564 | platform_device_register_simple( | ||
565 | "ak4554-adc-dac", 1, NULL, 0); | ||
566 | |||
567 | platform_device_register_resndata( | ||
568 | &platform_bus, "rcar_sound", -1, | ||
569 | rsnd_resources, ARRAY_SIZE(rsnd_resources), | ||
570 | &rsnd_info, sizeof(rsnd_info)); | ||
571 | |||
572 | for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) { | ||
573 | struct platform_device_info cardinfo = { | ||
574 | .parent = &platform_bus, | ||
575 | .name = "asoc-simple-card", | ||
576 | .id = i, | ||
577 | .data = &rsnd_card_info[i], | ||
578 | .size_data = sizeof(struct asoc_simple_card_info), | ||
579 | .dma_mask = ~0, | ||
580 | }; | ||
581 | |||
582 | platform_device_register_full(&cardinfo); | ||
583 | } | ||
312 | } | 584 | } |
313 | 585 | ||
314 | static const char *bockw_boards_compat_dt[] __initdata = { | 586 | static const char *bockw_boards_compat_dt[] __initdata = { |