Lines 1-10
Link Here
|
1 |
/* |
1 |
/* |
2 |
* HD audio interface patch for Conexant HDA audio codec |
2 |
* HD audio interface patch for Conexant HDA audio/modem codec |
3 |
* |
3 |
* |
4 |
* Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com> |
4 |
* Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com> |
5 |
* Takashi Iwai <tiwai@suse.de> |
5 |
* Takashi Iwai <tiwai@suse.de> |
6 |
* Tobin Davis <tdavis@dsl-only.net> |
6 |
* Tobin Davis <tdavis@dsl-only.net> |
7 |
* |
7 |
* |
|
|
8 |
* Copyright (c) 2005-2010 Linuxant inc. |
9 |
* |
8 |
* This driver is free software; you can redistribute it and/or modify |
10 |
* This driver is free software; you can redistribute it and/or modify |
9 |
* it under the terms of the GNU General Public License as published by |
11 |
* it under the terms of the GNU General Public License as published by |
10 |
* the Free Software Foundation; either version 2 of the License, or |
12 |
* the Free Software Foundation; either version 2 of the License, or |
Lines 53-58
Link Here
|
53 |
#define AUTO_MIC_PORTB (1 << 1) |
55 |
#define AUTO_MIC_PORTB (1 << 1) |
54 |
#define AUTO_MIC_PORTC (1 << 2) |
56 |
#define AUTO_MIC_PORTC (1 << 2) |
55 |
|
57 |
|
|
|
58 |
#if defined(__i386__) |
59 |
#define __shimcall__ __attribute__((regparm(0))) |
60 |
#else |
61 |
#define __shimcall__ |
62 |
#endif |
63 |
|
64 |
//#define CONFIG_SND_DEBUG |
65 |
|
56 |
struct pin_dac_pair { |
66 |
struct pin_dac_pair { |
57 |
hda_nid_t pin; |
67 |
hda_nid_t pin; |
58 |
hda_nid_t dac; |
68 |
hda_nid_t dac; |
Lines 118-124
Link Here
|
118 |
int num_channel_mode; |
128 |
int num_channel_mode; |
119 |
|
129 |
|
120 |
/* PCM information */ |
130 |
/* PCM information */ |
121 |
struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ |
131 |
struct hda_pcm pcm_rec[3]; /* used in build_pcms() */ |
122 |
|
132 |
|
123 |
unsigned int spdif_route; |
133 |
unsigned int spdif_route; |
124 |
|
134 |
|
Lines 164-169
Link Here
|
164 |
|
174 |
|
165 |
unsigned int beep_amp; |
175 |
unsigned int beep_amp; |
166 |
|
176 |
|
|
|
177 |
/* HSF modem */ |
178 |
void *modem_devnode; |
179 |
unsigned int modem_stream_tags[2]; |
180 |
int modem_do_prepare[2]; |
181 |
void (*modem_cbHdaEvent)(void *Context, unsigned int res) __shimcall__; |
182 |
void *modem_cbHdaEventContext; |
183 |
unsigned char modem_cbHdaTag; |
184 |
|
167 |
/* extra EAPD pins */ |
185 |
/* extra EAPD pins */ |
168 |
unsigned int num_eapds; |
186 |
unsigned int num_eapds; |
169 |
hda_nid_t eapds[4]; |
187 |
hda_nid_t eapds[4]; |
Lines 257-263
Link Here
|
257 |
return 0; |
275 |
return 0; |
258 |
} |
276 |
} |
259 |
|
277 |
|
|
|
278 |
#if defined(__i386__) |
279 |
#define __shimcall__ __attribute__((regparm(0))) |
280 |
#else |
281 |
#define __shimcall__ |
282 |
#endif |
283 |
|
284 |
//#define CONFIG_SND_DEBUG |
285 |
static int conexant_modem_pcm_prepare(struct hda_pcm_stream *hinfo, |
286 |
struct hda_codec *codec, |
287 |
unsigned int stream_tag, |
288 |
unsigned int format, |
289 |
struct snd_pcm_substream *substream) |
290 |
{ |
291 |
struct conexant_spec *spec = codec->spec; |
292 |
|
293 |
//printk(KERN_DEBUG"%s: codec=%p stream=%d stream_tag=%x format=0x%x substream=%p\n", __FUNCTION__, codec, substream->stream, stream_tag, format, substream); |
294 |
|
295 |
spec->modem_stream_tags[substream->stream] = stream_tag; |
296 |
|
297 |
return 0; |
298 |
} |
299 |
|
300 |
static int conexant_modem_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, |
301 |
struct snd_pcm_substream *substream) |
302 |
{ |
303 |
static unsigned int rates[] = { 16000 }; |
304 |
static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
305 |
.count = ARRAY_SIZE(rates), |
306 |
.list = rates, |
307 |
.mask = 0, |
308 |
}; |
309 |
|
310 |
//printk(KERN_DEBUG"%s: codec=%p substream=%p\n", __FUNCTION__, codec, substream); |
260 |
|
311 |
|
|
|
312 |
return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); |
313 |
} |
261 |
|
314 |
|
262 |
static const struct hda_pcm_stream conexant_pcm_analog_playback = { |
315 |
static const struct hda_pcm_stream conexant_pcm_analog_playback = { |
263 |
.substreams = 1, |
316 |
.substreams = 1, |
Lines 337-374
Link Here
|
337 |
}, |
390 |
}, |
338 |
}; |
391 |
}; |
339 |
|
392 |
|
|
|
393 |
static struct hda_pcm_stream conexant_modem_pcm = { |
394 |
.substreams = 1, |
395 |
.channels_min = 1, |
396 |
.channels_max = 1, |
397 |
.nid = 0x1, |
398 |
.rates = SNDRV_PCM_RATE_16000, |
399 |
.formats = SNDRV_PCM_FMTBIT_S16_LE, |
400 |
.maxbps = 16, |
401 |
.ops = { |
402 |
.open = conexant_modem_pcm_open, |
403 |
.prepare = conexant_modem_pcm_prepare, |
404 |
}, |
405 |
}; |
406 |
|
340 |
static int conexant_build_pcms(struct hda_codec *codec) |
407 |
static int conexant_build_pcms(struct hda_codec *codec) |
341 |
{ |
408 |
{ |
342 |
struct conexant_spec *spec = codec->spec; |
409 |
struct conexant_spec *spec = codec->spec; |
343 |
struct hda_pcm *info = spec->pcm_rec; |
410 |
struct hda_pcm *info = spec->pcm_rec; |
344 |
|
411 |
|
345 |
codec->num_pcms = 1; |
412 |
codec->num_pcms = 0; |
346 |
codec->pcm_info = info; |
413 |
codec->pcm_info = info; |
347 |
|
414 |
|
348 |
info->name = "CONEXANT Analog"; |
415 |
if (codec->afg) { |
349 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; |
416 |
info->name = "CONEXANT Analog"; |
350 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = |
417 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; |
351 |
spec->multiout.max_channels; |
418 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = |
352 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = |
419 |
spec->multiout.max_channels; |
353 |
spec->multiout.dac_nids[0]; |
420 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = |
354 |
if (spec->capture_stream) |
421 |
spec->multiout.dac_nids[0]; |
355 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; |
422 |
if (codec->vendor_id == 0x14f15051) |
356 |
else { |
423 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
357 |
if (codec->vendor_id == 0x14f15051) |
424 |
cx5051_pcm_analog_capture; |
358 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
425 |
else |
359 |
cx5051_pcm_analog_capture; |
426 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
360 |
else { |
427 |
conexant_pcm_analog_capture; |
361 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
428 |
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; |
362 |
conexant_pcm_analog_capture; |
429 |
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; |
363 |
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = |
|
|
364 |
spec->num_adc_nids; |
365 |
} |
366 |
} |
367 |
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; |
368 |
|
369 |
if (spec->multiout.dig_out_nid) { |
370 |
info++; |
430 |
info++; |
371 |
codec->num_pcms++; |
431 |
codec->num_pcms++; |
|
|
432 |
} |
433 |
|
434 |
if (spec->multiout.dig_out_nid) { |
372 |
info->name = "Conexant Digital"; |
435 |
info->name = "Conexant Digital"; |
373 |
info->pcm_type = HDA_PCM_TYPE_SPDIF; |
436 |
info->pcm_type = HDA_PCM_TYPE_SPDIF; |
374 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = |
437 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = |
Lines 383-388
Link Here
|
383 |
} |
446 |
} |
384 |
if (spec->slave_dig_outs[0]) |
447 |
if (spec->slave_dig_outs[0]) |
385 |
codec->slave_dig_outs = spec->slave_dig_outs; |
448 |
codec->slave_dig_outs = spec->slave_dig_outs; |
|
|
449 |
|
450 |
info++; |
451 |
codec->num_pcms++; |
452 |
} |
453 |
|
454 |
if (codec->mfg) { |
455 |
conexant_modem_pcm.nid = codec->mfg; |
456 |
|
457 |
info->name = "Conexant HSF Modem"; |
458 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_modem_pcm; |
459 |
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = conexant_modem_pcm.nid; |
460 |
info->stream[SNDRV_PCM_STREAM_CAPTURE] = conexant_modem_pcm; |
461 |
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = conexant_modem_pcm.nid; |
462 |
info->pcm_type = HDA_PCM_TYPE_MODEM; |
463 |
|
464 |
info++; |
465 |
codec->num_pcms++; |
386 |
} |
466 |
} |
387 |
|
467 |
|
388 |
return 0; |
468 |
return 0; |
Lines 433-448
Link Here
|
433 |
snd_hda_codec_set_power_to_all(codec, fg, power_state, true); |
513 |
snd_hda_codec_set_power_to_all(codec, fg, power_state, true); |
434 |
} |
514 |
} |
435 |
|
515 |
|
|
|
516 |
static void *conexant_hsfmodem_interface_funcs[]; |
517 |
|
436 |
static int conexant_init(struct hda_codec *codec) |
518 |
static int conexant_init(struct hda_codec *codec) |
437 |
{ |
519 |
{ |
438 |
struct conexant_spec *spec = codec->spec; |
520 |
struct conexant_spec *spec = codec->spec; |
439 |
int i; |
521 |
int i, ret; |
|
|
522 |
|
523 |
//printk(KERN_DEBUG"%s: codec=%p\n", __FUNCTION__, codec); |
524 |
if(codec->mfg) { |
525 |
int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode, void **ppInterfaceFuncs); |
526 |
|
527 |
//snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); |
528 |
|
529 |
cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe); |
530 |
if(!cnxthwhda_probe) { |
531 |
printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__); |
532 |
if(!codec->afg) |
533 |
return -ENOENT; |
534 |
} else { |
535 |
ret = cnxthwhda_probe(codec, codec->bus->card->dev, &spec->modem_devnode, conexant_hsfmodem_interface_funcs); |
536 |
if(ret) { |
537 |
printk(KERN_ERR"%s: cnxthwhda_probe() failed: %d\n", __FUNCTION__, ret); |
538 |
symbol_put(cnxthwhda_probe); |
539 |
if(!codec->afg) |
540 |
return ret; |
541 |
} |
542 |
} |
543 |
} |
440 |
|
544 |
|
441 |
for (i = 0; i < spec->num_init_verbs; i++) |
545 |
for (i = 0; i < spec->num_init_verbs; i++) |
442 |
snd_hda_sequence_write(codec, spec->init_verbs[i]); |
546 |
snd_hda_sequence_write(codec, spec->init_verbs[i]); |
443 |
return 0; |
547 |
return 0; |
444 |
} |
548 |
} |
445 |
|
549 |
|
|
|
550 |
static int conexant_exit(struct hda_codec *codec) |
551 |
{ |
552 |
struct conexant_spec *spec = codec->spec; |
553 |
|
554 |
//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec); |
555 |
|
556 |
if(codec->mfg && spec && spec->modem_devnode) { |
557 |
void (*cnxthwhda_remove)(void *ptr); |
558 |
|
559 |
cnxthwhda_remove = (void*)symbol_request(cnxthwhda_remove); |
560 |
if(cnxthwhda_remove) { |
561 |
cnxthwhda_remove(spec->modem_devnode); |
562 |
spec->modem_devnode = NULL; |
563 |
symbol_put(cnxthwhda_remove); |
564 |
symbol_put(cnxthwhda_probe); |
565 |
} else { |
566 |
printk(KERN_ERR"%s: symbol_request(cnxthwhda_remove) failed\n", __FUNCTION__); |
567 |
} |
568 |
} |
569 |
|
570 |
return 0; |
571 |
} |
572 |
|
446 |
static void conexant_free(struct hda_codec *codec) |
573 |
static void conexant_free(struct hda_codec *codec) |
447 |
{ |
574 |
{ |
448 |
struct conexant_spec *spec = codec->spec; |
575 |
struct conexant_spec *spec = codec->spec; |
Lines 451-456
Link Here
|
451 |
kfree(spec); |
578 |
kfree(spec); |
452 |
} |
579 |
} |
453 |
|
580 |
|
|
|
581 |
static void conexant_unsol_event(struct hda_codec *codec, unsigned int res) |
582 |
{ |
583 |
struct conexant_spec *spec = codec->spec; |
584 |
|
585 |
//printk(KERN_DEBUG"%s: codec=%p res=0x%02x spec=%p cbHdaEvent=%p\n", __FUNCTION__, codec, res, spec, spec->modem_cbHdaEvent); |
586 |
|
587 |
if(codec->mfg && spec && spec->modem_cbHdaEvent) { |
588 |
if(((res >> 26) & 0x3f) == spec->modem_cbHdaTag) { |
589 |
//printk(KERN_DEBUG"%s: res=0x%02x cbHdaEvent=%p\n", __FUNCTION__, res, spec->modem_bHdaEvent); |
590 |
//printk(KERN_DEBUG"%s: calling cbHdaEvent=%p ctx=%p\n", __FUNCTION__, spec->modem_cHdaEvent, spec->modem_cbHdaEventContext); |
591 |
spec->modem_cbHdaEvent(spec->modem_cbHdaEventContext, res); |
592 |
} else { |
593 |
printk(KERN_DEBUG"%s: ignoring res=0x08%x\n", __FUNCTION__, res); |
594 |
} |
595 |
} |
596 |
} |
597 |
|
598 |
typedef struct tagHDAOSHAL { |
599 |
void *hda_codec; |
600 |
int bInSuspendResume; |
601 |
} HDAOSHAL, *PHDAOSHAL; |
602 |
|
603 |
typedef struct tagOS_DEVNODE { |
604 |
void *hwDev; |
605 |
// intentionally left incomplete |
606 |
} OS_DEVNODE, *POS_DEVNODE; |
607 |
|
608 |
#ifdef CONFIG_PM |
609 |
static int conexant_suspend(struct hda_codec *codec, pm_message_t state) |
610 |
{ |
611 |
struct conexant_spec *spec = codec->spec; |
612 |
int (*cnxthwhda_suspend)(void *devnode, pm_message_t state); |
613 |
int ret = 0; |
614 |
|
615 |
//printk(KERN_DEBUG"%s: codec=%p spec=%p state=0x%x\n", __FUNCTION__, codec, spec, *((u32 *)&state)); |
616 |
|
617 |
if(spec && spec->modem_devnode) { |
618 |
cnxthwhda_suspend = (void*)symbol_request(cnxthwhda_suspend); |
619 |
if(!cnxthwhda_suspend) { |
620 |
printk(KERN_ERR"%s: symbol_request(cnxthwhda_suspend) failed\n", __FUNCTION__); |
621 |
return -ENOSYS; |
622 |
} |
623 |
|
624 |
if(((POS_DEVNODE)spec->modem_devnode)->hwDev) { |
625 |
((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume++; |
626 |
} |
627 |
ret = cnxthwhda_suspend(spec->modem_devnode, state); |
628 |
if(((POS_DEVNODE)spec->modem_devnode)->hwDev) { |
629 |
((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume--; |
630 |
} |
631 |
symbol_put(cnxthwhda_suspend); |
632 |
} |
633 |
|
634 |
return ret; |
635 |
} |
636 |
|
637 |
static int conexant_resume(struct hda_codec *codec) |
638 |
{ |
639 |
struct conexant_spec *spec = codec->spec; |
640 |
int ret = 0; |
641 |
hda_nid_t mfg; |
642 |
|
643 |
mfg = codec->mfg; |
644 |
codec->mfg = 0; |
645 |
codec->patch_ops.init(codec); |
646 |
codec->mfg = mfg; |
647 |
|
648 |
snd_hda_codec_resume_amp(codec); |
649 |
snd_hda_codec_resume_cache(codec); |
650 |
|
651 |
if(spec && spec->modem_devnode) { |
652 |
int (*cnxthwhda_resume)(void *devnode); |
653 |
|
654 |
//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec); |
655 |
|
656 |
cnxthwhda_resume = (void*)symbol_request(cnxthwhda_resume); |
657 |
if(!cnxthwhda_resume) { |
658 |
printk(KERN_ERR"%s: symbol_request(cnxthwhda_resume) failed\n", __FUNCTION__); |
659 |
return -ENOSYS; |
660 |
} |
661 |
|
662 |
//snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); |
663 |
|
664 |
if(((POS_DEVNODE)spec->modem_devnode)->hwDev) { |
665 |
((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume++; |
666 |
} |
667 |
|
668 |
ret = cnxthwhda_resume(spec->modem_devnode); |
669 |
|
670 |
if(((POS_DEVNODE)spec->modem_devnode)->hwDev) { |
671 |
((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume--; |
672 |
} |
673 |
|
674 |
symbol_put(cnxthwhda_resume); |
675 |
} |
676 |
|
677 |
return ret; |
678 |
} |
679 |
#endif |
680 |
|
454 |
static const struct snd_kcontrol_new cxt_capture_mixers[] = { |
681 |
static const struct snd_kcontrol_new cxt_capture_mixers[] = { |
455 |
{ |
682 |
{ |
456 |
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
683 |
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
Lines 565-571
Link Here
|
565 |
.build_controls = conexant_build_controls, |
792 |
.build_controls = conexant_build_controls, |
566 |
.build_pcms = conexant_build_pcms, |
793 |
.build_pcms = conexant_build_pcms, |
567 |
.init = conexant_init, |
794 |
.init = conexant_init, |
|
|
795 |
.exit = conexant_exit, |
568 |
.free = conexant_free, |
796 |
.free = conexant_free, |
|
|
797 |
.unsol_event = conexant_unsol_event, |
798 |
#ifdef CONFIG_PM |
799 |
.suspend = conexant_suspend, |
800 |
.resume = conexant_resume, |
801 |
#endif |
569 |
.set_power_state = conexant_set_power, |
802 |
.set_power_state = conexant_set_power, |
570 |
#ifdef CONFIG_SND_HDA_POWER_SAVE |
803 |
#ifdef CONFIG_SND_HDA_POWER_SAVE |
571 |
.suspend = conexant_suspend, |
804 |
.suspend = conexant_suspend, |
Lines 581-586
Link Here
|
581 |
#endif |
814 |
#endif |
582 |
|
815 |
|
583 |
static int patch_conexant_auto(struct hda_codec *codec); |
816 |
static int patch_conexant_auto(struct hda_codec *codec); |
|
|
817 |
|
818 |
static int patch_cxthsfmodem(struct hda_codec *codec) |
819 |
{ |
820 |
struct conexant_spec *spec; |
821 |
int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode); |
822 |
|
823 |
//printk(KERN_DEBUG"%s: codec=%p\n", __FUNCTION__, codec); |
824 |
if(!codec->mfg) { // we only support modems here |
825 |
return -ENODEV; |
826 |
} |
827 |
|
828 |
spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
829 |
if (!spec) |
830 |
return -ENOMEM; |
831 |
codec->spec = spec; |
832 |
|
833 |
codec->patch_ops = conexant_patch_ops; |
834 |
|
835 |
cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe); |
836 |
if(cnxthwhda_probe) { |
837 |
symbol_put(cnxthwhda_probe); |
838 |
} else { |
839 |
printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__); |
840 |
codec->spec = NULL; |
841 |
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); |
842 |
kfree(spec); |
843 |
return -ENOSYS; |
844 |
} |
845 |
|
846 |
return 0; |
847 |
} |
848 |
|
584 |
/* |
849 |
/* |
585 |
* EAPD control |
850 |
* EAPD control |
586 |
* the private value = nid | (invert << 8) |
851 |
* the private value = nid | (invert << 8) |
Lines 752-764
Link Here
|
752 |
static void cxt5045_hp_automic(struct hda_codec *codec) |
1017 |
static void cxt5045_hp_automic(struct hda_codec *codec) |
753 |
{ |
1018 |
{ |
754 |
static const struct hda_verb mic_jack_on[] = { |
1019 |
static const struct hda_verb mic_jack_on[] = { |
755 |
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
1020 |
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | AC_AMP_MUTE}, |
756 |
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1021 |
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT}, |
|
|
1022 |
{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, |
757 |
{} |
1023 |
{} |
758 |
}; |
1024 |
}; |
759 |
static const struct hda_verb mic_jack_off[] = { |
1025 |
static const struct hda_verb mic_jack_off[] = { |
760 |
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
1026 |
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | AC_AMP_MUTE}, |
761 |
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1027 |
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT}, |
|
|
1028 |
{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, |
762 |
{} |
1029 |
{} |
763 |
}; |
1030 |
}; |
764 |
unsigned int present; |
1031 |
unsigned int present; |
Lines 788-802
Link Here
|
788 |
static void cxt5045_hp_unsol_event(struct hda_codec *codec, |
1055 |
static void cxt5045_hp_unsol_event(struct hda_codec *codec, |
789 |
unsigned int res) |
1056 |
unsigned int res) |
790 |
{ |
1057 |
{ |
791 |
res >>= 26; |
1058 |
switch (res >> 26) { |
792 |
switch (res) { |
|
|
793 |
case CONEXANT_HP_EVENT: |
1059 |
case CONEXANT_HP_EVENT: |
|
|
1060 |
//printk("%s: CONEXANT_HP_EVENT\n", __FUNCTION__); |
794 |
cxt5045_hp_automute(codec); |
1061 |
cxt5045_hp_automute(codec); |
795 |
break; |
1062 |
break; |
796 |
case CONEXANT_MIC_EVENT: |
1063 |
case CONEXANT_MIC_EVENT: |
|
|
1064 |
//printk("%s: CONEXANT_MIC_EVENT\n", __FUNCTION__); |
797 |
cxt5045_hp_automic(codec); |
1065 |
cxt5045_hp_automic(codec); |
798 |
break; |
1066 |
break; |
799 |
|
1067 |
default: |
|
|
1068 |
//printk("%s: CONEXANT_OTHER_EVENT\n", __FUNCTION__); |
1069 |
conexant_unsol_event(codec, res); |
1070 |
break; |
800 |
} |
1071 |
} |
801 |
} |
1072 |
} |
802 |
|
1073 |
|
Lines 1184-1189
Link Here
|
1184 |
if (spec->beep_amp) |
1455 |
if (spec->beep_amp) |
1185 |
snd_hda_attach_beep_device(codec, spec->beep_amp); |
1456 |
snd_hda_attach_beep_device(codec, spec->beep_amp); |
1186 |
|
1457 |
|
|
|
1458 |
if(codec->mfg) { |
1459 |
int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode); |
1460 |
cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe); |
1461 |
if(cnxthwhda_probe) |
1462 |
symbol_put(cnxthwhda_probe); |
1463 |
else |
1464 |
printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__); |
1465 |
} |
1466 |
|
1187 |
return 0; |
1467 |
return 0; |
1188 |
} |
1468 |
} |
1189 |
|
1469 |
|
Lines 1222-1228
Link Here
|
1222 |
* the headphone jack |
1502 |
* the headphone jack |
1223 |
*/ |
1503 |
*/ |
1224 |
bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
1504 |
bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
1225 |
/* NOTE: Conexat codec needs the index for *OUTPUT* amp of |
1505 |
/* NOTE: Conexant codec needs the index for *OUTPUT* amp of |
1226 |
* pin widgets unlike other codecs. In this case, we need to |
1506 |
* pin widgets unlike other codecs. In this case, we need to |
1227 |
* set index 0x01 for the volume from the mixer amp 0x19. |
1507 |
* set index 0x01 for the volume from the mixer amp 0x19. |
1228 |
*/ |
1508 |
*/ |
Lines 1573-1578
Link Here
|
1573 |
codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1853 |
codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1574 |
#endif |
1854 |
#endif |
1575 |
} |
1855 |
} |
|
|
1856 |
|
1857 |
if(codec->mfg) { |
1858 |
int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode); |
1859 |
cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe); |
1860 |
if(cnxthwhda_probe) |
1861 |
symbol_put(cnxthwhda_probe); |
1862 |
else |
1863 |
printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__); |
1864 |
} |
1865 |
|
1576 |
spec->vmaster_nid = 0x13; |
1866 |
spec->vmaster_nid = 0x13; |
1577 |
|
1867 |
|
1578 |
switch (codec->subsystem_id >> 16) { |
1868 |
switch (codec->subsystem_id >> 16) { |
Lines 1689-1694
Link Here
|
1689 |
case CXT5051_PORTC_EVENT: |
1979 |
case CXT5051_PORTC_EVENT: |
1690 |
cxt5051_portc_automic(codec); |
1980 |
cxt5051_portc_automic(codec); |
1691 |
break; |
1981 |
break; |
|
|
1982 |
default: |
1983 |
conexant_unsol_event(codec, res); |
1984 |
break; |
1692 |
} |
1985 |
} |
1693 |
} |
1986 |
} |
1694 |
|
1987 |
|
Lines 1963-1968
Link Here
|
1963 |
if (spec->beep_amp) |
2256 |
if (spec->beep_amp) |
1964 |
snd_hda_attach_beep_device(codec, spec->beep_amp); |
2257 |
snd_hda_attach_beep_device(codec, spec->beep_amp); |
1965 |
|
2258 |
|
|
|
2259 |
if(codec->mfg) { |
2260 |
int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode); |
2261 |
cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe); |
2262 |
if(cnxthwhda_probe) |
2263 |
symbol_put(cnxthwhda_probe); |
2264 |
else |
2265 |
printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__); |
2266 |
} |
2267 |
|
1966 |
return 0; |
2268 |
return 0; |
1967 |
} |
2269 |
} |
1968 |
|
2270 |
|
Lines 4562-4567
Link Here
|
4562 |
/* |
4864 |
/* |
4563 |
*/ |
4865 |
*/ |
4564 |
|
4866 |
|
|
|
4867 |
typedef enum { |
4868 |
OsHdaStreamStateReset = 0, |
4869 |
OsHdaStreamStateStop = 1, |
4870 |
OsHdaStreamStateRun = 2 |
4871 |
} OSHDA_STREAM_STATE; |
4872 |
|
4873 |
static __shimcall__ |
4874 |
unsigned int conexant_hsfmodem_OsHdaCodecGetAddr(PHDAOSHAL pHdaOsHal) |
4875 |
{ |
4876 |
return ((struct hda_codec *)pHdaOsHal->hda_codec)->addr; |
4877 |
} |
4878 |
|
4879 |
static __shimcall__ |
4880 |
unsigned int conexant_hsfmodem_OsHdaCodecGetVendorId(PHDAOSHAL pHdaOsHal) |
4881 |
{ |
4882 |
return ((struct hda_codec *)pHdaOsHal->hda_codec)->vendor_id; |
4883 |
} |
4884 |
|
4885 |
static __shimcall__ |
4886 |
unsigned int conexant_hsfmodem_OsHdaCodecGetSubsystemId(PHDAOSHAL pHdaOsHal) |
4887 |
{ |
4888 |
return ((struct hda_codec *)pHdaOsHal->hda_codec)->subsystem_id; |
4889 |
} |
4890 |
|
4891 |
static __shimcall__ |
4892 |
unsigned int conexant_hsfmodem_OsHdaCodecGetRevisionId(PHDAOSHAL pHdaOsHal) |
4893 |
{ |
4894 |
return ((struct hda_codec *)pHdaOsHal->hda_codec)->revision_id; |
4895 |
} |
4896 |
|
4897 |
static __shimcall__ |
4898 |
unsigned int conexant_hsfmodem_OsHdaCodecRead(PHDAOSHAL pHdaOsHal, unsigned short nid, int direct, unsigned int verb, unsigned int para) |
4899 |
{ |
4900 |
#if 1 |
4901 |
return snd_hda_codec_read((struct hda_codec *)pHdaOsHal->hda_codec, nid, direct, verb, para); |
4902 |
#else |
4903 |
unsigned int res; |
4904 |
|
4905 |
res = snd_hda_codec_read((struct hda_codec *)pHdaOsHal->hda_codec, nid, direct, verb, para); |
4906 |
|
4907 |
printk(KERN_DEBUG"%s: nid=%x direct=%d verb=0x%x para=0x%x res=0x%08x\n", __FUNCTION__, nid, direct, verb, para, res); |
4908 |
|
4909 |
return res; |
4910 |
#endif |
4911 |
} |
4912 |
|
4913 |
static __shimcall__ |
4914 |
unsigned int conexant_hsfmodem_OsHdaCodecWallclock(PHDAOSHAL pHdaOsHal) |
4915 |
{ |
4916 |
return snd_hda_codec_wallclock((struct hda_codec *)pHdaOsHal->hda_codec); |
4917 |
} |
4918 |
|
4919 |
static __shimcall__ |
4920 |
void conexant_hsfmodem_OsHdaCodecSetEventCallback(PHDAOSHAL pHdaOsHal, void (*cbHdaEvent)(void *Context, unsigned int res), void *cbHdaEventContext, unsigned char *cbHdaTag) |
4921 |
{ |
4922 |
struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec; |
4923 |
|
4924 |
*cbHdaTag = ((struct hda_codec *)pHdaOsHal->hda_codec)->mfg; |
4925 |
|
4926 |
spec->modem_cbHdaTag = *cbHdaTag; |
4927 |
spec->modem_cbHdaEventContext = cbHdaEventContext; |
4928 |
spec->modem_cbHdaEvent = (void*)cbHdaEvent; |
4929 |
} |
4930 |
|
4931 |
static __shimcall__ |
4932 |
void conexant_hsfmodem_OsHdaCodecClearEventCallback(PHDAOSHAL pHdaOsHal, unsigned char cbHdaTag) |
4933 |
{ |
4934 |
struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec; |
4935 |
|
4936 |
if(spec) { |
4937 |
spec->modem_cbHdaEvent = NULL; |
4938 |
spec->modem_cbHdaEventContext = NULL; |
4939 |
spec->modem_cbHdaTag = 0; |
4940 |
} |
4941 |
} |
4942 |
|
4943 |
#include <sound/pcm_params.h> |
4944 |
|
4945 |
static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) |
4946 |
{ |
4947 |
struct snd_interval t; |
4948 |
t.empty = 0; |
4949 |
t.min = t.max = val; |
4950 |
t.openmin = t.openmax = 0; |
4951 |
t.integer = 1; |
4952 |
return snd_interval_refine(i, &t); |
4953 |
} |
4954 |
|
4955 |
static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, |
4956 |
snd_pcm_hw_param_t var, unsigned int val, |
4957 |
int dir) |
4958 |
{ |
4959 |
int changed; |
4960 |
if (hw_is_mask(var)) { |
4961 |
struct snd_mask *m = hw_param_mask(params, var); |
4962 |
if (val == 0 && dir < 0) { |
4963 |
changed = -EINVAL; |
4964 |
snd_mask_none(m); |
4965 |
} else { |
4966 |
if (dir > 0) |
4967 |
val++; |
4968 |
else if (dir < 0) |
4969 |
val--; |
4970 |
changed = snd_mask_refine_set(hw_param_mask(params, var), val); |
4971 |
} |
4972 |
} else if (hw_is_interval(var)) { |
4973 |
struct snd_interval *i = hw_param_interval(params, var); |
4974 |
if (val == 0 && dir < 0) { |
4975 |
changed = -EINVAL; |
4976 |
snd_interval_none(i); |
4977 |
} else if (dir == 0) |
4978 |
changed = snd_interval_refine_set(i, val); |
4979 |
else { |
4980 |
struct snd_interval t; |
4981 |
t.openmin = 1; |
4982 |
t.openmax = 1; |
4983 |
t.empty = 0; |
4984 |
t.integer = 0; |
4985 |
if (dir < 0) { |
4986 |
t.min = val - 1; |
4987 |
t.max = val; |
4988 |
} else { |
4989 |
t.min = val; |
4990 |
t.max = val+1; |
4991 |
} |
4992 |
changed = snd_interval_refine(i, &t); |
4993 |
} |
4994 |
} else |
4995 |
return -EINVAL; |
4996 |
if (changed) { |
4997 |
params->cmask |= 1 << var; |
4998 |
params->rmask |= 1 << var; |
4999 |
} |
5000 |
return changed; |
5001 |
} |
5002 |
|
5003 |
static int conexant_modem_snd_pcm_change_params(struct snd_pcm_substream *substream, int hw_param_buffer_bytes) |
5004 |
{ |
5005 |
struct snd_pcm_hw_params *sparams; |
5006 |
int err; |
5007 |
|
5008 |
sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); |
5009 |
if (/*!params ||*/ !sparams) { |
5010 |
return -ENOMEM; |
5011 |
} |
5012 |
|
5013 |
_snd_pcm_hw_params_any(sparams); |
5014 |
_snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
5015 |
hw_param_buffer_bytes, 0); |
5016 |
|
5017 |
snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
5018 |
|
5019 |
if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) { |
5020 |
printk(KERN_ERR"%s: SNDRV_PCM_IOCTL_HW_PARAMS failed (%d)\n", __FUNCTION__, err); |
5021 |
//return err; |
5022 |
} |
5023 |
|
5024 |
return 0; |
5025 |
} |
5026 |
|
5027 |
static int conexant_modem_snd_pcm_prepare_substream(PHDAOSHAL pHdaOsHal, struct snd_pcm_substream *substream) |
5028 |
{ |
5029 |
int err; |
5030 |
struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec; |
5031 |
|
5032 |
if(spec->modem_do_prepare[substream->stream]) { |
5033 |
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); |
5034 |
if (err < 0) { |
5035 |
printk(KERN_ERR"%s: SNDRV_PCM_IOCTL_PREPARE failed (%d)\n", __FUNCTION__, err); |
5036 |
return err; |
5037 |
} |
5038 |
spec->modem_do_prepare[substream->stream] = 0; |
5039 |
} |
5040 |
|
5041 |
return 0; |
5042 |
} |
5043 |
|
5044 |
static __shimcall__ |
5045 |
int conexant_hsfmodem_OsHdaCodecOpenDMA(PHDAOSHAL pHdaOsHal, int hw_param_buffer_bytes, void **ppPlaybackStream, void **ppCaptureStream) |
5046 |
{ |
5047 |
int i, err; |
5048 |
struct hda_codec *codec = (struct hda_codec *)pHdaOsHal->hda_codec; |
5049 |
struct hda_pcm *info = codec->pcm_info; |
5050 |
struct snd_pcm *pcm; |
5051 |
struct conexant_spec *spec = codec->spec; |
5052 |
|
5053 |
struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; |
5054 |
static struct file fil; |
5055 |
|
5056 |
for(i = 0; i < codec->num_pcms && info[i].pcm_type != HDA_PCM_TYPE_MODEM; i++); |
5057 |
if(i == codec->num_pcms) { |
5058 |
printk(KERN_ERR"%s: modem pcm not found\n", __FUNCTION__); |
5059 |
return -ENOENT; |
5060 |
} |
5061 |
pcm = info[i].pcm; |
5062 |
|
5063 |
if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, &fil, &psubstream)) < 0) { |
5064 |
printk(KERN_ERR"%s: snd_pcm_open_substream STREAM_PLAYBACK failed (%d)\n", __FUNCTION__, err); |
5065 |
return err; |
5066 |
} |
5067 |
|
5068 |
if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, &fil, &csubstream)) < 0) { |
5069 |
printk(KERN_ERR"%s: snd_pcm_open_substream STREAM_CAPTURE failed (%d)\n", __FUNCTION__, err); |
5070 |
return err; |
5071 |
} |
5072 |
|
5073 |
err = conexant_modem_snd_pcm_change_params(psubstream, hw_param_buffer_bytes); |
5074 |
if (err < 0) { |
5075 |
printk(KERN_ERR"%s: conexant_modem_snd_pcm_change_params STREAM_PLAYBACK failed (%d)\n", __FUNCTION__, err); |
5076 |
} |
5077 |
|
5078 |
err = conexant_modem_snd_pcm_change_params(csubstream, hw_param_buffer_bytes); |
5079 |
if (err < 0) { |
5080 |
printk(KERN_ERR"%s: conexant_modem_snd_pcm_change_params STREAM_CAPTURE failed (%d)\n", __FUNCTION__, err); |
5081 |
} |
5082 |
|
5083 |
#if 0 |
5084 |
printk(KERN_DEBUG"%s: psubstream=%p dma_buffer_p=%p area=%p addr=0x%lx bytes=%d\n", __FUNCTION__, |
5085 |
psubstream, |
5086 |
psubstream->runtime->dma_buffer_p, |
5087 |
psubstream->runtime->dma_area, |
5088 |
(unsigned long)psubstream->runtime->dma_addr, |
5089 |
psubstream->runtime->dma_bytes); |
5090 |
|
5091 |
printk(KERN_DEBUG"%s: csubstream=%p dma_buffer_p=%p area=%p addr=0x%lx bytes=%d\n", __FUNCTION__, |
5092 |
csubstream, |
5093 |
csubstream->runtime->dma_buffer_p, |
5094 |
csubstream->runtime->dma_area, |
5095 |
(unsigned long)csubstream->runtime->dma_addr, |
5096 |
csubstream->runtime->dma_bytes); |
5097 |
#endif |
5098 |
|
5099 |
spec->modem_do_prepare[psubstream->stream] = 1; |
5100 |
spec->modem_do_prepare[csubstream->stream] = 1; |
5101 |
|
5102 |
if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, psubstream)) < 0) |
5103 |
return err; |
5104 |
|
5105 |
if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, csubstream)) < 0) |
5106 |
return err; |
5107 |
|
5108 |
*ppPlaybackStream = psubstream; |
5109 |
*ppCaptureStream = csubstream; |
5110 |
|
5111 |
return 0; |
5112 |
} |
5113 |
|
5114 |
static void conexant_modem_snd_pcm_close_stream(struct snd_pcm_substream *substream) |
5115 |
{ |
5116 |
#if SNDRV_PCM_VERSION <= SNDRV_PROTOCOL_VERSION(2, 0, 7) |
5117 |
snd_pcm_stream_lock_irq(substream); |
5118 |
if (snd_pcm_running(substream)) |
5119 |
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); |
5120 |
snd_pcm_stream_unlock_irq(substream); |
5121 |
|
5122 |
if (substream->ops->hw_free != NULL) |
5123 |
substream->ops->hw_free(substream); |
5124 |
|
5125 |
substream->ops->close(substream); |
5126 |
#endif |
5127 |
//printk(KERN_DEBUG"%s: substream=%p refcount=%d\n", __FUNCTION__, substream, substream->ref_count); |
5128 |
snd_pcm_release_substream(substream); |
5129 |
} |
5130 |
|
5131 |
static __shimcall__ |
5132 |
void conexant_hsfmodem_OsHdaCodecCloseDMA(PHDAOSHAL pHdaOsHal, void *pPlaybackStream, void *pCaptureStream) |
5133 |
{ |
5134 |
//printk(KERN_DEBUG"%s: pHdaOsHal=%p pPlaybackStream=%p pCaptureStream=%p\n", __FUNCTION__, pHdaOsHal, pPlaybackStream, pCaptureStream); |
5135 |
if(pHdaOsHal) { |
5136 |
if(pPlaybackStream) |
5137 |
conexant_modem_snd_pcm_close_stream(pPlaybackStream); |
5138 |
if(pCaptureStream) |
5139 |
conexant_modem_snd_pcm_close_stream(pCaptureStream); |
5140 |
} |
5141 |
} |
5142 |
|
5143 |
static __shimcall__ |
5144 |
void conexant_hsfmodem_OsHdaCodecDMAInfo(PHDAOSHAL pHdaOsHal, void *Stream, unsigned char *StreamID, unsigned long *FifoSize, short unsigned int **ppBufAddr) |
5145 |
{ |
5146 |
struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec; |
5147 |
struct snd_pcm_substream *substream = (struct snd_pcm_substream *)Stream; |
5148 |
|
5149 |
#if 0 |
5150 |
printk(KERN_DEBUG"%s: substream=%p stream=%u id/tag=%u fifo_size=%u bufAddr=%p\n", __FUNCTION__, |
5151 |
substream, |
5152 |
substream->stream, |
5153 |
spec->modem_stream_tags[substream->stream], |
5154 |
substream->runtime->hw.fifo_size, |
5155 |
substream->runtime->dma_area); |
5156 |
#endif |
5157 |
|
5158 |
*StreamID = spec->modem_stream_tags[substream->stream]; |
5159 |
*FifoSize = substream->runtime->hw.fifo_size; // XXX |
5160 |
*ppBufAddr = (short unsigned int *)substream->runtime->dma_area; |
5161 |
} |
5162 |
|
5163 |
static __shimcall__ |
5164 |
int conexant_hsfmodem_OsHdaCodecSetDMAState(PHDAOSHAL pHdaOsHal, OSHDA_STREAM_STATE streamState, void *pPlaybackStream, void *pCaptureStream) |
5165 |
{ |
5166 |
struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec; |
5167 |
struct snd_pcm_substream *psubstream = (struct snd_pcm_substream *)pPlaybackStream; |
5168 |
struct snd_pcm_substream *csubstream = (struct snd_pcm_substream *)pCaptureStream; |
5169 |
int err = 0, cmd; |
5170 |
unsigned long flags, flags2; |
5171 |
|
5172 |
switch(streamState) { |
5173 |
case OsHdaStreamStateRun: |
5174 |
// printk(KERN_DEBUG"%s: Run\n", __FUNCTION__); |
5175 |
if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, psubstream)) < 0) |
5176 |
return err; |
5177 |
if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, csubstream)) < 0) |
5178 |
return err; |
5179 |
|
5180 |
cmd = SNDRV_PCM_IOCTL_START; |
5181 |
psubstream->runtime->start_threshold = 1; |
5182 |
psubstream->runtime->stop_threshold = psubstream->runtime->boundary; |
5183 |
csubstream->runtime->start_threshold = 1; |
5184 |
csubstream->runtime->stop_threshold = csubstream->runtime->boundary; |
5185 |
break; |
5186 |
case OsHdaStreamStateStop: |
5187 |
// printk(KERN_DEBUG"%s: Stop\n", __FUNCTION__); |
5188 |
cmd = SNDRV_PCM_IOCTL_DROP; |
5189 |
break; |
5190 |
case OsHdaStreamStateReset: |
5191 |
// printk(KERN_DEBUG"%s: Reset\n", __FUNCTION__); |
5192 |
cmd = SNDRV_PCM_IOCTL_RESET; |
5193 |
psubstream->runtime->start_threshold = psubstream->runtime->boundary; |
5194 |
csubstream->runtime->start_threshold = csubstream->runtime->boundary; |
5195 |
break; |
5196 |
default: |
5197 |
printk(KERN_ERR"%s: unknown state %d\n", __FUNCTION__, streamState); |
5198 |
return -ENOSYS; |
5199 |
} |
5200 |
|
5201 |
switch(cmd) { |
5202 |
case SNDRV_PCM_IOCTL_START: |
5203 |
snd_pcm_stream_lock_irqsave(psubstream, flags); |
5204 |
snd_pcm_stream_lock_irqsave(csubstream, flags2); |
5205 |
psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_START); |
5206 |
csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_START); |
5207 |
snd_pcm_stream_unlock_irqrestore(csubstream, flags2); |
5208 |
snd_pcm_stream_unlock_irqrestore(psubstream, flags); |
5209 |
break; |
5210 |
case SNDRV_PCM_IOCTL_DROP: |
5211 |
snd_pcm_stream_lock_irqsave(psubstream, flags); |
5212 |
snd_pcm_stream_lock_irqsave(csubstream, flags2); |
5213 |
psubstream->runtime->start_threshold = psubstream->runtime->boundary; |
5214 |
csubstream->runtime->start_threshold = csubstream->runtime->boundary; |
5215 |
psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_STOP); |
5216 |
csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_STOP); |
5217 |
snd_pcm_stream_unlock_irqrestore(csubstream, flags2); |
5218 |
snd_pcm_stream_unlock_irqrestore(psubstream, flags); |
5219 |
break; |
5220 |
case SNDRV_PCM_IOCTL_RESET: |
5221 |
//psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_STOP); |
5222 |
//csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_STOP); |
5223 |
/*FALLTHROUGH*/ |
5224 |
default: |
5225 |
err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); |
5226 |
if (err < 0) { |
5227 |
printk(KERN_ERR"%s: snd_pcm_kernel_ioctl (playback) failed (%d)\n", __FUNCTION__, err); |
5228 |
} |
5229 |
|
5230 |
err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); |
5231 |
if (err < 0) { |
5232 |
printk(KERN_ERR"%s: snd_pcm_kernel_ioctl (capture) failed (%d)\n", __FUNCTION__, err); |
5233 |
} |
5234 |
break; |
5235 |
} |
5236 |
if(cmd != SNDRV_PCM_IOCTL_START) { |
5237 |
spec->modem_do_prepare[psubstream->stream] = 1; |
5238 |
spec->modem_do_prepare[csubstream->stream] = 1; |
5239 |
} |
5240 |
|
5241 |
return err; |
5242 |
} |
5243 |
|
5244 |
static __shimcall__ |
5245 |
unsigned long conexant_hsfmodem_OsHdaCodecGetDMAPos(PHDAOSHAL pHdaOsHal, void *Stream) |
5246 |
{ |
5247 |
struct hda_codec *codec = (struct hda_codec *)pHdaOsHal->hda_codec; |
5248 |
struct snd_pcm_substream *substream = (struct snd_pcm_substream *)Stream; |
5249 |
int ret; |
5250 |
|
5251 |
if(codec->bus->ops.get_linkpos) |
5252 |
ret = codec->bus->ops.get_linkpos(substream); |
5253 |
else |
5254 |
ret = frames_to_bytes(substream->runtime, substream->ops->pointer(substream)); |
5255 |
|
5256 |
//printk(KERN_DEBUG"%s: substream=%p pos=%ld, ret=%d\n", __FUNCTION__, substream, pos, ret); |
5257 |
|
5258 |
return ret; |
5259 |
} |
5260 |
|
5261 |
static void *conexant_hsfmodem_interface_funcs[] = { |
5262 |
conexant_hsfmodem_OsHdaCodecGetAddr, |
5263 |
conexant_hsfmodem_OsHdaCodecGetVendorId, |
5264 |
conexant_hsfmodem_OsHdaCodecGetSubsystemId, |
5265 |
conexant_hsfmodem_OsHdaCodecGetRevisionId, |
5266 |
conexant_hsfmodem_OsHdaCodecRead, |
5267 |
conexant_hsfmodem_OsHdaCodecWallclock, |
5268 |
conexant_hsfmodem_OsHdaCodecSetEventCallback, |
5269 |
conexant_hsfmodem_OsHdaCodecClearEventCallback, |
5270 |
conexant_hsfmodem_OsHdaCodecOpenDMA, |
5271 |
conexant_hsfmodem_OsHdaCodecCloseDMA, |
5272 |
conexant_hsfmodem_OsHdaCodecDMAInfo, |
5273 |
conexant_hsfmodem_OsHdaCodecSetDMAState, |
5274 |
conexant_hsfmodem_OsHdaCodecGetDMAPos, |
5275 |
NULL |
5276 |
}; |
5277 |
|
5278 |
/* |
5279 |
*/ |
5280 |
|
4565 |
static const struct hda_codec_preset snd_hda_preset_conexant[] = { |
5281 |
static const struct hda_codec_preset snd_hda_preset_conexant[] = { |
4566 |
{ .id = 0x14f15045, .name = "CX20549 (Venice)", |
5282 |
{ .id = 0x14f15045, .name = "CX20549 (Venice)", |
4567 |
.patch = patch_cxt5045 }, |
5283 |
.patch = patch_cxt5045 }, |
Lines 4579-4584
Link Here
|
4579 |
.patch = patch_cxt5066 }, |
5295 |
.patch = patch_cxt5066 }, |
4580 |
{ .id = 0x14f1506c, .name = "CX20588", |
5296 |
{ .id = 0x14f1506c, .name = "CX20588", |
4581 |
.patch = patch_cxt5066 }, |
5297 |
.patch = patch_cxt5066 }, |
|
|
5298 |
{ .id = 0x14f12bfa, .mfg = 2, .name = "HSF", |
5299 |
.patch = patch_cxthsfmodem }, |
5300 |
{ .id = 0x14f12c06, .mfg = 2, .name = "HSF", |
5301 |
.patch = patch_cxthsfmodem }, |
5302 |
{ .id = 0x14f10000, .mask = 0xffff0000, .mfg = 2, .name = "HSF", |
5303 |
.patch = patch_cxthsfmodem }, |
4582 |
{ .id = 0x14f1506e, .name = "CX20590", |
5304 |
{ .id = 0x14f1506e, .name = "CX20590", |
4583 |
.patch = patch_cxt5066 }, |
5305 |
.patch = patch_cxt5066 }, |
4584 |
{ .id = 0x14f15097, .name = "CX20631", |
5306 |
{ .id = 0x14f15097, .name = "CX20631", |
Lines 4613-4618
Link Here
|
4613 |
MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
5335 |
MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
4614 |
MODULE_ALIAS("snd-hda-codec-id:14f15068"); |
5336 |
MODULE_ALIAS("snd-hda-codec-id:14f15068"); |
4615 |
MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
5337 |
MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
|
|
5338 |
MODULE_ALIAS("snd-hda-codec-id:14f12bfa"); |
5339 |
MODULE_ALIAS("snd-hda-codec-id:14f12c06"); |
5340 |
MODULE_ALIAS("snd-hda-codec-id:14f1*"); |
4616 |
MODULE_ALIAS("snd-hda-codec-id:14f1506c"); |
5341 |
MODULE_ALIAS("snd-hda-codec-id:14f1506c"); |
4617 |
MODULE_ALIAS("snd-hda-codec-id:14f1506e"); |
5342 |
MODULE_ALIAS("snd-hda-codec-id:14f1506e"); |
4618 |
MODULE_ALIAS("snd-hda-codec-id:14f15097"); |
5343 |
MODULE_ALIAS("snd-hda-codec-id:14f15097"); |
Lines 4628-4634
Link Here
|
4628 |
MODULE_ALIAS("snd-hda-codec-id:14f15111"); |
5353 |
MODULE_ALIAS("snd-hda-codec-id:14f15111"); |
4629 |
|
5354 |
|
4630 |
MODULE_LICENSE("GPL"); |
5355 |
MODULE_LICENSE("GPL"); |
4631 |
MODULE_DESCRIPTION("Conexant HD-audio codec"); |
5356 |
MODULE_DESCRIPTION("Conexant HD-audio and modem codec"); |
4632 |
|
5357 |
|
4633 |
static struct hda_codec_preset_list conexant_list = { |
5358 |
static struct hda_codec_preset_list conexant_list = { |
4634 |
.preset = snd_hda_preset_conexant, |
5359 |
.preset = snd_hda_preset_conexant, |