Thanks for the Raspberry Pi!

Oleksandr Tymoshenko gonzo at bluezbox.com
Mon Jan 28 23:54:04 UTC 2013


On 1/28/2013 3:15 AM, George Mitchell wrote:
> Today is my birthday, and the best present I have is that my Raspberry
> Pi is running FreeBSD plus CUPS and acting as a print server for the
> FreeBSD machines (and one Windoze machine) on my home network.  My
> sincere thanks go to everybody who helped bring FreeBSD to the ARM and
> specifically to the Pi.  It would be awesome if we could get ARM
> promoted to Tier 1 support this year
Happy birthday. George! :)

> I'm interested in working on a driver for the pulse-width modulation
> audio output on the Pi, and I have the Broadcom document describing how
> it works.  What are the chances I could base such a driver on some
> existing FreeBSD audio driver? 

I do not think there is PWM-based audio driver. I was trying to implement
VCHIQ-based audio driver[1] but ran into some locking issues with VCHIQ 
driver
and put the project on hold. You can use it as a skeleton for your audio 
driver
though. Also as far as I can see from spec PWM utilizes DMA  so you
might want to give a try  this driver[2]. It's reworked version of
Daisuke Aoyama's patch. Usage pattern would be something like code below.
In real driver you'd want to use bus_dma operations though, not direct 
calls to
cache ops.

[1] http://people.freebsd.org/~gonzo/arm/rpi/vchiq_audio.tar.gz
[2] http://people.freebsd.org/~gonzo/arm/patches/rpi_dma.diff

int dma_started = 0;
int dma_set = 0;

int dma = 0;

void *page1 = NULL;
void *page2 = NULL;
vm_paddr_t pa1;
vm_paddr_t pa2;

static uint8_t pattern = 0xa5;

static void
dma_intr(int ch, void *arg)
{
         uint32_t *p1, *p2;
         printf("dma_intr: %d, %p\n", ch, arg);

         cpu_dcache_inv_range((vm_offset_t)page2, PAGE_SIZE);
         cpu_l2cache_inv_range((vm_offset_t)page2, PAGE_SIZE);

         p1 = (void*)page1;
         p2 = (void*)page2;
         printf("%08x vs %08x\n", *p1, *p2);
         for (int i = 0; i < PAGE_SIZE/4; i++) {
                 if (p1[i] != p2[i]) {
                         printf("diff at %d\n", i);
                         break;
                 }
         }

         dma_started = 0;
}

static int
start_dma_test()
{

         return (0);

         if (!dma_set) {
                 printf("Setting DMA\n");
                 dma_set = 1;
                 page1 = contigmalloc(PAGE_SIZE, M_DEVBUF,
                         M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0);
                 page2 = contigmalloc(PAGE_SIZE, M_DEVBUF,
                         M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0);
                 pa1 = vtophys(page1);
                 pa2 = vtophys(page2);
                 printf("page1 = %p -> %p\n", page1, (void*)pa1);
                 printf("page2 = %p -> %p\n", page2, (void*)pa1);

                 dma = bcm_dma_allocate(BCM_DMA_CH_ANY);
                 printf("Allocated channel: %d\n", dma);
                 bcm_dma_setup_intr(dma, dma_intr, NULL);
                 bcm_dma_setup_src(dma, 0, 1);
                 bcm_dma_setup_dst(dma, 0, 1);
         }

         if (!dma_started) {
                 memset(page1, pattern, PAGE_SIZE);
                 memset(page2, 0x00, PAGE_SIZE);
                 pattern++;

                 cpu_dcache_wbinv_range((vm_offset_t)page1, PAGE_SIZE);
                 cpu_l2cache_wbinv_range((vm_offset_t)page1, PAGE_SIZE);
                 cpu_dcache_wbinv_range((vm_offset_t)page2, PAGE_SIZE);
                 cpu_l2cache_wbinv_range((vm_offset_t)page2, PAGE_SIZE);

                 printf("DMA started!\n");
                 bcm_dma_start(dma, pa1, pa2, PAGE_SIZE);
         }

         dma_started = 1;
         return (0);
}




More information about the freebsd-arm mailing list