aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-06-24 10:25:29 -0400
committerMark Brown <broonie@linaro.org>2013-06-25 05:26:47 -0400
commit6b36d370ad66aa73328a0cd8763f6028e7b28f6c (patch)
treee32c4937997c12caa09f609a56abf17b3ee51519 /sound
parent9e895ace5d82df8929b16f58e9f515f6d54ab82d (diff)
ASoC: tas5086: open-code I2C transfer routines
In order to support registers of unequal sizes, the I2C I/O has to be open-coded. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/tas5086.c85
1 files changed, 84 insertions, 1 deletions
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index d447c4aa1d5e..57c9de02b14f 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -119,6 +119,17 @@ static const struct reg_default tas5086_reg_defaults[] = {
119 { 0x1c, 0x05 }, 119 { 0x1c, 0x05 },
120}; 120};
121 121
122static int tas5086_register_size(struct device *dev, unsigned int reg)
123{
124 switch (reg) {
125 case TAS5086_DEV_ID ... TAS5086_BKNDERR:
126 return 1;
127 }
128
129 dev_err(dev, "Unsupported register address: %d\n", reg);
130 return 0;
131}
132
122static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) 133static bool tas5086_accessible_reg(struct device *dev, unsigned int reg)
123{ 134{
124 return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17)); 135 return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17));
@@ -140,6 +151,76 @@ static bool tas5086_writeable_reg(struct device *dev, unsigned int reg)
140 return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); 151 return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID);
141} 152}
142 153
154static int tas5086_reg_write(void *context, unsigned int reg,
155 unsigned int value)
156{
157 struct i2c_client *client = context;
158 unsigned int i, size;
159 uint8_t buf[5];
160 int ret;
161
162 size = tas5086_register_size(&client->dev, reg);
163 if (size == 0)
164 return -EINVAL;
165
166 buf[0] = reg;
167
168 for (i = size; i >= 1; --i) {
169 buf[i] = value;
170 value >>= 8;
171 }
172
173 ret = i2c_master_send(client, buf, size + 1);
174 if (ret == size + 1)
175 return 0;
176 else if (ret < 0)
177 return ret;
178 else
179 return -EIO;
180}
181
182static int tas5086_reg_read(void *context, unsigned int reg,
183 unsigned int *value)
184{
185 struct i2c_client *client = context;
186 uint8_t send_buf, recv_buf[4];
187 struct i2c_msg msgs[2];
188 unsigned int size;
189 unsigned int i;
190 int ret;
191
192 size = tas5086_register_size(&client->dev, reg);
193 if (size == 0)
194 return -EINVAL;
195
196 send_buf = reg;
197
198 msgs[0].addr = client->addr;
199 msgs[0].len = sizeof(send_buf);
200 msgs[0].buf = &send_buf;
201 msgs[0].flags = 0;
202
203 msgs[1].addr = client->addr;
204 msgs[1].len = size;
205 msgs[1].buf = recv_buf;
206 msgs[1].flags = I2C_M_RD;
207
208 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
209 if (ret < 0)
210 return ret;
211 else if (ret != ARRAY_SIZE(msgs))
212 return -EIO;
213
214 *value = 0;
215
216 for (i = 0; i < size; i++) {
217 *value <<= 8;
218 *value |= recv_buf[i];
219 }
220
221 return 0;
222}
223
143struct tas5086_private { 224struct tas5086_private {
144 struct regmap *regmap; 225 struct regmap *regmap;
145 unsigned int mclk, sclk; 226 unsigned int mclk, sclk;
@@ -508,6 +589,8 @@ static const struct regmap_config tas5086_regmap = {
508 .volatile_reg = tas5086_volatile_reg, 589 .volatile_reg = tas5086_volatile_reg,
509 .writeable_reg = tas5086_writeable_reg, 590 .writeable_reg = tas5086_writeable_reg,
510 .readable_reg = tas5086_accessible_reg, 591 .readable_reg = tas5086_accessible_reg,
592 .reg_read = tas5086_reg_read,
593 .reg_write = tas5086_reg_write,
511}; 594};
512 595
513static int tas5086_i2c_probe(struct i2c_client *i2c, 596static int tas5086_i2c_probe(struct i2c_client *i2c,
@@ -522,7 +605,7 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
522 if (!priv) 605 if (!priv)
523 return -ENOMEM; 606 return -ENOMEM;
524 607
525 priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap); 608 priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
526 if (IS_ERR(priv->regmap)) { 609 if (IS_ERR(priv->regmap)) {
527 ret = PTR_ERR(priv->regmap); 610 ret = PTR_ERR(priv->regmap);
528 dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); 611 dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);