1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/delay.h>
24#include <linux/io.h>
25#include <linux/pci.h>
26#include <sound/core.h>
27#include <sound/control.h>
28#include <sound/tlv.h>
29#include <sound/asoundef.h>
30#include "pcxhr.h"
31#include "pcxhr_core.h"
32#include "pcxhr_mix22.h"
33
34
35
36#define PCXHR_DSP_RESET 0x20
37#define PCXHR_XLX_CFG 0x24
38#define PCXHR_XLX_RUER 0x28
39#define PCXHR_XLX_DATA 0x2C
40#define PCXHR_XLX_STATUS 0x30
41#define PCXHR_XLX_LOFREQ 0x34
42#define PCXHR_XLX_HIFREQ 0x38
43#define PCXHR_XLX_CSUER 0x3C
44#define PCXHR_XLX_SELMIC 0x40
45
46#define PCXHR_DSP 2
47
48
49#define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x))
50#define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x))
51
52
53
54#define PCXHR_DSP_RESET_DSP 0x01
55#define PCXHR_DSP_RESET_MUTE 0x02
56#define PCXHR_DSP_RESET_CODEC 0x08
57#define PCXHR_DSP_RESET_SMPTE 0x10
58#define PCXHR_DSP_RESET_GPO_OFFSET 5
59#define PCXHR_DSP_RESET_GPO_MASK 0x60
60
61
62#define PCXHR_CFG_SYNCDSP_MASK 0x80
63#define PCXHR_CFG_DEPENDENCY_MASK 0x60
64#define PCXHR_CFG_INDEPENDANT_SEL 0x00
65#define PCXHR_CFG_MASTER_SEL 0x40
66#define PCXHR_CFG_SLAVE_SEL 0x20
67#define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10
68#define PCXHR_CFG_DATAIN_SEL_MASK 0x08
69#define PCXHR_CFG_SRC_MASK 0x04
70#define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02
71#define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01
72
73
74#define PCXHR_DATA_CODEC 0x80
75#define AKM_POWER_CONTROL_CMD 0xA007
76#define AKM_RESET_ON_CMD 0xA100
77#define AKM_RESET_OFF_CMD 0xA103
78#define AKM_CLOCK_INF_55K_CMD 0xA240
79#define AKM_CLOCK_SUP_55K_CMD 0xA24D
80#define AKM_MUTE_CMD 0xA38D
81#define AKM_UNMUTE_CMD 0xA30D
82#define AKM_LEFT_LEVEL_CMD 0xA600
83#define AKM_RIGHT_LEVEL_CMD 0xA700
84
85
86#define PCXHR_STAT_SRC_LOCK 0x01
87#define PCXHR_STAT_LEVEL_IN 0x02
88#define PCXHR_STAT_GPI_OFFSET 2
89#define PCXHR_STAT_GPI_MASK 0x0C
90#define PCXHR_STAT_MIC_CAPS 0x10
91
92#define PCXHR_STAT_FREQ_SYNC_MASK 0x01
93#define PCXHR_STAT_FREQ_UER1_MASK 0x02
94#define PCXHR_STAT_FREQ_SAVE_MASK 0x80
95
96
97#define PCXHR_SUER1_BIT_U_READ_MASK 0x80
98#define PCXHR_SUER1_BIT_C_READ_MASK 0x40
99#define PCXHR_SUER1_DATA_PRESENT_MASK 0x20
100#define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10
101#define PCXHR_SUER_BIT_U_READ_MASK 0x08
102#define PCXHR_SUER_BIT_C_READ_MASK 0x04
103#define PCXHR_SUER_DATA_PRESENT_MASK 0x02
104#define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01
105
106#define PCXHR_SUER_BIT_U_WRITE_MASK 0x02
107#define PCXHR_SUER_BIT_C_WRITE_MASK 0x01
108
109
110#define PCXHR_SELMIC_PREAMPLI_OFFSET 2
111#define PCXHR_SELMIC_PREAMPLI_MASK 0x0C
112#define PCXHR_SELMIC_PHANTOM_ALIM 0x80
113
114
115static const unsigned char g_hr222_p_level[] = {
116 0x00,
117 0x01,
118 0x01,
119 0x01,
120 0x01,
121 0x01,
122 0x01,
123 0x01,
124 0x01,
125 0x02,
126 0x02,
127 0x02,
128 0x02,
129 0x02,
130 0x02,
131 0x02,
132 0x02,
133 0x02,
134 0x02,
135 0x03,
136 0x03,
137 0x03,
138 0x03,
139 0x03,
140 0x03,
141 0x04,
142 0x04,
143 0x04,
144 0x04,
145 0x05,
146 0x05,
147 0x05,
148 0x05,
149 0x06,
150 0x06,
151 0x06,
152 0x07,
153 0x07,
154 0x08,
155 0x08,
156 0x09,
157 0x09,
158 0x0a,
159 0x0a,
160 0x0b,
161 0x0b,
162 0x0c,
163 0x0d,
164 0x0e,
165 0x0e,
166 0x0f,
167 0x10,
168 0x11,
169 0x12,
170 0x13,
171 0x14,
172 0x15,
173 0x17,
174 0x18,
175 0x1a,
176 0x1b,
177 0x1d,
178 0x1e,
179 0x20,
180 0x22,
181 0x24,
182 0x26,
183 0x28,
184 0x2b,
185 0x2d,
186 0x30,
187 0x33,
188 0x36,
189 0x39,
190 0x3c,
191 0x40,
192 0x44,
193 0x48,
194 0x4c,
195 0x51,
196 0x55,
197 0x5a,
198 0x60,
199 0x66,
200 0x6c,
201 0x72,
202 0x79,
203 0x80,
204 0x87,
205 0x8f,
206 0x98,
207 0xa1,
208 0xaa,
209 0xb5,
210 0xbf,
211 0xcb,
212 0xd7,
213 0xe3,
214 0xf1,
215 0xff,
216};
217
218
219static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data)
220{
221 unsigned short mask = 0x8000;
222
223 PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ);
224
225 while (mask) {
226 PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
227 data & mask ? PCXHR_DATA_CODEC : 0);
228 mask >>= 1;
229 }
230
231 PCXHR_INPB(mgr, PCXHR_XLX_RUER);
232}
233
234
235static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr,
236 int idx, int level)
237{
238 unsigned short cmd;
239 if (idx > 1 ||
240 level < 0 ||
241 level >= ARRAY_SIZE(g_hr222_p_level))
242 return -EINVAL;
243
244 if (idx == 0)
245 cmd = AKM_LEFT_LEVEL_CMD;
246 else
247 cmd = AKM_RIGHT_LEVEL_CMD;
248
249
250 cmd += g_hr222_p_level[level];
251
252 hr222_config_akm(mgr, cmd);
253 return 0;
254}
255
256
257static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr,
258 int level_l, int level_r, int level_mic)
259{
260
261 unsigned int data;
262 int i;
263
264 if (!mgr->capture_chips)
265 return -EINVAL;
266
267 data = ((level_mic & 0xff) << 24);
268 data |= ((level_mic & 0xff) << 16);
269 data |= ((level_r & 0xff) << 8);
270 data |= (level_l & 0xff);
271
272 PCXHR_INPB(mgr, PCXHR_XLX_DATA);
273
274 for (i = 0; i < 32; i++, data <<= 1) {
275 PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
276 (data & 0x80000000) ? PCXHR_DATA_CODEC : 0);
277 }
278 PCXHR_INPB(mgr, PCXHR_XLX_RUER);
279 return 0;
280}
281
282static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level);
283
284int hr222_sub_init(struct pcxhr_mgr *mgr)
285{
286 unsigned char reg;
287
288 mgr->board_has_analog = 1;
289 mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK;
290
291 reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
292 if (reg & PCXHR_STAT_MIC_CAPS)
293 mgr->board_has_mic = 1;
294 dev_dbg(&mgr->pci->dev,
295 "MIC input available = %d\n", mgr->board_has_mic);
296
297
298 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
299 PCXHR_DSP_RESET_DSP);
300 msleep(5);
301 mgr->dsp_reset = PCXHR_DSP_RESET_DSP |
302 PCXHR_DSP_RESET_MUTE |
303 PCXHR_DSP_RESET_CODEC;
304 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
305
306 msleep(5);
307
308
309 hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD);
310 hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
311 hr222_config_akm(mgr, AKM_UNMUTE_CMD);
312 hr222_config_akm(mgr, AKM_RESET_OFF_CMD);
313
314
315 hr222_micro_boost(mgr, 0);
316
317 return 0;
318}
319
320
321
322
323static int hr222_pll_freq_register(unsigned int freq,
324 unsigned int *pllreg,
325 unsigned int *realfreq)
326{
327 unsigned int reg;
328
329 if (freq < 6900 || freq > 219000)
330 return -EINVAL;
331 reg = (28224000 * 2) / freq;
332 reg = (reg - 1) / 2;
333 if (reg < 0x100)
334 *pllreg = reg + 0xC00;
335 else if (reg < 0x200)
336 *pllreg = reg + 0x800;
337 else if (reg < 0x400)
338 *pllreg = reg & 0x1ff;
339 else if (reg < 0x800) {
340 *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
341 reg &= ~1;
342 } else {
343 *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
344 reg &= ~3;
345 }
346 if (realfreq)
347 *realfreq = (28224000 / (reg + 1));
348 return 0;
349}
350
351int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
352 unsigned int rate,
353 int *changed)
354{
355 unsigned int speed, pllreg = 0;
356 int err;
357 unsigned realfreq = rate;
358
359 switch (mgr->use_clock_type) {
360 case HR22_CLOCK_TYPE_INTERNAL:
361 err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
362 if (err)
363 return err;
364
365 mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK |
366 PCXHR_CFG_CLOCK_UER1_SEL_MASK);
367 break;
368 case HR22_CLOCK_TYPE_AES_SYNC:
369 mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK;
370 mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK;
371 break;
372 case HR22_CLOCK_TYPE_AES_1:
373 if (!mgr->board_has_aes1)
374 return -EINVAL;
375
376 mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK |
377 PCXHR_CFG_CLOCK_UER1_SEL_MASK);
378 break;
379 default:
380 return -EINVAL;
381 }
382 hr222_config_akm(mgr, AKM_MUTE_CMD);
383
384 if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) {
385 PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8);
386 PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff);
387 }
388
389
390 PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg);
391
392
393 speed = rate < 55000 ? 0 : 1;
394 if (mgr->codec_speed != speed) {
395 mgr->codec_speed = speed;
396 if (speed == 0)
397 hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
398 else
399 hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD);
400 }
401
402 mgr->sample_rate_real = realfreq;
403 mgr->cur_clock_type = mgr->use_clock_type;
404
405 if (changed)
406 *changed = 1;
407
408 hr222_config_akm(mgr, AKM_UNMUTE_CMD);
409
410 dev_dbg(&mgr->pci->dev, "set_clock to %dHz (realfreq=%d pllreg=%x)\n",
411 rate, realfreq, pllreg);
412 return 0;
413}
414
415int hr222_get_external_clock(struct pcxhr_mgr *mgr,
416 enum pcxhr_clock_type clock_type,
417 int *sample_rate)
418{
419 int rate, calc_rate = 0;
420 unsigned int ticks;
421 unsigned char mask, reg;
422
423 if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) {
424
425 mask = (PCXHR_SUER_CLOCK_PRESENT_MASK |
426 PCXHR_SUER_DATA_PRESENT_MASK);
427 reg = PCXHR_STAT_FREQ_SYNC_MASK;
428
429 } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) {
430
431 mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK |
432 PCXHR_SUER1_DATA_PRESENT_MASK);
433 reg = PCXHR_STAT_FREQ_UER1_MASK;
434
435 } else {
436 dev_dbg(&mgr->pci->dev,
437 "get_external_clock : type %d not supported\n",
438 clock_type);
439 return -EINVAL;
440 }
441
442 if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) {
443 dev_dbg(&mgr->pci->dev,
444 "get_external_clock(%d) = 0 Hz\n", clock_type);
445 *sample_rate = 0;
446 return 0;
447 }
448
449 PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg);
450
451
452 reg |= PCXHR_STAT_FREQ_SAVE_MASK;
453
454 if (mgr->last_reg_stat != reg) {
455 udelay(500);
456 mgr->last_reg_stat = reg;
457 }
458
459 PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg);
460
461
462 ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG);
463 ticks = (ticks & 0x03) << 8;
464 ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET);
465
466 if (ticks != 0)
467 calc_rate = 28224000 / ticks;
468
469 if (calc_rate > 184200)
470 rate = 192000;
471 else if (calc_rate > 152200)
472 rate = 176400;
473 else if (calc_rate > 112000)
474 rate = 128000;
475 else if (calc_rate > 92100)
476 rate = 96000;
477 else if (calc_rate > 76100)
478 rate = 88200;
479 else if (calc_rate > 56000)
480 rate = 64000;
481 else if (calc_rate > 46050)
482 rate = 48000;
483 else if (calc_rate > 38050)
484 rate = 44100;
485 else if (calc_rate > 28000)
486 rate = 32000;
487 else if (calc_rate > 23025)
488 rate = 24000;
489 else if (calc_rate > 19025)
490 rate = 22050;
491 else if (calc_rate > 14000)
492 rate = 16000;
493 else if (calc_rate > 11512)
494 rate = 12000;
495 else if (calc_rate > 9512)
496 rate = 11025;
497 else if (calc_rate > 7000)
498 rate = 8000;
499 else
500 rate = 0;
501
502 dev_dbg(&mgr->pci->dev, "External clock is at %d Hz (measured %d Hz)\n",
503 rate, calc_rate);
504 *sample_rate = rate;
505 return 0;
506}
507
508
509int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value)
510{
511 if (is_gpi) {
512 unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
513 *value = (int)(reg & PCXHR_STAT_GPI_MASK) >>
514 PCXHR_STAT_GPI_OFFSET;
515 } else {
516 *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >>
517 PCXHR_DSP_RESET_GPO_OFFSET;
518 }
519 return 0;
520}
521
522
523int hr222_write_gpo(struct pcxhr_mgr *mgr, int value)
524{
525 unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK;
526
527 reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) &
528 PCXHR_DSP_RESET_GPO_MASK;
529
530 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg);
531 mgr->dsp_reset = reg;
532 return 0;
533}
534
535int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable)
536{
537 if (enable)
538 mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE;
539 else
540 mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE;
541
542 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
543 return 0;
544}
545
546int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
547 int is_capture, int channel)
548{
549 dev_dbg(chip->card->dev,
550 "hr222_update_analog_audio_level(%s chan=%d)\n",
551 is_capture ? "capture" : "playback", channel);
552 if (is_capture) {
553 int level_l, level_r, level_mic;
554
555 if (chip->analog_capture_active) {
556 level_l = chip->analog_capture_volume[0];
557 level_r = chip->analog_capture_volume[1];
558 } else {
559 level_l = HR222_LINE_CAPTURE_LEVEL_MIN;
560 level_r = HR222_LINE_CAPTURE_LEVEL_MIN;
561 }
562 if (chip->mic_active)
563 level_mic = chip->mic_volume;
564 else
565 level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN;
566 return hr222_set_hw_capture_level(chip->mgr,
567 level_l, level_r, level_mic);
568 } else {
569 int vol;
570 if (chip->analog_playback_active[channel])
571 vol = chip->analog_playback_volume[channel];
572 else
573 vol = HR222_LINE_PLAYBACK_LEVEL_MIN;
574 return hr222_set_hw_playback_level(chip->mgr, channel, vol);
575 }
576}
577
578
579
580#define SOURCE_LINE 0
581#define SOURCE_DIGITAL 1
582#define SOURCE_DIGISRC 2
583#define SOURCE_MIC 3
584#define SOURCE_LINEMIC 4
585
586int hr222_set_audio_source(struct snd_pcxhr *chip)
587{
588 int digital = 0;
589
590 chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK |
591 PCXHR_CFG_DATAIN_SEL_MASK |
592 PCXHR_CFG_DATA_UER1_SEL_MASK);
593
594 if (chip->audio_capture_source == SOURCE_DIGISRC) {
595 chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK;
596 digital = 1;
597 } else {
598 if (chip->audio_capture_source == SOURCE_DIGITAL)
599 digital = 1;
600 }
601 if (digital) {
602 chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK;
603 if (chip->mgr->board_has_aes1) {
604
605 chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK;
606 }
607
608
609 } else {
610 int update_lvl = 0;
611 chip->analog_capture_active = 0;
612 chip->mic_active = 0;
613 if (chip->audio_capture_source == SOURCE_LINE ||
614 chip->audio_capture_source == SOURCE_LINEMIC) {
615 if (chip->analog_capture_active == 0)
616 update_lvl = 1;
617 chip->analog_capture_active = 1;
618 }
619 if (chip->audio_capture_source == SOURCE_MIC ||
620 chip->audio_capture_source == SOURCE_LINEMIC) {
621 if (chip->mic_active == 0)
622 update_lvl = 1;
623 chip->mic_active = 1;
624 }
625 if (update_lvl) {
626
627 hr222_update_analog_audio_level(chip, 1, 0);
628 }
629 }
630
631 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg);
632 return 0;
633}
634
635
636int hr222_iec958_capture_byte(struct snd_pcxhr *chip,
637 int aes_idx, unsigned char *aes_bits)
638{
639 unsigned char idx = (unsigned char)(aes_idx * 8);
640 unsigned char temp = 0;
641 unsigned char mask = chip->mgr->board_has_aes1 ?
642 PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK;
643 int i;
644 for (i = 0; i < 8; i++) {
645 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++);
646 temp <<= 1;
647 if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask)
648 temp |= 1;
649 }
650 dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n",
651 chip->chip_idx, aes_idx, temp);
652 *aes_bits = temp;
653 return 0;
654}
655
656
657int hr222_iec958_update_byte(struct snd_pcxhr *chip,
658 int aes_idx, unsigned char aes_bits)
659{
660 int i;
661 unsigned char new_bits = aes_bits;
662 unsigned char old_bits = chip->aes_bits[aes_idx];
663 unsigned char idx = (unsigned char)(aes_idx * 8);
664 for (i = 0; i < 8; i++) {
665 if ((old_bits & 0x01) != (new_bits & 0x01)) {
666
667 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx);
668
669 PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ?
670 PCXHR_SUER_BIT_C_WRITE_MASK : 0);
671 }
672 idx++;
673 old_bits >>= 1;
674 new_bits >>= 1;
675 }
676 chip->aes_bits[aes_idx] = aes_bits;
677 return 0;
678}
679
680static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level)
681{
682 unsigned char boost_mask;
683 boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET);
684 if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK))
685 return;
686
687 mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK;
688 mgr->xlx_selmic |= boost_mask;
689
690 PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
691
692 dev_dbg(&mgr->pci->dev, "hr222_micro_boost : set %x\n", boost_mask);
693}
694
695static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power)
696{
697 if (power)
698 mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM;
699 else
700 mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM;
701
702 PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
703
704 dev_dbg(&mgr->pci->dev, "hr222_phantom_power : set %d\n", power);
705}
706
707
708
709static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650);
710
711static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol,
712 struct snd_ctl_elem_info *uinfo)
713{
714 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
715 uinfo->count = 1;
716 uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN;
717
718 uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX;
719 return 0;
720}
721
722static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol,
723 struct snd_ctl_elem_value *ucontrol)
724{
725 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
726 mutex_lock(&chip->mgr->mixer_mutex);
727 ucontrol->value.integer.value[0] = chip->mic_volume;
728 mutex_unlock(&chip->mgr->mixer_mutex);
729 return 0;
730}
731
732static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol,
733 struct snd_ctl_elem_value *ucontrol)
734{
735 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
736 int changed = 0;
737 mutex_lock(&chip->mgr->mixer_mutex);
738 if (chip->mic_volume != ucontrol->value.integer.value[0]) {
739 changed = 1;
740 chip->mic_volume = ucontrol->value.integer.value[0];
741 hr222_update_analog_audio_level(chip, 1, 0);
742 }
743 mutex_unlock(&chip->mgr->mixer_mutex);
744 return changed;
745}
746
747static struct snd_kcontrol_new hr222_control_mic_level = {
748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
749 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
750 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
751 .name = "Mic Capture Volume",
752 .info = hr222_mic_vol_info,
753 .get = hr222_mic_vol_get,
754 .put = hr222_mic_vol_put,
755 .tlv = { .p = db_scale_mic_hr222 },
756};
757
758
759
760static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400);
761
762static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol,
763 struct snd_ctl_elem_info *uinfo)
764{
765 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
766 uinfo->count = 1;
767 uinfo->value.integer.min = 0;
768 uinfo->value.integer.max = 3;
769 return 0;
770}
771
772static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol,
773 struct snd_ctl_elem_value *ucontrol)
774{
775 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
776 mutex_lock(&chip->mgr->mixer_mutex);
777 ucontrol->value.integer.value[0] = chip->mic_boost;
778 mutex_unlock(&chip->mgr->mixer_mutex);
779 return 0;
780}
781
782static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol,
783 struct snd_ctl_elem_value *ucontrol)
784{
785 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
786 int changed = 0;
787 mutex_lock(&chip->mgr->mixer_mutex);
788 if (chip->mic_boost != ucontrol->value.integer.value[0]) {
789 changed = 1;
790 chip->mic_boost = ucontrol->value.integer.value[0];
791 hr222_micro_boost(chip->mgr, chip->mic_boost);
792 }
793 mutex_unlock(&chip->mgr->mixer_mutex);
794 return changed;
795}
796
797static struct snd_kcontrol_new hr222_control_mic_boost = {
798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
799 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
800 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
801 .name = "MicBoost Capture Volume",
802 .info = hr222_mic_boost_info,
803 .get = hr222_mic_boost_get,
804 .put = hr222_mic_boost_put,
805 .tlv = { .p = db_scale_micboost_hr222 },
806};
807
808
809
810#define hr222_phantom_power_info snd_ctl_boolean_mono_info
811
812static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol,
813 struct snd_ctl_elem_value *ucontrol)
814{
815 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
816 mutex_lock(&chip->mgr->mixer_mutex);
817 ucontrol->value.integer.value[0] = chip->phantom_power;
818 mutex_unlock(&chip->mgr->mixer_mutex);
819 return 0;
820}
821
822static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol,
823 struct snd_ctl_elem_value *ucontrol)
824{
825 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
826 int power, changed = 0;
827
828 mutex_lock(&chip->mgr->mixer_mutex);
829 power = !!ucontrol->value.integer.value[0];
830 if (chip->phantom_power != power) {
831 hr222_phantom_power(chip->mgr, power);
832 chip->phantom_power = power;
833 changed = 1;
834 }
835 mutex_unlock(&chip->mgr->mixer_mutex);
836 return changed;
837}
838
839static struct snd_kcontrol_new hr222_phantom_power_switch = {
840 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
841 .name = "Phantom Power Switch",
842 .info = hr222_phantom_power_info,
843 .get = hr222_phantom_power_get,
844 .put = hr222_phantom_power_put,
845};
846
847
848int hr222_add_mic_controls(struct snd_pcxhr *chip)
849{
850 int err;
851 if (!chip->mgr->board_has_mic)
852 return 0;
853
854
855 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level,
856 chip));
857 if (err < 0)
858 return err;
859
860 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost,
861 chip));
862 if (err < 0)
863 return err;
864
865 err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch,
866 chip));
867 return err;
868}
869