diff options
Diffstat (limited to 'sound/soc/codecs/cs42l51.c')
-rw-r--r-- | sound/soc/codecs/cs42l51.c | 71 |
1 files changed, 33 insertions, 38 deletions
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a91..3eab46020a30 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sound/pcm_params.h> | 30 | #include <sound/pcm_params.h> |
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/regmap.h> | ||
33 | 34 | ||
34 | #include "cs42l51.h" | 35 | #include "cs42l51.h" |
35 | 36 | ||
@@ -40,7 +41,6 @@ enum master_slave_mode { | |||
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct cs42l51_private { | 43 | struct cs42l51_private { |
43 | enum snd_soc_control_type control_type; | ||
44 | unsigned int mclk; | 44 | unsigned int mclk; |
45 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ | 45 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ |
46 | enum master_slave_mode func; | 46 | enum master_slave_mode func; |
@@ -52,24 +52,6 @@ struct cs42l51_private { | |||
52 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | 52 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ |
53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | 53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) |
54 | 54 | ||
55 | static int cs42l51_fill_cache(struct snd_soc_codec *codec) | ||
56 | { | ||
57 | u8 *cache = codec->reg_cache + 1; | ||
58 | struct i2c_client *i2c_client = to_i2c_client(codec->dev); | ||
59 | s32 length; | ||
60 | |||
61 | length = i2c_smbus_read_i2c_block_data(i2c_client, | ||
62 | CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); | ||
63 | if (length != CS42L51_NUMREGS) { | ||
64 | dev_err(&i2c_client->dev, | ||
65 | "I2C read failure, addr=0x%x (ret=%d vs %d)\n", | ||
66 | i2c_client->addr, length, CS42L51_NUMREGS); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, | 55 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, |
74 | struct snd_ctl_elem_value *ucontrol) | 56 | struct snd_ctl_elem_value *ucontrol) |
75 | { | 57 | { |
@@ -505,16 +487,9 @@ static struct snd_soc_dai_driver cs42l51_dai = { | |||
505 | 487 | ||
506 | static int cs42l51_probe(struct snd_soc_codec *codec) | 488 | static int cs42l51_probe(struct snd_soc_codec *codec) |
507 | { | 489 | { |
508 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | ||
509 | int ret, reg; | 490 | int ret, reg; |
510 | 491 | ||
511 | ret = cs42l51_fill_cache(codec); | 492 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
512 | if (ret < 0) { | ||
513 | dev_err(codec->dev, "failed to fill register cache\n"); | ||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); | ||
518 | if (ret < 0) { | 493 | if (ret < 0) { |
519 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 494 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
520 | return ret; | 495 | return ret; |
@@ -538,8 +513,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) | |||
538 | 513 | ||
539 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | 514 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { |
540 | .probe = cs42l51_probe, | 515 | .probe = cs42l51_probe, |
541 | .reg_cache_size = CS42L51_NUMREGS + 1, | ||
542 | .reg_word_size = sizeof(u8), | ||
543 | 516 | ||
544 | .controls = cs42l51_snd_controls, | 517 | .controls = cs42l51_snd_controls, |
545 | .num_controls = ARRAY_SIZE(cs42l51_snd_controls), | 518 | .num_controls = ARRAY_SIZE(cs42l51_snd_controls), |
@@ -549,38 +522,53 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | |||
549 | .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), | 522 | .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), |
550 | }; | 523 | }; |
551 | 524 | ||
525 | static const struct regmap_config cs42l51_regmap = { | ||
526 | .reg_bits = 8, | ||
527 | .val_bits = 8, | ||
528 | |||
529 | .max_register = CS42L51_CHARGE_FREQ, | ||
530 | .cache_type = REGCACHE_RBTREE, | ||
531 | }; | ||
532 | |||
552 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, | 533 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, |
553 | const struct i2c_device_id *id) | 534 | const struct i2c_device_id *id) |
554 | { | 535 | { |
555 | struct cs42l51_private *cs42l51; | 536 | struct cs42l51_private *cs42l51; |
537 | struct regmap *regmap; | ||
538 | unsigned int val; | ||
556 | int ret; | 539 | int ret; |
557 | 540 | ||
541 | regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap); | ||
542 | if (IS_ERR(regmap)) { | ||
543 | ret = PTR_ERR(regmap); | ||
544 | dev_err(&i2c_client->dev, "Failed to create regmap: %d\n", | ||
545 | ret); | ||
546 | return ret; | ||
547 | } | ||
548 | |||
558 | /* Verify that we have a CS42L51 */ | 549 | /* Verify that we have a CS42L51 */ |
559 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); | 550 | ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); |
560 | if (ret < 0) { | 551 | if (ret < 0) { |
561 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | 552 | dev_err(&i2c_client->dev, "failed to read I2C\n"); |
562 | goto error; | 553 | goto error; |
563 | } | 554 | } |
564 | 555 | ||
565 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | 556 | if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && |
566 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | 557 | (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { |
567 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | 558 | dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val); |
568 | ret = -ENODEV; | 559 | ret = -ENODEV; |
569 | goto error; | 560 | goto error; |
570 | } | 561 | } |
571 | 562 | ||
572 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | 563 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", |
573 | ret & 7); | 564 | val & 7); |
574 | 565 | ||
575 | cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), | 566 | cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), |
576 | GFP_KERNEL); | 567 | GFP_KERNEL); |
577 | if (!cs42l51) { | 568 | if (!cs42l51) |
578 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
579 | return -ENOMEM; | 569 | return -ENOMEM; |
580 | } | ||
581 | 570 | ||
582 | i2c_set_clientdata(i2c_client, cs42l51); | 571 | i2c_set_clientdata(i2c_client, cs42l51); |
583 | cs42l51->control_type = SND_SOC_I2C; | ||
584 | 572 | ||
585 | ret = snd_soc_register_codec(&i2c_client->dev, | 573 | ret = snd_soc_register_codec(&i2c_client->dev, |
586 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); | 574 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); |
@@ -600,10 +588,17 @@ static const struct i2c_device_id cs42l51_id[] = { | |||
600 | }; | 588 | }; |
601 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | 589 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); |
602 | 590 | ||
591 | static const struct of_device_id cs42l51_of_match[] = { | ||
592 | { .compatible = "cirrus,cs42l51", }, | ||
593 | { } | ||
594 | }; | ||
595 | MODULE_DEVICE_TABLE(of, cs42l51_of_match); | ||
596 | |||
603 | static struct i2c_driver cs42l51_i2c_driver = { | 597 | static struct i2c_driver cs42l51_i2c_driver = { |
604 | .driver = { | 598 | .driver = { |
605 | .name = "cs42l51-codec", | 599 | .name = "cs42l51-codec", |
606 | .owner = THIS_MODULE, | 600 | .owner = THIS_MODULE, |
601 | .of_match_table = cs42l51_of_match, | ||
607 | }, | 602 | }, |
608 | .id_table = cs42l51_id, | 603 | .id_table = cs42l51_id, |
609 | .probe = cs42l51_i2c_probe, | 604 | .probe = cs42l51_i2c_probe, |