0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/delay.h>
0011 #include <linux/io.h>
0012 #include <linux/pci.h>
0013 #include <sound/core.h>
0014 #include <sound/control.h>
0015 #include <sound/tlv.h>
0016 #include <sound/asoundef.h>
0017 #include "pcxhr.h"
0018 #include "pcxhr_core.h"
0019 #include "pcxhr_mix22.h"
0020
0021
0022
0023 #define PCXHR_DSP_RESET 0x20
0024 #define PCXHR_XLX_CFG 0x24
0025 #define PCXHR_XLX_RUER 0x28
0026 #define PCXHR_XLX_DATA 0x2C
0027 #define PCXHR_XLX_STATUS 0x30
0028 #define PCXHR_XLX_LOFREQ 0x34
0029 #define PCXHR_XLX_HIFREQ 0x38
0030 #define PCXHR_XLX_CSUER 0x3C
0031 #define PCXHR_XLX_SELMIC 0x40
0032
0033 #define PCXHR_DSP 2
0034
0035
0036 #define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x))
0037 #define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x))
0038
0039
0040
0041 #define PCXHR_DSP_RESET_DSP 0x01
0042 #define PCXHR_DSP_RESET_MUTE 0x02
0043 #define PCXHR_DSP_RESET_CODEC 0x08
0044 #define PCXHR_DSP_RESET_SMPTE 0x10
0045 #define PCXHR_DSP_RESET_GPO_OFFSET 5
0046 #define PCXHR_DSP_RESET_GPO_MASK 0x60
0047
0048
0049 #define PCXHR_CFG_SYNCDSP_MASK 0x80
0050 #define PCXHR_CFG_DEPENDENCY_MASK 0x60
0051 #define PCXHR_CFG_INDEPENDANT_SEL 0x00
0052 #define PCXHR_CFG_MASTER_SEL 0x40
0053 #define PCXHR_CFG_SLAVE_SEL 0x20
0054 #define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10
0055 #define PCXHR_CFG_DATAIN_SEL_MASK 0x08
0056 #define PCXHR_CFG_SRC_MASK 0x04
0057 #define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02
0058 #define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01
0059
0060
0061 #define PCXHR_DATA_CODEC 0x80
0062 #define AKM_POWER_CONTROL_CMD 0xA007
0063 #define AKM_RESET_ON_CMD 0xA100
0064 #define AKM_RESET_OFF_CMD 0xA103
0065 #define AKM_CLOCK_INF_55K_CMD 0xA240
0066 #define AKM_CLOCK_SUP_55K_CMD 0xA24D
0067 #define AKM_MUTE_CMD 0xA38D
0068 #define AKM_UNMUTE_CMD 0xA30D
0069 #define AKM_LEFT_LEVEL_CMD 0xA600
0070 #define AKM_RIGHT_LEVEL_CMD 0xA700
0071
0072
0073 #define PCXHR_STAT_SRC_LOCK 0x01
0074 #define PCXHR_STAT_LEVEL_IN 0x02
0075 #define PCXHR_STAT_GPI_OFFSET 2
0076 #define PCXHR_STAT_GPI_MASK 0x0C
0077 #define PCXHR_STAT_MIC_CAPS 0x10
0078
0079 #define PCXHR_STAT_FREQ_SYNC_MASK 0x01
0080 #define PCXHR_STAT_FREQ_UER1_MASK 0x02
0081 #define PCXHR_STAT_FREQ_SAVE_MASK 0x80
0082
0083
0084 #define PCXHR_SUER1_BIT_U_READ_MASK 0x80
0085 #define PCXHR_SUER1_BIT_C_READ_MASK 0x40
0086 #define PCXHR_SUER1_DATA_PRESENT_MASK 0x20
0087 #define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10
0088 #define PCXHR_SUER_BIT_U_READ_MASK 0x08
0089 #define PCXHR_SUER_BIT_C_READ_MASK 0x04
0090 #define PCXHR_SUER_DATA_PRESENT_MASK 0x02
0091 #define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01
0092
0093 #define PCXHR_SUER_BIT_U_WRITE_MASK 0x02
0094 #define PCXHR_SUER_BIT_C_WRITE_MASK 0x01
0095
0096
0097 #define PCXHR_SELMIC_PREAMPLI_OFFSET 2
0098 #define PCXHR_SELMIC_PREAMPLI_MASK 0x0C
0099 #define PCXHR_SELMIC_PHANTOM_ALIM 0x80
0100
0101
0102 static const unsigned char g_hr222_p_level[] = {
0103 0x00,
0104 0x01,
0105 0x01,
0106 0x01,
0107 0x01,
0108 0x01,
0109 0x01,
0110 0x01,
0111 0x01,
0112 0x02,
0113 0x02,
0114 0x02,
0115 0x02,
0116 0x02,
0117 0x02,
0118 0x02,
0119 0x02,
0120 0x02,
0121 0x02,
0122 0x03,
0123 0x03,
0124 0x03,
0125 0x03,
0126 0x03,
0127 0x03,
0128 0x04,
0129 0x04,
0130 0x04,
0131 0x04,
0132 0x05,
0133 0x05,
0134 0x05,
0135 0x05,
0136 0x06,
0137 0x06,
0138 0x06,
0139 0x07,
0140 0x07,
0141 0x08,
0142 0x08,
0143 0x09,
0144 0x09,
0145 0x0a,
0146 0x0a,
0147 0x0b,
0148 0x0b,
0149 0x0c,
0150 0x0d,
0151 0x0e,
0152 0x0e,
0153 0x0f,
0154 0x10,
0155 0x11,
0156 0x12,
0157 0x13,
0158 0x14,
0159 0x15,
0160 0x17,
0161 0x18,
0162 0x1a,
0163 0x1b,
0164 0x1d,
0165 0x1e,
0166 0x20,
0167 0x22,
0168 0x24,
0169 0x26,
0170 0x28,
0171 0x2b,
0172 0x2d,
0173 0x30,
0174 0x33,
0175 0x36,
0176 0x39,
0177 0x3c,
0178 0x40,
0179 0x44,
0180 0x48,
0181 0x4c,
0182 0x51,
0183 0x55,
0184 0x5a,
0185 0x60,
0186 0x66,
0187 0x6c,
0188 0x72,
0189 0x79,
0190 0x80,
0191 0x87,
0192 0x8f,
0193 0x98,
0194 0xa1,
0195 0xaa,
0196 0xb5,
0197 0xbf,
0198 0xcb,
0199 0xd7,
0200 0xe3,
0201 0xf1,
0202 0xff,
0203 };
0204
0205
0206 static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data)
0207 {
0208 unsigned short mask = 0x8000;
0209
0210 PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ);
0211
0212 while (mask) {
0213 PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
0214 data & mask ? PCXHR_DATA_CODEC : 0);
0215 mask >>= 1;
0216 }
0217
0218 PCXHR_INPB(mgr, PCXHR_XLX_RUER);
0219 }
0220
0221
0222 static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr,
0223 int idx, int level)
0224 {
0225 unsigned short cmd;
0226 if (idx > 1 ||
0227 level < 0 ||
0228 level >= ARRAY_SIZE(g_hr222_p_level))
0229 return -EINVAL;
0230
0231 if (idx == 0)
0232 cmd = AKM_LEFT_LEVEL_CMD;
0233 else
0234 cmd = AKM_RIGHT_LEVEL_CMD;
0235
0236
0237 cmd += g_hr222_p_level[level];
0238
0239 hr222_config_akm(mgr, cmd);
0240 return 0;
0241 }
0242
0243
0244 static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr,
0245 int level_l, int level_r, int level_mic)
0246 {
0247
0248 unsigned int data;
0249 int i;
0250
0251 if (!mgr->capture_chips)
0252 return -EINVAL;
0253
0254 data = ((level_mic & 0xff) << 24);
0255 data |= ((level_mic & 0xff) << 16);
0256 data |= ((level_r & 0xff) << 8);
0257 data |= (level_l & 0xff);
0258
0259 PCXHR_INPB(mgr, PCXHR_XLX_DATA);
0260
0261 for (i = 0; i < 32; i++, data <<= 1) {
0262 PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
0263 (data & 0x80000000) ? PCXHR_DATA_CODEC : 0);
0264 }
0265 PCXHR_INPB(mgr, PCXHR_XLX_RUER);
0266 return 0;
0267 }
0268
0269 static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level);
0270
0271 int hr222_sub_init(struct pcxhr_mgr *mgr)
0272 {
0273 unsigned char reg;
0274
0275 mgr->board_has_analog = 1;
0276 mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK;
0277
0278 reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
0279 if (reg & PCXHR_STAT_MIC_CAPS)
0280 mgr->board_has_mic = 1;
0281 dev_dbg(&mgr->pci->dev,
0282 "MIC input available = %d\n", mgr->board_has_mic);
0283
0284
0285 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
0286 PCXHR_DSP_RESET_DSP);
0287 msleep(5);
0288 mgr->dsp_reset = PCXHR_DSP_RESET_DSP |
0289 PCXHR_DSP_RESET_MUTE |
0290 PCXHR_DSP_RESET_CODEC;
0291 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
0292
0293 msleep(5);
0294
0295
0296 hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD);
0297 hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
0298 hr222_config_akm(mgr, AKM_UNMUTE_CMD);
0299 hr222_config_akm(mgr, AKM_RESET_OFF_CMD);
0300
0301
0302 hr222_micro_boost(mgr, 0);
0303
0304 return 0;
0305 }
0306
0307
0308
0309
0310 static int hr222_pll_freq_register(unsigned int freq,
0311 unsigned int *pllreg,
0312 unsigned int *realfreq)
0313 {
0314 unsigned int reg;
0315
0316 if (freq < 6900 || freq > 219000)
0317 return -EINVAL;
0318 reg = (28224000 * 2) / freq;
0319 reg = (reg - 1) / 2;
0320 if (reg < 0x100)
0321 *pllreg = reg + 0xC00;
0322 else if (reg < 0x200)
0323 *pllreg = reg + 0x800;
0324 else if (reg < 0x400)
0325 *pllreg = reg & 0x1ff;
0326 else if (reg < 0x800) {
0327 *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
0328 reg &= ~1;
0329 } else {
0330 *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
0331 reg &= ~3;
0332 }
0333 if (realfreq)
0334 *realfreq = (28224000 / (reg + 1));
0335 return 0;
0336 }
0337
0338 int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
0339 unsigned int rate,
0340 int *changed)
0341 {
0342 unsigned int speed, pllreg = 0;
0343 int err;
0344 unsigned realfreq = rate;
0345
0346 switch (mgr->use_clock_type) {
0347 case HR22_CLOCK_TYPE_INTERNAL:
0348 err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
0349 if (err)
0350 return err;
0351
0352 mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK |
0353 PCXHR_CFG_CLOCK_UER1_SEL_MASK);
0354 break;
0355 case HR22_CLOCK_TYPE_AES_SYNC:
0356 mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK;
0357 mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK;
0358 break;
0359 case HR22_CLOCK_TYPE_AES_1:
0360 if (!mgr->board_has_aes1)
0361 return -EINVAL;
0362
0363 mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK |
0364 PCXHR_CFG_CLOCK_UER1_SEL_MASK);
0365 break;
0366 default:
0367 return -EINVAL;
0368 }
0369 hr222_config_akm(mgr, AKM_MUTE_CMD);
0370
0371 if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) {
0372 PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8);
0373 PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff);
0374 }
0375
0376
0377 PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg);
0378
0379
0380 speed = rate < 55000 ? 0 : 1;
0381 if (mgr->codec_speed != speed) {
0382 mgr->codec_speed = speed;
0383 if (speed == 0)
0384 hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
0385 else
0386 hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD);
0387 }
0388
0389 mgr->sample_rate_real = realfreq;
0390 mgr->cur_clock_type = mgr->use_clock_type;
0391
0392 if (changed)
0393 *changed = 1;
0394
0395 hr222_config_akm(mgr, AKM_UNMUTE_CMD);
0396
0397 dev_dbg(&mgr->pci->dev, "set_clock to %dHz (realfreq=%d pllreg=%x)\n",
0398 rate, realfreq, pllreg);
0399 return 0;
0400 }
0401
0402 int hr222_get_external_clock(struct pcxhr_mgr *mgr,
0403 enum pcxhr_clock_type clock_type,
0404 int *sample_rate)
0405 {
0406 int rate, calc_rate = 0;
0407 unsigned int ticks;
0408 unsigned char mask, reg;
0409
0410 if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) {
0411
0412 mask = (PCXHR_SUER_CLOCK_PRESENT_MASK |
0413 PCXHR_SUER_DATA_PRESENT_MASK);
0414 reg = PCXHR_STAT_FREQ_SYNC_MASK;
0415
0416 } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) {
0417
0418 mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK |
0419 PCXHR_SUER1_DATA_PRESENT_MASK);
0420 reg = PCXHR_STAT_FREQ_UER1_MASK;
0421
0422 } else {
0423 dev_dbg(&mgr->pci->dev,
0424 "get_external_clock : type %d not supported\n",
0425 clock_type);
0426 return -EINVAL;
0427 }
0428
0429 if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) {
0430 dev_dbg(&mgr->pci->dev,
0431 "get_external_clock(%d) = 0 Hz\n", clock_type);
0432 *sample_rate = 0;
0433 return 0;
0434 }
0435
0436 PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg);
0437
0438
0439 reg |= PCXHR_STAT_FREQ_SAVE_MASK;
0440
0441 if (mgr->last_reg_stat != reg) {
0442 udelay(500);
0443 mgr->last_reg_stat = reg;
0444 }
0445
0446 PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg);
0447
0448
0449 ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG);
0450 ticks = (ticks & 0x03) << 8;
0451 ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET);
0452
0453 if (ticks != 0)
0454 calc_rate = 28224000 / ticks;
0455
0456 if (calc_rate > 184200)
0457 rate = 192000;
0458 else if (calc_rate > 152200)
0459 rate = 176400;
0460 else if (calc_rate > 112000)
0461 rate = 128000;
0462 else if (calc_rate > 92100)
0463 rate = 96000;
0464 else if (calc_rate > 76100)
0465 rate = 88200;
0466 else if (calc_rate > 56000)
0467 rate = 64000;
0468 else if (calc_rate > 46050)
0469 rate = 48000;
0470 else if (calc_rate > 38050)
0471 rate = 44100;
0472 else if (calc_rate > 28000)
0473 rate = 32000;
0474 else if (calc_rate > 23025)
0475 rate = 24000;
0476 else if (calc_rate > 19025)
0477 rate = 22050;
0478 else if (calc_rate > 14000)
0479 rate = 16000;
0480 else if (calc_rate > 11512)
0481 rate = 12000;
0482 else if (calc_rate > 9512)
0483 rate = 11025;
0484 else if (calc_rate > 7000)
0485 rate = 8000;
0486 else
0487 rate = 0;
0488
0489 dev_dbg(&mgr->pci->dev, "External clock is at %d Hz (measured %d Hz)\n",
0490 rate, calc_rate);
0491 *sample_rate = rate;
0492 return 0;
0493 }
0494
0495
0496 int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value)
0497 {
0498 if (is_gpi) {
0499 unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
0500 *value = (int)(reg & PCXHR_STAT_GPI_MASK) >>
0501 PCXHR_STAT_GPI_OFFSET;
0502 } else {
0503 *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >>
0504 PCXHR_DSP_RESET_GPO_OFFSET;
0505 }
0506 return 0;
0507 }
0508
0509
0510 int hr222_write_gpo(struct pcxhr_mgr *mgr, int value)
0511 {
0512 unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK;
0513
0514 reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) &
0515 PCXHR_DSP_RESET_GPO_MASK;
0516
0517 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg);
0518 mgr->dsp_reset = reg;
0519 return 0;
0520 }
0521
0522 int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable)
0523 {
0524 if (enable)
0525 mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE;
0526 else
0527 mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE;
0528
0529 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
0530 return 0;
0531 }
0532
0533 int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
0534 int is_capture, int channel)
0535 {
0536 dev_dbg(chip->card->dev,
0537 "hr222_update_analog_audio_level(%s chan=%d)\n",
0538 is_capture ? "capture" : "playback", channel);
0539 if (is_capture) {
0540 int level_l, level_r, level_mic;
0541
0542 if (chip->analog_capture_active) {
0543 level_l = chip->analog_capture_volume[0];
0544 level_r = chip->analog_capture_volume[1];
0545 } else {
0546 level_l = HR222_LINE_CAPTURE_LEVEL_MIN;
0547 level_r = HR222_LINE_CAPTURE_LEVEL_MIN;
0548 }
0549 if (chip->mic_active)
0550 level_mic = chip->mic_volume;
0551 else
0552 level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN;
0553 return hr222_set_hw_capture_level(chip->mgr,
0554 level_l, level_r, level_mic);
0555 } else {
0556 int vol;
0557 if (chip->analog_playback_active[channel])
0558 vol = chip->analog_playback_volume[channel];
0559 else
0560 vol = HR222_LINE_PLAYBACK_LEVEL_MIN;
0561 return hr222_set_hw_playback_level(chip->mgr, channel, vol);
0562 }
0563 }
0564
0565
0566
0567 #define SOURCE_LINE 0
0568 #define SOURCE_DIGITAL 1
0569 #define SOURCE_DIGISRC 2
0570 #define SOURCE_MIC 3
0571 #define SOURCE_LINEMIC 4
0572
0573 int hr222_set_audio_source(struct snd_pcxhr *chip)
0574 {
0575 int digital = 0;
0576
0577 chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK |
0578 PCXHR_CFG_DATAIN_SEL_MASK |
0579 PCXHR_CFG_DATA_UER1_SEL_MASK);
0580
0581 if (chip->audio_capture_source == SOURCE_DIGISRC) {
0582 chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK;
0583 digital = 1;
0584 } else {
0585 if (chip->audio_capture_source == SOURCE_DIGITAL)
0586 digital = 1;
0587 }
0588 if (digital) {
0589 chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK;
0590 if (chip->mgr->board_has_aes1) {
0591
0592 chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK;
0593 }
0594
0595
0596 } else {
0597 int update_lvl = 0;
0598 chip->analog_capture_active = 0;
0599 chip->mic_active = 0;
0600 if (chip->audio_capture_source == SOURCE_LINE ||
0601 chip->audio_capture_source == SOURCE_LINEMIC) {
0602 if (chip->analog_capture_active == 0)
0603 update_lvl = 1;
0604 chip->analog_capture_active = 1;
0605 }
0606 if (chip->audio_capture_source == SOURCE_MIC ||
0607 chip->audio_capture_source == SOURCE_LINEMIC) {
0608 if (chip->mic_active == 0)
0609 update_lvl = 1;
0610 chip->mic_active = 1;
0611 }
0612 if (update_lvl) {
0613
0614 hr222_update_analog_audio_level(chip, 1, 0);
0615 }
0616 }
0617
0618 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg);
0619 return 0;
0620 }
0621
0622
0623 int hr222_iec958_capture_byte(struct snd_pcxhr *chip,
0624 int aes_idx, unsigned char *aes_bits)
0625 {
0626 unsigned char idx = (unsigned char)(aes_idx * 8);
0627 unsigned char temp = 0;
0628 unsigned char mask = chip->mgr->board_has_aes1 ?
0629 PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK;
0630 int i;
0631 for (i = 0; i < 8; i++) {
0632 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++);
0633 temp <<= 1;
0634 if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask)
0635 temp |= 1;
0636 }
0637 dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n",
0638 chip->chip_idx, aes_idx, temp);
0639 *aes_bits = temp;
0640 return 0;
0641 }
0642
0643
0644 int hr222_iec958_update_byte(struct snd_pcxhr *chip,
0645 int aes_idx, unsigned char aes_bits)
0646 {
0647 int i;
0648 unsigned char new_bits = aes_bits;
0649 unsigned char old_bits = chip->aes_bits[aes_idx];
0650 unsigned char idx = (unsigned char)(aes_idx * 8);
0651 for (i = 0; i < 8; i++) {
0652 if ((old_bits & 0x01) != (new_bits & 0x01)) {
0653
0654 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx);
0655
0656 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ?
0657 PCXHR_SUER_BIT_C_WRITE_MASK : 0);
0658 }
0659 idx++;
0660 old_bits >>= 1;
0661 new_bits >>= 1;
0662 }
0663 chip->aes_bits[aes_idx] = aes_bits;
0664 return 0;
0665 }
0666
0667 static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level)
0668 {
0669 unsigned char boost_mask;
0670 boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET);
0671 if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK))
0672 return;
0673
0674 mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK;
0675 mgr->xlx_selmic |= boost_mask;
0676
0677 PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
0678
0679 dev_dbg(&mgr->pci->dev, "hr222_micro_boost : set %x\n", boost_mask);
0680 }
0681
0682 static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power)
0683 {
0684 if (power)
0685 mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM;
0686 else
0687 mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM;
0688
0689 PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
0690
0691 dev_dbg(&mgr->pci->dev, "hr222_phantom_power : set %d\n", power);
0692 }
0693
0694
0695
0696 static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650);
0697
0698 static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol,
0699 struct snd_ctl_elem_info *uinfo)
0700 {
0701 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0702 uinfo->count = 1;
0703 uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN;
0704
0705 uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX;
0706 return 0;
0707 }
0708
0709 static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol,
0710 struct snd_ctl_elem_value *ucontrol)
0711 {
0712 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0713 mutex_lock(&chip->mgr->mixer_mutex);
0714 ucontrol->value.integer.value[0] = chip->mic_volume;
0715 mutex_unlock(&chip->mgr->mixer_mutex);
0716 return 0;
0717 }
0718
0719 static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol,
0720 struct snd_ctl_elem_value *ucontrol)
0721 {
0722 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0723 int changed = 0;
0724 mutex_lock(&chip->mgr->mixer_mutex);
0725 if (chip->mic_volume != ucontrol->value.integer.value[0]) {
0726 changed = 1;
0727 chip->mic_volume = ucontrol->value.integer.value[0];
0728 hr222_update_analog_audio_level(chip, 1, 0);
0729 }
0730 mutex_unlock(&chip->mgr->mixer_mutex);
0731 return changed;
0732 }
0733
0734 static const struct snd_kcontrol_new hr222_control_mic_level = {
0735 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0736 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
0737 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
0738 .name = "Mic Capture Volume",
0739 .info = hr222_mic_vol_info,
0740 .get = hr222_mic_vol_get,
0741 .put = hr222_mic_vol_put,
0742 .tlv = { .p = db_scale_mic_hr222 },
0743 };
0744
0745
0746
0747 static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400);
0748
0749 static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol,
0750 struct snd_ctl_elem_info *uinfo)
0751 {
0752 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0753 uinfo->count = 1;
0754 uinfo->value.integer.min = 0;
0755 uinfo->value.integer.max = 3;
0756 return 0;
0757 }
0758
0759 static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol,
0760 struct snd_ctl_elem_value *ucontrol)
0761 {
0762 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0763 mutex_lock(&chip->mgr->mixer_mutex);
0764 ucontrol->value.integer.value[0] = chip->mic_boost;
0765 mutex_unlock(&chip->mgr->mixer_mutex);
0766 return 0;
0767 }
0768
0769 static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol,
0770 struct snd_ctl_elem_value *ucontrol)
0771 {
0772 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0773 int changed = 0;
0774 mutex_lock(&chip->mgr->mixer_mutex);
0775 if (chip->mic_boost != ucontrol->value.integer.value[0]) {
0776 changed = 1;
0777 chip->mic_boost = ucontrol->value.integer.value[0];
0778 hr222_micro_boost(chip->mgr, chip->mic_boost);
0779 }
0780 mutex_unlock(&chip->mgr->mixer_mutex);
0781 return changed;
0782 }
0783
0784 static const struct snd_kcontrol_new hr222_control_mic_boost = {
0785 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0786 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
0787 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
0788 .name = "MicBoost Capture Volume",
0789 .info = hr222_mic_boost_info,
0790 .get = hr222_mic_boost_get,
0791 .put = hr222_mic_boost_put,
0792 .tlv = { .p = db_scale_micboost_hr222 },
0793 };
0794
0795
0796
0797 #define hr222_phantom_power_info snd_ctl_boolean_mono_info
0798
0799 static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol,
0800 struct snd_ctl_elem_value *ucontrol)
0801 {
0802 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0803 mutex_lock(&chip->mgr->mixer_mutex);
0804 ucontrol->value.integer.value[0] = chip->phantom_power;
0805 mutex_unlock(&chip->mgr->mixer_mutex);
0806 return 0;
0807 }
0808
0809 static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol,
0810 struct snd_ctl_elem_value *ucontrol)
0811 {
0812 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
0813 int power, changed = 0;
0814
0815 mutex_lock(&chip->mgr->mixer_mutex);
0816 power = !!ucontrol->value.integer.value[0];
0817 if (chip->phantom_power != power) {
0818 hr222_phantom_power(chip->mgr, power);
0819 chip->phantom_power = power;
0820 changed = 1;
0821 }
0822 mutex_unlock(&chip->mgr->mixer_mutex);
0823 return changed;
0824 }
0825
0826 static const struct snd_kcontrol_new hr222_phantom_power_switch = {
0827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0828 .name = "Phantom Power Switch",
0829 .info = hr222_phantom_power_info,
0830 .get = hr222_phantom_power_get,
0831 .put = hr222_phantom_power_put,
0832 };
0833
0834
0835 int hr222_add_mic_controls(struct snd_pcxhr *chip)
0836 {
0837 int err;
0838 if (!chip->mgr->board_has_mic)
0839 return 0;
0840
0841
0842 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level,
0843 chip));
0844 if (err < 0)
0845 return err;
0846
0847 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost,
0848 chip));
0849 if (err < 0)
0850 return err;
0851
0852 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch,
0853 chip));
0854 return err;
0855 }