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