V4L/DVB (8913): cx18: Create cx18_ specific wrappers for all pci mmio accessesors.

cx18: Create cx18_ specific wrappers for all pci mmio accessesors.  This is a
first step in instrumenting all CX23418 PCI bus IO, to debug problems with
accessing the CX23418's PCI memory mapped IO.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Andy Walls 2008-08-30 16:03:44 -03:00 committed by Mauro Carvalho Chehab
parent 4519064c1c
commit b1526421ea
19 changed files with 465 additions and 260 deletions

View File

@ -2,7 +2,7 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.
cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
cx18-dvb.o
cx18-dvb.o cx18-io.o
obj-$(CONFIG_VIDEO_CX18) += cx18.o

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-i2c.h"
#include "cx18-cards.h"
#include "cx18-audio.h"
@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx)
if (err)
return err;
val = read_reg(CX18_AUDIO_ENABLE) & ~0x30;
val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
(audio_input << 4);
write_reg(val | 0xb00, CX18_AUDIO_ENABLE);
cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE);
cx18_vapi(cx, CX18_APU_RESETAI, 1, 0);
return 0;
}

View File

@ -22,27 +22,29 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
{
u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
u32 reg = 0xc40000 + (addr & ~3);
u32 mask = 0xff;
int shift = (addr & 3) * 8;
u32 x = cx18_read_reg(cx, reg);
x = (x & ~(mask << shift)) | ((u32)value << shift);
writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
cx18_write_reg(cx, x, reg);
return 0;
}
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
{
writel(value, cx->reg_mem + 0xc40000 + addr);
cx18_write_reg(cx, value, 0xc40000 + addr);
return 0;
}
u8 cx18_av_read(struct cx18 *cx, u16 addr)
{
u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
int shift = (addr & 3) * 8;
return (x >> shift) & 0xff;
@ -50,7 +52,7 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr)
u32 cx18_av_read4(struct cx18 *cx, u16 addr)
{
return readl(cx->reg_mem + 0xc40000 + addr);
return cx18_read_reg(cx, 0xc40000 + addr);
}
int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,

View File

@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include <linux/firmware.h>
#define CX18_AUDIO_ENABLE 0xc72014
@ -119,10 +120,10 @@ int cx18_av_loadfw(struct cx18 *cx)
have a name in the spec. */
cx18_av_write4(cx, 0x09CC, 1);
v = read_reg(CX18_AUDIO_ENABLE);
/* If bit 11 is 1 */
v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
/* If bit 11 is 1, clear bit 10 */
if (v & 0x800)
write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE);
/* Enable WW auto audio standard detection */
v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-version.h"
#include "cx18-cards.h"
#include "cx18-i2c.h"
@ -651,7 +652,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
goto free_mem;
}
cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
devtype = read_reg(0xC72028);
devtype = cx18_read_reg(cx, 0xC72028);
switch (devtype & 0xff000000) {
case 0xff000000:
CX18_INFO("cx23418 revision %08x (A)\n", devtype);
@ -897,8 +898,8 @@ static void cx18_remove(struct pci_dev *pci_dev)
cx18_stop_all_captures(cx);
/* Interrupts */
sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
cx18_halt_firmware(cx);

View File

@ -457,47 +457,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
/* First-open initialization: load firmware, etc. */
int cx18_init_on_first_open(struct cx18 *cx);
/* This is a PCI post thing, where if the pci register is not read, then
the write doesn't always take effect right away. By reading back the
register any pending PCI writes will be performed (in order), and so
you can be sure that the writes are guaranteed to be done.
Rarely needed, only in some timing sensitive cases.
Apparently if this is not done some motherboards seem
to kill the firmware and get into the broken state until computer is
rebooted. */
#define write_sync(val, reg) \
do { writel(val, reg); readl(reg); } while (0)
#define read_reg(reg) readl(cx->reg_mem + (reg))
#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
#define write_reg_sync(val, reg) \
do { write_reg(val, reg); read_reg(reg); } while (0)
#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
#define write_enc_sync(val, addr) \
do { write_enc(val, addr); read_enc(addr); } while (0)
#define sw1_irq_enable(val) do { \
write_reg(val, SW1_INT_STATUS); \
write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
} while (0)
#define sw1_irq_disable(val) \
write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
#define sw2_irq_enable(val) do { \
write_reg(val, SW2_INT_STATUS); \
write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
} while (0)
#define sw2_irq_disable(val) \
write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
#define setup_page(addr) do { \
u32 val = read_reg(0xD000F8) & ~0x1f00; \
write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
} while (0)
#endif /* CX18_DRIVER_H */

View File

@ -21,6 +21,7 @@
#include "cx18-version.h"
#include "cx18-dvb.h"
#include "cx18-io.h"
#include "cx18-streams.h"
#include "cx18-cards.h"
#include "s5h1409.h"
@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
switch (cx->card->type) {
case CX18_CARD_HVR_1600_ESMT:
case CX18_CARD_HVR_1600_SAMSUNG:
v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
v |= 0x00400000; /* Serial Mode */
v |= 0x00002000; /* Data Length - Byte */
v |= 0x00010000; /* Error - Polarity */
v |= 0x00020000; /* Error - Passthru */
v |= 0x000c0000; /* Error - Ignore */
write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
break;
default:

View File

@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-scb.h"
#include "cx18-irq.h"
#include "cx18-firmware.h"
@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
src = (const u32 *)fw->data;
for (i = 0; i < fw->size; i += 4096) {
setup_page(i);
cx18_setup_page(cx, i);
for (j = i; j < fw->size && j < i + 4096; j += 4) {
/* no need for endianness conversion on the ppc */
__raw_writel(*src, dst);
if (__raw_readl(dst) != *src) {
cx18_raw_writel(cx, *src, dst);
if (cx18_raw_readl(cx, dst) != *src) {
CX18_ERR("Mismatch at offset %x\n", i);
release_firmware(fw);
return -EIO;
@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
if (offset + seghdr.size > sz)
break;
for (i = 0; i < seghdr.size; i += 4096) {
setup_page(offset + i);
cx18_setup_page(cx, offset + i);
for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
/* no need for endianness conversion on the ppc */
__raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
CX18_ERR("Mismatch at offset %x\n", offset + j);
cx18_raw_writel(cx, src[(offset + j) / 4],
dst + seghdr.addr + j);
if (cx18_raw_readl(cx, dst + seghdr.addr + j)
!= src[(offset + j) / 4]) {
CX18_ERR("Mismatch at offset %x\n",
offset + j);
release_firmware(fw);
return -EIO;
}
@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
size = fw->size;
release_firmware(fw);
/* Clear bit0 for APU to start from 0 */
write_reg(read_reg(0xc72030) & ~1, 0xc72030);
cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
return size;
}
void cx18_halt_firmware(struct cx18 *cx)
{
CX18_DEBUG_INFO("Preparing for firmware halt.\n");
write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
write_reg(0x00020002, CX18_ADEC_CONTROL);
cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
}
void cx18_init_power(struct cx18 *cx, int lowpwr)
{
/* power-down Spare and AOM PLLs */
/* power-up fast, slow and mpeg PLLs */
write_reg(0x00000008, CX18_PLL_POWER_DOWN);
cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
/* ADEC out of sleep */
write_reg(0x00020000, CX18_ADEC_CONTROL);
cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL);
/* The fast clock is at 200/245 MHz */
write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
CX18_FAST_CLOCK_PLL_FRAC);
write_reg(2, CX18_FAST_CLOCK_PLL_POST);
write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
/* set slow clock to 125/120 MHz */
write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8,
CX18_SLOW_CLOCK_PLL_FRAC);
cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST);
/* mpeg clock pll 54MHz */
write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
/* Defaults */
/* APU = SC or SC/2 = 125/62.5 */
@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
/* VFC = disabled */
/* USB = disabled */
write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
CX18_CLOCK_SELECT1);
cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
CX18_CLOCK_SELECT2);
write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
}
void cx18_init_memory(struct cx18 *cx)
{
cx18_msleep_timeout(10, 0);
write_reg(0x10000, CX18_DDR_SOFT_RESET);
cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET);
cx18_msleep_timeout(10, 0);
write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
cx18_msleep_timeout(10, 0);
write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
cx18_msleep_timeout(10, 0);
/* Initialize DQS pad time */
write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
cx18_msleep_timeout(10, 0);
write_reg(0x20000, CX18_DDR_SOFT_RESET);
cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET);
cx18_msleep_timeout(10, 0);
/* use power-down mode when idle */
write_reg(0x00000010, CX18_DDR_POWER_REG);
cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN);
write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */
write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */
write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */
write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */
write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */
write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */
write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */
write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */
cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */
}
int cx18_firmware_init(struct cx18 *cx)
{
/* Allow chip to control CLKRUN */
write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
cx18_msleep_timeout(1, 0);
sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
/* Only if the processor is not running */
if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) {
int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
cx->enc_mem, cx);
write_enc(0xE51FF004, 0);
write_enc(0xa00000, 4); /* todo: not hardcoded */
write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */
cx18_write_enc(cx, 0xE51FF004, 0);
cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
/* Start APU */
cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET);
cx18_msleep_timeout(500, 0);
sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx)
int retries = 0;
/* start the CPU */
write_reg(0x00080000, CX18_PROC_SOFT_RESET);
cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET);
while (retries++ < 50) { /* Loop for max 500mS */
if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
& 1) == 0)
break;
cx18_msleep_timeout(10, 0);
}
@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx)
return -EIO;
}
/* initialize GPIO */
write_reg(0x14001400, 0xC78110);
cx18_write_reg(cx, 0x14001400, 0xC78110);
return 0;
}

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-cards.h"
#include "cx18-gpio.h"
#include "tuner-xc2028.h"
@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx)
u32 dir = cx->gpio_dir;
u32 val = cx->gpio_val;
write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff),
CX18_REG_GPIO_OUT1);
write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2);
cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
CX18_REG_GPIO_OUT2);
}
@ -141,8 +142,10 @@ void cx18_gpio_init(struct cx18 *cx)
}
CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
gpio_write(cx);
mutex_unlock(&cx->gpio_lock);

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-cards.h"
#include "cx18-gpio.h"
#include "cx18-av-core.h"
@ -156,12 +157,12 @@ static void cx18_setscl(void *data, int state)
struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
u32 r = read_reg(addr);
u32 r = cx18_read_reg(cx, addr);
if (state)
write_reg_sync(r | SETSCL_BIT, addr);
cx18_write_reg_sync(cx, r | SETSCL_BIT, addr);
else
write_reg_sync(r & ~SETSCL_BIT, addr);
cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr);
}
static void cx18_setsda(void *data, int state)
@ -169,12 +170,12 @@ static void cx18_setsda(void *data, int state)
struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
u32 r = read_reg(addr);
u32 r = cx18_read_reg(cx, addr);
if (state)
write_reg_sync(r | SETSDL_BIT, addr);
cx18_write_reg_sync(cx, r | SETSDL_BIT, addr);
else
write_reg_sync(r & ~SETSDL_BIT, addr);
cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr);
}
static int cx18_getscl(void *data)
@ -183,7 +184,7 @@ static int cx18_getscl(void *data)
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
return read_reg(addr) & GETSCL_BIT;
return cx18_read_reg(cx, addr) & GETSCL_BIT;
}
static int cx18_getsda(void *data)
@ -192,7 +193,7 @@ static int cx18_getsda(void *data)
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
return read_reg(addr) & GETSDL_BIT;
return cx18_read_reg(cx, addr) & GETSDL_BIT;
}
/* template for i2c-bit-algo */
@ -392,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx)
cx->i2c_adap[i].dev.parent = &cx->dev->dev;
}
if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
/* Reset/Unreset I2C hardware block */
write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
/* Clock select 220MHz */
cx18_write_reg(cx, 0x10000000, 0xc71004);
/* Clock Enable */
cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
}
/* courtesy of Steven Toth <stoth@hauppauge.com> */
write_reg_sync(0x00c00000, 0xc7001c);
cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
mdelay(10);
write_reg_sync(0x00c000c0, 0xc7001c);
cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
mdelay(10);
write_reg_sync(0x00c00000, 0xc7001c);
cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
mdelay(10);
write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
/* Set to edge-triggered intrs. */
cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
/* Clear any stale intrs */
cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
/* Hw I2C1 Clock Freq ~100kHz */
write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
/* Hw I2C2 Clock Freq ~100kHz */
write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
@ -428,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx)
{
int i;
CX18_DEBUG_I2C("i2c exit\n");
write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
CX18_REG_I2C_1_WR);
cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
CX18_REG_I2C_2_WR);
for (i = 0; i < 2; i++) {
i2c_del_adapter(&cx->i2c_adap[i]);

View File

@ -0,0 +1,142 @@
/*
* cx18 driver PCI memory mapped IO access routines
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
#include "cx18-driver.h"
#include "cx18-irq.h"
void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
{
__raw_writel(val, addr);
}
u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
{
return __raw_readl(addr);
}
u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr)
{
writel(val, addr);
return readl(addr);
}
void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
{
writel(val, addr);
}
u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
{
return readl(addr);
}
/* Access "register" region of CX23418 memory mapped I/O */
u32 cx18_read_reg(struct cx18 *cx, u32 reg)
{
return readl(cx->reg_mem + reg);
}
void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
{
writel(val, cx->reg_mem + reg);
}
u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg)
{
return cx18_write_sync(cx, val, cx->reg_mem + reg);
}
/* Access "encoder memory" region of CX23418 memory mapped I/O */
u32 cx18_read_enc(struct cx18 *cx, u32 addr)
{
return readl(cx->enc_mem + addr);
}
void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
{
writel(val, cx->enc_mem + addr);
}
u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr)
{
return cx18_write_sync(cx, val, cx->enc_mem + addr);
}
void cx18_memcpy_fromio(struct cx18 *cx, void *to,
const void __iomem *from, unsigned int len)
{
memcpy_fromio(to, from, len);
}
void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
{
memset_io(addr, val, count);
}
void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
{
u32 r;
cx18_write_reg(cx, val, SW1_INT_STATUS);
r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
}
void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
{
u32 r;
r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI);
}
void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
{
u32 r;
cx18_write_reg(cx, val, SW2_INT_STATUS);
r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
}
void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
{
u32 r;
r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI);
}
void cx18_setup_page(struct cx18 *cx, u32 addr)
{
u32 val;
val = cx18_read_reg(cx, 0xD000F8);
val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
cx18_write_reg(cx, val, 0xD000F8);
}
/* Tries to recover from the CX23418 responding improperly on the PCI bus */
int cx18_pci_try_recover(struct cx18 *cx)
{
u16 status;
pci_read_config_word(cx->dev, PCI_STATUS, &status);
pci_write_config_word(cx->dev, PCI_STATUS, status);
return 0;
}

View File

@ -0,0 +1,69 @@
/*
* cx18 driver PCI memory mapped IO access routines
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
#ifndef CX18_IO_H
#define CX18_IO_H
#include "cx18-driver.h"
/* This is a PCI post thing, where if the pci register is not read, then
the write doesn't always take effect right away. By reading back the
register any pending PCI writes will be performed (in order), and so
you can be sure that the writes are guaranteed to be done.
Rarely needed, only in some timing sensitive cases.
Apparently if this is not done some motherboards seem
to kill the firmware and get into the broken state until computer is
rebooted. */
u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr);
void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr);
u32 cx18_readl(struct cx18 *cx, const void __iomem *addr);
/* No endiannes conversion calls */
void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr);
u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr);
/* Access "register" region of CX23418 memory mapped I/O */
u32 cx18_read_reg(struct cx18 *cx, u32 reg);
void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg);
u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg);
/* Access "encoder memory" region of CX23418 memory mapped I/O */
u32 cx18_read_enc(struct cx18 *cx, u32 addr);
void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr);
u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr);
void cx18_memcpy_fromio(struct cx18 *cx, void *to,
const void __iomem *from, unsigned int len);
void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
void cx18_setup_page(struct cx18 *cx, u32 addr);
/* Tries to recover from the CX23418 responding improperly on the PCI bus */
int cx18_pci_try_recover(struct cx18 *cx);
#endif /* CX18_IO_H */

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-version.h"
#include "cx18-mailbox.h"
#include "cx18-i2c.h"
@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
spin_lock_irqsave(&cx18_cards_lock, flags);
if (cmd == VIDIOC_DBG_G_REGISTER)
regs->val = read_enc(regs->reg);
regs->val = cx18_read_enc(cx, regs->reg);
else
write_enc(regs->val, regs->reg);
cx18_write_enc(cx, regs->val, regs->reg);
spin_unlock_irqrestore(&cx18_cards_lock, flags);
return 0;
}

View File

@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-firmware.h"
#include "cx18-fileops.h"
#include "cx18-queue.h"
@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
if (mb->args[2] != 1)
CX18_WARN("Ack struct = %d for %s\n",
mb->args[2], s->name);
id = read_enc(off);
buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4));
id = cx18_read_enc(cx, off);
buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4));
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
if (buf) {
cx18_buf_sync_for_cpu(s, buf);
@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
} else {
CX18_WARN("Could not find buf %d for stream %s\n",
read_enc(off), s->name);
cx18_read_enc(cx, off), s->name);
}
mb->error = 0;
mb->cmd = 0;
@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
char *p;
if (mb->args[1]) {
setup_page(mb->args[1]);
memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
cx18_setup_page(cx, mb->args[1]);
cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252);
str[252] = 0;
}
cx18_mb_ack(cx, mb);
@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1)
struct cx18_mailbox mb;
if (sw1 & IRQ_CPU_TO_EPU) {
memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb));
mb.error = 0;
switch (mb.cmd) {
@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
spin_lock(&cx->dma_reg_lock);
hw2_mask = read_reg(HW2_INT_MASK5_PCI);
hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
write_reg(sw2&sw2_mask, SW2_INT_STATUS);
write_reg(sw1&sw1_mask, SW1_INT_STATUS);
write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS);
cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS);
cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS);
if (sw1 || sw2 || hw2)
CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
*/
if (sw2) {
if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) |
readl(&cx->scb->cpu2epu_irq_ack)))
if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) |
cx18_readl(cx, &cx->scb->cpu2epu_irq_ack)))
wake_up(&cx->mb_cpu_waitq);
if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) |
readl(&cx->scb->apu2epu_irq_ack)))
if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) |
cx18_readl(cx, &cx->scb->apu2epu_irq_ack)))
wake_up(&cx->mb_apu_waitq);
if (sw2 & readl(&cx->scb->epu2hpu_irq_ack))
if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack))
wake_up(&cx->mb_epu_waitq);
if (sw2 & readl(&cx->scb->hpu2epu_irq_ack))
if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack))
wake_up(&cx->mb_hpu_waitq);
}

View File

@ -22,6 +22,7 @@
#include <stdarg.h>
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-scb.h"
#include "cx18-irq.h"
#include "cx18-mailbox.h"
@ -106,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
switch (rpu) {
case APU:
mb = &cx->scb->epu2apu_mb;
*state = readl(&cx->scb->apu_state);
*irq = readl(&cx->scb->epu2apu_irq);
*state = cx18_readl(cx, &cx->scb->apu_state);
*irq = cx18_readl(cx, &cx->scb->epu2apu_irq);
break;
case CPU:
mb = &cx->scb->epu2cpu_mb;
*state = readl(&cx->scb->cpu_state);
*irq = readl(&cx->scb->epu2cpu_irq);
*state = cx18_readl(cx, &cx->scb->cpu_state);
*irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
break;
case HPU:
mb = &cx->scb->epu2hpu_mb;
*state = readl(&cx->scb->hpu_state);
*irq = readl(&cx->scb->epu2hpu_irq);
*state = cx18_readl(cx, &cx->scb->hpu_state);
*irq = cx18_readl(cx, &cx->scb->epu2hpu_irq);
break;
}
@ -127,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
return mb;
do {
*req = readl(&mb->request);
ack = readl(&mb->ack);
*req = cx18_readl(cx, &mb->request);
ack = cx18_readl(cx, &mb->ack);
wait_count++;
} while (*req != ack && wait_count < 600);
@ -173,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
return -EINVAL;
}
setup_page(SCB_OFFSET);
write_sync(mb->request, &ack_mb->ack);
write_reg(ack_irq, SW2_INT_SET);
cx18_setup_page(cx, SCB_OFFSET);
cx18_write_sync(cx, mb->request, &ack_mb->ack);
cx18_write_reg(cx, ack_irq, SW2_INT_SET);
return 0;
}
@ -200,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
CX18_DEBUG_HI_API("%s\n", info->name);
else
CX18_DEBUG_API("%s\n", info->name);
setup_page(SCB_OFFSET);
cx18_setup_page(cx, SCB_OFFSET);
mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
if (mb == NULL) {
@ -209,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
}
oldreq = req - 1;
writel(cmd, &mb->cmd);
cx18_writel(cx, cmd, &mb->cmd);
for (i = 0; i < args; i++)
writel(data[i], &mb->args[i]);
writel(0, &mb->error);
writel(req, &mb->request);
cx18_writel(cx, data[i], &mb->args[i]);
cx18_writel(cx, 0, &mb->error);
cx18_writel(cx, req, &mb->request);
switch (info->rpu) {
case APU: waitq = &cx->mb_apu_waitq; break;
@ -224,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
}
if (info->flags & API_FAST)
timeout /= 2;
write_reg(irq, SW1_INT_SET);
cx18_write_reg(cx, irq, SW1_INT_SET);
while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request)
&& cnt < 660) {
if (cnt > 200 && !in_atomic())
sig = cx18_msleep_timeout(10, 1);
cnt++;
@ -234,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
if (sig)
return -EINTR;
if (cnt == 660) {
writel(oldreq, &mb->request);
cx18_writel(cx, oldreq, &mb->request);
CX18_ERR("mb %s failed\n", info->name);
return -EINVAL;
}
for (i = 0; i < MAX_MB_ARGUMENTS; i++)
data[i] = readl(&mb->args[i]);
err = readl(&mb->error);
data[i] = cx18_readl(cx, &mb->args[i]);
err = cx18_readl(cx, &mb->error);
if (!in_atomic() && (info->flags & API_SLOW))
cx18_msleep_timeout(300, 0);
if (err)

View File

@ -170,6 +170,7 @@ int cx18_stream_alloc(struct cx18_stream *s)
}
buf->id = cx->buffer_id++;
INIT_LIST_HEAD(&buf->list);
/* FIXME - check for mmio */
buf->dma_handle = pci_map_single(s->cx->dev,
buf->buf, s->buf_size, s->dma);
cx18_buf_sync_for_cpu(s, buf);
@ -193,6 +194,7 @@ void cx18_stream_free(struct cx18_stream *s)
/* empty q_free */
while ((buf = cx18_dequeue(s, &s->q_free))) {
/* FIXME - check for mmio */
pci_unmap_single(s->cx->dev, buf->dma_handle,
s->buf_size, s->dma);
kfree(buf->buf);

View File

@ -28,6 +28,7 @@
static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
struct cx18_buffer *buf)
{
/* FIXME check IO transfers */
pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle,
s->buf_size, s->dma);
}
@ -35,6 +36,7 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
struct cx18_buffer *buf)
{
/* FIXME check IO transfers */
pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle,
s->buf_size, s->dma);
}

View File

@ -20,102 +20,103 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-scb.h"
void cx18_init_scb(struct cx18 *cx)
{
setup_page(SCB_OFFSET);
memset_io(cx->scb, 0, 0x10000);
cx18_setup_page(cx, SCB_OFFSET);
cx18_memset_io(cx, cx->scb, 0, 0x10000);
writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
cx18_writel(cx, IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
cx18_writel(cx, IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
cx18_writel(cx, IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
cx18_writel(cx, IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
cx18_writel(cx, IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
cx18_writel(cx, IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
cx18_writel(cx, IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
cx18_writel(cx, IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
cx18_writel(cx, IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
cx18_writel(cx, IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
cx18_writel(cx, IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
cx18_writel(cx, IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
cx18_writel(cx, IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
cx18_writel(cx, IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
cx18_writel(cx, IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
cx18_writel(cx, IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
cx18_writel(cx, IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
cx18_writel(cx, IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
cx18_writel(cx, IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
cx18_writel(cx, IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
&cx->scb->apu2cpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
&cx->scb->hpu2cpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
&cx->scb->ppu2cpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
&cx->scb->epu2cpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
&cx->scb->cpu2apu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
&cx->scb->hpu2apu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
&cx->scb->ppu2apu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
&cx->scb->epu2apu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
&cx->scb->cpu2hpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
&cx->scb->apu2hpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
&cx->scb->ppu2hpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
&cx->scb->epu2hpu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
&cx->scb->cpu2ppu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
&cx->scb->apu2ppu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
&cx->scb->hpu2ppu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
&cx->scb->epu2ppu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
&cx->scb->cpu2epu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
&cx->scb->apu2epu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
&cx->scb->hpu2epu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
&cx->scb->ppu2epu_mb_offset);
writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
&cx->scb->ipc_offset);
writel(1, &cx->scb->hpu_state);
writel(1, &cx->scb->epu_state);
cx18_writel(cx, 1, &cx->scb->hpu_state);
cx18_writel(cx, 1, &cx->scb->epu_state);
}

View File

@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-fileops.h"
#include "cx18-mailbox.h"
#include "cx18-i2c.h"
@ -469,7 +470,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
if (atomic_read(&cx->tot_capturing) == 0) {
clear_bit(CX18_F_I_EOS, &cx->i_flags);
write_reg(7, CX18_DSP0_INTERRUPT_MASK);
cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
}
cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
@ -479,8 +480,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
list_for_each(p, &s->q_free.list) {
struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
cx18_writel(cx, buf->dma_handle,
&cx->scb->cpu_mdl[buf->id].paddr);
cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
(void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
1, buf->id, s->buf_size);
@ -563,7 +565,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
if (atomic_read(&cx->tot_capturing) > 0)
return 0;
write_reg(5, CX18_DSP0_INTERRUPT_MASK);
cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
wake_up(&s->waitq);
return 0;