aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile/board-bockw.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2013-08-26 04:52:35 -0400
committerSimon Horman <horms+renesas@verge.net.au>2013-09-30 03:56:11 -0400
commit688e6a6df880ee70e76f6ec1991dd0f186c25329 (patch)
treecaa139836ebdfcd041e44d00b751bd406b06ea04 /arch/arm/mach-shmobile/board-bockw.c
parent71d7472f63385f4f6fb7c8548450b2e4665dc542 (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.c274
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
43static void __iomem *fpga; 46static 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 */
71static struct regulator_consumer_supply dummy_supplies[] = { 103static 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 = {
122static struct i2c_board_info i2c0_devices[] = { 154static 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 = { \
185BOCKW_CAMERA(0); 219BOCKW_CAMERA(0);
186BOCKW_CAMERA(1); 220BOCKW_CAMERA(1);
187 221
222/* Sound */
223static 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
229static 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
241static struct rsnd_scu_platform_info rsnd_scu[9] = {
242 /* no member at this point */
243};
244
245enum {
246 AK4554_34 = 0,
247 AK4643_56,
248 AK4554_78,
249 SOUND_MAX,
250};
251
252static 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
303static int rsnd_start(int id)
304{
305 return rsnd_codec_power(id, 1);
306}
307
308static int rsnd_stop(int id)
309{
310 return rsnd_codec_power(id, 0);
311}
312
313static 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
323static 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
188static const struct pinctrl_map bockw_pinctrl_map[] = { 403static 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[] = {
233static void __init bockw_init(void) 473static 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
314static const char *bockw_boards_compat_dt[] __initdata = { 586static const char *bockw_boards_compat_dt[] __initdata = {