aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra/tegra20_i2s.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-07-19 02:03:20 -0400
committerTakashi Iwai <tiwai@suse.de>2012-07-19 02:03:20 -0400
commit4609ed6b1f0ab9f11a9d0361573b53d9d057c440 (patch)
tree802119cc6ddea286bc03d56431286ac52166352e /sound/soc/tegra/tegra20_i2s.c
parent639aa4bd58582f3015ae5621b7e9e754dcb58e6b (diff)
parent409b78cc17a4a3d07a541037575da648ced99437 (diff)
Merge tag 'asoc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for 3.6 This has been a pretty quiet release - very little activity in framework terms, mostly just a few new drivers and updates: - Added the ability to add and remove DAPM paths dynamically, mostly for reparenting on clock changes. - New machine drivers for Marvell Brownstone, ST-Ericsson Ux500 reference platform and ttc-dkp. - New CPU drivers for Blackfin BF6xx SPORTs in I2S mode, Marvell MMP, Synopsis Designware I2S controllers, and SPEAr DMA and S/PDIF - New CODEC drivers for Dialog DA732x, ST STA529, ST-Ericsson AB8500, TI Isabelle and Wolfson Microelectronics WM5102 and WM5110
Diffstat (limited to 'sound/soc/tegra/tegra20_i2s.c')
-rw-r--r--sound/soc/tegra/tegra20_i2s.c94
1 files changed, 46 insertions, 48 deletions
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 0c7af63d444b..c5fc6b1404f6 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -46,18 +46,6 @@
46 46
47#define DRV_NAME "tegra20-i2s" 47#define DRV_NAME "tegra20-i2s"
48 48
49static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
50{
51 regmap_write(i2s->regmap, reg, val);
52}
53
54static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
55{
56 u32 val;
57 regmap_read(i2s->regmap, reg, &val);
58 return val;
59}
60
61static int tegra20_i2s_runtime_suspend(struct device *dev) 49static int tegra20_i2s_runtime_suspend(struct device *dev)
62{ 50{
63 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 51 struct tegra20_i2s *i2s = dev_get_drvdata(dev);
@@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
85 unsigned int fmt) 73 unsigned int fmt)
86{ 74{
87 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 75 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
76 unsigned int mask, val;
88 77
89 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 78 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
90 case SND_SOC_DAIFMT_NB_NF: 79 case SND_SOC_DAIFMT_NB_NF:
@@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
93 return -EINVAL; 82 return -EINVAL;
94 } 83 }
95 84
96 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; 85 mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
97 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 86 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
98 case SND_SOC_DAIFMT_CBS_CFS: 87 case SND_SOC_DAIFMT_CBS_CFS:
99 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; 88 val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
100 break; 89 break;
101 case SND_SOC_DAIFMT_CBM_CFM: 90 case SND_SOC_DAIFMT_CBM_CFM:
102 break; 91 break;
@@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
104 return -EINVAL; 93 return -EINVAL;
105 } 94 }
106 95
107 i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | 96 mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
108 TEGRA20_I2S_CTRL_LRCK_MASK); 97 TEGRA20_I2S_CTRL_LRCK_MASK;
109 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 98 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
110 case SND_SOC_DAIFMT_DSP_A: 99 case SND_SOC_DAIFMT_DSP_A:
111 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 100 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
112 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 101 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
113 break; 102 break;
114 case SND_SOC_DAIFMT_DSP_B: 103 case SND_SOC_DAIFMT_DSP_B:
115 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 104 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
116 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; 105 val |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
117 break; 106 break;
118 case SND_SOC_DAIFMT_I2S: 107 case SND_SOC_DAIFMT_I2S:
119 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; 108 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
120 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 109 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
121 break; 110 break;
122 case SND_SOC_DAIFMT_RIGHT_J: 111 case SND_SOC_DAIFMT_RIGHT_J:
123 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; 112 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
124 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 113 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
125 break; 114 break;
126 case SND_SOC_DAIFMT_LEFT_J: 115 case SND_SOC_DAIFMT_LEFT_J:
127 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; 116 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
128 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 117 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
129 break; 118 break;
130 default: 119 default:
131 return -EINVAL; 120 return -EINVAL;
132 } 121 }
133 122
123 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
124
134 return 0; 125 return 0;
135} 126}
136 127
@@ -138,29 +129,34 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
138 struct snd_pcm_hw_params *params, 129 struct snd_pcm_hw_params *params,
139 struct snd_soc_dai *dai) 130 struct snd_soc_dai *dai)
140{ 131{
141 struct device *dev = substream->pcm->card->dev; 132 struct device *dev = dai->dev;
142 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 133 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
143 u32 reg; 134 unsigned int mask, val;
144 int ret, sample_size, srate, i2sclock, bitcnt; 135 int ret, sample_size, srate, i2sclock, bitcnt;
145 136
146 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; 137 mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
147 switch (params_format(params)) { 138 switch (params_format(params)) {
148 case SNDRV_PCM_FORMAT_S16_LE: 139 case SNDRV_PCM_FORMAT_S16_LE:
149 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; 140 val = TEGRA20_I2S_CTRL_BIT_SIZE_16;
150 sample_size = 16; 141 sample_size = 16;
151 break; 142 break;
152 case SNDRV_PCM_FORMAT_S24_LE: 143 case SNDRV_PCM_FORMAT_S24_LE:
153 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; 144 val = TEGRA20_I2S_CTRL_BIT_SIZE_24;
154 sample_size = 24; 145 sample_size = 24;
155 break; 146 break;
156 case SNDRV_PCM_FORMAT_S32_LE: 147 case SNDRV_PCM_FORMAT_S32_LE:
157 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; 148 val = TEGRA20_I2S_CTRL_BIT_SIZE_32;
158 sample_size = 32; 149 sample_size = 32;
159 break; 150 break;
160 default: 151 default:
161 return -EINVAL; 152 return -EINVAL;
162 } 153 }
163 154
155 mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
156 val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
157
158 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
159
164 srate = params_rate(params); 160 srate = params_rate(params);
165 161
166 /* Final "* 2" required by Tegra hardware */ 162 /* Final "* 2" required by Tegra hardware */
@@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
175 bitcnt = (i2sclock / (2 * srate)) - 1; 171 bitcnt = (i2sclock / (2 * srate)) - 1;
176 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) 172 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
177 return -EINVAL; 173 return -EINVAL;
178 reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; 174 val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
179 175
180 if (i2sclock % (2 * srate)) 176 if (i2sclock % (2 * srate))
181 reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; 177 val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
182 178
183 tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); 179 regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val);
184 180
185 tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, 181 regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR,
186 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | 182 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
187 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); 183 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
188 184
189 return 0; 185 return 0;
190} 186}
191 187
192static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) 188static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
193{ 189{
194 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; 190 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
195 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 191 TEGRA20_I2S_CTRL_FIFO1_ENABLE,
192 TEGRA20_I2S_CTRL_FIFO1_ENABLE);
196} 193}
197 194
198static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) 195static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
199{ 196{
200 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; 197 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
201 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 198 TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0);
202} 199}
203 200
204static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) 201static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
205{ 202{
206 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; 203 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
207 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 204 TEGRA20_I2S_CTRL_FIFO2_ENABLE,
205 TEGRA20_I2S_CTRL_FIFO2_ENABLE);
208} 206}
209 207
210static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) 208static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
211{ 209{
212 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; 210 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
213 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 211 TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0);
214} 212}
215 213
216static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 214static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -261,12 +259,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
261static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { 259static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
262 .probe = tegra20_i2s_probe, 260 .probe = tegra20_i2s_probe,
263 .playback = { 261 .playback = {
262 .stream_name = "Playback",
264 .channels_min = 2, 263 .channels_min = 2,
265 .channels_max = 2, 264 .channels_max = 2,
266 .rates = SNDRV_PCM_RATE_8000_96000, 265 .rates = SNDRV_PCM_RATE_8000_96000,
267 .formats = SNDRV_PCM_FMTBIT_S16_LE, 266 .formats = SNDRV_PCM_FMTBIT_S16_LE,
268 }, 267 },
269 .capture = { 268 .capture = {
269 .stream_name = "Capture",
270 .channels_min = 2, 270 .channels_min = 2,
271 .channels_max = 2, 271 .channels_max = 2,
272 .rates = SNDRV_PCM_RATE_8000_96000, 272 .rates = SNDRV_PCM_RATE_8000_96000,
@@ -412,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
412 i2s->playback_dma_data.width = 32; 412 i2s->playback_dma_data.width = 32;
413 i2s->playback_dma_data.req_sel = dma_ch; 413 i2s->playback_dma_data.req_sel = dma_ch;
414 414
415 i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
416
417 pm_runtime_enable(&pdev->dev); 415 pm_runtime_enable(&pdev->dev);
418 if (!pm_runtime_enabled(&pdev->dev)) { 416 if (!pm_runtime_enabled(&pdev->dev)) {
419 ret = tegra20_i2s_runtime_resume(&pdev->dev); 417 ret = tegra20_i2s_runtime_resume(&pdev->dev);