Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/soc/sh/siu_dai.c
10817 views
1
/*
2
* siu_dai.c - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
3
*
4
* Copyright (C) 2009-2010 Guennadi Liakhovetski <[email protected]>
5
* Copyright (C) 2006 Carlos Munoz <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
*/
21
22
#include <linux/delay.h>
23
#include <linux/firmware.h>
24
#include <linux/pm_runtime.h>
25
#include <linux/slab.h>
26
27
#include <asm/clock.h>
28
#include <asm/siu.h>
29
30
#include <sound/control.h>
31
#include <sound/soc.h>
32
33
#include "siu.h"
34
35
/* Board specifics */
36
#if defined(CONFIG_CPU_SUBTYPE_SH7722)
37
# define SIU_MAX_VOLUME 0x1000
38
#else
39
# define SIU_MAX_VOLUME 0x7fff
40
#endif
41
42
#define PRAM_SIZE 0x2000
43
#define XRAM_SIZE 0x800
44
#define YRAM_SIZE 0x800
45
46
#define XRAM_OFFSET 0x4000
47
#define YRAM_OFFSET 0x6000
48
#define REG_OFFSET 0xc000
49
50
#define PLAYBACK_ENABLED 1
51
#define CAPTURE_ENABLED 2
52
53
#define VOLUME_CAPTURE 0
54
#define VOLUME_PLAYBACK 1
55
#define DFLT_VOLUME_LEVEL 0x08000800
56
57
/*
58
* SPDIF is only available on port A and on some SIU implementations it is only
59
* available for input. Due to the lack of hardware to test it, SPDIF is left
60
* disabled in this driver version
61
*/
62
struct format_flag {
63
u32 i2s;
64
u32 pcm;
65
u32 spdif;
66
u32 mask;
67
};
68
69
struct port_flag {
70
struct format_flag playback;
71
struct format_flag capture;
72
};
73
74
struct siu_info *siu_i2s_data;
75
76
static struct port_flag siu_flags[SIU_PORT_NUM] = {
77
[SIU_PORT_A] = {
78
.playback = {
79
.i2s = 0x50000000,
80
.pcm = 0x40000000,
81
.spdif = 0x80000000, /* not on all SIU versions */
82
.mask = 0xd0000000,
83
},
84
.capture = {
85
.i2s = 0x05000000,
86
.pcm = 0x04000000,
87
.spdif = 0x08000000,
88
.mask = 0x0d000000,
89
},
90
},
91
[SIU_PORT_B] = {
92
.playback = {
93
.i2s = 0x00500000,
94
.pcm = 0x00400000,
95
.spdif = 0, /* impossible - turn off */
96
.mask = 0x00500000,
97
},
98
.capture = {
99
.i2s = 0x00050000,
100
.pcm = 0x00040000,
101
.spdif = 0, /* impossible - turn off */
102
.mask = 0x00050000,
103
},
104
},
105
};
106
107
static void siu_dai_start(struct siu_port *port_info)
108
{
109
struct siu_info *info = siu_i2s_data;
110
u32 __iomem *base = info->reg;
111
112
dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
113
114
/* Turn on SIU clock */
115
pm_runtime_get_sync(info->dev);
116
117
/* Issue software reset to siu */
118
siu_write32(base + SIU_SRCTL, 0);
119
120
/* Wait for the reset to take effect */
121
udelay(1);
122
123
port_info->stfifo = 0;
124
port_info->trdat = 0;
125
126
/* portA, portB, SIU operate */
127
siu_write32(base + SIU_SRCTL, 0x301);
128
129
/* portA=256fs, portB=256fs */
130
siu_write32(base + SIU_CKCTL, 0x40400000);
131
132
/* portA's BRG does not divide SIUCKA */
133
siu_write32(base + SIU_BRGASEL, 0);
134
siu_write32(base + SIU_BRRA, 0);
135
136
/* portB's BRG divides SIUCKB by half */
137
siu_write32(base + SIU_BRGBSEL, 1);
138
siu_write32(base + SIU_BRRB, 0);
139
140
siu_write32(base + SIU_IFCTL, 0x44440000);
141
142
/* portA: 32 bit/fs, master; portB: 32 bit/fs, master */
143
siu_write32(base + SIU_SFORM, 0x0c0c0000);
144
145
/*
146
* Volume levels: looks like the DSP firmware implements volume controls
147
* differently from what's described in the datasheet
148
*/
149
siu_write32(base + SIU_SBDVCA, port_info->playback.volume);
150
siu_write32(base + SIU_SBDVCB, port_info->capture.volume);
151
}
152
153
static void siu_dai_stop(struct siu_port *port_info)
154
{
155
struct siu_info *info = siu_i2s_data;
156
u32 __iomem *base = info->reg;
157
158
/* SIU software reset */
159
siu_write32(base + SIU_SRCTL, 0);
160
161
/* Turn off SIU clock */
162
pm_runtime_put_sync(info->dev);
163
}
164
165
static void siu_dai_spbAselect(struct siu_port *port_info)
166
{
167
struct siu_info *info = siu_i2s_data;
168
struct siu_firmware *fw = &info->fw;
169
u32 *ydef = fw->yram0;
170
u32 idx;
171
172
/* path A use */
173
if (!info->port_id)
174
idx = 1; /* portA */
175
else
176
idx = 2; /* portB */
177
178
ydef[0] = (fw->spbpar[idx].ab1a << 16) |
179
(fw->spbpar[idx].ab0a << 8) |
180
(fw->spbpar[idx].dir << 7) | 3;
181
ydef[1] = fw->yram0[1]; /* 0x03000300 */
182
ydef[2] = (16 / 2) << 24;
183
ydef[3] = fw->yram0[3]; /* 0 */
184
ydef[4] = fw->yram0[4]; /* 0 */
185
ydef[7] = fw->spbpar[idx].event;
186
port_info->stfifo |= fw->spbpar[idx].stfifo;
187
port_info->trdat |= fw->spbpar[idx].trdat;
188
}
189
190
static void siu_dai_spbBselect(struct siu_port *port_info)
191
{
192
struct siu_info *info = siu_i2s_data;
193
struct siu_firmware *fw = &info->fw;
194
u32 *ydef = fw->yram0;
195
u32 idx;
196
197
/* path B use */
198
if (!info->port_id)
199
idx = 7; /* portA */
200
else
201
idx = 8; /* portB */
202
203
ydef[5] = (fw->spbpar[idx].ab1a << 16) |
204
(fw->spbpar[idx].ab0a << 8) | 1;
205
ydef[6] = fw->spbpar[idx].event;
206
port_info->stfifo |= fw->spbpar[idx].stfifo;
207
port_info->trdat |= fw->spbpar[idx].trdat;
208
}
209
210
static void siu_dai_open(struct siu_stream *siu_stream)
211
{
212
struct siu_info *info = siu_i2s_data;
213
u32 __iomem *base = info->reg;
214
u32 srctl, ifctl;
215
216
srctl = siu_read32(base + SIU_SRCTL);
217
ifctl = siu_read32(base + SIU_IFCTL);
218
219
switch (info->port_id) {
220
case SIU_PORT_A:
221
/* portA operates */
222
srctl |= 0x200;
223
ifctl &= ~0xc2;
224
break;
225
case SIU_PORT_B:
226
/* portB operates */
227
srctl |= 0x100;
228
ifctl &= ~0x31;
229
break;
230
}
231
232
siu_write32(base + SIU_SRCTL, srctl);
233
/* Unmute and configure portA */
234
siu_write32(base + SIU_IFCTL, ifctl);
235
}
236
237
/*
238
* At the moment only fixed Left-upper, Left-lower, Right-upper, Right-lower
239
* packing is supported
240
*/
241
static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
242
{
243
struct siu_info *info = siu_i2s_data;
244
u32 __iomem *base = info->reg;
245
u32 dpak;
246
247
dpak = siu_read32(base + SIU_DPAK);
248
249
switch (info->port_id) {
250
case SIU_PORT_A:
251
dpak &= ~0xc0000000;
252
break;
253
case SIU_PORT_B:
254
dpak &= ~0x00c00000;
255
break;
256
}
257
258
siu_write32(base + SIU_DPAK, dpak);
259
}
260
261
static int siu_dai_spbstart(struct siu_port *port_info)
262
{
263
struct siu_info *info = siu_i2s_data;
264
u32 __iomem *base = info->reg;
265
struct siu_firmware *fw = &info->fw;
266
u32 *ydef = fw->yram0;
267
int cnt;
268
u32 __iomem *add;
269
u32 *ptr;
270
271
/* Load SPB Program in PRAM */
272
ptr = fw->pram0;
273
add = info->pram;
274
for (cnt = 0; cnt < PRAM0_SIZE; cnt++, add++, ptr++)
275
siu_write32(add, *ptr);
276
277
ptr = fw->pram1;
278
add = info->pram + (0x0100 / sizeof(u32));
279
for (cnt = 0; cnt < PRAM1_SIZE; cnt++, add++, ptr++)
280
siu_write32(add, *ptr);
281
282
/* XRAM initialization */
283
add = info->xram;
284
for (cnt = 0; cnt < XRAM0_SIZE + XRAM1_SIZE + XRAM2_SIZE; cnt++, add++)
285
siu_write32(add, 0);
286
287
/* YRAM variable area initialization */
288
add = info->yram;
289
for (cnt = 0; cnt < YRAM_DEF_SIZE; cnt++, add++)
290
siu_write32(add, ydef[cnt]);
291
292
/* YRAM FIR coefficient area initialization */
293
add = info->yram + (0x0200 / sizeof(u32));
294
for (cnt = 0; cnt < YRAM_FIR_SIZE; cnt++, add++)
295
siu_write32(add, fw->yram_fir_coeff[cnt]);
296
297
/* YRAM IIR coefficient area initialization */
298
add = info->yram + (0x0600 / sizeof(u32));
299
for (cnt = 0; cnt < YRAM_IIR_SIZE; cnt++, add++)
300
siu_write32(add, 0);
301
302
siu_write32(base + SIU_TRDAT, port_info->trdat);
303
port_info->trdat = 0x0;
304
305
306
/* SPB start condition: software */
307
siu_write32(base + SIU_SBACTIV, 0);
308
/* Start SPB */
309
siu_write32(base + SIU_SBCTL, 0xc0000000);
310
/* Wait for program to halt */
311
cnt = 0x10000;
312
while (--cnt && siu_read32(base + SIU_SBCTL) != 0x80000000)
313
cpu_relax();
314
315
if (!cnt)
316
return -EBUSY;
317
318
/* SPB program start address setting */
319
siu_write32(base + SIU_SBPSET, 0x00400000);
320
/* SPB hardware start(FIFOCTL source) */
321
siu_write32(base + SIU_SBACTIV, 0xc0000000);
322
323
return 0;
324
}
325
326
static void siu_dai_spbstop(struct siu_port *port_info)
327
{
328
struct siu_info *info = siu_i2s_data;
329
u32 __iomem *base = info->reg;
330
331
siu_write32(base + SIU_SBACTIV, 0);
332
/* SPB stop */
333
siu_write32(base + SIU_SBCTL, 0);
334
335
port_info->stfifo = 0;
336
}
337
338
/* API functions */
339
340
/* Playback and capture hardware properties are identical */
341
static struct snd_pcm_hardware siu_dai_pcm_hw = {
342
.info = SNDRV_PCM_INFO_INTERLEAVED,
343
.formats = SNDRV_PCM_FMTBIT_S16,
344
.rates = SNDRV_PCM_RATE_8000_48000,
345
.rate_min = 8000,
346
.rate_max = 48000,
347
.channels_min = 2,
348
.channels_max = 2,
349
.buffer_bytes_max = SIU_BUFFER_BYTES_MAX,
350
.period_bytes_min = SIU_PERIOD_BYTES_MIN,
351
.period_bytes_max = SIU_PERIOD_BYTES_MAX,
352
.periods_min = SIU_PERIODS_MIN,
353
.periods_max = SIU_PERIODS_MAX,
354
};
355
356
static int siu_dai_info_volume(struct snd_kcontrol *kctrl,
357
struct snd_ctl_elem_info *uinfo)
358
{
359
struct siu_port *port_info = snd_kcontrol_chip(kctrl);
360
361
dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
362
363
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
364
uinfo->count = 2;
365
uinfo->value.integer.min = 0;
366
uinfo->value.integer.max = SIU_MAX_VOLUME;
367
368
return 0;
369
}
370
371
static int siu_dai_get_volume(struct snd_kcontrol *kctrl,
372
struct snd_ctl_elem_value *ucontrol)
373
{
374
struct siu_port *port_info = snd_kcontrol_chip(kctrl);
375
struct device *dev = port_info->pcm->card->dev;
376
u32 vol;
377
378
dev_dbg(dev, "%s\n", __func__);
379
380
switch (kctrl->private_value) {
381
case VOLUME_PLAYBACK:
382
/* Playback is always on port 0 */
383
vol = port_info->playback.volume;
384
ucontrol->value.integer.value[0] = vol & 0xffff;
385
ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
386
break;
387
case VOLUME_CAPTURE:
388
/* Capture is always on port 1 */
389
vol = port_info->capture.volume;
390
ucontrol->value.integer.value[0] = vol & 0xffff;
391
ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
392
break;
393
default:
394
dev_err(dev, "%s() invalid private_value=%ld\n",
395
__func__, kctrl->private_value);
396
return -EINVAL;
397
}
398
399
return 0;
400
}
401
402
static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
403
struct snd_ctl_elem_value *ucontrol)
404
{
405
struct siu_port *port_info = snd_kcontrol_chip(kctrl);
406
struct device *dev = port_info->pcm->card->dev;
407
struct siu_info *info = siu_i2s_data;
408
u32 __iomem *base = info->reg;
409
u32 new_vol;
410
u32 cur_vol;
411
412
dev_dbg(dev, "%s\n", __func__);
413
414
if (ucontrol->value.integer.value[0] < 0 ||
415
ucontrol->value.integer.value[0] > SIU_MAX_VOLUME ||
416
ucontrol->value.integer.value[1] < 0 ||
417
ucontrol->value.integer.value[1] > SIU_MAX_VOLUME)
418
return -EINVAL;
419
420
new_vol = ucontrol->value.integer.value[0] |
421
ucontrol->value.integer.value[1] << 16;
422
423
/* See comment above - DSP firmware implementation */
424
switch (kctrl->private_value) {
425
case VOLUME_PLAYBACK:
426
/* Playback is always on port 0 */
427
cur_vol = port_info->playback.volume;
428
siu_write32(base + SIU_SBDVCA, new_vol);
429
port_info->playback.volume = new_vol;
430
break;
431
case VOLUME_CAPTURE:
432
/* Capture is always on port 1 */
433
cur_vol = port_info->capture.volume;
434
siu_write32(base + SIU_SBDVCB, new_vol);
435
port_info->capture.volume = new_vol;
436
break;
437
default:
438
dev_err(dev, "%s() invalid private_value=%ld\n",
439
__func__, kctrl->private_value);
440
return -EINVAL;
441
}
442
443
if (cur_vol != new_vol)
444
return 1;
445
446
return 0;
447
}
448
449
static struct snd_kcontrol_new playback_controls = {
450
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
451
.name = "PCM Playback Volume",
452
.index = 0,
453
.info = siu_dai_info_volume,
454
.get = siu_dai_get_volume,
455
.put = siu_dai_put_volume,
456
.private_value = VOLUME_PLAYBACK,
457
};
458
459
static struct snd_kcontrol_new capture_controls = {
460
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
461
.name = "PCM Capture Volume",
462
.index = 0,
463
.info = siu_dai_info_volume,
464
.get = siu_dai_get_volume,
465
.put = siu_dai_put_volume,
466
.private_value = VOLUME_CAPTURE,
467
};
468
469
int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card)
470
{
471
struct device *dev = card->dev;
472
struct snd_kcontrol *kctrl;
473
int ret;
474
475
*port_info = kzalloc(sizeof(**port_info), GFP_KERNEL);
476
if (!*port_info)
477
return -ENOMEM;
478
479
dev_dbg(dev, "%s: port #%d@%p\n", __func__, port, *port_info);
480
481
(*port_info)->playback.volume = DFLT_VOLUME_LEVEL;
482
(*port_info)->capture.volume = DFLT_VOLUME_LEVEL;
483
484
/*
485
* Add mixer support. The SPB is used to change the volume. Both
486
* ports use the same SPB. Therefore, we only register one
487
* control instance since it will be used by both channels.
488
* In error case we continue without controls.
489
*/
490
kctrl = snd_ctl_new1(&playback_controls, *port_info);
491
ret = snd_ctl_add(card, kctrl);
492
if (ret < 0)
493
dev_err(dev,
494
"failed to add playback controls %p port=%d err=%d\n",
495
kctrl, port, ret);
496
497
kctrl = snd_ctl_new1(&capture_controls, *port_info);
498
ret = snd_ctl_add(card, kctrl);
499
if (ret < 0)
500
dev_err(dev,
501
"failed to add capture controls %p port=%d err=%d\n",
502
kctrl, port, ret);
503
504
return 0;
505
}
506
507
void siu_free_port(struct siu_port *port_info)
508
{
509
kfree(port_info);
510
}
511
512
static int siu_dai_startup(struct snd_pcm_substream *substream,
513
struct snd_soc_dai *dai)
514
{
515
struct siu_info *info = snd_soc_dai_get_drvdata(dai);
516
struct snd_pcm_runtime *rt = substream->runtime;
517
struct siu_port *port_info = siu_port_info(substream);
518
int ret;
519
520
dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
521
info->port_id, port_info);
522
523
snd_soc_set_runtime_hwparams(substream, &siu_dai_pcm_hw);
524
525
ret = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
526
if (unlikely(ret < 0))
527
return ret;
528
529
siu_dai_start(port_info);
530
531
return 0;
532
}
533
534
static void siu_dai_shutdown(struct snd_pcm_substream *substream,
535
struct snd_soc_dai *dai)
536
{
537
struct siu_info *info = snd_soc_dai_get_drvdata(dai);
538
struct siu_port *port_info = siu_port_info(substream);
539
540
dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
541
info->port_id, port_info);
542
543
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
544
port_info->play_cap &= ~PLAYBACK_ENABLED;
545
else
546
port_info->play_cap &= ~CAPTURE_ENABLED;
547
548
/* Stop the siu if the other stream is not using it */
549
if (!port_info->play_cap) {
550
/* during stmread or stmwrite ? */
551
BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);
552
siu_dai_spbstop(port_info);
553
siu_dai_stop(port_info);
554
}
555
}
556
557
/* PCM part of siu_dai_playback_prepare() / siu_dai_capture_prepare() */
558
static int siu_dai_prepare(struct snd_pcm_substream *substream,
559
struct snd_soc_dai *dai)
560
{
561
struct siu_info *info = snd_soc_dai_get_drvdata(dai);
562
struct snd_pcm_runtime *rt = substream->runtime;
563
struct siu_port *port_info = siu_port_info(substream);
564
struct siu_stream *siu_stream;
565
int self, ret;
566
567
dev_dbg(substream->pcm->card->dev,
568
"%s: port %d, active streams %lx, %d channels\n",
569
__func__, info->port_id, port_info->play_cap, rt->channels);
570
571
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
572
self = PLAYBACK_ENABLED;
573
siu_stream = &port_info->playback;
574
} else {
575
self = CAPTURE_ENABLED;
576
siu_stream = &port_info->capture;
577
}
578
579
/* Set up the siu if not already done */
580
if (!port_info->play_cap) {
581
siu_stream->rw_flg = 0; /* stream-data transfer flag */
582
583
siu_dai_spbAselect(port_info);
584
siu_dai_spbBselect(port_info);
585
586
siu_dai_open(siu_stream);
587
588
siu_dai_pcmdatapack(siu_stream);
589
590
ret = siu_dai_spbstart(port_info);
591
if (ret < 0)
592
goto fail;
593
} else {
594
ret = 0;
595
}
596
597
port_info->play_cap |= self;
598
599
fail:
600
return ret;
601
}
602
603
/*
604
* SIU can set bus format to I2S / PCM / SPDIF independently for playback and
605
* capture, however, the current API sets the bus format globally for a DAI.
606
*/
607
static int siu_dai_set_fmt(struct snd_soc_dai *dai,
608
unsigned int fmt)
609
{
610
struct siu_info *info = snd_soc_dai_get_drvdata(dai);
611
u32 __iomem *base = info->reg;
612
u32 ifctl;
613
614
dev_dbg(dai->dev, "%s: fmt 0x%x on port %d\n",
615
__func__, fmt, info->port_id);
616
617
if (info->port_id < 0)
618
return -ENODEV;
619
620
/* Here select between I2S / PCM / SPDIF */
621
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
622
case SND_SOC_DAIFMT_I2S:
623
ifctl = siu_flags[info->port_id].playback.i2s |
624
siu_flags[info->port_id].capture.i2s;
625
break;
626
case SND_SOC_DAIFMT_LEFT_J:
627
ifctl = siu_flags[info->port_id].playback.pcm |
628
siu_flags[info->port_id].capture.pcm;
629
break;
630
/* SPDIF disabled - see comment at the top */
631
default:
632
return -EINVAL;
633
}
634
635
ifctl |= ~(siu_flags[info->port_id].playback.mask |
636
siu_flags[info->port_id].capture.mask) &
637
siu_read32(base + SIU_IFCTL);
638
siu_write32(base + SIU_IFCTL, ifctl);
639
640
return 0;
641
}
642
643
static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
644
unsigned int freq, int dir)
645
{
646
struct clk *siu_clk, *parent_clk;
647
char *siu_name, *parent_name;
648
int ret;
649
650
if (dir != SND_SOC_CLOCK_IN)
651
return -EINVAL;
652
653
dev_dbg(dai->dev, "%s: using clock %d\n", __func__, clk_id);
654
655
switch (clk_id) {
656
case SIU_CLKA_PLL:
657
siu_name = "siua_clk";
658
parent_name = "pll_clk";
659
break;
660
case SIU_CLKA_EXT:
661
siu_name = "siua_clk";
662
parent_name = "siumcka_clk";
663
break;
664
case SIU_CLKB_PLL:
665
siu_name = "siub_clk";
666
parent_name = "pll_clk";
667
break;
668
case SIU_CLKB_EXT:
669
siu_name = "siub_clk";
670
parent_name = "siumckb_clk";
671
break;
672
default:
673
return -EINVAL;
674
}
675
676
siu_clk = clk_get(dai->dev, siu_name);
677
if (IS_ERR(siu_clk)) {
678
dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__,
679
PTR_ERR(siu_clk));
680
return PTR_ERR(siu_clk);
681
}
682
683
parent_clk = clk_get(dai->dev, parent_name);
684
if (IS_ERR(parent_clk)) {
685
ret = PTR_ERR(parent_clk);
686
dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret);
687
goto epclkget;
688
}
689
690
ret = clk_set_parent(siu_clk, parent_clk);
691
if (ret < 0) {
692
dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret);
693
goto eclksetp;
694
}
695
696
ret = clk_set_rate(siu_clk, freq);
697
if (ret < 0)
698
dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret);
699
700
/* TODO: when clkdev gets reference counting we'll move these to siu_dai_shutdown() */
701
eclksetp:
702
clk_put(parent_clk);
703
epclkget:
704
clk_put(siu_clk);
705
706
return ret;
707
}
708
709
static struct snd_soc_dai_ops siu_dai_ops = {
710
.startup = siu_dai_startup,
711
.shutdown = siu_dai_shutdown,
712
.prepare = siu_dai_prepare,
713
.set_sysclk = siu_dai_set_sysclk,
714
.set_fmt = siu_dai_set_fmt,
715
};
716
717
static struct snd_soc_dai_driver siu_i2s_dai = {
718
.name = "siu-i2s-dai",
719
.playback = {
720
.channels_min = 2,
721
.channels_max = 2,
722
.formats = SNDRV_PCM_FMTBIT_S16,
723
.rates = SNDRV_PCM_RATE_8000_48000,
724
},
725
.capture = {
726
.channels_min = 2,
727
.channels_max = 2,
728
.formats = SNDRV_PCM_FMTBIT_S16,
729
.rates = SNDRV_PCM_RATE_8000_48000,
730
},
731
.ops = &siu_dai_ops,
732
};
733
734
static int __devinit siu_probe(struct platform_device *pdev)
735
{
736
const struct firmware *fw_entry;
737
struct resource *res, *region;
738
struct siu_info *info;
739
int ret;
740
741
info = kmalloc(sizeof(*info), GFP_KERNEL);
742
if (!info)
743
return -ENOMEM;
744
siu_i2s_data = info;
745
info->dev = &pdev->dev;
746
747
ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);
748
if (ret)
749
goto ereqfw;
750
751
/*
752
* Loaded firmware is "const" - read only, but we have to modify it in
753
* snd_siu_sh7343_spbAselect() and snd_siu_sh7343_spbBselect()
754
*/
755
memcpy(&info->fw, fw_entry->data, fw_entry->size);
756
757
release_firmware(fw_entry);
758
759
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
760
if (!res) {
761
ret = -ENODEV;
762
goto egetres;
763
}
764
765
region = request_mem_region(res->start, resource_size(res),
766
pdev->name);
767
if (!region) {
768
dev_err(&pdev->dev, "SIU region already claimed\n");
769
ret = -EBUSY;
770
goto ereqmemreg;
771
}
772
773
ret = -ENOMEM;
774
info->pram = ioremap(res->start, PRAM_SIZE);
775
if (!info->pram)
776
goto emappram;
777
info->xram = ioremap(res->start + XRAM_OFFSET, XRAM_SIZE);
778
if (!info->xram)
779
goto emapxram;
780
info->yram = ioremap(res->start + YRAM_OFFSET, YRAM_SIZE);
781
if (!info->yram)
782
goto emapyram;
783
info->reg = ioremap(res->start + REG_OFFSET, resource_size(res) -
784
REG_OFFSET);
785
if (!info->reg)
786
goto emapreg;
787
788
dev_set_drvdata(&pdev->dev, info);
789
790
/* register using ARRAY version so we can keep dai name */
791
ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1);
792
if (ret < 0)
793
goto edaiinit;
794
795
ret = snd_soc_register_platform(&pdev->dev, &siu_platform);
796
if (ret < 0)
797
goto esocregp;
798
799
pm_runtime_enable(&pdev->dev);
800
801
return ret;
802
803
esocregp:
804
snd_soc_unregister_dai(&pdev->dev);
805
edaiinit:
806
iounmap(info->reg);
807
emapreg:
808
iounmap(info->yram);
809
emapyram:
810
iounmap(info->xram);
811
emapxram:
812
iounmap(info->pram);
813
emappram:
814
release_mem_region(res->start, resource_size(res));
815
ereqmemreg:
816
egetres:
817
ereqfw:
818
kfree(info);
819
820
return ret;
821
}
822
823
static int __devexit siu_remove(struct platform_device *pdev)
824
{
825
struct siu_info *info = dev_get_drvdata(&pdev->dev);
826
struct resource *res;
827
828
pm_runtime_disable(&pdev->dev);
829
830
snd_soc_unregister_platform(&pdev->dev);
831
snd_soc_unregister_dai(&pdev->dev);
832
833
iounmap(info->reg);
834
iounmap(info->yram);
835
iounmap(info->xram);
836
iounmap(info->pram);
837
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
838
if (res)
839
release_mem_region(res->start, resource_size(res));
840
kfree(info);
841
842
return 0;
843
}
844
845
static struct platform_driver siu_driver = {
846
.driver = {
847
.owner = THIS_MODULE,
848
.name = "siu-pcm-audio",
849
},
850
.probe = siu_probe,
851
.remove = __devexit_p(siu_remove),
852
};
853
854
static int __init siu_init(void)
855
{
856
return platform_driver_register(&siu_driver);
857
}
858
859
static void __exit siu_exit(void)
860
{
861
platform_driver_unregister(&siu_driver);
862
}
863
864
module_init(siu_init)
865
module_exit(siu_exit)
866
867
MODULE_AUTHOR("Carlos Munoz <[email protected]>");
868
MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
869
MODULE_LICENSE("GPL");
870
871