inno_rk3036.c (cf40a76e7d5874bb25f4404eecc58a2e033af885) inno_rk3036.c (40aa60a2e9ab5242593101bb6270563ee5acdf46)
1/*
2 * Driver of Inno codec for rk3036 by Rockchip Inc.
3 *
4 * Author: Rockchip Inc.
5 * Author: Zheng ShunQian<zhengsq@rock-chips.com>
6 */
7
8#include <sound/soc.h>

--- 182 unchanged lines hidden (view full) ---

191 {"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
192
193 {"HPL", NULL, "HP Left Switch"},
194 {"HPR", NULL, "HP Right Switch"},
195};
196
197static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
198{
1/*
2 * Driver of Inno codec for rk3036 by Rockchip Inc.
3 *
4 * Author: Rockchip Inc.
5 * Author: Zheng ShunQian<zhengsq@rock-chips.com>
6 */
7
8#include <sound/soc.h>

--- 182 unchanged lines hidden (view full) ---

191 {"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
192
193 {"HPL", NULL, "HP Left Switch"},
194 {"HPR", NULL, "HP Right Switch"},
195};
196
197static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
198{
199 struct snd_soc_codec *codec = dai->codec;
199 struct snd_soc_component *component = dai->component;
200 unsigned int reg01_val = 0, reg02_val = 0, reg03_val = 0;
201
200 unsigned int reg01_val = 0, reg02_val = 0, reg03_val = 0;
201
202 dev_dbg(codec->dev, "rk3036_codec dai set fmt : %08x\n", fmt);
202 dev_dbg(component->dev, "rk3036_codec dai set fmt : %08x\n", fmt);
203
204 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
205 case SND_SOC_DAIFMT_CBS_CFS:
206 reg01_val |= INNO_R01_PINDIR_IN_SLAVE |
207 INNO_R01_I2SMODE_SLAVE;
208 break;
209 case SND_SOC_DAIFMT_CBM_CFM:
210 reg01_val |= INNO_R01_PINDIR_OUT_MASTER |
211 INNO_R01_I2SMODE_MASTER;
212 break;
213 default:
203
204 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
205 case SND_SOC_DAIFMT_CBS_CFS:
206 reg01_val |= INNO_R01_PINDIR_IN_SLAVE |
207 INNO_R01_I2SMODE_SLAVE;
208 break;
209 case SND_SOC_DAIFMT_CBM_CFM:
210 reg01_val |= INNO_R01_PINDIR_OUT_MASTER |
211 INNO_R01_I2SMODE_MASTER;
212 break;
213 default:
214 dev_err(codec->dev, "invalid fmt\n");
214 dev_err(component->dev, "invalid fmt\n");
215 return -EINVAL;
216 }
217
218 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
219 case SND_SOC_DAIFMT_DSP_A:
220 reg02_val |= INNO_R02_DACM_PCM;
221 break;
222 case SND_SOC_DAIFMT_I2S:
223 reg02_val |= INNO_R02_DACM_I2S;
224 break;
225 case SND_SOC_DAIFMT_RIGHT_J:
226 reg02_val |= INNO_R02_DACM_RJM;
227 break;
228 case SND_SOC_DAIFMT_LEFT_J:
229 reg02_val |= INNO_R02_DACM_LJM;
230 break;
231 default:
215 return -EINVAL;
216 }
217
218 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
219 case SND_SOC_DAIFMT_DSP_A:
220 reg02_val |= INNO_R02_DACM_PCM;
221 break;
222 case SND_SOC_DAIFMT_I2S:
223 reg02_val |= INNO_R02_DACM_I2S;
224 break;
225 case SND_SOC_DAIFMT_RIGHT_J:
226 reg02_val |= INNO_R02_DACM_RJM;
227 break;
228 case SND_SOC_DAIFMT_LEFT_J:
229 reg02_val |= INNO_R02_DACM_LJM;
230 break;
231 default:
232 dev_err(codec->dev, "set dai format failed\n");
232 dev_err(component->dev, "set dai format failed\n");
233 return -EINVAL;
234 }
235
236 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
237 case SND_SOC_DAIFMT_NB_NF:
238 reg02_val |= INNO_R02_LRCP_NORMAL;
239 reg03_val |= INNO_R03_BCP_NORMAL;
240 break;

--- 5 unchanged lines hidden (view full) ---

246 reg02_val |= INNO_R02_LRCP_REVERSAL;
247 reg03_val |= INNO_R03_BCP_NORMAL;
248 break;
249 case SND_SOC_DAIFMT_NB_IF:
250 reg02_val |= INNO_R02_LRCP_NORMAL;
251 reg03_val |= INNO_R03_BCP_REVERSAL;
252 break;
253 default:
233 return -EINVAL;
234 }
235
236 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
237 case SND_SOC_DAIFMT_NB_NF:
238 reg02_val |= INNO_R02_LRCP_NORMAL;
239 reg03_val |= INNO_R03_BCP_NORMAL;
240 break;

--- 5 unchanged lines hidden (view full) ---

246 reg02_val |= INNO_R02_LRCP_REVERSAL;
247 reg03_val |= INNO_R03_BCP_NORMAL;
248 break;
249 case SND_SOC_DAIFMT_NB_IF:
250 reg02_val |= INNO_R02_LRCP_NORMAL;
251 reg03_val |= INNO_R03_BCP_REVERSAL;
252 break;
253 default:
254 dev_err(codec->dev, "set dai format failed\n");
254 dev_err(component->dev, "set dai format failed\n");
255 return -EINVAL;
256 }
257
255 return -EINVAL;
256 }
257
258 snd_soc_update_bits(codec, INNO_R01, INNO_R01_I2SMODE_MSK |
258 snd_soc_component_update_bits(component, INNO_R01, INNO_R01_I2SMODE_MSK |
259 INNO_R01_PINDIR_MSK, reg01_val);
259 INNO_R01_PINDIR_MSK, reg01_val);
260 snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
260 snd_soc_component_update_bits(component, INNO_R02, INNO_R02_LRCP_MSK |
261 INNO_R02_DACM_MSK, reg02_val);
261 INNO_R02_DACM_MSK, reg02_val);
262 snd_soc_update_bits(codec, INNO_R03, INNO_R03_BCP_MSK, reg03_val);
262 snd_soc_component_update_bits(component, INNO_R03, INNO_R03_BCP_MSK, reg03_val);
263
264 return 0;
265}
266
267static int rk3036_codec_dai_hw_params(struct snd_pcm_substream *substream,
268 struct snd_pcm_hw_params *hw_params,
269 struct snd_soc_dai *dai)
270{
263
264 return 0;
265}
266
267static int rk3036_codec_dai_hw_params(struct snd_pcm_substream *substream,
268 struct snd_pcm_hw_params *hw_params,
269 struct snd_soc_dai *dai)
270{
271 struct snd_soc_codec *codec = dai->codec;
271 struct snd_soc_component *component = dai->component;
272 unsigned int reg02_val = 0, reg03_val = 0;
273
274 switch (params_format(hw_params)) {
275 case SNDRV_PCM_FORMAT_S16_LE:
276 reg02_val |= INNO_R02_VWL_16BIT;
277 break;
278 case SNDRV_PCM_FORMAT_S20_3LE:
279 reg02_val |= INNO_R02_VWL_20BIT;

--- 6 unchanged lines hidden (view full) ---

286 break;
287 default:
288 return -EINVAL;
289 }
290
291 reg02_val |= INNO_R02_LRCP_NORMAL;
292 reg03_val |= INNO_R03_FWL_32BIT | INNO_R03_DACR_WORK;
293
272 unsigned int reg02_val = 0, reg03_val = 0;
273
274 switch (params_format(hw_params)) {
275 case SNDRV_PCM_FORMAT_S16_LE:
276 reg02_val |= INNO_R02_VWL_16BIT;
277 break;
278 case SNDRV_PCM_FORMAT_S20_3LE:
279 reg02_val |= INNO_R02_VWL_20BIT;

--- 6 unchanged lines hidden (view full) ---

286 break;
287 default:
288 return -EINVAL;
289 }
290
291 reg02_val |= INNO_R02_LRCP_NORMAL;
292 reg03_val |= INNO_R03_FWL_32BIT | INNO_R03_DACR_WORK;
293
294 snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
294 snd_soc_component_update_bits(component, INNO_R02, INNO_R02_LRCP_MSK |
295 INNO_R02_VWL_MSK, reg02_val);
295 INNO_R02_VWL_MSK, reg02_val);
296 snd_soc_update_bits(codec, INNO_R03, INNO_R03_DACR_MSK |
296 snd_soc_component_update_bits(component, INNO_R03, INNO_R03_DACR_MSK |
297 INNO_R03_FWL_MSK, reg03_val);
298 return 0;
299}
300
301#define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000 | \
302 SNDRV_PCM_RATE_16000 | \
303 SNDRV_PCM_RATE_32000 | \
304 SNDRV_PCM_RATE_44100 | \

--- 20 unchanged lines hidden (view full) ---

325 .rates = RK3036_CODEC_RATES,
326 .formats = RK3036_CODEC_FMTS,
327 },
328 .ops = &rk3036_codec_dai_ops,
329 .symmetric_rates = 1,
330 },
331};
332
297 INNO_R03_FWL_MSK, reg03_val);
298 return 0;
299}
300
301#define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000 | \
302 SNDRV_PCM_RATE_16000 | \
303 SNDRV_PCM_RATE_32000 | \
304 SNDRV_PCM_RATE_44100 | \

--- 20 unchanged lines hidden (view full) ---

325 .rates = RK3036_CODEC_RATES,
326 .formats = RK3036_CODEC_FMTS,
327 },
328 .ops = &rk3036_codec_dai_ops,
329 .symmetric_rates = 1,
330 },
331};
332
333static void rk3036_codec_reset(struct snd_soc_codec *codec)
333static void rk3036_codec_reset(struct snd_soc_component *component)
334{
334{
335 snd_soc_write(codec, INNO_R00,
335 snd_soc_component_write(component, INNO_R00,
336 INNO_R00_CSR_RESET | INNO_R00_CDCR_RESET);
336 INNO_R00_CSR_RESET | INNO_R00_CDCR_RESET);
337 snd_soc_write(codec, INNO_R00,
337 snd_soc_component_write(component, INNO_R00,
338 INNO_R00_CSR_WORK | INNO_R00_CDCR_WORK);
339}
340
338 INNO_R00_CSR_WORK | INNO_R00_CDCR_WORK);
339}
340
341static int rk3036_codec_probe(struct snd_soc_codec *codec)
341static int rk3036_codec_probe(struct snd_soc_component *component)
342{
342{
343 rk3036_codec_reset(codec);
343 rk3036_codec_reset(component);
344 return 0;
345}
346
344 return 0;
345}
346
347static int rk3036_codec_remove(struct snd_soc_codec *codec)
347static void rk3036_codec_remove(struct snd_soc_component *component)
348{
348{
349 rk3036_codec_reset(codec);
350 return 0;
349 rk3036_codec_reset(component);
351}
352
350}
351
353static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec,
352static int rk3036_codec_set_bias_level(struct snd_soc_component *component,
354 enum snd_soc_bias_level level)
355{
356 switch (level) {
357 case SND_SOC_BIAS_STANDBY:
358 /* set a big current for capacitor charging. */
353 enum snd_soc_bias_level level)
354{
355 switch (level) {
356 case SND_SOC_BIAS_STANDBY:
357 /* set a big current for capacitor charging. */
359 snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
358 snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
360 /* start precharge */
359 /* start precharge */
361 snd_soc_write(codec, INNO_R06, INNO_R06_DAC_PRECHARGE);
360 snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_PRECHARGE);
362
363 break;
364
365 case SND_SOC_BIAS_OFF:
366 /* set a big current for capacitor discharging. */
361
362 break;
363
364 case SND_SOC_BIAS_OFF:
365 /* set a big current for capacitor discharging. */
367 snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
366 snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
368 /* start discharge. */
367 /* start discharge. */
369 snd_soc_write(codec, INNO_R06, INNO_R06_DAC_DISCHARGE);
368 snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_DISCHARGE);
370
371 break;
372 default:
373 break;
374 }
375
376 return 0;
377}
378
369
370 break;
371 default:
372 break;
373 }
374
375 return 0;
376}
377
379static const struct snd_soc_codec_driver rk3036_codec_driver = {
378static const struct snd_soc_component_driver rk3036_codec_driver = {
380 .probe = rk3036_codec_probe,
381 .remove = rk3036_codec_remove,
382 .set_bias_level = rk3036_codec_set_bias_level,
379 .probe = rk3036_codec_probe,
380 .remove = rk3036_codec_remove,
381 .set_bias_level = rk3036_codec_set_bias_level,
383 .component_driver = {
384 .controls = rk3036_codec_dapm_controls,
385 .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls),
386 .dapm_routes = rk3036_codec_dapm_routes,
387 .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes),
388 .dapm_widgets = rk3036_codec_dapm_widgets,
389 .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets),
390 },
382 .controls = rk3036_codec_dapm_controls,
383 .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls),
384 .dapm_routes = rk3036_codec_dapm_routes,
385 .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes),
386 .dapm_widgets = rk3036_codec_dapm_widgets,
387 .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets),
388 .idle_bias_on = 1,
389 .use_pmdown_time = 1,
390 .endianness = 1,
391 .non_legacy_dai_naming = 1,
391};
392
393static const struct regmap_config rk3036_codec_regmap_config = {
394 .reg_bits = 32,
395 .reg_stride = 4,
396 .val_bits = 32,
397};
398

--- 45 unchanged lines hidden (view full) ---

444 if (ret < 0) {
445 dev_err(&pdev->dev, "failed to enable clk\n");
446 return ret;
447 }
448
449 priv->dev = &pdev->dev;
450 dev_set_drvdata(&pdev->dev, priv);
451
392};
393
394static const struct regmap_config rk3036_codec_regmap_config = {
395 .reg_bits = 32,
396 .reg_stride = 4,
397 .val_bits = 32,
398};
399

--- 45 unchanged lines hidden (view full) ---

445 if (ret < 0) {
446 dev_err(&pdev->dev, "failed to enable clk\n");
447 return ret;
448 }
449
450 priv->dev = &pdev->dev;
451 dev_set_drvdata(&pdev->dev, priv);
452
452 ret = snd_soc_register_codec(&pdev->dev, &rk3036_codec_driver,
453 ret = devm_snd_soc_register_component(&pdev->dev, &rk3036_codec_driver,
453 rk3036_codec_dai_driver,
454 ARRAY_SIZE(rk3036_codec_dai_driver));
455 if (ret) {
456 clk_disable_unprepare(priv->pclk);
457 dev_set_drvdata(&pdev->dev, NULL);
458 }
459
460 return ret;
461}
462
463static int rk3036_codec_platform_remove(struct platform_device *pdev)
464{
465 struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev);
466
454 rk3036_codec_dai_driver,
455 ARRAY_SIZE(rk3036_codec_dai_driver));
456 if (ret) {
457 clk_disable_unprepare(priv->pclk);
458 dev_set_drvdata(&pdev->dev, NULL);
459 }
460
461 return ret;
462}
463
464static int rk3036_codec_platform_remove(struct platform_device *pdev)
465{
466 struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev);
467
467 snd_soc_unregister_codec(&pdev->dev);
468 clk_disable_unprepare(priv->pclk);
469
470 return 0;
471}
472
473static const struct of_device_id rk3036_codec_of_match[] = {
474 { .compatible = "rockchip,rk3036-codec", },
475 {}

--- 17 unchanged lines hidden ---
468 clk_disable_unprepare(priv->pclk);
469
470 return 0;
471}
472
473static const struct of_device_id rk3036_codec_of_match[] = {
474 { .compatible = "rockchip,rk3036-codec", },
475 {}

--- 17 unchanged lines hidden ---