Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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