@@ -1223,6 +1223,23 @@ void cs_8409_capture_cleanup(struct hda_codec *codec)
1223
1223
1224
1224
}
1225
1225
1226
+ // routine to clear unsol list
1227
+ static void cs_8409_clear_external_device_unsolicited_responses (struct hda_codec * codec )
1228
+ {
1229
+ struct cs8409_apple_spec * spec = codec -> spec ;
1230
+ struct unsol_item * unsol_entry = NULL ;
1231
+ struct unsol_item * unsol_temp = NULL ;
1232
+ if (!list_empty (& spec -> unsol_list )) {
1233
+ codec_info (codec , "cs_8409_clear_external_device_unsolicited_responses UNSOL start\n" );
1234
+ list_for_each_entry_safe (unsol_entry , unsol_temp , & spec -> unsol_list , list )
1235
+ {
1236
+ list_del_init (& unsol_entry -> list );
1237
+ spec -> unsol_items_prealloc_used [unsol_entry -> idx ] = 0 ;
1238
+ memset (unsol_entry , 0 , sizeof (struct unsol_item ));
1239
+ }
1240
+ codec_info (codec , "cs_8409_clear_external_device_unsolicited_responses UNSOL end\n" );
1241
+ }
1242
+ }
1226
1243
1227
1244
static void cs_8409_cs42l83_unsolicited_response_finalize (struct hda_codec * codec , unsigned int res );
1228
1245
@@ -1486,7 +1503,17 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
1486
1503
struct timespec curtim ;
1487
1504
getnstimeofday (& curtim );
1488
1505
#endif
1489
- myprintk ("snd_hda_intel: command cs_8409_pcm_playback_pre_prepare_hook HOOK PREPARE init %d last %lld cur %lld" ,spec -> play_init ,spec -> last_play_time .tv_sec ,curtim .tv_sec );
1506
+ spec -> play_init_count ++ ;
1507
+ myprintk ("snd_hda_intel: command cs_8409_pcm_playback_pre_prepare_hook HOOK PREPARE init %d %d last %lld cur %lld" ,spec -> play_init ,spec -> play_init_count ,spec -> last_play_time .tv_sec ,curtim .tv_sec );
1508
+ //dump_stack();
1509
+ // for some reason this is being called twice within short time so setup is being done twice
1510
+ // with no intervening cleanup
1511
+ // which may be introducing glitches in the headset/headphone stream - which it is!!!
1512
+ // try suppressing any further calls
1513
+ // well great apparently its a feature this function can be called multiple times!!
1514
+ // looking at examples and Alsa driver docs it appears the idea of this function is to set
1515
+ // the stream parameters - so lets let it set the stream parameters every time
1516
+ // but only do the main apple setup once
1490
1517
if (1 ) {
1491
1518
struct hda_cvt_setup_apple * p = NULL ;
1492
1519
//int power_chk = 0;
@@ -1510,6 +1537,10 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
1510
1537
1511
1538
hda_check_power_state (codec , 0x1a , 1 );
1512
1539
hda_check_power_state (codec , 0x3c , 1 );
1540
+ }
1541
+
1542
+ if (spec -> play_init_count == 1 ) {
1543
+ struct hda_cvt_setup_apple * p = NULL ;
1513
1544
1514
1545
// for the moment have junky test here
1515
1546
if (spec -> jack_present )
@@ -1607,17 +1638,24 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
1607
1638
//struct hda_cvt_setup_apple *p = NULL;
1608
1639
myprintk ("snd_hda_intel: command cs_8409_playback_pcm_hook open" );
1609
1640
1641
+ spec -> play_init_count = 0 ;
1642
+
1610
1643
myprintk ("snd_hda_intel: command cs_8409_playback_pcm_hook open end" );
1611
1644
} else if (action == HDA_GEN_PCM_ACT_PREPARE ) {
1612
1645
// so this comes AFTER the stream format, frequency setup verbs are sent for the pcm stream
1646
+ // note that this can be called multiple times apparently
1647
+ // not clear what if any the differences are for those multiple calls
1648
+ // - does mean we need to ensure we only do most operations once
1649
+ // (most of the work is done in the pre prepare function)
1613
1650
#if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 8 , 0 )
1614
1651
struct timespec64 curtim ;
1615
1652
ktime_get_real_ts64 (& curtim );
1616
1653
#else
1617
1654
struct timespec curtim ;
1618
1655
getnstimeofday (& curtim );
1619
1656
#endif
1620
- myprintk ("snd_hda_intel: command cs_8409_playback_pcm_hook HOOK PREPARE init %d last %lld cur %lld" ,spec -> play_init ,spec -> last_play_time .tv_sec ,curtim .tv_sec );
1657
+ myprintk ("snd_hda_intel: command cs_8409_playback_pcm_hook HOOK PREPARE init %d %d last %lld cur %lld" ,spec -> play_init ,spec -> play_init_count ,spec -> last_play_time .tv_sec ,curtim .tv_sec );
1658
+ //dump_stack();
1621
1659
//int power_chk = 0;
1622
1660
//power_chk = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_POWER_STATE, 0);
1623
1661
//myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook power check 0x01 2 %d", power_chk);
@@ -1628,6 +1666,7 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
1628
1666
{
1629
1667
codec_info (codec , "cs_8409_playback_pcm_hook - performing UNSOL responses\n" );
1630
1668
cs_8409_perform_external_device_unsolicited_responses (codec );
1669
+ //cs_8409_clear_external_device_unsolicited_responses(codec);
1631
1670
}
1632
1671
spec -> playing = 1 ;
1633
1672
myprintk ("snd_hda_intel: command cs_8409_playback_pcm_hook HOOK PREPARE end" );
@@ -1657,6 +1696,7 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
1657
1696
codec_info (codec , "cs_8409_playback_pcm_hook - performing UNSOL responses\n" );
1658
1697
cs_8409_perform_external_device_unsolicited_responses (codec );
1659
1698
}
1699
+ spec -> play_init_count = 0 ;
1660
1700
// not sure of this position yet
1661
1701
spec -> playing = 0 ;
1662
1702
power_chk = snd_hda_codec_read (codec , codec -> core .afg , 0 , AC_VERB_GET_POWER_STATE , 0 );
@@ -1677,7 +1717,14 @@ static void cs_8409_pcm_capture_pre_prepare_hook(struct hda_pcm_stream *hinfo, s
1677
1717
struct cs8409_apple_spec * spec = codec -> spec ;
1678
1718
1679
1719
if (action == HDA_GEN_PCM_ACT_PREPARE ) {
1680
- myprintk ("snd_hda_intel: command cs_8409_pcm_capture_pre_prepare_hook HOOK PREPARE init %d" ,spec -> capture_init );
1720
+ spec -> capture_init_count ++ ;
1721
+ myprintk ("snd_hda_intel: command cs_8409_pcm_capture_pre_prepare_hook HOOK PREPARE init %d %d" ,spec -> capture_init ,spec -> capture_init_count );
1722
+
1723
+ // for some reason this is being called twice within short time
1724
+ // well great apparently its a feature this function can be called multiple times!!
1725
+ // looking at examples and Alsa driver docs it appears the idea of this function is to set
1726
+ // the stream parameters - so lets let it set the stream parameters every time
1727
+ // but only do the main apple setup once
1681
1728
1682
1729
// so the first action for internal mike recording (via Quicktime)
1683
1730
// is a headphone sense
@@ -1697,32 +1744,36 @@ static void cs_8409_pcm_capture_pre_prepare_hook(struct hda_pcm_stream *hinfo, s
1697
1744
//cs_8409_setup_stream_format(codec, hinfo->nid, stream_tag, format);
1698
1745
cs_8409_store_stream_format (codec , hinfo -> nid , stream_tag , format );
1699
1746
1747
+ // ensure the setup is only done once
1748
+ if (spec -> capture_init_count == 1 ) {
1700
1749
1701
- // for the moment have junky test here
1702
- if (spec -> jack_present ) {
1703
- spec -> block_unsol = 1 ;
1704
- if (spec -> have_mike )
1705
- {
1706
- // so it seems if we have a headset mike we always enable the
1707
- // headphones even if just capturing
1708
- if (spec -> headset_play_format_setup_needed )
1709
- {
1710
- cs_8409_headplay_setup (codec );
1711
- spec -> headset_play_format_setup_needed = 0 ;
1712
- }
1713
- if (spec -> headset_capture_format_setup_needed )
1750
+ // for the moment have junky test here
1751
+ if (spec -> jack_present ) {
1752
+ spec -> block_unsol = 1 ;
1753
+ if (spec -> have_mike )
1714
1754
{
1715
- cs_8409_headcapture_setup (codec );
1716
- spec -> headset_capture_format_setup_needed = 0 ;
1755
+ // so it seems if we have a headset mike we always enable the
1756
+ // headphones even if just capturing
1757
+ if (spec -> headset_play_format_setup_needed )
1758
+ {
1759
+ cs_8409_headplay_setup (codec );
1760
+ spec -> headset_play_format_setup_needed = 0 ;
1761
+ }
1762
+ if (spec -> headset_capture_format_setup_needed )
1763
+ {
1764
+ cs_8409_headcapture_setup (codec );
1765
+ spec -> headset_capture_format_setup_needed = 0 ;
1766
+ }
1717
1767
}
1768
+ // I think this is impossible - this would say we tried to capture
1769
+ // using a headset without mike
1770
+ // NOTE - still not fixed linein/lineout working - this may need
1771
+ // changing here
1718
1772
}
1719
- // I think this is impossible - this would say we tried to capture
1720
- // using a headset without mike
1721
- // NOTE - still not fixed linein/lineout working - this may need
1722
- // changing here
1773
+ else
1774
+ cs_8409_capture_setup (codec );
1723
1775
}
1724
- else
1725
- cs_8409_capture_setup (codec );
1776
+
1726
1777
myprintk ("snd_hda_intel: command cs_8409_capture_pcm_hook setup capture called" );
1727
1778
1728
1779
spec -> capturing = 0 ;
@@ -1776,10 +1827,15 @@ static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_co
1776
1827
if (action == HDA_GEN_PCM_ACT_OPEN ) {
1777
1828
//struct hda_cvt_setup_apple *p = NULL;
1778
1829
myprintk ("snd_hda_intel: command cs_8409_capture_pcm_hook open" );
1830
+ spec -> capture_init_count = 0 ;
1779
1831
1780
1832
myprintk ("snd_hda_intel: command cs_8409_capture_pcm_hook open end" );
1781
1833
} else if (action == HDA_GEN_PCM_ACT_PREPARE ) {
1782
1834
// so this comes AFTER the stream format, frequency setup verbs are sent for the pcm stream
1835
+ // note that this can be called multiple times apparently
1836
+ // not clear what if any the differences are for those multiple calls
1837
+ // - does mean we need to ensure we only do most operations once
1838
+ // (most of the work is done in the pre prepare function)
1783
1839
myprintk ("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK PREPARE init %d" ,spec -> capture_init );
1784
1840
// this is where we need to finally unset the block_unsol
1785
1841
// - which also means this is where we should check for unsolicited responses
@@ -1827,6 +1883,7 @@ static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_co
1827
1883
codec_info (codec , "cs_8409_capture_pcm_hook - performing UNSOL responses\n" );
1828
1884
cs_8409_perform_external_device_unsolicited_responses (codec );
1829
1885
}
1886
+ spec -> capture_init_count = 0 ;
1830
1887
// not sure of this position yet
1831
1888
spec -> capturing = 0 ;
1832
1889
power_chk = snd_hda_codec_read (codec , codec -> core .afg , 0 , AC_VERB_GET_POWER_STATE , 0 );
0 commit comments