0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/init.h>
0013 #include <linux/sched.h>
0014 #include <linux/errno.h>
0015 #include <sound/core.h>
0016 #include <sound/pcm.h>
0017 #include <sound/ad1843.h>
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 struct ad1843_bitfield {
0029 char reg;
0030 char lo_bit;
0031 char nbits;
0032 };
0033
0034 static const struct ad1843_bitfield
0035 ad1843_PDNO = { 0, 14, 1 },
0036 ad1843_INIT = { 0, 15, 1 },
0037 ad1843_RIG = { 2, 0, 4 },
0038 ad1843_RMGE = { 2, 4, 1 },
0039 ad1843_RSS = { 2, 5, 3 },
0040 ad1843_LIG = { 2, 8, 4 },
0041 ad1843_LMGE = { 2, 12, 1 },
0042 ad1843_LSS = { 2, 13, 3 },
0043 ad1843_RD2M = { 3, 0, 5 },
0044 ad1843_RD2MM = { 3, 7, 1 },
0045 ad1843_LD2M = { 3, 8, 5 },
0046 ad1843_LD2MM = { 3, 15, 1 },
0047 ad1843_RX1M = { 4, 0, 5 },
0048 ad1843_RX1MM = { 4, 7, 1 },
0049 ad1843_LX1M = { 4, 8, 5 },
0050 ad1843_LX1MM = { 4, 15, 1 },
0051 ad1843_RX2M = { 5, 0, 5 },
0052 ad1843_RX2MM = { 5, 7, 1 },
0053 ad1843_LX2M = { 5, 8, 5 },
0054 ad1843_LX2MM = { 5, 15, 1 },
0055 ad1843_RMCM = { 7, 0, 5 },
0056 ad1843_RMCMM = { 7, 7, 1 },
0057 ad1843_LMCM = { 7, 8, 5 },
0058 ad1843_LMCMM = { 7, 15, 1 },
0059 ad1843_HPOS = { 8, 4, 1 },
0060 ad1843_HPOM = { 8, 5, 1 },
0061 ad1843_MPOM = { 8, 6, 1 },
0062 ad1843_RDA1G = { 9, 0, 6 },
0063 ad1843_RDA1GM = { 9, 7, 1 },
0064 ad1843_LDA1G = { 9, 8, 6 },
0065 ad1843_LDA1GM = { 9, 15, 1 },
0066 ad1843_RDA2G = { 10, 0, 6 },
0067 ad1843_RDA2GM = { 10, 7, 1 },
0068 ad1843_LDA2G = { 10, 8, 6 },
0069 ad1843_LDA2GM = { 10, 15, 1 },
0070 ad1843_RDA1AM = { 11, 7, 1 },
0071 ad1843_LDA1AM = { 11, 15, 1 },
0072 ad1843_RDA2AM = { 12, 7, 1 },
0073 ad1843_LDA2AM = { 12, 15, 1 },
0074 ad1843_ADLC = { 15, 0, 2 },
0075 ad1843_ADRC = { 15, 2, 2 },
0076 ad1843_DA1C = { 15, 8, 2 },
0077 ad1843_DA2C = { 15, 10, 2 },
0078 ad1843_C1C = { 17, 0, 16 },
0079 ad1843_C2C = { 20, 0, 16 },
0080 ad1843_C3C = { 23, 0, 16 },
0081 ad1843_DAADL = { 25, 4, 2 },
0082 ad1843_DAADR = { 25, 6, 2 },
0083 ad1843_DAMIX = { 25, 14, 1 },
0084 ad1843_DRSFLT = { 25, 15, 1 },
0085 ad1843_ADLF = { 26, 0, 2 },
0086 ad1843_ADRF = { 26, 2, 2 },
0087 ad1843_ADTLK = { 26, 4, 1 },
0088 ad1843_SCF = { 26, 7, 1 },
0089 ad1843_DA1F = { 26, 8, 2 },
0090 ad1843_DA2F = { 26, 10, 2 },
0091 ad1843_DA1SM = { 26, 14, 1 },
0092 ad1843_DA2SM = { 26, 15, 1 },
0093 ad1843_ADLEN = { 27, 0, 1 },
0094 ad1843_ADREN = { 27, 1, 1 },
0095 ad1843_AAMEN = { 27, 4, 1 },
0096 ad1843_ANAEN = { 27, 7, 1 },
0097 ad1843_DA1EN = { 27, 8, 1 },
0098 ad1843_DA2EN = { 27, 9, 1 },
0099 ad1843_DDMEN = { 27, 12, 1 },
0100 ad1843_C1EN = { 28, 11, 1 },
0101 ad1843_C2EN = { 28, 12, 1 },
0102 ad1843_C3EN = { 28, 13, 1 },
0103 ad1843_PDNI = { 28, 15, 1 };
0104
0105
0106
0107
0108
0109
0110
0111 struct ad1843_gain {
0112 int negative;
0113 const struct ad1843_bitfield *lfield;
0114 const struct ad1843_bitfield *rfield;
0115 const struct ad1843_bitfield *lmute;
0116 const struct ad1843_bitfield *rmute;
0117 };
0118
0119 static const struct ad1843_gain ad1843_gain_RECLEV = {
0120 .negative = 0,
0121 .lfield = &ad1843_LIG,
0122 .rfield = &ad1843_RIG
0123 };
0124 static const struct ad1843_gain ad1843_gain_LINE = {
0125 .negative = 1,
0126 .lfield = &ad1843_LX1M,
0127 .rfield = &ad1843_RX1M,
0128 .lmute = &ad1843_LX1MM,
0129 .rmute = &ad1843_RX1MM
0130 };
0131 static const struct ad1843_gain ad1843_gain_LINE_2 = {
0132 .negative = 1,
0133 .lfield = &ad1843_LDA2G,
0134 .rfield = &ad1843_RDA2G,
0135 .lmute = &ad1843_LDA2GM,
0136 .rmute = &ad1843_RDA2GM
0137 };
0138 static const struct ad1843_gain ad1843_gain_MIC = {
0139 .negative = 1,
0140 .lfield = &ad1843_LMCM,
0141 .rfield = &ad1843_RMCM,
0142 .lmute = &ad1843_LMCMM,
0143 .rmute = &ad1843_RMCMM
0144 };
0145 static const struct ad1843_gain ad1843_gain_PCM_0 = {
0146 .negative = 1,
0147 .lfield = &ad1843_LDA1G,
0148 .rfield = &ad1843_RDA1G,
0149 .lmute = &ad1843_LDA1GM,
0150 .rmute = &ad1843_RDA1GM
0151 };
0152 static const struct ad1843_gain ad1843_gain_PCM_1 = {
0153 .negative = 1,
0154 .lfield = &ad1843_LD2M,
0155 .rfield = &ad1843_RD2M,
0156 .lmute = &ad1843_LD2MM,
0157 .rmute = &ad1843_RD2MM
0158 };
0159
0160 static const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] =
0161 {
0162 &ad1843_gain_RECLEV,
0163 &ad1843_gain_LINE,
0164 &ad1843_gain_LINE_2,
0165 &ad1843_gain_MIC,
0166 &ad1843_gain_PCM_0,
0167 &ad1843_gain_PCM_1,
0168 };
0169
0170
0171
0172 static int ad1843_read_bits(struct snd_ad1843 *ad1843,
0173 const struct ad1843_bitfield *field)
0174 {
0175 int w;
0176
0177 w = ad1843->read(ad1843->chip, field->reg);
0178 return w >> field->lo_bit & ((1 << field->nbits) - 1);
0179 }
0180
0181
0182
0183
0184
0185 static int ad1843_write_bits(struct snd_ad1843 *ad1843,
0186 const struct ad1843_bitfield *field,
0187 int newval)
0188 {
0189 int w, mask, oldval, newbits;
0190
0191 w = ad1843->read(ad1843->chip, field->reg);
0192 mask = ((1 << field->nbits) - 1) << field->lo_bit;
0193 oldval = (w & mask) >> field->lo_bit;
0194 newbits = (newval << field->lo_bit) & mask;
0195 w = (w & ~mask) | newbits;
0196 ad1843->write(ad1843->chip, field->reg, w);
0197
0198 return oldval;
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...)
0215 {
0216 va_list ap;
0217 const struct ad1843_bitfield *fp;
0218 int w = 0, mask, *value, reg = -1;
0219
0220 va_start(ap, argcount);
0221 while (--argcount >= 0) {
0222 fp = va_arg(ap, const struct ad1843_bitfield *);
0223 value = va_arg(ap, int *);
0224 if (reg == -1) {
0225 reg = fp->reg;
0226 w = ad1843->read(ad1843->chip, reg);
0227 }
0228
0229 mask = (1 << fp->nbits) - 1;
0230 *value = w >> fp->lo_bit & mask;
0231 }
0232 va_end(ap);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 static void ad1843_write_multi(struct snd_ad1843 *ad1843, int argcount, ...)
0247 {
0248 va_list ap;
0249 int reg;
0250 const struct ad1843_bitfield *fp;
0251 int value;
0252 int w, m, mask, bits;
0253
0254 mask = 0;
0255 bits = 0;
0256 reg = -1;
0257
0258 va_start(ap, argcount);
0259 while (--argcount >= 0) {
0260 fp = va_arg(ap, const struct ad1843_bitfield *);
0261 value = va_arg(ap, int);
0262 if (reg == -1)
0263 reg = fp->reg;
0264 else
0265 WARN_ON(reg != fp->reg);
0266 m = ((1 << fp->nbits) - 1) << fp->lo_bit;
0267 mask |= m;
0268 bits |= (value << fp->lo_bit) & m;
0269 }
0270 va_end(ap);
0271
0272 if (~mask & 0xFFFF)
0273 w = ad1843->read(ad1843->chip, reg);
0274 else
0275 w = 0;
0276 w = (w & ~mask) | bits;
0277 ad1843->write(ad1843->chip, reg, w);
0278 }
0279
0280 int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id)
0281 {
0282 const struct ad1843_gain *gp = ad1843_gain[id];
0283 int ret;
0284
0285 ret = (1 << gp->lfield->nbits);
0286 if (!gp->lmute)
0287 ret -= 1;
0288 return ret;
0289 }
0290
0291
0292
0293
0294
0295
0296 int ad1843_get_gain(struct snd_ad1843 *ad1843, int id)
0297 {
0298 int lg, rg, lm, rm;
0299 const struct ad1843_gain *gp = ad1843_gain[id];
0300 unsigned short mask = (1 << gp->lfield->nbits) - 1;
0301
0302 ad1843_read_multi(ad1843, 2, gp->lfield, &lg, gp->rfield, &rg);
0303 if (gp->negative) {
0304 lg = mask - lg;
0305 rg = mask - rg;
0306 }
0307 if (gp->lmute) {
0308 ad1843_read_multi(ad1843, 2, gp->lmute, &lm, gp->rmute, &rm);
0309 if (lm)
0310 lg = 0;
0311 if (rm)
0312 rg = 0;
0313 }
0314 return lg << 0 | rg << 8;
0315 }
0316
0317
0318
0319
0320
0321
0322
0323 int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval)
0324 {
0325 const struct ad1843_gain *gp = ad1843_gain[id];
0326 unsigned short mask = (1 << gp->lfield->nbits) - 1;
0327
0328 int lg = (newval >> 0) & mask;
0329 int rg = (newval >> 8) & mask;
0330 int lm = (lg == 0) ? 1 : 0;
0331 int rm = (rg == 0) ? 1 : 0;
0332
0333 if (gp->negative) {
0334 lg = mask - lg;
0335 rg = mask - rg;
0336 }
0337 if (gp->lmute)
0338 ad1843_write_multi(ad1843, 2, gp->lmute, lm, gp->rmute, rm);
0339 ad1843_write_multi(ad1843, 2, gp->lfield, lg, gp->rfield, rg);
0340 return ad1843_get_gain(ad1843, id);
0341 }
0342
0343
0344
0345 int ad1843_get_recsrc(struct snd_ad1843 *ad1843)
0346 {
0347 int val = ad1843_read_bits(ad1843, &ad1843_LSS);
0348
0349 if (val < 0 || val > 2) {
0350 val = 2;
0351 ad1843_write_multi(ad1843, 2,
0352 &ad1843_LSS, val, &ad1843_RSS, val);
0353 }
0354 return val;
0355 }
0356
0357
0358
0359
0360
0361
0362
0363 int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc)
0364 {
0365 if (newsrc < 0 || newsrc > 2)
0366 return -EINVAL;
0367
0368 ad1843_write_multi(ad1843, 2, &ad1843_LSS, newsrc, &ad1843_RSS, newsrc);
0369 return newsrc;
0370 }
0371
0372
0373
0374 void ad1843_setup_dac(struct snd_ad1843 *ad1843,
0375 unsigned int id,
0376 unsigned int framerate,
0377 snd_pcm_format_t fmt,
0378 unsigned int channels)
0379 {
0380 int ad_fmt = 0, ad_mode = 0;
0381
0382 switch (fmt) {
0383 case SNDRV_PCM_FORMAT_S8:
0384 ad_fmt = 0;
0385 break;
0386 case SNDRV_PCM_FORMAT_U8:
0387 ad_fmt = 0;
0388 break;
0389 case SNDRV_PCM_FORMAT_S16_LE:
0390 ad_fmt = 1;
0391 break;
0392 case SNDRV_PCM_FORMAT_MU_LAW:
0393 ad_fmt = 2;
0394 break;
0395 case SNDRV_PCM_FORMAT_A_LAW:
0396 ad_fmt = 3;
0397 break;
0398 default:
0399 break;
0400 }
0401
0402 switch (channels) {
0403 case 2:
0404 ad_mode = 0;
0405 break;
0406 case 1:
0407 ad_mode = 1;
0408 break;
0409 default:
0410 break;
0411 }
0412
0413 if (id) {
0414 ad1843_write_bits(ad1843, &ad1843_C2C, framerate);
0415 ad1843_write_multi(ad1843, 2,
0416 &ad1843_DA2SM, ad_mode,
0417 &ad1843_DA2F, ad_fmt);
0418 } else {
0419 ad1843_write_bits(ad1843, &ad1843_C1C, framerate);
0420 ad1843_write_multi(ad1843, 2,
0421 &ad1843_DA1SM, ad_mode,
0422 &ad1843_DA1F, ad_fmt);
0423 }
0424 }
0425
0426 void ad1843_shutdown_dac(struct snd_ad1843 *ad1843, unsigned int id)
0427 {
0428 if (id)
0429 ad1843_write_bits(ad1843, &ad1843_DA2F, 1);
0430 else
0431 ad1843_write_bits(ad1843, &ad1843_DA1F, 1);
0432 }
0433
0434 void ad1843_setup_adc(struct snd_ad1843 *ad1843,
0435 unsigned int framerate,
0436 snd_pcm_format_t fmt,
0437 unsigned int channels)
0438 {
0439 int da_fmt = 0;
0440
0441 switch (fmt) {
0442 case SNDRV_PCM_FORMAT_S8: da_fmt = 0; break;
0443 case SNDRV_PCM_FORMAT_U8: da_fmt = 0; break;
0444 case SNDRV_PCM_FORMAT_S16_LE: da_fmt = 1; break;
0445 case SNDRV_PCM_FORMAT_MU_LAW: da_fmt = 2; break;
0446 case SNDRV_PCM_FORMAT_A_LAW: da_fmt = 3; break;
0447 default: break;
0448 }
0449
0450 ad1843_write_bits(ad1843, &ad1843_C3C, framerate);
0451 ad1843_write_multi(ad1843, 2,
0452 &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt);
0453 }
0454
0455 void ad1843_shutdown_adc(struct snd_ad1843 *ad1843)
0456 {
0457
0458 }
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468 int ad1843_init(struct snd_ad1843 *ad1843)
0469 {
0470 unsigned long later;
0471
0472 if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) {
0473 printk(KERN_ERR "ad1843: AD1843 won't initialize\n");
0474 return -EIO;
0475 }
0476
0477 ad1843_write_bits(ad1843, &ad1843_SCF, 1);
0478
0479
0480 ad1843_write_bits(ad1843, &ad1843_PDNI, 0);
0481 later = jiffies + msecs_to_jiffies(500);
0482
0483 while (ad1843_read_bits(ad1843, &ad1843_PDNO)) {
0484 if (time_after(jiffies, later)) {
0485 printk(KERN_ERR
0486 "ad1843: AD1843 won't power up\n");
0487 return -EIO;
0488 }
0489 schedule_timeout_interruptible(5);
0490 }
0491
0492
0493 ad1843_write_multi(ad1843, 3,
0494 &ad1843_C1EN, 1,
0495 &ad1843_C2EN, 1,
0496 &ad1843_C3EN, 1);
0497
0498
0499
0500
0501 ad1843_write_multi(ad1843, 4,
0502 &ad1843_DA1C, 1,
0503 &ad1843_DA2C, 2,
0504 &ad1843_ADLC, 3,
0505 &ad1843_ADRC, 3);
0506
0507
0508 ad1843_write_bits(ad1843, &ad1843_ADTLK, 1);
0509 ad1843_write_multi(ad1843, 7,
0510 &ad1843_ANAEN, 1,
0511 &ad1843_AAMEN, 1,
0512 &ad1843_DA1EN, 1,
0513 &ad1843_DA2EN, 1,
0514 &ad1843_DDMEN, 1,
0515 &ad1843_ADLEN, 1,
0516 &ad1843_ADREN, 1);
0517
0518
0519
0520
0521 ad1843_set_gain(ad1843, AD1843_GAIN_RECLEV, 0);
0522 ad1843_set_gain(ad1843, AD1843_GAIN_LINE, 0);
0523 ad1843_set_gain(ad1843, AD1843_GAIN_LINE_2, 0);
0524 ad1843_set_gain(ad1843, AD1843_GAIN_MIC, 0);
0525 ad1843_set_gain(ad1843, AD1843_GAIN_PCM_0, 0);
0526 ad1843_set_gain(ad1843, AD1843_GAIN_PCM_1, 0);
0527
0528
0529
0530 ad1843_write_multi(ad1843, 2, &ad1843_LDA1GM, 0, &ad1843_RDA1GM, 0);
0531
0532 ad1843_write_multi(ad1843, 2, &ad1843_LDA2GM, 0, &ad1843_RDA2GM, 0);
0533
0534
0535
0536
0537 ad1843_set_recsrc(ad1843, 2);
0538 ad1843_write_multi(ad1843, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1);
0539
0540
0541 ad1843_write_multi(ad1843, 3,
0542 &ad1843_HPOS, 1,
0543 &ad1843_HPOM, 0,
0544 &ad1843_MPOM, 0);
0545
0546 return 0;
0547 }