Subversion Repositories Kolibri OS

Rev

Rev 1695 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2.  
  3. #define FORCED_PIO
  4.  
  5. #include <ddk.h>
  6. #include "pci.h"
  7. #include <syscall.h>
  8.  
  9. #include "geode.h"
  10.  
  11. //#define DBG(format,...) dbgprintf(format,##__VA_ARGS__)
  12. #define DBG(format,...)
  13.  
  14. #define  BM0_IRQ            0x04
  15. #define  BM1_IRQ            0x08
  16. #define BITS_8_TO_16(x) ( ( (long) ((unsigned char) x - 128) ) << 8 )
  17.  
  18. #define PCI_VENDOR_ID_NS  0x100b
  19. #define PCI_VENDOR_ID_AMD 0x1022
  20.  
  21.  
  22. #ifndef PCI_DEVICE_ID_NS_CS5535_AUDIO
  23.     #define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e
  24. #endif
  25. #ifndef PCI_DEVICE_ID_AMD_CS5536_AUDIO
  26.     #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093
  27. #endif
  28.  
  29. #define  ID_DEV_1   ((PCI_DEVICE_ID_NS_CS5535_AUDIO  << 16)|PCI_VENDOR_ID_NS)
  30. #define  ID_DEV_2   ((PCI_DEVICE_ID_AMD_CS5536_AUDIO << 16)|PCI_VENDOR_ID_AMD)
  31.  
  32. #define SET                 1
  33. #define CLEAR                           0
  34.  
  35. int __stdcall srv_sound(ioctl_t *io);
  36.  
  37.  
  38. PRD_ENTRY __attribute__((aligned(16))) prd_tab[5];
  39.  
  40.  
  41. typedef struct
  42. {
  43.     PCITAG  pciTag;
  44.     Bool    is_iomapped;
  45.     addr_t  F3BAR0;
  46.  
  47.     Bool    fAD1819A;
  48.  
  49.     int     CurrentPowerState;
  50.  
  51.     addr_t  buffer;
  52.     addr_t  buffer_dma;
  53.     addr_t  prd_dma;
  54.  
  55.     addr_t  irq_line;
  56.     u32_t   irq_mask;
  57.  
  58.     void    __stdcall (*callback)(addr_t buffer);
  59. }geode_t;
  60.  
  61. geode_t  geode;
  62.  
  63.  
  64. static inline void ctrl_write_32(addr_t reg, u32_t data)
  65. {
  66.     reg+= geode.F3BAR0;
  67.  
  68. #ifdef FORCED_PIO
  69.        out32((u16_t)reg, data);
  70. #else
  71.     if(geode.is_iomapped)
  72.        out32((u16_t)reg, data);
  73.     else
  74.         *(u32_t*)reg = data;
  75. #endif
  76. }
  77.  
  78. static inline u32_t ctrl_read_32(addr_t reg)
  79. {
  80.     reg+= geode.F3BAR0;
  81. #ifdef FORCED_PIO
  82.         return in32((u16_t)reg);
  83. #else
  84.     if(geode.is_iomapped)
  85.         return in32((u16_t)reg);
  86.     else
  87.         return *(u32_t*)reg;
  88. #endif
  89. }
  90.  
  91.  
  92.  
  93. Bool snd_hw_WaitForBit(addr_t offset, u32_t Bit,
  94.                               unsigned char Operation,
  95.                               count_t timeout,
  96.                               u32_t *pReturnValue)
  97. {
  98.     volatile u32_t  tmp;
  99.  
  100.     tmp = ctrl_read_32(offset);
  101.  
  102.     while (timeout)
  103.     {
  104.         if (Operation==CLEAR){
  105.             if (!(tmp & Bit))
  106.                 break;
  107.         } else if (tmp & Bit)
  108.                 break;
  109.  
  110.         /*If the Bit is not clear yet, we wait for 10 milisecond and try again*/
  111.         delay(10/10);
  112.  
  113.         tmp = ctrl_read_32(offset);
  114.  
  115.         timeout--;
  116.     };
  117.  
  118.     if (pReturnValue)
  119.         *pReturnValue=tmp;
  120.  
  121.     if (!timeout)
  122.         return FALSE;
  123.  
  124.     return TRUE;
  125. }
  126.  
  127. u16_t snd_hw_CodecRead ( u8_t CodecRegister )
  128. {
  129.     u32_t CodecRegister_data = 0;
  130.     u32_t timeout=10;
  131.     volatile u32_t val=0;
  132.  
  133.     CodecRegister_data  = ((u32_t)CodecRegister)<<24;
  134.     CodecRegister_data |= 0x80000000;   /* High-bit set (p.106) is a CODEC reg READ.*/
  135.  
  136. /*  Set the bit.  We are going to access the CODEC...*/
  137.     CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW;
  138.  
  139. /*Request the data*/
  140.     ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data);
  141.  
  142. /*  Now we need to wait for BIT_5535_CODEC_COMMAND_NEW of the Codec control register to clear
  143.     (For subsequent Reads/Writes)*/
  144.     if (!snd_hw_WaitForBit (CODEC_CONTROL_REG_5535,
  145.                             BIT_5535_CODEC_COMMAND_NEW, CLEAR, 50, NULL))
  146.         DBG("BIT_5535_CODEC_COMMAND_NEW did not clear!!\n");
  147.  
  148. /* Wait for CODEC_STATUS_NEW and confirm the read of the requested register*/
  149.     timeout = 50;
  150.     do
  151.     {
  152.         val = ctrl_read_32(CODEC_STATUS_REG_5535);
  153.         if ((val & BIT_5535_CODEC_STATUS_NEW) &&
  154.             ((u32_t) CodecRegister == ((0xFF000000 & val)>>24)))
  155.             break;
  156.         else
  157.             /*Wait for 10 miliseconds and try again*/
  158.             delay(10/10);
  159.     } while ( --timeout);
  160.  
  161.     if (!timeout)
  162.        DBG("Could not read the CODEC!!  Returning what we got.\n");
  163.  
  164.     return( (u16_t)val );
  165. }
  166.  
  167. void snd_hw_CodecWrite( u8_t CodecRegister, u16_t CodecData  )
  168. {
  169.     u32_t CodecRegister_data;
  170.     u32_t Temp, timeout;
  171.  
  172.     CodecRegister_data = ((u32_t) CodecRegister)<<24;
  173.     CodecRegister_data |= (u32_t) CodecData;
  174.     CodecRegister_data &= CODEC_COMMAND_MASK;
  175.  
  176.     /*Set the bit.  We are going to access the CODEC...*/
  177.     CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW;
  178.  
  179.     /*Write the data*/
  180.     ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data);
  181.     //OS_DbgMsg("Writing: %08X\n", CodecRegister_data);
  182.  
  183.     /*We need to wait for bit16 of the Codec control register to clear*/
  184.     Temp = ctrl_read_32(CODEC_CONTROL_REG_5535);
  185.  
  186.     timeout = 50;
  187.  
  188.     while ((Temp & BIT_5535_CODEC_COMMAND_NEW) && timeout-- )
  189.         Temp = ctrl_read_32(CODEC_CONTROL_REG_5535);
  190.  
  191.     if (!timeout)
  192.         DBG("Could not Write the CODEC!!\n"
  193.                   "BIT_5535_CODEC_COMMAND_NEW did not clear!\n");
  194. }
  195.  
  196.  
  197. void snd_hw_SetCodecRate(u32_t SampleRate)
  198. {
  199.     u16_t val;
  200.  
  201.     DBG("Rate: %d\n", SampleRate);
  202.  
  203.     /*If Double-Rate is supported (Bit 2 on register 28h)...*/
  204.     val=snd_hw_CodecRead(EXTENDED_AUDIO_ID);
  205.  
  206.     if (val & 0x02)
  207.     {
  208.         DBG("Codec supports Double rate.\n");
  209.         val=snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT);
  210.  
  211.         if (SampleRate>48000)
  212.         {
  213.             snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val|0x0002));
  214.             SampleRate/=2;
  215.         }
  216.         else
  217.             snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val&0xFFFD));
  218.     }
  219.     if (geode.fAD1819A)
  220.     {
  221.         DBG("AD1819...\n");
  222.         snd_hw_CodecWrite(AD1819A_PCM_SR0,(u16_t)SampleRate);
  223.     }
  224.     else
  225.         snd_hw_CodecWrite(PCM_FRONT_DAC_RATE,(u16_t)SampleRate);
  226. }
  227.  
  228. Bool init_device()
  229. {
  230.     u32_t io_base = pciReadLong(geode.pciTag, 0x10);
  231.  
  232.     if( PCI_MAP_IS_IO(io_base))
  233.     {
  234.         geode.is_iomapped = TRUE;
  235.         geode.F3BAR0 = PCIGETIO(io_base);
  236.         DBG("io mapped F3BAR0 %x\n", geode.F3BAR0);
  237.     }
  238.     else if(PCI_MAP_IS_MEM(io_base))
  239.     {
  240.         geode.is_iomapped = FALSE;
  241.         io_base = PCIGETMEMORY(io_base);
  242.         geode.F3BAR0 = MapIoMem(io_base, 128, PG_SW+PG_NOCACHE);
  243.         DBG("memory mapped F3BAR0 %x\n", geode.F3BAR0);
  244.     }
  245.  
  246.     geode.buffer = KernelAlloc(64*1024);
  247.  
  248.     addr_t buffer = geode.buffer;
  249.     addr_t dma = GetPgAddr(geode.buffer);
  250.     geode.buffer_dma = dma;
  251.  
  252.     geode.prd_dma  = (((addr_t)prd_tab) & 4095) + GetPgAddr((void*)prd_tab);
  253.  
  254.     prd_tab[0].ulPhysAddr = dma;
  255.     prd_tab[0].SizeFlags = 16384 | PRD_EOP_BIT ;
  256.  
  257.     prd_tab[1].ulPhysAddr = dma + 16384;
  258.     prd_tab[1].SizeFlags = 16384 | PRD_EOP_BIT ;
  259.  
  260.     prd_tab[2].ulPhysAddr = dma + 16384*2;
  261.     prd_tab[2].SizeFlags = 16384 | PRD_EOP_BIT ;
  262.  
  263.     prd_tab[3].ulPhysAddr = dma + 16384*3;
  264.     prd_tab[3].SizeFlags = 16384 | PRD_EOP_BIT ;
  265.  
  266.     prd_tab[4].ulPhysAddr = geode.prd_dma;
  267.     prd_tab[4].SizeFlags = PRD_JMP_BIT ;
  268.  
  269.     ctrl_write_32(0x24, geode.prd_dma);
  270.  
  271.     __clear((void*)buffer,64*1024);
  272. //    u32_t tmp = ctrl_read_32(0x24);
  273.  
  274. //    dbgprintf("Create primary buffer at %x dma at %x\n", geode.buffer, dma );
  275.  
  276. //    dbgprintf("Set prd dma %x, read prd dma %x\n", geode.prd_dma, tmp);
  277.  
  278.     geode.irq_line = pciReadLong(geode.pciTag, 0x3C) & 0xFF;
  279.     geode.irq_mask = ~(1<<geode.irq_line);
  280.  
  281.     DBG("Irq line %d, mask %x\n", geode.irq_line, geode.irq_mask);
  282.  
  283.  
  284. /*
  285.     geode.CommandRegister  = geode.F3BAR0+0x20;
  286.     geode.PRDTableAddress  = geode.F3BAR0+0x24;
  287.     geode.DMAPointer       = geode.F3BAR0+0x60;
  288.  
  289.     geode.IRQControlRegister        = geode.F3BAR0+0x1C;
  290.     geode.InternalIRQEnableRegister = geode.F3BAR0+0x1A;
  291.     geode.SMI_StatusRegister        = geode.F3BAR0+0x21;
  292. */
  293.  
  294.  
  295.  
  296. /*CODEC - RESET and volumes initalization.*/
  297. /*Set the Warm RESET and CODEC_COMMAND_NEW bits.*/
  298.  
  299.     DBG("reset codec...\n");
  300.  
  301.     ctrl_write_32(CODEC_CONTROL_REG_5535, 0x00030000 );
  302.  
  303.     if (!snd_hw_WaitForBit (CODEC_STATUS_REG_5535, BIT_CODEC_READY, SET, 40, NULL))
  304.     {
  305.        DBG("Primary Codec NOT Ready...Aborting\n");
  306.        return FALSE;
  307.     }
  308.  
  309.     u16_t id7c, id7e;
  310.  
  311.     id7c = snd_hw_CodecRead(AD1819A_VENDORID1);
  312.     id7e = snd_hw_CodecRead(AD1819A_VENDORID2);
  313.  
  314.     dbgprintf("codec id 0x7C %x  0x7E %x\n", id7c, id7e);
  315.  
  316.     /*Check which codec is being used */
  317.     if ( (id7c == 0x4144) &&
  318.          (id7e == 0x5303) )
  319.     {
  320.         geode.fAD1819A = TRUE;
  321.         /*  Enable non-48kHz sample rates. */
  322.         snd_hw_CodecWrite (AD1819A_SER_CONF,
  323.                            snd_hw_CodecRead(AD1819A_SER_CONF>>8) |
  324.                            AD1819A_SER_CONF_DRQEN);
  325.         DBG("detect AD1819A audio codec\n");
  326.     }
  327.     else
  328.     {
  329.         geode.fAD1819A = FALSE;
  330.         snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT,
  331.         (snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT) | 0x0001));
  332.         /* set the VRA bit to ON*/
  333.     }
  334.  
  335.     /* set default volume*/
  336.     snd_hw_CodecWrite( MASTER_VOLUME,       0x0909);
  337.     snd_hw_CodecWrite( PCM_OUT_VOL,         0x0606);
  338.     snd_hw_CodecWrite( PC_BEEP_VOLUME,      0x0000);
  339.     snd_hw_CodecWrite( PHONE_VOLUME,        0x0606);
  340.     snd_hw_CodecWrite( MIC_VOLUME,          0x8048);
  341.     snd_hw_CodecWrite( LINE_IN_VOLUME,      0x0808);
  342.     snd_hw_CodecWrite( CD_VOLUME,           0x8000);
  343.     snd_hw_CodecWrite( VIDEO_VOLUME,        0x8000);
  344.     snd_hw_CodecWrite( TV_VOLUME,           0x8000);
  345.     snd_hw_CodecWrite( RECORD_SELECT,       0x0000);
  346.     snd_hw_CodecWrite( RECORD_GAIN,         0x0a0a);
  347.     snd_hw_CodecWrite( GENERAL_PURPOSE,     0x0200);
  348.     snd_hw_CodecWrite( MASTER_VOLUME_MONO,  0x0000);
  349.  
  350.     snd_hw_SetCodecRate(48000);
  351.     /*Set all the power state bits to 0 (Reg 26h)*/
  352.     snd_hw_CodecWrite (POWERDOWN_CTRL_STAT, 0x0000);
  353.     geode.CurrentPowerState = GEODEAUDIO_D0;
  354. //    OS_DbgMsg("<--snd_hw_InitAudioRegs\n");
  355.  
  356.  
  357.     return TRUE;
  358. }
  359.  
  360. static int snd_StartDMA ()
  361. {
  362.  
  363. #ifdef FORCED_PIO
  364.         out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER);
  365. #else
  366.     if (geode.is_iomapped)
  367.         out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER);
  368.     else
  369.         *(u8_t*)(geode.F3BAR0+0x20)= PCI_READS | ENABLE_BUSMASTER;
  370. #endif
  371.     return 0;
  372. };
  373.  
  374. static u8_t snd_hw_InterruptID ()
  375. {
  376.     volatile u8_t *TempInterruptID, ID;
  377.  
  378. #ifdef FORCED_PIO
  379.         ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12));
  380. #else
  381.     if (geode.is_iomapped)
  382.         ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12));
  383.     else
  384.     {
  385.         TempInterruptID=(u8_t*)(geode.F3BAR0 + 0x12);
  386.         ID=*TempInterruptID;
  387.     }
  388. #endif
  389.     return (ID);
  390. }
  391.  
  392.  
  393. static u8_t snd_hw_ClearStat(int Channel)
  394. {
  395.     volatile u8_t status;      /*Volatile to force read-to-clear.*/
  396.  
  397.     /*Read to clear*/
  398.  
  399. #ifdef FORCED_PIO
  400.         status = in8((u16_t) geode.F3BAR0 + 0x21);
  401. #else
  402.     if (geode.is_iomapped)
  403.         status = in8((u16_t) geode.F3BAR0 + 0x21);
  404.     else
  405.         status = *((u8_t*)geode.F3BAR0 + 0x21);
  406. #endif
  407.     return status;
  408. }
  409.  
  410.  
  411. void snd_interrupt()
  412. {
  413.     u8_t IntID;
  414.  
  415.     IntID = snd_hw_InterruptID();
  416.  
  417. //    dbgprintf("IRQ id %x\n", IntID);
  418.  
  419.     snd_hw_ClearStat(CHANNEL0_PLAYBACK);
  420. //    snd_hw_ClearStat(CHANNEL1_RECORD);
  421.  
  422.     if(IntID & BM0_IRQ)
  423.     {
  424.       addr_t prd, offset, base;
  425.  
  426.       prd = ctrl_read_32(0x24);
  427.       offset = (1 + (prd - geode.prd_dma)>>3) & 3;
  428.  
  429.       base = geode.buffer + 16384*offset;
  430.  
  431.       geode.callback(base);
  432.       __asm__ volatile("":::"ebx","esi","edi");
  433.  
  434. //      dbgprintf(">>BM0_IRQ prd %x offset %x base %x\n", prd, offset, base);
  435.     };
  436. };
  437.  
  438. Bool FindPciDevice()
  439. {
  440.     u32_t bus, last_bus;
  441.     PCITAG tag;
  442.  
  443.     if( (last_bus = PciApi(1))==-1)
  444.         return FALSE;
  445.  
  446.     for(bus=0;bus<=last_bus;bus++)
  447.     {
  448.         u32_t devfn;
  449.  
  450.         for(devfn=0;devfn<256;devfn++)
  451.         {
  452.             u32_t pciId=0;
  453.  
  454.             pciId = PciRead32(bus,devfn, 0);
  455.  
  456.             if( (pciId == ID_DEV_1) ||
  457.                 (pciId == ID_DEV_2) )
  458.             {
  459.                 DBG("detect companion audio device %x\n", pciId);
  460.                 geode.pciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7);
  461.                 return TRUE;
  462.             };
  463.         };
  464.     };
  465.     return FALSE;
  466. };
  467.  
  468.  
  469. u32_t drvEntry(int action, char *cmdline)
  470. {
  471.     u32_t retval;
  472.  
  473.     int i;
  474.  
  475.     if(action != 1)
  476.         return 0;
  477.  
  478.     if(!dbg_open("/rd/1/drivers/geode.log"))
  479.     {
  480.         printf("Can't open /rd/1/drivers/geode.log\nExit\n");
  481.         return 0;
  482.     }
  483.  
  484.     printf("AMD Geode CS5536 audio driver\n");
  485.  
  486.     if( FindPciDevice() == FALSE)
  487.     {
  488.         dbgprintf("Device not found\n");
  489.         return 0;
  490.     };
  491.  
  492.     init_device();
  493.  
  494.     retval = RegService("SOUND", srv_sound);
  495.  
  496.     AttachIntHandler(geode.irq_line, snd_interrupt, 0);
  497.  
  498.     DBG("reg service %s as: %x\n", "SOUND", retval);
  499.  
  500.     return retval;
  501. };
  502.  
  503.  
  504. #define API_VERSION     0x01000100
  505.  
  506. #define SRV_GETVERSION         0
  507. #define DEV_PLAY               1
  508. #define DEV_STOP               2
  509. #define DEV_CALLBACK           3
  510. #define DEV_SET_BUFF           4
  511. #define DEV_NOTIFY             5
  512. #define DEV_SET_MASTERVOL      6
  513. #define DEV_GET_MASTERVOL      7
  514. #define DEV_GET_INFO           8
  515. #define DEV_GET_POS            9
  516.  
  517. int __stdcall srv_sound(ioctl_t *io)
  518. {
  519.     u32_t *inp;
  520.     u32_t *outp;
  521.  
  522.     inp = io->input;
  523.     outp = io->output;
  524.  
  525.     switch(io->io_code)
  526.     {
  527.         case SRV_GETVERSION:
  528.             if(io->out_size==4)
  529.             {
  530.                 *outp = API_VERSION;
  531.                 return 0;
  532.             }
  533.             break;
  534.  
  535.         case DEV_PLAY:
  536.                 return snd_StartDMA();
  537.             break;
  538.  
  539.         case DEV_STOP:
  540.             break;
  541.  
  542.         case DEV_CALLBACK:
  543.             if(io->inp_size==4)
  544.             {
  545.                 geode.callback = (void*)(*inp);
  546.                 return 0;
  547.             }
  548.             break;
  549.  
  550.         case DEV_GET_POS:
  551.             if(io->out_size==4)
  552.             {
  553.                 u32_t  dma;
  554.                 dma = ctrl_read_32(0x60);
  555.                 dma-= geode.buffer_dma;
  556.                 *outp = (dma & 16383)>>2;
  557.                 return 0;
  558.             }
  559.             break;
  560.  
  561.     default:
  562.       return ERR_PARAM;
  563.   };
  564.   return ERR_PARAM;
  565. }
  566.  
  567.  
  568.