Subversion Repositories Kolibri OS

Rev

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