Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branch 'asoc/topic/pcm1681' into asoc-new-pcm

Trivial add/add conflicts:
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile

+334
+15
Documentation/devicetree/bindings/sound/ti,pcm1681.txt
··· 1 + Texas Instruments PCM1681 8-channel PWM Processor 2 + 3 + Required properties: 4 + 5 + - compatible: Should contain "ti,pcm1681". 6 + - reg: The i2c address. Should contain <0x4c>. 7 + 8 + Examples: 9 + 10 + i2c_bus { 11 + pcm1681@4c { 12 + compatible = "ti,pcm1681"; 13 + reg = <0x4c>; 14 + }; 15 + };
+4
sound/soc/codecs/Kconfig
··· 54 54 select SND_SOC_MC13783 if MFD_MC13XXX 55 55 select SND_SOC_ML26124 if I2C 56 56 select SND_SOC_HDMI_CODEC 57 + select SND_SOC_PCM1681 if I2C 57 58 select SND_SOC_PCM1792A if SPI_MASTER 58 59 select SND_SOC_PCM3008 59 60 select SND_SOC_RT5631 if I2C ··· 292 291 tristate 293 292 294 293 config SND_SOC_HDMI_CODEC 294 + tristate 295 + 296 + config SND_SOC_PCM1681 295 297 tristate 296 298 297 299 config SND_SOC_PCM1792A
+2
sound/soc/codecs/Makefile
··· 42 42 snd-soc-mc13783-objs := mc13783.o 43 43 snd-soc-ml26124-objs := ml26124.o 44 44 snd-soc-hdmi-codec-objs := hdmi.o 45 + snd-soc-pcm1681-objs := pcm1681.o 45 46 snd-soc-pcm1792a-codec-objs := pcm1792a.o 46 47 snd-soc-pcm3008-objs := pcm3008.o 47 48 snd-soc-rt5631-objs := rt5631.o ··· 173 172 obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 174 173 obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 175 174 obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o 175 + obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o 176 176 obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o 177 177 obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 178 178 obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
+313
sound/soc/codecs/pcm1681.c
··· 1 + /* 2 + * PCM1681 ASoC codec driver 3 + * 4 + * Copyright (c) StreamUnlimited GmbH 2013 5 + * Marek Belisko <marek.belisko@streamunlimited.com> 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; either version 2 10 + * of the License, or (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + */ 17 + 18 + #include <linux/module.h> 19 + #include <linux/slab.h> 20 + #include <linux/delay.h> 21 + #include <linux/gpio.h> 22 + #include <linux/i2c.h> 23 + #include <linux/regmap.h> 24 + #include <linux/of_device.h> 25 + #include <linux/of_gpio.h> 26 + #include <sound/pcm.h> 27 + #include <sound/pcm_params.h> 28 + #include <sound/soc.h> 29 + #include <sound/tlv.h> 30 + 31 + #define PCM1681_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 32 + SNDRV_PCM_FMTBIT_S24_LE) 33 + 34 + #define PCM1681_PCM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ 35 + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 36 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ 37 + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) 38 + 39 + #define PCM1681_SOFT_MUTE_ALL 0xff 40 + #define PCM1681_DEEMPH_RATE_MASK 0x18 41 + #define PCM1681_DEEMPH_MASK 0x01 42 + 43 + #define PCM1681_ATT_CONTROL(X) (X <= 6 ? X : X + 9) /* Attenuation level */ 44 + #define PCM1681_SOFT_MUTE 0x07 /* Soft mute control register */ 45 + #define PCM1681_DAC_CONTROL 0x08 /* DAC operation control */ 46 + #define PCM1681_FMT_CONTROL 0x09 /* Audio interface data format */ 47 + #define PCM1681_DEEMPH_CONTROL 0x0a /* De-emphasis control */ 48 + #define PCM1681_ZERO_DETECT_STATUS 0x0e /* Zero detect status reg */ 49 + 50 + static const struct reg_default pcm1681_reg_defaults[] = { 51 + { 0x01, 0xff }, 52 + { 0x02, 0xff }, 53 + { 0x03, 0xff }, 54 + { 0x04, 0xff }, 55 + { 0x05, 0xff }, 56 + { 0x06, 0xff }, 57 + { 0x07, 0x00 }, 58 + { 0x08, 0x00 }, 59 + { 0x09, 0x06 }, 60 + { 0x0A, 0x00 }, 61 + { 0x0B, 0xff }, 62 + { 0x0C, 0x0f }, 63 + { 0x0D, 0x00 }, 64 + { 0x10, 0xff }, 65 + { 0x11, 0xff }, 66 + { 0x12, 0x00 }, 67 + { 0x13, 0x00 }, 68 + }; 69 + 70 + static bool pcm1681_accessible_reg(struct device *dev, unsigned int reg) 71 + { 72 + return !((reg == 0x00) || (reg == 0x0f)); 73 + } 74 + 75 + static bool pcm1681_writeable_reg(struct device *dev, unsigned register reg) 76 + { 77 + return pcm1681_accessible_reg(dev, reg) && 78 + (reg != PCM1681_ZERO_DETECT_STATUS); 79 + } 80 + 81 + struct pcm1681_private { 82 + struct regmap *regmap; 83 + unsigned int format; 84 + /* Current deemphasis status */ 85 + unsigned int deemph; 86 + /* Current rate for deemphasis control */ 87 + unsigned int rate; 88 + }; 89 + 90 + static const int pcm1681_deemph[] = { 44100, 48000, 32000 }; 91 + 92 + static int pcm1681_set_deemph(struct snd_soc_codec *codec) 93 + { 94 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 95 + int i = 0, val = -1, enable = 0; 96 + 97 + if (priv->deemph) 98 + for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) 99 + if (pcm1681_deemph[i] == priv->rate) 100 + val = i; 101 + 102 + if (val != -1) { 103 + regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, 104 + PCM1681_DEEMPH_RATE_MASK, val); 105 + enable = 1; 106 + } else 107 + enable = 0; 108 + 109 + /* enable/disable deemphasis functionality */ 110 + return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, 111 + PCM1681_DEEMPH_MASK, enable); 112 + } 113 + 114 + static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol, 115 + struct snd_ctl_elem_value *ucontrol) 116 + { 117 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 118 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 119 + 120 + ucontrol->value.enumerated.item[0] = priv->deemph; 121 + 122 + return 0; 123 + } 124 + 125 + static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol, 126 + struct snd_ctl_elem_value *ucontrol) 127 + { 128 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 129 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 130 + 131 + priv->deemph = ucontrol->value.enumerated.item[0]; 132 + 133 + return pcm1681_set_deemph(codec); 134 + } 135 + 136 + static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai, 137 + unsigned int format) 138 + { 139 + struct snd_soc_codec *codec = codec_dai->codec; 140 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 141 + 142 + /* The PCM1681 can only be slave to all clocks */ 143 + if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { 144 + dev_err(codec->dev, "Invalid clocking mode\n"); 145 + return -EINVAL; 146 + } 147 + 148 + priv->format = format; 149 + 150 + return 0; 151 + } 152 + 153 + static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute) 154 + { 155 + struct snd_soc_codec *codec = dai->codec; 156 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 157 + int val; 158 + 159 + if (mute) 160 + val = PCM1681_SOFT_MUTE_ALL; 161 + else 162 + val = 0; 163 + 164 + return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val); 165 + } 166 + 167 + static int pcm1681_hw_params(struct snd_pcm_substream *substream, 168 + struct snd_pcm_hw_params *params, 169 + struct snd_soc_dai *dai) 170 + { 171 + struct snd_soc_codec *codec = dai->codec; 172 + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); 173 + int val = 0, ret; 174 + int pcm_format = params_format(params); 175 + 176 + priv->rate = params_rate(params); 177 + 178 + switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { 179 + case SND_SOC_DAIFMT_RIGHT_J: 180 + if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) 181 + val = 0x00; 182 + else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) 183 + val = 0x03; 184 + break; 185 + case SND_SOC_DAIFMT_I2S: 186 + val = 0x04; 187 + break; 188 + case SND_SOC_DAIFMT_LEFT_J: 189 + val = 0x05; 190 + break; 191 + default: 192 + dev_err(codec->dev, "Invalid DAI format\n"); 193 + return -EINVAL; 194 + } 195 + 196 + ret = regmap_update_bits(priv->regmap, PCM1681_FMT_CONTROL, 0x0f, val); 197 + if (ret < 0) 198 + return ret; 199 + 200 + return pcm1681_set_deemph(codec); 201 + } 202 + 203 + static const struct snd_soc_dai_ops pcm1681_dai_ops = { 204 + .set_fmt = pcm1681_set_dai_fmt, 205 + .hw_params = pcm1681_hw_params, 206 + .digital_mute = pcm1681_digital_mute, 207 + }; 208 + 209 + static const DECLARE_TLV_DB_SCALE(pcm1681_dac_tlv, -6350, 50, 1); 210 + 211 + static const struct snd_kcontrol_new pcm1681_controls[] = { 212 + SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume", 213 + PCM1681_ATT_CONTROL(1), PCM1681_ATT_CONTROL(2), 0, 214 + 0x7f, 0, pcm1681_dac_tlv), 215 + SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume", 216 + PCM1681_ATT_CONTROL(3), PCM1681_ATT_CONTROL(4), 0, 217 + 0x7f, 0, pcm1681_dac_tlv), 218 + SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume", 219 + PCM1681_ATT_CONTROL(5), PCM1681_ATT_CONTROL(6), 0, 220 + 0x7f, 0, pcm1681_dac_tlv), 221 + SOC_DOUBLE_R_TLV("Channel 7/8 Playback Volume", 222 + PCM1681_ATT_CONTROL(7), PCM1681_ATT_CONTROL(8), 0, 223 + 0x7f, 0, pcm1681_dac_tlv), 224 + SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0, 225 + pcm1681_get_deemph, pcm1681_put_deemph), 226 + }; 227 + 228 + struct snd_soc_dai_driver pcm1681_dai = { 229 + .name = "pcm1681-hifi", 230 + .playback = { 231 + .stream_name = "Playback", 232 + .channels_min = 2, 233 + .channels_max = 8, 234 + .rates = PCM1681_PCM_RATES, 235 + .formats = PCM1681_PCM_FORMATS, 236 + }, 237 + .ops = &pcm1681_dai_ops, 238 + }; 239 + 240 + #ifdef CONFIG_OF 241 + static const struct of_device_id pcm1681_dt_ids[] = { 242 + { .compatible = "ti,pcm1681", }, 243 + { } 244 + }; 245 + MODULE_DEVICE_TABLE(of, pcm1681_dt_ids); 246 + #endif 247 + 248 + static const struct regmap_config pcm1681_regmap = { 249 + .reg_bits = 8, 250 + .val_bits = 8, 251 + .max_register = ARRAY_SIZE(pcm1681_reg_defaults) + 1, 252 + .reg_defaults = pcm1681_reg_defaults, 253 + .num_reg_defaults = ARRAY_SIZE(pcm1681_reg_defaults), 254 + .writeable_reg = pcm1681_writeable_reg, 255 + .readable_reg = pcm1681_accessible_reg, 256 + }; 257 + 258 + static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = { 259 + .controls = pcm1681_controls, 260 + .num_controls = ARRAY_SIZE(pcm1681_controls), 261 + }; 262 + 263 + static const struct i2c_device_id pcm1681_i2c_id[] = { 264 + {"pcm1681", 0}, 265 + {} 266 + }; 267 + MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id); 268 + 269 + static int pcm1681_i2c_probe(struct i2c_client *client, 270 + const struct i2c_device_id *id) 271 + { 272 + int ret; 273 + struct pcm1681_private *priv; 274 + 275 + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 276 + if (!priv) 277 + return -ENOMEM; 278 + 279 + priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap); 280 + if (IS_ERR(priv->regmap)) { 281 + ret = PTR_ERR(priv->regmap); 282 + dev_err(&client->dev, "Failed to create regmap: %d\n", ret); 283 + return ret; 284 + } 285 + 286 + i2c_set_clientdata(client, priv); 287 + 288 + return snd_soc_register_codec(&client->dev, &soc_codec_dev_pcm1681, 289 + &pcm1681_dai, 1); 290 + } 291 + 292 + static int pcm1681_i2c_remove(struct i2c_client *client) 293 + { 294 + snd_soc_unregister_codec(&client->dev); 295 + return 0; 296 + } 297 + 298 + static struct i2c_driver pcm1681_i2c_driver = { 299 + .driver = { 300 + .name = "pcm1681", 301 + .owner = THIS_MODULE, 302 + .of_match_table = of_match_ptr(pcm1681_dt_ids), 303 + }, 304 + .id_table = pcm1681_i2c_id, 305 + .probe = pcm1681_i2c_probe, 306 + .remove = pcm1681_i2c_remove, 307 + }; 308 + 309 + module_i2c_driver(pcm1681_i2c_driver); 310 + 311 + MODULE_DESCRIPTION("Texas Instruments PCM1681 ALSA SoC Codec Driver"); 312 + MODULE_AUTHOR("Marek Belisko <marek.belisko@streamunlimited.com>"); 313 + MODULE_LICENSE("GPL");