diff options
author | Andy Walls <awalls@radix.net> | 2008-08-30 16:03:44 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 09:36:58 -0200 |
commit | b1526421eac9a912b2cda7e147f1da2aa31be278 (patch) | |
tree | 5c21474d865bd43dc00514f0a55a84bdf05ba440 /drivers/media | |
parent | 4519064c1c7ccdd319d26181bdd12ee2df6e336e (diff) |
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/cx18/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-audio.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 12 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-firmware.c | 7 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.c | 7 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.h | 43 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-dvb.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-firmware.c | 140 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-gpio.c | 15 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-i2c.c | 47 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-io.c | 142 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-io.h | 69 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-irq.c | 43 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 44 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.h | 2 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-scb.c | 131 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 10 |
19 files changed, 468 insertions, 263 deletions
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index b23d2e26120..f7bf0edf93f 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile @@ -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 diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 6d5b94fc708..57beddf0af4 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -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; } diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 3b0a2c45060..d8626e35465 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -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, diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index e996a4e3123..0488b629770 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -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); diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3dfceb360b5..d31e1ec8d14 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -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); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 7bdd2fcdf20..2cfdbe44582 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -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 */ diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 1e420a804fc..afc694e7bdb 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -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: diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 78fadd2ada5..51534428cd0 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c @@ -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); - - write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN); - - write_reg(0x48, CX18_DDR_MB_PER_ROW_7); - write_reg(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, 0x00000010, CX18_DDR_POWER_REG); + + cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN); + + cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); + cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); + + 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; } diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 3d495dba498..3bdffbf7a96 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -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); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 7d8fb25baae..aa09e557b19 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -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]); diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c new file mode 100644 index 00000000000..c53d9b6e5e4 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.c @@ -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; +} diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h new file mode 100644 index 00000000000..7c08c0add49 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.h @@ -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); + |