diff options
Diffstat (limited to 'sound/soc/codecs/ad193x.c')
-rw-r--r-- | sound/soc/codecs/ad193x.c | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index eedb6f5e5823..120602130b5c 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* codec private data */ | 24 | /* codec private data */ |
25 | struct ad193x_priv { | 25 | struct ad193x_priv { |
26 | enum snd_soc_control_type control_type; | 26 | struct regmap *regmap; |
27 | int sysclk; | 27 | int sysclk; |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -103,12 +103,14 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
103 | static int ad193x_mute(struct snd_soc_dai *dai, int mute) | 103 | static int ad193x_mute(struct snd_soc_dai *dai, int mute) |
104 | { | 104 | { |
105 | struct snd_soc_codec *codec = dai->codec; | 105 | struct snd_soc_codec *codec = dai->codec; |
106 | int reg; | ||
107 | 106 | ||
108 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); | 107 | if (mute) |
109 | reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg & | 108 | snd_soc_update_bits(codec, AD193X_DAC_CTRL2, |
110 | (~AD193X_DAC_MASTER_MUTE); | 109 | AD193X_DAC_MASTER_MUTE, |
111 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); | 110 | AD193X_DAC_MASTER_MUTE); |
111 | else | ||
112 | snd_soc_update_bits(codec, AD193X_DAC_CTRL2, | ||
113 | AD193X_DAC_MASTER_MUTE, 0); | ||
112 | 114 | ||
113 | return 0; | 115 | return 0; |
114 | } | 116 | } |
@@ -262,7 +264,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
262 | struct snd_pcm_hw_params *params, | 264 | struct snd_pcm_hw_params *params, |
263 | struct snd_soc_dai *dai) | 265 | struct snd_soc_dai *dai) |
264 | { | 266 | { |
265 | int word_len = 0, reg = 0, master_rate = 0; | 267 | int word_len = 0, master_rate = 0; |
266 | 268 | ||
267 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 269 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
268 | struct snd_soc_codec *codec = rtd->codec; | 270 | struct snd_soc_codec *codec = rtd->codec; |
@@ -297,18 +299,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
297 | break; | 299 | break; |
298 | } | 300 | } |
299 | 301 | ||
300 | reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0); | 302 | snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0, |
301 | reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate; | 303 | AD193X_PLL_INPUT_MASK, master_rate); |
302 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); | ||
303 | 304 | ||
304 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); | 305 | snd_soc_update_bits(codec, AD193X_DAC_CTRL2, |
305 | reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | 306 | AD193X_DAC_WORD_LEN_MASK, |
306 | | (word_len << AD193X_DAC_WORD_LEN_SHFT); | 307 | word_len << AD193X_DAC_WORD_LEN_SHFT); |
307 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); | ||
308 | 308 | ||
309 | reg = snd_soc_read(codec, AD193X_ADC_CTRL1); | 309 | snd_soc_update_bits(codec, AD193X_ADC_CTRL1, |
310 | reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len; | 310 | AD193X_ADC_WORD_LEN_MASK, word_len); |
311 | snd_soc_write(codec, AD193X_ADC_CTRL1, reg); | ||
312 | 311 | ||
313 | return 0; | 312 | return 0; |
314 | } | 313 | } |
@@ -349,10 +348,8 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
349 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 348 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
350 | int ret; | 349 | int ret; |
351 | 350 | ||
352 | if (ad193x->control_type == SND_SOC_I2C) | 351 | codec->control_data = ad193x->regmap; |
353 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type); | 352 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); |
354 | else | ||
355 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type); | ||
356 | if (ret < 0) { | 353 | if (ret < 0) { |
357 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | 354 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); |
358 | return ret; | 355 | return ret; |
@@ -388,6 +385,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | |||
388 | }; | 385 | }; |
389 | 386 | ||
390 | #if defined(CONFIG_SPI_MASTER) | 387 | #if defined(CONFIG_SPI_MASTER) |
388 | |||
389 | static const struct regmap_config ad193x_spi_regmap_config = { | ||
390 | .val_bits = 8, | ||
391 | .reg_bits = 16, | ||
392 | .read_flag_mask = 0x09, | ||
393 | .write_flag_mask = 0x08, | ||
394 | }; | ||
395 | |||
391 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 396 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
392 | { | 397 | { |
393 | struct ad193x_priv *ad193x; | 398 | struct ad193x_priv *ad193x; |
@@ -397,20 +402,36 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi) | |||
397 | if (ad193x == NULL) | 402 | if (ad193x == NULL) |
398 | return -ENOMEM; | 403 | return -ENOMEM; |
399 | 404 | ||
405 | ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); | ||
406 | if (IS_ERR(ad193x->regmap)) { | ||
407 | ret = PTR_ERR(ad193x->regmap); | ||
408 | goto err_free; | ||
409 | } | ||
410 | |||
400 | spi_set_drvdata(spi, ad193x); | 411 | spi_set_drvdata(spi, ad193x); |
401 | ad193x->control_type = SND_SOC_SPI; | ||
402 | 412 | ||
403 | ret = snd_soc_register_codec(&spi->dev, | 413 | ret = snd_soc_register_codec(&spi->dev, |
404 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 414 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
405 | if (ret < 0) | 415 | if (ret < 0) |
406 | kfree(ad193x); | 416 | goto err_regmap_exit; |
417 | |||
418 | return 0; | ||
419 | |||
420 | err_regmap_exit: | ||
421 | regmap_exit(ad193x->regmap); | ||
422 | err_free: | ||
423 | kfree(ad193x); | ||
424 | |||
407 | return ret; | 425 | return ret; |
408 | } | 426 | } |
409 | 427 | ||
410 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 428 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
411 | { | 429 | { |
430 | struct ad193x_priv *ad193x = spi_get_drvdata(spi); | ||
431 | |||
412 | snd_soc_unregister_codec(&spi->dev); | 432 | snd_soc_unregister_codec(&spi->dev); |
413 | kfree(spi_get_drvdata(spi)); | 433 | regmap_exit(ad193x->regmap); |
434 | kfree(ad193x); | ||
414 | return 0; | 435 | return 0; |
415 | } | 436 | } |
416 | 437 | ||
@@ -425,6 +446,12 @@ static struct spi_driver ad193x_spi_driver = { | |||
425 | #endif | 446 | #endif |
426 | 447 | ||
427 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 448 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
449 | |||
450 | static const struct regmap_config ad193x_i2c_regmap_config = { | ||
451 | .val_bits = 8, | ||
452 | .reg_bits = 8, | ||
453 | }; | ||
454 | |||
428 | static const struct i2c_device_id ad193x_id[] = { | 455 | static const struct i2c_device_id ad193x_id[] = { |
429 | { "ad1936", 0 }, | 456 | { "ad1936", 0 }, |
430 | { "ad1937", 0 }, | 457 | { "ad1937", 0 }, |
@@ -442,20 +469,35 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
442 | if (ad193x == NULL) | 469 | if (ad193x == NULL) |
443 | return -ENOMEM; | 470 | return -ENOMEM; |
444 | 471 | ||
472 | ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); | ||
473 | if (IS_ERR(ad193x->regmap)) { | ||
474 | ret = PTR_ERR(ad193x->regmap); | ||
475 | goto err_free; | ||
476 | } | ||
477 | |||
445 | i2c_set_clientdata(client, ad193x); | 478 | i2c_set_clientdata(client, ad193x); |
446 | ad193x->control_type = SND_SOC_I2C; | ||
447 | 479 | ||
448 | ret = snd_soc_register_codec(&client->dev, | 480 | ret = snd_soc_register_codec(&client->dev, |
449 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 481 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
450 | if (ret < 0) | 482 | if (ret < 0) |
451 | kfree(ad193x); | 483 | goto err_regmap_exit; |
484 | |||
485 | return 0; | ||
486 | |||
487 | err_regmap_exit: | ||
488 | regmap_exit(ad193x->regmap); | ||
489 | err_free: | ||
490 | kfree(ad193x); | ||
452 | return ret; | 491 | return ret; |
453 | } | 492 | } |
454 | 493 | ||
455 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 494 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
456 | { | 495 | { |
496 | struct ad193x_priv *ad193x = i2c_get_clientdata(client); | ||
497 | |||
457 | snd_soc_unregister_codec(&client->dev); | 498 | snd_soc_unregister_codec(&client->dev); |
458 | kfree(i2c_get_clientdata(client)); | 499 | regmap_exit(ad193x->regmap); |
500 | kfree(ad193x); | ||
459 | return 0; | 501 | return 0; |
460 | } | 502 | } |
461 | 503 | ||