From: "Ronald S. Bultje" Attached patch adds some host<->le conversion functions for 32-bit integers. The hardware expects 32-bit integers, which the host does not always provide. With the attached patch, the hardware runs fine on PPC hardware as well. Original patch by Ben Capper . Signed-off-by: Ronald S. Bultje Signed-off-by: Andrew Morton --- 25-akpm/drivers/media/video/zoran_device.c | 31 +++++++++------- 25-akpm/drivers/media/video/zoran_driver.c | 56 +++++++++++++++++------------ 2 files changed, 51 insertions(+), 36 deletions(-) diff -puN drivers/media/video/zoran_device.c~zr36067-driver-ppc-be-port drivers/media/video/zoran_device.c --- 25/drivers/media/video/zoran_device.c~zr36067-driver-ppc-be-port 2004-12-31 01:33:04.129269512 -0800 +++ 25-akpm/drivers/media/video/zoran_device.c 2004-12-31 01:33:04.137268296 -0800 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -758,7 +759,7 @@ init_jpeg_queue (struct zoran *zr) zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ } for (i = 0; i < BUZ_NUM_STAT_COM; i++) { - zr->stat_com[i] = 1; /* mark as unavailable to zr36057 */ + zr->stat_com[i] = cpu_to_le32(1); /* mark as unavailable to zr36057 */ } } @@ -1163,20 +1164,20 @@ zoran_feed_stat_com (struct zoran *zr) /* fill 1 stat_com entry */ i = (zr->jpg_dma_head - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - if (!(zr->stat_com[i] & 1)) + if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - zr->jpg_buffers.buffer[frame].frag_tab_bus; + cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); } else { /* fill 2 stat_com entries */ i = ((zr->jpg_dma_head - zr->jpg_err_shift) & 1) * 2; - if (!(zr->stat_com[i] & 1)) + if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - zr->jpg_buffers.buffer[frame].frag_tab_bus; + cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); zr->stat_com[i + 1] = - zr->jpg_buffers.buffer[frame].frag_tab_bus; + cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); } zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA; zr->jpg_dma_head++; @@ -1213,7 +1214,7 @@ zoran_reap_stat_com (struct zoran *zr) i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2 + 1; - stat_com = zr->stat_com[i]; + stat_com = le32_to_cpu(zr->stat_com[i]); if ((stat_com & 1) == 0) { return; @@ -1309,7 +1310,7 @@ error_handler (struct zoran *zr, for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { - if (zr->stat_com[j] == + if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers. buffer[i]. frag_tab_bus) { @@ -1321,7 +1322,6 @@ error_handler (struct zoran *zr, printk("\n"); } } - /* Find an entry in stat_com and rotate contents */ { int i; @@ -1334,9 +1334,9 @@ error_handler (struct zoran *zr, zr->jpg_err_shift) & 1) * 2; if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { /* Mimic zr36067 operation */ - zr->stat_com[i] |= 1; + zr->stat_com[i] |= cpu_to_le32(1); if (zr->jpg_settings.TmpDcm != 1) - zr->stat_com[i + 1] |= 1; + zr->stat_com[i + 1] |= cpu_to_le32(1); /* Refill */ zoran_reap_stat_com(zr); zoran_feed_stat_com(zr); @@ -1355,12 +1355,17 @@ error_handler (struct zoran *zr, int j; u32 bus_addr[BUZ_NUM_STAT_COM]; + /* Here we are copying the stat_com array, which + * is already in little endian format, so + * no endian conversions here + */ memcpy(bus_addr, zr->stat_com, sizeof(bus_addr)); for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM]; + } zr->jpg_err_shift += i; zr->jpg_err_shift &= BUZ_MASK_STAT_COM; @@ -1564,7 +1569,7 @@ zoran_irq (int irq, int i; strcpy(sv, sc); for (i = 0; i < 4; i++) { - if (zr->stat_com[i] & 1) + if (le32_to_cpu(zr->stat_com[i]) & 1) sv[i] = '1'; } sv[4] = 0; @@ -1592,7 +1597,7 @@ zoran_irq (int irq, ZR_DEVNAME(zr), zr->jpg_seq_num); for (i = 0; i < 4; i++) { printk(" %08x", - zr->stat_com[i]); + le32_to_cpu(zr->stat_com[i])); } printk("\n"); } diff -puN drivers/media/video/zoran_driver.c~zr36067-driver-ppc-be-port drivers/media/video/zoran_driver.c --- 25/drivers/media/video/zoran_driver.c~zr36067-driver-ppc-be-port 2004-12-31 01:33:04.131269208 -0800 +++ 25-akpm/drivers/media/video/zoran_driver.c 2004-12-31 01:33:04.141267688 -0800 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -516,6 +517,16 @@ v4l_fbuffer_free (struct file *file) * virtual addresses) and then again have to make a lot of efforts * to get the physical address. * + * Ben Capper: + * On big-endian architectures (such as ppc) some extra steps + * are needed. When reading and writing to the stat_com array + * and fragment buffers, the device expects to see little- + * endian values. The use of cpu_to_le32() and le32_to_cpu() + * in this function (and one or two others in zoran_device.c) + * ensure that these values are always stored in little-endian + * form, regardless of architecture. The zr36057 does Very Bad + * Things on big endian architectures if the stat_com array + * and fragment buffers are not little-endian. */ static int @@ -569,9 +580,9 @@ jpg_fbuffer_alloc (struct file *file) return -ENOBUFS; } fh->jpg_buffers.buffer[i].frag_tab[0] = - virt_to_bus((void *) mem); + cpu_to_le32(virt_to_bus((void *) mem)); fh->jpg_buffers.buffer[i].frag_tab[1] = - ((fh->jpg_buffers.buffer_size / 4) << 1) | 1; + cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1); for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) SetPageReserved(MAP_NR(mem + off)); @@ -591,14 +602,14 @@ jpg_fbuffer_alloc (struct file *file) } fh->jpg_buffers.buffer[i].frag_tab[2 * j] = - virt_to_bus((void *) mem); + cpu_to_le32(virt_to_bus((void *) mem)); fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = - (PAGE_SIZE / 4) << 1; + cpu_to_le32((PAGE_SIZE / 4) << 1); SetPageReserved(MAP_NR(mem)); } - fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= 1; + fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1); } } @@ -631,13 +642,8 @@ jpg_fbuffer_free (struct file *file) //if (alloc_contig) { if (fh->jpg_buffers.need_contiguous) { if (fh->jpg_buffers.buffer[i].frag_tab[0]) { - mem = - (unsigned char *) bus_to_virt(fh-> - jpg_buffers. - buffer - [i]. - frag_tab - [0]); + mem = (unsigned char *) bus_to_virt(le32_to_cpu( + fh->jpg_buffers.buffer[i].frag_tab[0])); for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) @@ -656,13 +662,16 @@ jpg_fbuffer_free (struct file *file) break; ClearPageReserved(MAP_NR (bus_to_virt - (fh->jpg_buffers. - buffer[i].frag_tab[2 * - j]))); + (le32_to_cpu + (fh->jpg_buffers. + buffer[i].frag_tab[2 * + j])))); free_page((unsigned long) - bus_to_virt(fh->jpg_buffers. + bus_to_virt + (le32_to_cpu + (fh->jpg_buffers. buffer[i]. - frag_tab[2 * j])); + frag_tab[2 * j]))); fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0; fh->jpg_buffers.buffer[i].frag_tab[2 * j + @@ -4539,14 +4548,14 @@ zoran_mmap (struct file *file, j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { fraglen = - (fh->jpg_buffers.buffer[i]. - frag_tab[2 * j + 1] & ~1) << 1; + (le32_to_cpu(fh->jpg_buffers.buffer[i]. + frag_tab[2 * j + 1]) & ~1) << 1; todo = size; if (todo > fraglen) todo = fraglen; pos = - (unsigned long) fh->jpg_buffers. - buffer[i].frag_tab[2 * j]; + le32_to_cpu((unsigned long) fh->jpg_buffers. + buffer[i].frag_tab[2 * j]); /* should just be pos on i386 */ page = virt_to_phys(bus_to_virt(pos)) >> PAGE_SHIFT; @@ -4563,8 +4572,8 @@ zoran_mmap (struct file *file, start += todo; if (size == 0) break; - if (fh->jpg_buffers.buffer[i]. - frag_tab[2 * j + 1] & 1) + if (le32_to_cpu(fh->jpg_buffers.buffer[i]. + frag_tab[2 * j + 1]) & 1) break; /* was last fragment */ } fh->jpg_buffers.buffer[i].map = map; @@ -4689,3 +4698,4 @@ struct video_device zoran_template __dev .release = &zoran_vdev_release, .minor = -1 }; + _