@@ -66,6 +66,7 @@ struct intelhd_card_s
6666 long pcmout_bufsize ;
6767 unsigned long * corb_buffer ;
6868 unsigned long long * rirb_buffer ;
69+ int first_rirb ;
6970 unsigned long pcmout_dmasize ;
7071 unsigned int pcmout_num_periods ;
7172 unsigned long pcmout_period_size ;
@@ -278,24 +279,57 @@ static unsigned int azx_get_response(struct intelhd_card_s *chip)
278279#endif
279280 return azx_readl (chip , IR );
280281 } else { //Immediate Commands are optional, some devices don't have it, use CORB
281- do {
282+ if ( chip -> first_rirb ) {
282283 azx_writeb (chip , RIRBCTL , 0x3 );
284+ }
285+ do {
283286 if (azx_readb (chip , RIRBSTS )& 1 )
284287 break ;
285288 pds_delay_10us (10 );
286- }while (-- timeout );
289+ }while (-- timeout );
287290 if (!timeout ){
288291 mpxplay_debugf (IHD_DEBUG_OUTPUT ,"read response timeout %d" , timeout );
292+ if (chip -> first_rirb ) {
293+ // Some chipsets will freeze if you now try to read the RIRB
294+ chip -> first_rirb = 0 ;
295+ return 0 ;
296+ }
289297 chip -> config_select |= AUCARDSCONFIG_IHD_USE_PIO ;
298+ chip -> first_rirb = 0 ;
290299 return 0xffffffff ;
291300 }
301+ chip -> first_rirb = 0 ;
292302 int rirbindex = azx_readw (chip , RIRBWP );
293303 long long data = chip -> rirb_buffer [rirbindex ];
294304 azx_writeb (chip , RIRBSTS , 1 );
295305 return (unsigned int )(data );
296306 }
297307}
298308
309+ static void switch_to_pio (struct intelhd_card_s * chip )
310+ {
311+ int timeout = 2000 ; // 200 ms
312+ printf ("Intel HDA: Switching to PIO.\n" );
313+ azx_writeb (chip , CORBCTL , 0 ); // DMA Stop
314+ int c ;
315+ do {
316+ c = azx_readb (chip , CORBCTL );
317+ pds_delay_10us (10 );
318+ if ((c & 2 ) == 0 ) {
319+ break ;
320+ }
321+ } while (-- timeout );
322+ azx_writew (chip , RIRBCTL , 0 ); // DMA Stop, Disable Interrupt
323+ do {
324+ c = azx_readb (chip , RIRBCTL );
325+ if ((c & 2 ) == 0 ) {
326+ break ;
327+ }
328+ pds_delay_10us (10 );
329+ } while (-- timeout );
330+ azx_writel (chip , GCTL , (azx_readl (chip , GCTL ) & (~ICH6_GCTL_UREN )));
331+ }
332+
299333static unsigned int snd_hda_codec_read (struct intelhd_card_s * chip , hda_nid_t nid ,
300334 uint32_t direct ,
301335 unsigned int verb , unsigned int parm )
@@ -306,26 +340,7 @@ static unsigned int snd_hda_codec_read(struct intelhd_card_s *chip, hda_nid_t ni
306340 snd_hda_codec_write (chip ,nid ,direct ,verb ,parm );
307341 unsigned int r = azx_get_response (chip );
308342 if (r == 0xffffffff && pio != (chip -> config_select & AUCARDSCONFIG_IHD_USE_PIO )) {
309- int timeout = 2000 ; // 200 ms
310- printf ("Intel HDA: Switching to PIO.\n" );
311- azx_writeb (chip , CORBCTL , 0 ); // DMA Stop
312- int c ;
313- do {
314- c = azx_readb (chip , CORBCTL );
315- pds_delay_10us (10 );
316- if ((c & 2 ) == 0 ) {
317- break ;
318- }
319- } while (-- timeout );
320- azx_writew (chip , RIRBCTL , 0 ); // DMA Stop, Disable Interrupt
321- do {
322- c = azx_readb (chip , RIRBCTL );
323- if ((c & 2 ) == 0 ) {
324- break ;
325- }
326- pds_delay_10us (10 );
327- } while (-- timeout );
328- azx_writel (chip , GCTL , (azx_readl (chip , GCTL ) & (~ICH6_GCTL_UREN )));
343+ switch_to_pio (chip );
329344 goto retry ;
330345 }
331346 return r ;
@@ -807,6 +822,7 @@ static unsigned int snd_ihd_buffer_init(struct mpxplay_audioout_info_s *aui,stru
807822#if SBEMU_USE_CORB
808823 card -> corb_buffer = (long * )(((uint32_t )card -> pcmout_buffer + card -> pcmout_bufsize + HDA_CORB_ALIGN - 1 )& (~(HDA_CORB_ALIGN - 1 )));
809824 card -> rirb_buffer = (long long * )(((uint32_t )card -> corb_buffer + HDA_CORB_MAXSIZE + HDA_RIRB_ALGIN - 1 )& (~(HDA_RIRB_ALGIN - 1 )));
825+ card -> first_rirb = 1 ;
810826#endif
811827
812828 gcap = (unsigned long )azx_readw (card ,GCAP );
@@ -858,8 +874,45 @@ static unsigned int snd_ihd_mixer_init(struct intelhd_card_s *card)
858874 mpxplay_debugf (IHD_DEBUG_OUTPUT ,"snd_ihd_mixer_init start" );
859875
860876 card -> codec_vendor_id = snd_hda_param_read (card , AC_NODE_ROOT ,AC_PAR_VENDOR_ID );
861- if (card -> codec_vendor_id <=0 )
862- card -> codec_vendor_id = snd_hda_param_read (card , AC_NODE_ROOT ,AC_PAR_VENDOR_ID );
877+ if (card -> codec_vendor_id <=0 ){
878+ // Heuristic to switch problematic chipsets to PIO
879+ azx_writeb (card , CORBCTL , 0 ); // DMA Stop
880+ int timeout = 2000 ;
881+ int c ;
882+ do {
883+ c = azx_readb (card , CORBCTL );
884+ pds_delay_10us (10 );
885+ if ((c & 2 ) == 0 ) {
886+ break ;
887+ }
888+ } while (-- timeout );
889+ azx_writel (card , CORBRP , 1 <<15 ); // Reset
890+ //pds_delay_10us(100); // need this delay? -> no
891+ timeout = 2000 ;
892+ do {
893+ int rp = azx_readl (card , CORBRP );
894+ if (rp & (1 <<15 )) break ;
895+ pds_delay_10us (10 );
896+ } while (-- timeout );
897+ //printf("Intel HDA: CORBRP timeout %d\n", timeout);
898+ mpxplay_debugf (IHD_DEBUG_OUTPUT ,"corbrp timeout %d\n" , timeout );
899+ if (timeout > 0 ) {
900+ card -> config_select |= AUCARDSCONFIG_IHD_USE_PIO ;
901+ switch_to_pio (card );
902+ azx_writel (card , CORBRP , 0 ); // No sound without this!
903+ pds_delay_10us (100 );
904+ card -> codec_vendor_id = snd_hda_param_read (card , AC_NODE_ROOT ,AC_PAR_VENDOR_ID );
905+ } else {
906+ timeout = 2000 ;
907+ azx_writel (card , CORBRP , 0 );
908+ do {
909+ int rp = azx_readl (card , CORBRP );
910+ if (rp & (1 <<15 ) == 0 ) break ;
911+ pds_delay_10us (10 );
912+ } while (-- timeout );
913+ card -> codec_vendor_id = snd_hda_param_read (card , AC_NODE_ROOT ,AC_PAR_VENDOR_ID );
914+ }
915+ }
863916 mpxplay_debugf (IHD_DEBUG_OUTPUT ,"codec vendor id:%8.8X" ,card -> codec_vendor_id );
864917
865918 snd_hda_search_audio_node (card );
0 commit comments