blob: 1693be477f7a1d1504cea7593606bd7e510472e9 [file] [log] [blame]
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001/*
2 * Fifo-attached Serial Interface (FSI) support for SH7724
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * Based on ssi.c
8 * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090015#include <linux/delay.h>
Kuninori Morimoto785d1c42009-11-30 20:24:48 +090016#include <linux/pm_runtime.h>
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090017#include <linux/io.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090019#include <sound/soc.h>
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090020#include <sound/sh_fsi.h>
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090021
22#define DO_FMT 0x0000
23#define DOFF_CTL 0x0004
24#define DOFF_ST 0x0008
25#define DI_FMT 0x000C
26#define DIFF_CTL 0x0010
27#define DIFF_ST 0x0014
28#define CKG1 0x0018
29#define CKG2 0x001C
30#define DIDT 0x0020
31#define DODT 0x0024
32#define MUTE_ST 0x0028
33#define REG_END MUTE_ST
34
Kuninori Morimotocc780d32010-03-25 19:15:53 +090035
36#define CPU_INT_ST 0x01F4
37#define CPU_IEMSK 0x01F8
38#define CPU_IMSK 0x01FC
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090039#define INT_ST 0x0200
40#define IEMSK 0x0204
41#define IMSK 0x0208
42#define MUTE 0x020C
43#define CLK_RST 0x0210
44#define SOFT_RST 0x0214
Kuninori Morimoto4a942b42010-03-25 19:15:51 +090045#define FIFO_SZ 0x0218
Kuninori Morimotocc780d32010-03-25 19:15:53 +090046#define MREG_START CPU_INT_ST
Kuninori Morimoto4a942b42010-03-25 19:15:51 +090047#define MREG_END FIFO_SZ
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090048
49/* DO_FMT */
50/* DI_FMT */
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +090051#define CR_MONO (0x0 << 4)
52#define CR_MONO_D (0x1 << 4)
53#define CR_PCM (0x2 << 4)
54#define CR_I2S (0x3 << 4)
55#define CR_TDM (0x4 << 4)
56#define CR_TDM_D (0x5 << 4)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090057
58/* DOFF_CTL */
59/* DIFF_CTL */
60#define IRQ_HALF 0x00100000
61#define FIFO_CLR 0x00000001
62
63/* DOFF_ST */
64#define ERR_OVER 0x00000010
65#define ERR_UNDER 0x00000001
Kuninori Morimoto59c3b002009-12-28 14:09:16 +090066#define ST_ERR (ERR_OVER | ERR_UNDER)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090067
68/* CLK_RST */
69#define B_CLK 0x00000010
70#define A_CLK 0x00000001
71
72/* INT_ST */
73#define INT_B_IN (1 << 12)
74#define INT_B_OUT (1 << 8)
75#define INT_A_IN (1 << 4)
76#define INT_A_OUT (1 << 0)
77
Kuninori Morimotofeb58cf2010-03-24 15:27:24 +090078/* SOFT_RST */
79#define PBSR (1 << 12) /* Port B Software Reset */
80#define PASR (1 << 8) /* Port A Software Reset */
81#define IR (1 << 4) /* Interrupt Reset */
82#define FSISR (1 << 0) /* Software Reset */
83
Kuninori Morimoto4a942b42010-03-25 19:15:51 +090084/* FIFO_SZ */
85#define OUT_SZ_MASK 0x7
86#define BO_SZ_SHIFT 8
87#define AO_SZ_SHIFT 0
88
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +090089#define FSI_RATES SNDRV_PCM_RATE_8000_96000
90
91#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
92
93/************************************************************************
94
95
96 struct
97
98
99************************************************************************/
100struct fsi_priv {
101 void __iomem *base;
102 struct snd_pcm_substream *substream;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900103 struct fsi_master *master;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900104
105 int fifo_max;
106 int chan;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900107
108 int byte_offset;
109 int period_len;
110 int buffer_len;
111 int periods;
112};
113
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900114struct fsi_core {
115 int ver;
116
Kuninori Morimotocc780d32010-03-25 19:15:53 +0900117 u32 int_st;
118 u32 iemsk;
119 u32 imsk;
120};
121
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900122struct fsi_master {
123 void __iomem *base;
124 int irq;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900125 struct fsi_priv fsia;
126 struct fsi_priv fsib;
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900127 struct fsi_core *core;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900128 struct sh_fsi_platform_info *info;
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900129 spinlock_t lock;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900130};
131
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900132/************************************************************************
133
134
135 basic read write function
136
137
138************************************************************************/
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100139static void __fsi_reg_write(u32 reg, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900140{
141 /* valid data area is 24bit */
142 data &= 0x00ffffff;
143
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100144 __raw_writel(data, reg);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900145}
146
147static u32 __fsi_reg_read(u32 reg)
148{
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100149 return __raw_readl(reg);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900150}
151
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100152static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900153{
154 u32 val = __fsi_reg_read(reg);
155
156 val &= ~mask;
157 val |= data & mask;
158
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100159 __fsi_reg_write(reg, val);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900160}
161
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100162static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900163{
164 if (reg > REG_END)
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100165 return;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900166
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100167 __fsi_reg_write((u32)(fsi->base + reg), data);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900168}
169
170static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
171{
172 if (reg > REG_END)
173 return 0;
174
175 return __fsi_reg_read((u32)(fsi->base + reg));
176}
177
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100178static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900179{
180 if (reg > REG_END)
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100181 return;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900182
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100183 __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900184}
185
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100186static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900187{
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900188 unsigned long flags;
189
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900190 if ((reg < MREG_START) ||
191 (reg > MREG_END))
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100192 return;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900193
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900194 spin_lock_irqsave(&master->lock, flags);
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100195 __fsi_reg_write((u32)(master->base + reg), data);
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900196 spin_unlock_irqrestore(&master->lock, flags);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900197}
198
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900199static u32 fsi_master_read(struct fsi_master *master, u32 reg)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900200{
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900201 u32 ret;
202 unsigned long flags;
203
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900204 if ((reg < MREG_START) ||
205 (reg > MREG_END))
206 return 0;
207
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900208 spin_lock_irqsave(&master->lock, flags);
209 ret = __fsi_reg_read((u32)(master->base + reg));
210 spin_unlock_irqrestore(&master->lock, flags);
211
212 return ret;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900213}
214
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100215static void fsi_master_mask_set(struct fsi_master *master,
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900216 u32 reg, u32 mask, u32 data)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900217{
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900218 unsigned long flags;
219
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900220 if ((reg < MREG_START) ||
221 (reg > MREG_END))
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100222 return;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900223
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900224 spin_lock_irqsave(&master->lock, flags);
Guennadi Liakhovetski0f69d972010-02-03 17:37:23 +0100225 __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900226 spin_unlock_irqrestore(&master->lock, flags);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900227}
228
229/************************************************************************
230
231
232 basic function
233
234
235************************************************************************/
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900236static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900237{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900238 return fsi->master;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900239}
240
241static int fsi_is_port_a(struct fsi_priv *fsi)
242{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900243 return fsi->master->base == fsi->base;
244}
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900245
Kuninori Morimoto142e8172009-12-28 14:09:11 +0900246static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900247{
248 struct snd_soc_pcm_runtime *rtd = substream->private_data;
249 struct snd_soc_dai_link *machine = rtd->dai;
Kuninori Morimoto142e8172009-12-28 14:09:11 +0900250
251 return machine->cpu_dai;
252}
253
254static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
255{
256 struct snd_soc_dai *dai = fsi_get_dai(substream);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900257
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900258 return dai->private_data;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900259}
260
261static u32 fsi_get_info_flags(struct fsi_priv *fsi)
262{
263 int is_porta = fsi_is_port_a(fsi);
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900264 struct fsi_master *master = fsi_get_master(fsi);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900265
266 return is_porta ? master->info->porta_flags :
267 master->info->portb_flags;
268}
269
270static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
271{
272 u32 mode;
273 u32 flags = fsi_get_info_flags(fsi);
274
275 mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE;
276
277 /* return
278 * 1 : master mode
279 * 0 : slave mode
280 */
281
282 return (mode & flags) != mode;
283}
284
285static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play)
286{
287 int is_porta = fsi_is_port_a(fsi);
288 u32 data;
289
290 if (is_porta)
291 data = is_play ? (1 << 0) : (1 << 4);
292 else
293 data = is_play ? (1 << 8) : (1 << 12);
294
295 return data;
296}
297
298static void fsi_stream_push(struct fsi_priv *fsi,
299 struct snd_pcm_substream *substream,
300 u32 buffer_len,
301 u32 period_len)
302{
303 fsi->substream = substream;
304 fsi->buffer_len = buffer_len;
305 fsi->period_len = period_len;
306 fsi->byte_offset = 0;
307 fsi->periods = 0;
308}
309
310static void fsi_stream_pop(struct fsi_priv *fsi)
311{
312 fsi->substream = NULL;
313 fsi->buffer_len = 0;
314 fsi->period_len = 0;
315 fsi->byte_offset = 0;
316 fsi->periods = 0;
317}
318
319static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
320{
321 u32 status;
322 u32 reg = is_play ? DOFF_ST : DIFF_ST;
323 int residue;
324
325 status = fsi_reg_read(fsi, reg);
326 residue = 0x1ff & (status >> 8);
327 residue *= fsi->chan;
328
329 return residue;
330}
331
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900332/************************************************************************
333
334
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900335 irq function
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900336
337
338************************************************************************/
339static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
340{
341 u32 data = fsi_port_ab_io_bit(fsi, is_play);
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900342 struct fsi_master *master = fsi_get_master(fsi);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900343
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900344 fsi_master_mask_set(master, master->core->imsk, data, data);
345 fsi_master_mask_set(master, master->core->iemsk, data, data);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900346}
347
348static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
349{
350 u32 data = fsi_port_ab_io_bit(fsi, is_play);
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900351 struct fsi_master *master = fsi_get_master(fsi);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900352
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900353 fsi_master_mask_set(master, master->core->imsk, data, 0);
354 fsi_master_mask_set(master, master->core->iemsk, data, 0);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900355}
356
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900357static u32 fsi_irq_get_status(struct fsi_master *master)
358{
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900359 return fsi_master_read(master, master->core->int_st);
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900360}
361
362static void fsi_irq_clear_all_status(struct fsi_master *master)
363{
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900364 fsi_master_write(master, master->core->int_st, 0);
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900365}
366
367static void fsi_irq_clear_status(struct fsi_priv *fsi)
368{
369 u32 data = 0;
370 struct fsi_master *master = fsi_get_master(fsi);
371
372 data |= fsi_port_ab_io_bit(fsi, 0);
373 data |= fsi_port_ab_io_bit(fsi, 1);
374
375 /* clear interrupt factor */
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900376 fsi_master_mask_set(master, master->core->int_st, data, 0);
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900377}
378
379/************************************************************************
380
381
382 ctrl function
383
384
385************************************************************************/
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900386static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
387{
388 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900389 struct fsi_master *master = fsi_get_master(fsi);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900390
391 if (enable)
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900392 fsi_master_mask_set(master, CLK_RST, val, val);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900393 else
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900394 fsi_master_mask_set(master, CLK_RST, val, 0);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900395}
396
Kuninori Morimoto4a942b42010-03-25 19:15:51 +0900397static void fsi_fifo_init(struct fsi_priv *fsi,
398 int is_play,
399 struct snd_soc_dai *dai)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900400{
Kuninori Morimoto4a942b42010-03-25 19:15:51 +0900401 struct fsi_master *master = fsi_get_master(fsi);
402 u32 ctrl, shift, i;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900403
Kuninori Morimoto4a942b42010-03-25 19:15:51 +0900404 /* get on-chip RAM capacity */
405 shift = fsi_master_read(master, FIFO_SZ);
406 shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT;
407 shift &= OUT_SZ_MASK;
408 fsi->fifo_max = 256 << shift;
409 dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max);
410
411 /*
412 * The maximum number of sample data varies depending
413 * on the number of channels selected for the format.
414 *
415 * FIFOs are used in 4-channel units in 3-channel mode
416 * and in 8-channel units in 5- to 7-channel mode
417 * meaning that more FIFOs than the required size of DPRAM
418 * are used.
419 *
420 * ex) if 256 words of DP-RAM is connected
421 * 1 channel: 256 (256 x 1 = 256)
422 * 2 channels: 128 (128 x 2 = 256)
423 * 3 channels: 64 ( 64 x 3 = 192)
424 * 4 channels: 64 ( 64 x 4 = 256)
425 * 5 channels: 32 ( 32 x 5 = 160)
426 * 6 channels: 32 ( 32 x 6 = 192)
427 * 7 channels: 32 ( 32 x 7 = 224)
428 * 8 channels: 32 ( 32 x 8 = 256)
429 */
430 for (i = 1; i < fsi->chan; i <<= 1)
431 fsi->fifo_max >>= 1;
432 dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900433
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900434 ctrl = is_play ? DOFF_CTL : DIFF_CTL;
435
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900436 /* set interrupt generation factor */
437 fsi_reg_write(fsi, ctrl, IRQ_HALF);
438
439 /* clear FIFO */
440 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900441}
442
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900443static void fsi_soft_all_reset(struct fsi_master *master)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900444{
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900445 /* port AB reset */
Kuninori Morimotofeb58cf2010-03-24 15:27:24 +0900446 fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900447 mdelay(10);
448
449 /* soft reset */
Kuninori Morimotofeb58cf2010-03-24 15:27:24 +0900450 fsi_master_mask_set(master, SOFT_RST, FSISR, 0);
451 fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900452 mdelay(10);
453}
454
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900455/* playback interrupt */
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900456static int fsi_data_push(struct fsi_priv *fsi, int startup)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900457{
458 struct snd_pcm_runtime *runtime;
459 struct snd_pcm_substream *substream = NULL;
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900460 u32 status;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900461 int send;
462 int fifo_free;
463 int width;
Kuninori Morimoto9ddc9aa2009-10-30 12:02:39 +0900464 u8 *start;
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900465 int i, over_period;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900466
467 if (!fsi ||
468 !fsi->substream ||
469 !fsi->substream->runtime)
470 return -EINVAL;
471
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900472 over_period = 0;
473 substream = fsi->substream;
474 runtime = substream->runtime;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900475
476 /* FSI FIFO has limit.
477 * So, this driver can not send periods data at a time
478 */
479 if (fsi->byte_offset >=
480 fsi->period_len * (fsi->periods + 1)) {
481
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900482 over_period = 1;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900483 fsi->periods = (fsi->periods + 1) % runtime->periods;
484
485 if (0 == fsi->periods)
486 fsi->byte_offset = 0;
487 }
488
489 /* get 1 channel data width */
490 width = frames_to_bytes(runtime, 1) / fsi->chan;
491
492 /* get send size for alsa */
493 send = (fsi->buffer_len - fsi->byte_offset) / width;
494
495 /* get FIFO free size */
496 fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1);
497
498 /* size check */
499 if (fifo_free < send)
500 send = fifo_free;
501
Kuninori Morimoto9ddc9aa2009-10-30 12:02:39 +0900502 start = runtime->dma_area;
503 start += fsi->byte_offset;
504
505 switch (width) {
506 case 2:
507 for (i = 0; i < send; i++)
508 fsi_reg_write(fsi, DODT,
509 ((u32)*((u16 *)start + i) << 8));
510 break;
511 case 4:
512 for (i = 0; i < send; i++)
513 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
514 break;
515 default:
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900516 return -EINVAL;
Kuninori Morimoto9ddc9aa2009-10-30 12:02:39 +0900517 }
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900518
519 fsi->byte_offset += send * width;
520
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900521 status = fsi_reg_read(fsi, DOFF_ST);
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900522 if (!startup) {
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900523 struct snd_soc_dai *dai = fsi_get_dai(substream);
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900524
525 if (status & ERR_OVER)
526 dev_err(dai->dev, "over run\n");
527 if (status & ERR_UNDER)
528 dev_err(dai->dev, "under run\n");
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900529 }
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900530 fsi_reg_write(fsi, DOFF_ST, 0);
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900531
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900532 fsi_irq_enable(fsi, 1);
533
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900534 if (over_period)
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900535 snd_pcm_period_elapsed(substream);
536
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900537 return 0;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900538}
539
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900540static int fsi_data_pop(struct fsi_priv *fsi, int startup)
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900541{
542 struct snd_pcm_runtime *runtime;
543 struct snd_pcm_substream *substream = NULL;
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900544 u32 status;
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900545 int free;
546 int fifo_fill;
547 int width;
548 u8 *start;
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900549 int i, over_period;
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900550
551 if (!fsi ||
552 !fsi->substream ||
553 !fsi->substream->runtime)
554 return -EINVAL;
555
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900556 over_period = 0;
557 substream = fsi->substream;
558 runtime = substream->runtime;
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900559
560 /* FSI FIFO has limit.
561 * So, this driver can not send periods data at a time
562 */
563 if (fsi->byte_offset >=
564 fsi->period_len * (fsi->periods + 1)) {
565
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900566 over_period = 1;
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900567 fsi->periods = (fsi->periods + 1) % runtime->periods;
568
569 if (0 == fsi->periods)
570 fsi->byte_offset = 0;
571 }
572
573 /* get 1 channel data width */
574 width = frames_to_bytes(runtime, 1) / fsi->chan;
575
576 /* get free space for alsa */
577 free = (fsi->buffer_len - fsi->byte_offset) / width;
578
579 /* get recv size */
580 fifo_fill = fsi_get_fifo_residue(fsi, 0);
581
582 if (free < fifo_fill)
583 fifo_fill = free;
584
585 start = runtime->dma_area;
586 start += fsi->byte_offset;
587
588 switch (width) {
589 case 2:
590 for (i = 0; i < fifo_fill; i++)
591 *((u16 *)start + i) =
592 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
593 break;
594 case 4:
595 for (i = 0; i < fifo_fill; i++)
596 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
597 break;
598 default:
599 return -EINVAL;
600 }
601
602 fsi->byte_offset += fifo_fill * width;
603
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900604 status = fsi_reg_read(fsi, DIFF_ST);
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900605 if (!startup) {
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900606 struct snd_soc_dai *dai = fsi_get_dai(substream);
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900607
608 if (status & ERR_OVER)
609 dev_err(dai->dev, "over run\n");
610 if (status & ERR_UNDER)
611 dev_err(dai->dev, "under run\n");
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900612 }
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900613 fsi_reg_write(fsi, DIFF_ST, 0);
Kuninori Morimoto59c3b002009-12-28 14:09:16 +0900614
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900615 fsi_irq_enable(fsi, 0);
616
Kuninori Morimoto1c418d12009-12-28 14:09:05 +0900617 if (over_period)
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900618 snd_pcm_period_elapsed(substream);
619
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900620 return 0;
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900621}
622
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900623static irqreturn_t fsi_interrupt(int irq, void *data)
624{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900625 struct fsi_master *master = data;
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900626 u32 int_st = fsi_irq_get_status(master);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900627
628 /* clear irq status */
Kuninori Morimotofeb58cf2010-03-24 15:27:24 +0900629 fsi_master_mask_set(master, SOFT_RST, IR, 0);
630 fsi_master_mask_set(master, SOFT_RST, IR, IR);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900631
632 if (int_st & INT_A_OUT)
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900633 fsi_data_push(&master->fsia, 0);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900634 if (int_st & INT_B_OUT)
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900635 fsi_data_push(&master->fsib, 0);
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900636 if (int_st & INT_A_IN)
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900637 fsi_data_pop(&master->fsia, 0);
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900638 if (int_st & INT_B_IN)
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900639 fsi_data_pop(&master->fsib, 0);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900640
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900641 fsi_irq_clear_all_status(master);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900642
643 return IRQ_HANDLED;
644}
645
646/************************************************************************
647
648
649 dai ops
650
651
652************************************************************************/
653static int fsi_dai_startup(struct snd_pcm_substream *substream,
654 struct snd_soc_dai *dai)
655{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900656 struct fsi_priv *fsi = fsi_get_priv(substream);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900657 u32 flags = fsi_get_info_flags(fsi);
658 u32 fmt;
659 u32 reg;
660 u32 data;
661 int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
662 int is_master;
663 int ret = 0;
664
Kuninori Morimoto785d1c42009-11-30 20:24:48 +0900665 pm_runtime_get_sync(dai->dev);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900666
667 /* CKG1 */
668 data = is_play ? (1 << 0) : (1 << 4);
669 is_master = fsi_is_master_mode(fsi, is_play);
670 if (is_master)
671 fsi_reg_mask_set(fsi, CKG1, data, data);
672 else
673 fsi_reg_mask_set(fsi, CKG1, data, 0);
674
675 /* clock inversion (CKG2) */
676 data = 0;
Kuninori Morimotob427b442010-07-13 12:01:15 +0900677 if (SH_FSI_LRM_INV & flags)
678 data |= 1 << 12;
679 if (SH_FSI_BRM_INV & flags)
680 data |= 1 << 8;
681 if (SH_FSI_LRS_INV & flags)
682 data |= 1 << 4;
683 if (SH_FSI_BRS_INV & flags)
684 data |= 1 << 0;
685
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900686 fsi_reg_write(fsi, CKG2, data);
687
688 /* do fmt, di fmt */
689 data = 0;
690 reg = is_play ? DO_FMT : DI_FMT;
691 fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
692 switch (fmt) {
693 case SH_FSI_FMT_MONO:
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900694 data = CR_MONO;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900695 fsi->chan = 1;
696 break;
697 case SH_FSI_FMT_MONO_DELAY:
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900698 data = CR_MONO_D;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900699 fsi->chan = 1;
700 break;
701 case SH_FSI_FMT_PCM:
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900702 data = CR_PCM;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900703 fsi->chan = 2;
704 break;
705 case SH_FSI_FMT_I2S:
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900706 data = CR_I2S;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900707 fsi->chan = 2;
708 break;
709 case SH_FSI_FMT_TDM:
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900710 fsi->chan = is_play ?
711 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900712 data = CR_TDM | (fsi->chan - 1);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900713 break;
714 case SH_FSI_FMT_TDM_DELAY:
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900715 fsi->chan = is_play ?
716 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
Kuninori Morimotoa7ffb522010-07-13 12:13:00 +0900717 data = CR_TDM_D | (fsi->chan - 1);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900718 break;
719 default:
720 dev_err(dai->dev, "unknown format.\n");
721 return -EINVAL;
722 }
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900723 fsi_reg_write(fsi, reg, data);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900724
725 /*
726 * clear clk reset if master mode
727 */
728 if (is_master)
729 fsi_clk_ctrl(fsi, 1);
730
Kuninori Morimoto10ea76c2010-03-23 11:47:54 +0900731 /* irq clear */
732 fsi_irq_disable(fsi, is_play);
733 fsi_irq_clear_status(fsi);
734
735 /* fifo init */
Kuninori Morimoto4a942b42010-03-25 19:15:51 +0900736 fsi_fifo_init(fsi, is_play, dai);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900737
738 return ret;
739}
740
741static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
742 struct snd_soc_dai *dai)
743{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900744 struct fsi_priv *fsi = fsi_get_priv(substream);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900745 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
746
747 fsi_irq_disable(fsi, is_play);
748 fsi_clk_ctrl(fsi, 0);
749
Kuninori Morimoto785d1c42009-11-30 20:24:48 +0900750 pm_runtime_put_sync(dai->dev);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900751}
752
753static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
754 struct snd_soc_dai *dai)
755{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900756 struct fsi_priv *fsi = fsi_get_priv(substream);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900757 struct snd_pcm_runtime *runtime = substream->runtime;
758 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
759 int ret = 0;
760
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900761 switch (cmd) {
762 case SNDRV_PCM_TRIGGER_START:
763 fsi_stream_push(fsi, substream,
764 frames_to_bytes(runtime, runtime->buffer_size),
765 frames_to_bytes(runtime, runtime->period_size));
Kuninori Morimoto47fc9a02010-02-22 16:41:57 +0900766 ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900767 break;
768 case SNDRV_PCM_TRIGGER_STOP:
769 fsi_irq_disable(fsi, is_play);
770 fsi_stream_pop(fsi);
771 break;
772 }
773
774 return ret;
775}
776
777static struct snd_soc_dai_ops fsi_dai_ops = {
778 .startup = fsi_dai_startup,
779 .shutdown = fsi_dai_shutdown,
780 .trigger = fsi_dai_trigger,
781};
782
783/************************************************************************
784
785
786 pcm ops
787
788
789************************************************************************/
790static struct snd_pcm_hardware fsi_pcm_hardware = {
791 .info = SNDRV_PCM_INFO_INTERLEAVED |
792 SNDRV_PCM_INFO_MMAP |
793 SNDRV_PCM_INFO_MMAP_VALID |
794 SNDRV_PCM_INFO_PAUSE,
795 .formats = FSI_FMTS,
796 .rates = FSI_RATES,
797 .rate_min = 8000,
798 .rate_max = 192000,
799 .channels_min = 1,
800 .channels_max = 2,
801 .buffer_bytes_max = 64 * 1024,
802 .period_bytes_min = 32,
803 .period_bytes_max = 8192,
804 .periods_min = 1,
805 .periods_max = 32,
806 .fifo_size = 256,
807};
808
809static int fsi_pcm_open(struct snd_pcm_substream *substream)
810{
811 struct snd_pcm_runtime *runtime = substream->runtime;
812 int ret = 0;
813
814 snd_soc_set_runtime_hwparams(substream, &fsi_pcm_hardware);
815
816 ret = snd_pcm_hw_constraint_integer(runtime,
817 SNDRV_PCM_HW_PARAM_PERIODS);
818
819 return ret;
820}
821
822static int fsi_hw_params(struct snd_pcm_substream *substream,
823 struct snd_pcm_hw_params *hw_params)
824{
825 return snd_pcm_lib_malloc_pages(substream,
826 params_buffer_bytes(hw_params));
827}
828
829static int fsi_hw_free(struct snd_pcm_substream *substream)
830{
831 return snd_pcm_lib_free_pages(substream);
832}
833
834static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
835{
836 struct snd_pcm_runtime *runtime = substream->runtime;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900837 struct fsi_priv *fsi = fsi_get_priv(substream);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900838 long location;
839
Kuninori Morimoto9ddc9aa2009-10-30 12:02:39 +0900840 location = (fsi->byte_offset - 1);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900841 if (location < 0)
842 location = 0;
843
844 return bytes_to_frames(runtime, location);
845}
846
847static struct snd_pcm_ops fsi_pcm_ops = {
848 .open = fsi_pcm_open,
849 .ioctl = snd_pcm_lib_ioctl,
850 .hw_params = fsi_hw_params,
851 .hw_free = fsi_hw_free,
852 .pointer = fsi_pointer,
853};
854
855/************************************************************************
856
857
858 snd_soc_platform
859
860
861************************************************************************/
862#define PREALLOC_BUFFER (32 * 1024)
863#define PREALLOC_BUFFER_MAX (32 * 1024)
864
865static void fsi_pcm_free(struct snd_pcm *pcm)
866{
867 snd_pcm_lib_preallocate_free_for_all(pcm);
868}
869
870static int fsi_pcm_new(struct snd_card *card,
871 struct snd_soc_dai *dai,
872 struct snd_pcm *pcm)
873{
874 /*
875 * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
876 * in MMAP mode (i.e. aplay -M)
877 */
878 return snd_pcm_lib_preallocate_pages_for_all(
879 pcm,
880 SNDRV_DMA_TYPE_CONTINUOUS,
881 snd_dma_continuous_data(GFP_KERNEL),
882 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
883}
884
885/************************************************************************
886
887
888 alsa struct
889
890
891************************************************************************/
892struct snd_soc_dai fsi_soc_dai[] = {
893 {
894 .name = "FSIA",
895 .id = 0,
896 .playback = {
897 .rates = FSI_RATES,
898 .formats = FSI_FMTS,
899 .channels_min = 1,
900 .channels_max = 8,
901 },
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900902 .capture = {
903 .rates = FSI_RATES,
904 .formats = FSI_FMTS,
905 .channels_min = 1,
906 .channels_max = 8,
907 },
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900908 .ops = &fsi_dai_ops,
909 },
910 {
911 .name = "FSIB",
912 .id = 1,
913 .playback = {
914 .rates = FSI_RATES,
915 .formats = FSI_FMTS,
916 .channels_min = 1,
917 .channels_max = 8,
918 },
Kuninori Morimoto07102f32009-10-30 12:02:44 +0900919 .capture = {
920 .rates = FSI_RATES,
921 .formats = FSI_FMTS,
922 .channels_min = 1,
923 .channels_max = 8,
924 },
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900925 .ops = &fsi_dai_ops,
926 },
927};
928EXPORT_SYMBOL_GPL(fsi_soc_dai);
929
930struct snd_soc_platform fsi_soc_platform = {
931 .name = "fsi-pcm",
932 .pcm_ops = &fsi_pcm_ops,
933 .pcm_new = fsi_pcm_new,
934 .pcm_free = fsi_pcm_free,
935};
936EXPORT_SYMBOL_GPL(fsi_soc_platform);
937
938/************************************************************************
939
940
941 platform function
942
943
944************************************************************************/
945static int fsi_probe(struct platform_device *pdev)
946{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900947 struct fsi_master *master;
Kuninori Morimotocc780d32010-03-25 19:15:53 +0900948 const struct platform_device_id *id_entry;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900949 struct resource *res;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900950 unsigned int irq;
951 int ret;
952
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900953 if (0 != pdev->id) {
954 dev_err(&pdev->dev, "current fsi support id 0 only now\n");
955 return -ENODEV;
956 }
957
Kuninori Morimotocc780d32010-03-25 19:15:53 +0900958 id_entry = pdev->id_entry;
959 if (!id_entry) {
960 dev_err(&pdev->dev, "unknown fsi device\n");
961 return -ENODEV;
962 }
963
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900964 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
965 irq = platform_get_irq(pdev, 0);
Uwe Kleine-Königb6aa1792009-12-16 17:10:09 +0100966 if (!res || (int)irq <= 0) {
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900967 dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
968 ret = -ENODEV;
969 goto exit;
970 }
971
972 master = kzalloc(sizeof(*master), GFP_KERNEL);
973 if (!master) {
974 dev_err(&pdev->dev, "Could not allocate master\n");
975 ret = -ENOMEM;
976 goto exit;
977 }
978
979 master->base = ioremap_nocache(res->start, resource_size(res));
980 if (!master->base) {
981 ret = -ENXIO;
982 dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n");
983 goto exit_kfree;
984 }
985
986 master->irq = irq;
987 master->info = pdev->dev.platform_data;
988 master->fsia.base = master->base;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900989 master->fsia.master = master;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900990 master->fsib.base = master->base + 0x40;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900991 master->fsib.master = master;
Kuninori Morimoto73b92c12010-07-13 12:13:04 +0900992 master->core = (struct fsi_core *)id_entry->driver_data;
Kuninori Morimoto8fc176d2010-01-28 13:46:16 +0900993 spin_lock_init(&master->lock);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900994
Kuninori Morimoto785d1c42009-11-30 20:24:48 +0900995 pm_runtime_enable(&pdev->dev);
996 pm_runtime_resume(&pdev->dev);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +0900997
998 fsi_soc_dai[0].dev = &pdev->dev;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +0900999 fsi_soc_dai[0].private_data = &master->fsia;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001000 fsi_soc_dai[1].dev = &pdev->dev;
Kuninori Morimoto71f6e062009-12-02 15:11:08 +09001001 fsi_soc_dai[1].private_data = &master->fsib;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001002
Kuninori Morimoto71f6e062009-12-02 15:11:08 +09001003 fsi_soft_all_reset(master);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001004
Kuninori Morimotocc780d32010-03-25 19:15:53 +09001005 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
1006 id_entry->name, master);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001007 if (ret) {
1008 dev_err(&pdev->dev, "irq request err\n");
Kuninori Morimoto9ddc9aa2009-10-30 12:02:39 +09001009 goto exit_iounmap;
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001010 }
1011
1012 ret = snd_soc_register_platform(&fsi_soc_platform);
1013 if (ret < 0) {
1014 dev_err(&pdev->dev, "cannot snd soc register\n");
1015 goto exit_free_irq;
1016 }
1017
1018 return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
1019
1020exit_free_irq:
1021 free_irq(irq, master);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001022exit_iounmap:
1023 iounmap(master->base);
Kuninori Morimoto785d1c42009-11-30 20:24:48 +09001024 pm_runtime_disable(&pdev->dev);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001025exit_kfree:
1026 kfree(master);
1027 master = NULL;
1028exit:
1029 return ret;
1030}
1031
1032static int fsi_remove(struct platform_device *pdev)
1033{
Kuninori Morimoto71f6e062009-12-02 15:11:08 +09001034 struct fsi_master *master;
1035
1036 master = fsi_get_master(fsi_soc_dai[0].private_data);
1037
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001038 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
1039 snd_soc_unregister_platform(&fsi_soc_platform);
1040
Kuninori Morimoto785d1c42009-11-30 20:24:48 +09001041 pm_runtime_disable(&pdev->dev);
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001042
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001043 free_irq(master->irq, master);
1044
1045 iounmap(master->base);
1046 kfree(master);
Kuninori Morimoto71f6e062009-12-02 15:11:08 +09001047
1048 fsi_soc_dai[0].dev = NULL;
1049 fsi_soc_dai[0].private_data = NULL;
1050 fsi_soc_dai[1].dev = NULL;
1051 fsi_soc_dai[1].private_data = NULL;
1052
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001053 return 0;
1054}
1055
Kuninori Morimoto785d1c42009-11-30 20:24:48 +09001056static int fsi_runtime_nop(struct device *dev)
1057{
1058 /* Runtime PM callback shared between ->runtime_suspend()
1059 * and ->runtime_resume(). Simply returns success.
1060 *
1061 * This driver re-initializes all registers after
1062 * pm_runtime_get_sync() anyway so there is no need
1063 * to save and restore registers here.
1064 */
1065 return 0;
1066}
1067
1068static struct dev_pm_ops fsi_pm_ops = {
1069 .runtime_suspend = fsi_runtime_nop,
1070 .runtime_resume = fsi_runtime_nop,
1071};
1072
Kuninori Morimoto73b92c12010-07-13 12:13:04 +09001073static struct fsi_core fsi1_core = {
1074 .ver = 1,
1075
1076 /* Interrupt */
Kuninori Morimotocc780d32010-03-25 19:15:53 +09001077 .int_st = INT_ST,
1078 .iemsk = IEMSK,
1079 .imsk = IMSK,
1080};
1081
Kuninori Morimoto73b92c12010-07-13 12:13:04 +09001082static struct fsi_core fsi2_core = {
1083 .ver = 2,
1084
1085 /* Interrupt */
Kuninori Morimotocc780d32010-03-25 19:15:53 +09001086 .int_st = CPU_INT_ST,
1087 .iemsk = CPU_IEMSK,
1088 .imsk = CPU_IMSK,
1089};
1090
1091static struct platform_device_id fsi_id_table[] = {
Kuninori Morimoto73b92c12010-07-13 12:13:04 +09001092 { "sh_fsi", (kernel_ulong_t)&fsi1_core },
1093 { "sh_fsi2", (kernel_ulong_t)&fsi2_core },
Kuninori Morimotocc780d32010-03-25 19:15:53 +09001094};
1095
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001096static struct platform_driver fsi_driver = {
1097 .driver = {
1098 .name = "sh_fsi",
Kuninori Morimoto785d1c42009-11-30 20:24:48 +09001099 .pm = &fsi_pm_ops,
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001100 },
1101 .probe = fsi_probe,
1102 .remove = fsi_remove,
Kuninori Morimotocc780d32010-03-25 19:15:53 +09001103 .id_table = fsi_id_table,
Kuninori Morimotoa4d7d552009-08-20 21:01:05 +09001104};
1105
1106static int __init fsi_mobile_init(void)
1107{
1108 return platform_driver_register(&fsi_driver);
1109}
1110
1111static void __exit fsi_mobile_exit(void)
1112{
1113 platform_driver_unregister(&fsi_driver);
1114}
1115module_init(fsi_mobile_init);
1116module_exit(fsi_mobile_exit);
1117
1118MODULE_LICENSE("GPL");
1119MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
1120MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");