diff --git a/packages/linux/patches/3.8.5/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/3.8.5/linux-950-saa716x_PCIe_interface_chipset.patch new file mode 100644 index 0000000000..d2ee6111cc --- /dev/null +++ b/packages/linux/patches/3.8.5/linux-950-saa716x_PCIe_interface_chipset.patch @@ -0,0 +1,12914 @@ +diff -Naur linux-3.7.2/drivers/media/common/Kconfig linux-3.7.2.patch/drivers/media/common/Kconfig +--- linux-3.7.2/drivers/media/common/Kconfig 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/Kconfig 2013-01-16 10:52:04.586923233 +0100 +@@ -1,3 +1,4 @@ + source "drivers/media/common/b2c2/Kconfig" + source "drivers/media/common/saa7146/Kconfig" ++source "drivers/media/common/saa716x/Kconfig" + source "drivers/media/common/siano/Kconfig" +diff -Naur linux-3.7.2/drivers/media/common/Makefile linux-3.7.2.patch/drivers/media/common/Makefile +--- linux-3.7.2/drivers/media/common/Makefile 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/Makefile 2013-01-16 10:52:15.443844483 +0100 +@@ -1 +1 @@ +-obj-y += b2c2/ saa7146/ siano/ ++obj-y += b2c2/ saa7146/ saa716x/ siano/ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/Kconfig linux-3.7.2.patch/drivers/media/common/saa716x/Kconfig +--- linux-3.7.2/drivers/media/common/saa716x/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/Kconfig 2013-01-16 10:41:10.906798319 +0100 +@@ -0,0 +1,67 @@ ++menuconfig SAA716X_SUPPORT ++ bool "Support for SAA716x family from NXP/Philips" ++ depends on PCI && I2C ++ help ++ support for saa716x ++ ++if SAA716X_SUPPORT ++config SAA716X_CORE ++ tristate "SAA7160/1/2 PCI Express bridge based devices" ++ depends on PCI && I2C ++ ++ help ++ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_BUDGET ++ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" ++ depends on SAA716X_CORE && DVB_CORE ++ select DVB_DS3000 if !DVB_FE_CUSTOMISE ++ select DVB_DS3103 if !DVB_FE_CUSTOMISE ++ select DVB_TS2022 if !DVB_FE_CUSTOMISE ++ ++ help ++ Support for the SAA7160/1/2 based Budget PCIe DVB cards ++ Currently supported devices are: ++ ++ * KNC1 Dual S2 (DVB-S, DVB-S/S2) ++ * Twinhan/Azurewave VP-1028 (DVB-S) ++ * Twinhan/Azurewave VP-3071 (DVB-T x2) ++ * Twinhan/Azurewave VP-6002 (DVB-S) ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_HYBRID ++ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" ++ depends on SAA716X_CORE && DVB_CORE ++ ++ help ++ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards ++ Currently supported devices are: ++ ++ * Avermedia H-788 (DVB-T) ++ * Avermedia HC-82 (DVB-T) ++ * NXP Reference (Atlantis) (DVB-T x2) ++ * NXP Reference (Nemo) (DVB-T) ++ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) ++ ++ Say Y if you own such a device and want to use it. ++ ++#config DVB_SAA716X_FF ++# tristate "SAA7160/1/2 based Full Fledged PCIe cards" ++# depends on SAA716X_CORE && DVB_CORE ++# depends on INPUT # IR ++# default n ++ ++# help ++# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards ++# These cards do feature a hardware MPEG decoder and other ++# peripherals. Also known as Premium cards. ++# Currently supported devices are: ++ ++# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) ++ ++# Say Y if you own such a device and want to use it. ++ ++endif # SAA716X_SUPPORT +diff -Naur linux-3.7.2/drivers/media/common/saa716x/Makefile linux-3.7.2.patch/drivers/media/common/saa716x/Makefile +--- linux-3.7.2/drivers/media/common/saa716x/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/Makefile 2013-01-16 10:54:20.634929700 +0100 +@@ -0,0 +1,26 @@ ++saa716x_core-objs := saa716x_pci.o \ ++ saa716x_i2c.o \ ++ saa716x_cgu.o \ ++ saa716x_msi.o \ ++ saa716x_dma.o \ ++ saa716x_vip.o \ ++ saa716x_aip.o \ ++ saa716x_phi.o \ ++ saa716x_boot.o \ ++ saa716x_fgpi.o \ ++ saa716x_adap.o \ ++ saa716x_gpio.o \ ++ saa716x_greg.o \ ++ saa716x_rom.o \ ++ saa716x_spi.o ++ ++#saa716x_ff-objs := saa716x_ff_main.o \ ++# saa716x_ff_cmd.o \ ++# saa716x_ff_ir.o ++ ++obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o ++obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o ++obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o ++#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o ++ ++EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.c 2013-01-16 10:41:10.907798312 +0100 +@@ -0,0 +1,274 @@ ++#include ++ ++#include "dmxdev.h" ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dvb_frontend.h" ++ ++#include "saa716x_mod.h" ++#include "saa716x_spi.h" ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_gpio.h" ++#include "saa716x_priv.h" ++#include "saa716x_budget.h" ++ ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++ ++void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ struct fgpi_stream_params params; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); ++ ++ params.bits = 8; ++ params.samples = 188; ++ params.lines = 348; ++ params.pitch = 188; ++ params.offset = 0; ++ params.page_tables = 0; ++ params.stream_type = FGPI_TRANSPORT_STREAM; ++ params.stream_flags = 0; ++ ++ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); ++} ++ ++void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); ++ ++ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); ++} ++ ++static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds++; ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", ++ saa716x_adap->feeds); ++ ++ if (saa716x_adap->feeds == 1) { ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); ++ saa716x_dma_start(saa716x, saa716x_adap->count); ++ } ++ ++ return saa716x_adap->feeds; ++} ++ ++static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds--; ++ if (saa716x_adap->feeds == 0) { ++ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); ++ saa716x_dma_stop(saa716x, saa716x_adap->count); ++ } ++ ++ return 0; ++} ++ ++int saa716x_dvb_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct saa716x_config *config = saa716x->config; ++ int result, i; ++ ++ mutex_init(&saa716x->adap_lock); ++ ++ for (i = 0; i < config->adapters; i++) { ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); ++ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, ++ "SAA716x dvb adapter", ++ THIS_MODULE, ++ &saa716x->pdev->dev, ++ adapter_nr) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); ++ return -ENODEV; ++ } ++ ++ saa716x_adap->count = i; ++ ++ saa716x_adap->dvb_adapter.priv = saa716x_adap; ++ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING; ++ ++ saa716x_adap->demux.priv = saa716x_adap; ++ saa716x_adap->demux.filternum = 256; ++ saa716x_adap->demux.feednum = 256; ++ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; ++ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; ++ saa716x_adap->demux.write_to_decoder = NULL; ++ switch (saa716x->pdev->subsystem_device) { ++ case TEVII_S472: { ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ u8 mac[6]; ++ u8 b0[] = { 0, 9 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .buf = b0, ++ .len = 2 ++ }, { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .buf = mac, ++ .len = 6 ++ } ++ }; ++ ++ i2c_transfer(adapter, msg, 2); ++ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); ++ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); ++ } ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); ++ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err0; ++ } ++ ++ saa716x_adap->dmxdev.filternum = 256; ++ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; ++ saa716x_adap->dmxdev.capabilities = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); ++ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, ++ &saa716x_adap->dvb_adapter)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); ++ goto err1; ++ } ++ ++ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err2; ++ } ++ ++ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_mem)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err3; ++ } ++ ++ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err4; ++ } ++ ++ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); ++// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); ++ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); ++ saa716x_adap->saa716x = saa716x; ++ ++ if (config->frontend_attach) { ++ result = config->frontend_attach(saa716x_adap, i); ++ if (result < 0) ++ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); ++ ++ if (saa716x_adap->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", ++ saa716x->pdev->vendor, ++ saa716x->pdev->device, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ } else { ++ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); ++ if (result < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); ++ goto err6; ++ } ++ } ++ ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); ++ } ++ ++ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, ++ config->adap_config[i].worker); ++ ++ saa716x_adap++; ++ } ++ ++ ++ return 0; ++ ++ /* Error conditions */ ++err6: ++ dvb_frontend_detach(saa716x_adap->fe); ++err4: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++err3: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++err2: ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++err1: ++ dvb_dmx_release(&saa716x_adap->demux); ++err0: ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ return result; ++} ++EXPORT_SYMBOL(saa716x_dvb_init); ++ ++void saa716x_dvb_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ int i; ++ ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ ++ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); ++ ++ if (saa716x_adap->fe) { ++ dvb_unregister_frontend(saa716x_adap->fe); ++ dvb_frontend_detach(saa716x_adap->fe); ++ } ++ ++// tasklet_kill(&saa716x->tasklet); ++ dvb_net_release(&saa716x_adap->dvb_net); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++ dvb_dmx_release(&saa716x_adap->demux); ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ saa716x_adap++; ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(saa716x_dvb_exit); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.h 2013-01-16 10:41:10.907798312 +0100 +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_ADAP_H ++#define __SAA716x_ADAP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_dvb_init(struct saa716x_dev *saa716x); ++extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ADAP_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.c 2013-01-16 10:41:10.907798312 +0100 +@@ -0,0 +1,20 @@ ++#include ++ ++#include "saa716x_mod.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_aip.h" ++#include "saa716x_priv.h" ++ ++int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) ++{ ++ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_status); ++ ++void saa716x_aip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(AI0, AI_CTL, 0x00); ++ SAA716x_EPWR(AI1, AI_CTL, 0x00); ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_disable); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.h 2013-01-16 10:41:10.907798312 +0100 +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_AIP_H ++#define __SAA716x_AIP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); ++extern void saa716x_aip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_AIP_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip_reg.h 2013-01-16 10:41:10.908798304 +0100 +@@ -0,0 +1,62 @@ ++#ifndef __SAA716x_AIP_REG_H ++#define __SAA716x_AIP_REG_H ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++#endif /* __SAA716x_AIP_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.c 2013-01-16 10:41:10.908798304 +0100 +@@ -0,0 +1,319 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_cgu_reg.h" ++#include "saa716x_vip_reg.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_gpio_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dcs_reg.h" ++ ++#include "saa716x_boot.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static int saa716x_ext_boot(struct saa716x_dev *saa716x) ++{ ++ /* Write GREG boot_ready to 0 ++ * DW_0 = 0x0001_2018 ++ * DW_1 = 0x0000_0000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); ++ ++ /* Clear VI0 interrupt ++ * DW_2 = 0x0000_0fe8 ++ * DW_3 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); ++ ++ /* Clear VI1 interrupt ++ * DW_4 = 0x0000_1fe8 ++ * DW_5 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); ++ ++ /* CLear FGPI0 interrupt ++ * DW_6 = 0x0000_2fe8 ++ * DW_7 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI1 interrupt ++ * DW_8 = 0x0000_3fe8 ++ * DW_9 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI2 interrupt ++ * DW_10 = 0x0000_4fe8 ++ * DW_11 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI3 interrupt ++ * DW_12 = 0x0000_5fe8 ++ * DW_13 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear AI0 interrupt ++ * DW_14 = 0x0000_6020 ++ * DW_15 = 0x0000_000f ++ */ ++ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); ++ ++ /* Clear AI1 interrupt ++ * DW_16 = 0x0000_7020 ++ * DW_17 = 0x0000_200f ++ */ ++ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); ++ ++ /* Set GREG boot_ready bit to 1 ++ * DW_18 = 0x0001_2018 ++ * DW_19 = 0x0000_2000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++#if 0 ++ /* End of Boot script command ++ * DW_20 = 0x0000_0006 ++ * Where to write this value ?? ++ * This seems very odd an address to trigger the ++ * Boot Control State Machine ! ++ */ ++ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); ++#endif ++ return 0; ++} ++ ++/* Internal Bootscript configuration */ ++static void saa716x_int_boot(struct saa716x_dev *saa716x) ++{ ++ /* #1 Configure PCI COnfig space ++ * GREG_JETSTR_CONFIG_0 ++ */ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); ++ ++ /* GREG_JETSTR_CONFIG_1 ++ * pmcsr_scale:7 = 0x00 ++ * pmcsr_scale:6 = 0x00 ++ * pmcsr_scale:5 = 0x00 ++ * pmcsr_scale:4 = 0x00 ++ * pmcsr_scale:3 = 0x00 ++ * pmcsr_scale:2 = 0x00 ++ * pmcsr_scale:1 = 0x00 ++ * pmcsr_scale:0 = 0x00 ++ * BAR mask = 20 bit ++ * BAR prefetch = no ++ * MSI capable = 32 messages ++ */ ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); ++ ++ /* GREG_JETSTR_CONFIG_2 ++ * pmcsr_data:3 = 0x0 ++ * pmcsr_data:2 = 0x0 ++ * pmcsr_data:1 = 0x0 ++ * pmcsr_data:0 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); ++ ++ /* GREG_JETSTR_CONFIG_3 ++ * pmcsr_data:7 = 0x0 ++ * pmcsr_data:6 = 0x0 ++ * pmcsr_data:5 = 0x0 ++ * pmcsr_data:4 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); ++ ++ /* #2 Release GREG resets ++ * ip_rst_an ++ * dpa1_rst_an ++ * jetsream_reset_an ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); ++ ++ /* #3 GPIO Setup ++ * GPIO 25:24 = Output ++ * GPIO Output "0" after Reset ++ */ ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ ++ /* #4 Custom stuff goes in here */ ++ ++ /* #5 Disable CGU Clocks ++ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG ++ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 ++ */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); ++ ++ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); ++ ++ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); ++ ++ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); ++ ++ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); ++ ++ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); ++ ++ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); ++ ++ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); ++ ++ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); ++ ++ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); ++ ++ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); ++ ++ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); ++ ++ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); ++ ++ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); ++ ++ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); ++ ++ /* #6 Set GREG boot_ready = 0x1 */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++ ++ /* #7 Disable GREG CGU Clock */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); ++ ++ /* End of Bootscript command ?? */ ++} ++ ++int saa716x_core_boot(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_config *config = saa716x->config; ++ ++ switch (config->boot_mode) { ++ case SAA716x_EXT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); ++ saa716x_ext_boot(saa716x); ++ break; ++ case SAA716x_INT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); ++ saa716x_int_boot(saa716x); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_core_boot); ++ ++static void saa716x_bus_report(struct pci_dev *pdev, int enable) ++{ ++ u32 reg; ++ ++ pci_read_config_dword(pdev, 0x04, ®); ++ if (enable) ++ reg |= 0x00000100; /* enable SERR */ ++ else ++ reg &= 0xfffffeff; /* disable SERR */ ++ pci_write_config_dword(pdev, 0x04, reg); ++ ++ pci_read_config_dword(pdev, 0x58, ®); ++ reg &= 0xfffffffd; ++ pci_write_config_dword(pdev, 0x58, reg); ++} ++ ++int saa716x_jetpack_init(struct saa716x_dev *saa716x) ++{ ++ /* ++ * configure PHY through config space not to report ++ * non-fatal error messages to avoid problems with ++ * quirky BIOS'es ++ */ ++ saa716x_bus_report(saa716x->pdev, 0); ++ ++ /* ++ * create time out for blocks that have no clock ++ * helps with lower bitrates on FGPI ++ */ ++ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); ++ ++ /* Reset all blocks */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ switch (saa716x->pdev->device) { ++ case SAA7162: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ ++ break; ++ case SAA7161: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ ++ break; ++ case SAA7160: ++ saa716x->i2c_rate = SAA716x_I2C_RATE_100; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); ++ return -ENODEV; ++ } ++ ++ /* General setup for MMU */ ++ SAA716x_EPWR(MMU, MMU_MODE, 0x14); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_jetpack_init); ++ ++void saa716x_core_reset(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); ++ ++ /* VIP */ ++ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); ++ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); ++ ++ /* FGPI */ ++ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* AIP */ ++ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); ++ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); ++ ++ /* BAM */ ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ /* MMU */ ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ ++ /* MSI */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++} ++EXPORT_SYMBOL_GPL(saa716x_core_reset); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.h 2013-01-16 10:41:10.908798304 +0100 +@@ -0,0 +1,18 @@ ++#ifndef __SAA716x_BOOT_H ++#define __SAA716x_BOOT_H ++ ++#define DISABLE_TIMEOUT 0x17 ++#define ENABLE_TIMEOUT 0x16 ++ ++enum saa716x_boot_mode { ++ SAA716x_EXT_BOOT = 1, ++ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++extern void saa716x_core_reset(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_BOOT_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.c 2013-01-16 10:41:10.909798296 +0100 +@@ -0,0 +1,717 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_budget.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "mb86a16.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "ds3103.h" ++#include "ts2022.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Budget" ++ ++static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); ++ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_budget_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" ++#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" ++ ++static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp3071_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP3071, ++ .dev_type = SAA716x_DEV_TWINHAN_VP3071, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_vp3071_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" ++#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" ++ ++static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp1028_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp1028_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count == 0) { ++ ++ mutex_lock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); ++ saa716x_gpio_set_output(saa716x, 10); ++ msleep(1); ++ ++ /* VP-1028 has inverted power supply control */ ++ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ ++ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ ++ msleep(100); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); ++ saa716x_gpio_set_output(saa716x, 12); ++ msleep(1); ++ ++ /* reset demodulator (Active LOW) */ ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 0); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ ++ mutex_unlock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp1028_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp1028_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP1028, ++ .dev_type = SAA716x_DEV_TWINHAN_VP1028, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp1028_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" ++#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" ++ ++static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp6002_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6002, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6002, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6002_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" ++#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" ++ ++static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_knc1_duals2_config = { ++ .model_name = SAA716x_MODEL_KNC1_DUALS2, ++ .dev_type = SAA716x_DEV_KNC1_DUALS2, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_knc1_duals2_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" ++#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" ++ ++static struct stv090x_config skystar2_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 8000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_sleep = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static int skystar2_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ int err; ++ u8 en = 0; ++ u8 sel = 0; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ en = 0; ++ break; ++ ++ case SEC_VOLTAGE_13: ++ en = 1; ++ sel = 0; ++ break; ++ ++ case SEC_VOLTAGE_18: ++ en = 1; ++ sel = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ err = stv090x_set_gpio(fe, 2, 0, en, 0); ++ if (err < 0) ++ goto exit; ++ err = stv090x_set_gpio(fe, 3, 0, sel, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) ++{ ++ int err; ++ u8 value; ++ ++ if (arg) ++ value = 1; ++ else ++ value = 0; ++ ++ err = stv090x_set_gpio(fe, 4, 0, value, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static struct stv6110x_config skystar2_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 16000000, ++ .clk_div = 2, ++}; ++ ++static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct stv6110x_devctl *ctl; ++ ++ if (count < saa716x->config->adapters) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ saa716x_gpio_set_output(saa716x, 26); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(stv090x_attach, ++ &skystar2_stv090x_config, ++ &i2c->i2c_adapter, ++ STV090x_DEMODULATOR_0); ++ ++ if (adapter->fe) { ++ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", ++ skystar2_stv090x_config.address); ++ } else { ++ goto exit; ++ } ++ ++ adapter->fe->ops.set_voltage = skystar2_set_voltage; ++ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; ++ ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &skystar2_stv6110x_config, ++ &i2c->i2c_adapter); ++ ++ if (ctl) { ++ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", ++ skystar2_stv6110x_config.addr); ++ ++ skystar2_stv090x_config.tuner_init = ctl->tuner_init; ++ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config skystar2_express_hd_config = { ++ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, ++ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = skystar2_express_hd_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct ds3103_config s472_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 1, ++}; ++ ++static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count != 0) ++ return 0; ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); ++ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, ++ &i2c->i2c_adapter); ++ ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", ++ s472_ds3103_config.demod_address); ++ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) ++ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); ++ else ++ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ ++} ++ ++static struct saa716x_config tevii_s472_config = { ++ .model_name = "TeVii S472 DVB-S2", ++ .dev_type = "DVB-S/S2", ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_s472_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct pci_device_id saa716x_budget_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ ++ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), ++ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), ++ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); ++ ++static struct pci_driver saa716x_budget_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_budget_pci_table, ++ .probe = saa716x_budget_pci_probe, ++ .remove = saa716x_budget_pci_remove, ++}; ++ ++static int saa716x_budget_init(void) ++{ ++ return pci_register_driver(&saa716x_budget_pci_driver); ++} ++ ++static void saa716x_budget_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_budget_pci_driver); ++} ++ ++module_init(saa716x_budget_init); ++module_exit(saa716x_budget_exit); ++ ++MODULE_DESCRIPTION("SAA716x Budget driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.h 2013-01-16 10:41:10.910798289 +0100 +@@ -0,0 +1,17 @@ ++#ifndef __SAA716x_BUDGET_H ++#define __SAA716x_BUDGET_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define TWINHAN_VP_3071 0x0039 ++#define TWINHAN_VP_1028 0x0044 ++#define TWINHAN_VP_6002 0x0047 ++ ++#define KNC_One 0x1894 ++#define KNC_Dual_S2 0x0110 ++ ++#define TECHNISAT 0x1AE4 ++#define SKYSTAR2_EXPRESS_HD 0x0700 ++#define TEVII 0x9022 ++#define TEVII_S472 0xd472 ++ ++#endif /* __SAA716x_BUDGET_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.c 2013-01-16 10:41:10.910798289 +0100 +@@ -0,0 +1,539 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_cgu_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++u32 cgu_clk[14] = { ++ CGU_FDC_0, ++ CGU_FDC_1, ++ CGU_FDC_2, ++ CGU_FDC_3, ++ CGU_FDC_4, ++ CGU_FDC_5, ++ CGU_FDC_6, ++ CGU_FDC_7, ++ CGU_FDC_8, ++ CGU_FDC_9, ++ CGU_FDC_10, ++ CGU_FDC_11, ++ CGU_FDC_12, ++ CGU_FDC_13 ++}; ++ ++char *clk_desc[14] = { ++ "Clk PSS", ++ "Clk DCS", ++ "Clk SPI", ++ "Clk I2C/Boot", ++ "Clk PHI", ++ "Clk VI0", ++ "Clk VI1", ++ "Clk FGPI0", ++ "Clk FGPI1", ++ "Clk FGPI2", ++ "Clk FGPI3", ++ "Clk AI0", ++ "Clk AI1", ++ "Clk Phy" ++}; ++ ++int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 i; ++ s8 N = 0; ++ s16 M = 0; ++ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ ++ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ ++ ++ /* get all dividers */ ++ for (i = 0; i < CGU_CLKS; i++) { ++ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); ++ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; ++ ++ N = (cgu->clk_boot_div[i] >> 11) & 0xff; ++ N *= -1; ++ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; ++ ++ if (M) ++ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; ++ else ++ cgu->clk_freq[i] = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", ++ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); ++ } ++ /* store clock settings */ ++ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ ++ return 0; ++} ++ ++int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ SAA716x_CGU_CLKRUN(7); ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ SAA716x_CGU_CLKRUN(8); ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ SAA716x_CGU_CLKRUN(9); ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ SAA716x_CGU_CLKRUN(10); ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ SAA716x_CGU_CLKRUN(11); ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ SAA716x_CGU_CLKRUN(12); ++ break; ++ ++ case PORT_ALL: ++ SAA716x_CGU_CLKRUN(5); ++ SAA716x_CGU_CLKRUN(6); ++ SAA716x_CGU_CLKRUN(7); ++ SAA716x_CGU_CLKRUN(8); ++ SAA716x_CGU_CLKRUN(9); ++ SAA716x_CGU_CLKRUN(10); ++ SAA716x_CGU_CLKRUN(11); ++ SAA716x_CGU_CLKRUN(12); ++ ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ cgu->clk_int_port[PORT_AI0] = 1; ++ cgu->clk_int_port[PORT_AI1] = 1; ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ } ++ ++ /* wait for PLL */ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ ++ } ++ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_get_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 *frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_VI0: ++ case CLK_DOMAIN_VI1: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ *frequency = cgu->clk_freq[domain]; ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_set_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u32 M = 1, N = 1, reset, i; ++ s8 N_tmp, M_tmp, sub, add, lsb; ++ ++ ++ if (cgu->clk_freq_min > frequency) ++ frequency = cgu->clk_freq_min; ++ ++ if (cgu->clk_freq_max < frequency) ++ frequency = cgu->clk_freq_max; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ ++ if (frequency == cgu->clk_freq[domain]) ++ return 0; /* same frequency */ ++ break; ++ ++ case CLK_DOMAIN_VI0: ++ ++ if (frequency == cgu->clk_vi_0[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_0[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI1: ++ if (frequency == cgu->clk_vi_1[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_1[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ if (frequency == cgu->clk_vi_0[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_0[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI0; /* change domain */ ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ if (frequency == cgu->clk_vi_1[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_1[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI1; /* change domain */ ++ break; ++ } ++ ++ /* calculate divider */ ++ do { ++ M = (N * PLL_FREQ) / frequency; ++ if (M == 0) ++ N++; ++ ++ } while (M == 0); ++ ++ /* calculate frequency */ ++ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; ++ ++ N_tmp = N & 0xff; ++ M_tmp = M & 0xff; ++ sub = -N_tmp; ++ add = M_tmp - N_tmp; ++ lsb = 4; /* run */ ++ ++ if (((10 * N) / M) < 5) ++ lsb |= 1; /* stretch */ ++ ++ /* store new divider */ ++ cgu->clk_curr_div[domain] = sub & 0xff; ++ cgu->clk_curr_div[domain] <<= 8; ++ cgu->clk_curr_div[domain] = add & 0xff; ++ cgu->clk_curr_div[domain] <<= 3; ++ cgu->clk_curr_div[domain] |= lsb; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", ++ domain, ++ frequency, ++ cgu->clk_freq[domain], ++ N, ++ M, ++ cgu->clk_curr_div[domain]); ++ ++ reset = 0; ++ ++ /* Reset */ ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); ++ ++ /* Reset disable */ ++ for (i = 0; i < 1000; i++) { ++ msleep(10); ++ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); ++ ++ if (cgu->clk_curr_div[domain == reset]) ++ break; ++ } ++ ++ if (cgu->clk_curr_div[domain] != reset) ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); ++ ++ return 0; ++} ++ ++int saa716x_cgu_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ cgu->clk_freq_min = PLL_FREQ / 255; ++ if (PLL_FREQ > (cgu->clk_freq_min * 255)) ++ cgu->clk_freq_min++; ++ ++ cgu->clk_freq_max = PLL_FREQ; ++ ++ saa716x_getbootscript_setup(saa716x); ++ saa716x_set_clk_internal(saa716x, PORT_ALL); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_cgu_init); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.h 2013-01-16 10:41:10.911798282 +0100 +@@ -0,0 +1,61 @@ ++#ifndef __SAA716x_CGU_H ++#define __SAA716x_CGU_H ++ ++#define PLL_FREQ 2500 ++ ++#define SAA716x_CGU_CLKRUN(__reg) do { \ ++ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ ++ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ ++ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ ++ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ ++} while (0) ++ ++enum saa716x_clk_domain { ++ CLK_DOMAIN_PSS = 0, ++ CLK_DOMAIN_DCS = 1, ++ CLK_DOMAIN_SPI = 2, ++ CLK_DOMAIN_I2C = 3, ++ CLK_DOMAIN_PHI = 4, ++ CLK_DOMAIN_VI0 = 5, ++ CLK_DOMAIN_VI1 = 6, ++ CLK_DOMAIN_FGPI0 = 7, ++ CLK_DOMAIN_FGPI1 = 8, ++ CLK_DOMAIN_FGPI2 = 9, ++ CLK_DOMAIN_FGPI3 = 10, ++ CLK_DOMAIN_AI0 = 11, ++ CLK_DOMAIN_AI1 = 12, ++ CLK_DOMAIN_PHY = 13, ++ CLK_DOMAIN_VI0VBI = 14, ++ CLK_DOMAIN_VI1VBI = 15 ++}; ++ ++#define PORT_VI0_VIDEO 0 ++#define PORT_VI0_VBI 2 ++#define PORT_VI1_VIDEO 3 ++#define PORT_VI1_VBI 5 ++#define PORT_FGPI0 6 ++#define PORT_FGPI1 7 ++#define PORT_FGPI2 8 ++#define PORT_FGPI3 9 ++#define PORT_AI0 10 ++#define PORT_AI1 11 ++#define PORT_ALL 12 ++ ++#define CGU_CLKS 14 ++ ++struct saa716x_cgu { ++ u8 clk_int_port[12]; ++ u32 clk_vi_0[3]; ++ u32 clk_vi_1[3]; ++ u32 clk_boot_div[CGU_CLKS]; ++ u32 clk_curr_div[CGU_CLKS]; ++ u32 clk_freq[CGU_CLKS]; ++ u32 clk_freq_min; ++ u32 clk_freq_max; ++}; ++ ++extern int saa716x_cgu_init(struct saa716x_dev *saa716x); ++extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); ++extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); ++ ++#endif /* __SAA716x_CGU_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu_reg.h 2013-01-16 10:41:10.911798282 +0100 +@@ -0,0 +1,178 @@ ++#ifndef __SAA716x_CGU_REG_H ++#define __SAA716x_CGU_REG_H ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++#endif /* __SAA716x_CGU_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dcs_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dcs_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_dcs_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dcs_reg.h 2013-01-16 10:41:10.912798275 +0100 +@@ -0,0 +1,56 @@ ++#ifndef __SAA716x_DCS_REG_H ++#define __SAA716x_DCS_REG_H ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_DCS_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.c 2013-01-16 10:41:10.912798275 +0100 +@@ -0,0 +1,306 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "saa716x_dma.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++/* Allocates one page of memory, which is stores the data of one ++ * 716x page table. The result gets stored in the passed DMA buffer ++ * structure. ++ */ ++static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); ++ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); ++ ++ if (dmabuf->mem_ptab_virt == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); ++ return -ENOMEM; ++ } ++ ++ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, ++ dmabuf->mem_ptab_virt, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ if (dmabuf->mem_ptab_phys == 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); ++ return -ENOMEM; ++ } ++ ++ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); ++ ++ return 0; ++} ++ ++static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); ++ ++ /* free physical PCI memory */ ++ if (dmabuf->mem_ptab_phys != 0) { ++ dma_unmap_single(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ dmabuf->mem_ptab_phys = 0; ++ } ++ ++ /* free kernel memory */ ++ if (dmabuf->mem_ptab_virt != NULL) { ++ free_page((unsigned long) dmabuf->mem_ptab_virt); ++ dmabuf->mem_ptab_virt = NULL; ++ } ++} ++ ++static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG free"); ++ ++ dmabuf->mem_virt = NULL; ++ if (dmabuf->mem_virt_noalign != NULL) { ++ if (dmabuf->dma_type == SAA716x_DMABUF_INT) ++ vfree(dmabuf->mem_virt_noalign); ++ ++ dmabuf->mem_virt_noalign = NULL; ++ } ++ ++ if (dmabuf->sg_list != NULL) { ++ kfree(dmabuf->sg_list); ++ dmabuf->sg_list = NULL; ++ } ++} ++ ++/* ++ * Create a SG, when an allocated buffer is passed to it, ++ * otherwise the needed memory gets allocated by itself ++ */ ++static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct scatterlist *list; ++ struct page *pg; ++ ++ int i, pages; ++ ++ BUG_ON(!(size > 0)); ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG allocate"); ++ ++ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ ++ pages = size / SAA716x_PAGE_SIZE + 1; ++ else ++ pages = size / SAA716x_PAGE_SIZE; ++ ++ /* Allocate memory for SG list */ ++ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); ++ if (dmabuf->sg_list == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); ++ return -ENOMEM; ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); ++ sg_init_table(dmabuf->sg_list, pages); ++ ++ if (buf == NULL) { ++ ++ /* allocate memory, unaligned */ ++ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); ++ if (dmabuf->mem_virt_noalign == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); ++ return -ENOMEM; ++ } ++ ++ /* align memory to page */ ++ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); ++ ++ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); ++ } else { ++ dmabuf->mem_virt = buf; ++ } ++ ++ dmabuf->list_len = pages; /* scatterlist length */ ++ list = dmabuf->sg_list; ++ ++ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); ++ for (i = 0; i < pages; i++) { ++ if (buf == NULL) ++ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ else ++ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ ++ BUG_ON(pg == NULL); ++ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Done!"); ++ return 0; ++} ++ ++/* Fill the "page table" page with the pointers to the specified SG buffer */ ++static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ struct scatterlist *sg_cur; ++ ++ u32 *page; ++ int i, j, k = 0; ++ dma_addr_t addr = 0; ++ ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(sg_list == NULL); ++ BUG_ON(pages == 0); ++ dprintk(SAA716x_DEBUG, 1, "SG page fill"); ++ ++ /* make page writable for the PC */ ++ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); ++ page = dmabuf->mem_ptab_virt; ++ ++ /* create page table */ ++ for (i = 0; i < pages; i++) { ++ sg_cur = &sg_list[i]; ++ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); ++ ++ if (i == 0) ++ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; ++ else ++ BUG_ON(sg_cur->offset != 0); ++ ++ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { ++ ++ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { ++ offset -= SAA716x_PAGE_SIZE; ++ continue; ++ } ++ ++ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; ++ ++ BUG_ON(addr == 0); ++ page[k * 2] = (u32 )addr; /* Low */ ++ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ ++ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); ++ k++; ++ } ++ } ++ ++ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { ++ page[k * 2] = (u32 ) addr; ++ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); ++ } ++ ++ /* make "page table" page writable for the PC */ ++ dma_sync_single_for_device(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_device(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_cpu(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++} ++ ++/* Allocates a DMA buffer for the specified external linear buffer. */ ++int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ int ret; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(! (size > 0)); ++ ++ dmabuf->dma_type = SAA716x_DMABUF_INT; ++ ++ dmabuf->mem_virt_noalign = NULL; ++ dmabuf->mem_virt = NULL; ++ dmabuf->mem_ptab_phys = 0; ++ dmabuf->mem_ptab_virt = NULL; ++ ++ dmabuf->list_len = 0; ++ dmabuf->saa716x = saa716x; ++ ++ /* Allocate page table */ ++ ret = saa716x_allocate_ptable(dmabuf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); ++ goto err1; ++ } ++ ++ /* Allocate buffer as SG */ ++ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); ++ goto err2; ++ } ++ ++ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG map failed"); ++ goto err3; ++ } ++ ++ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); ++ ++ return 0; ++err3: ++ saa716x_dmabuf_sgfree(dmabuf); ++err2: ++ saa716x_free_ptable(dmabuf); ++err1: ++ return ret; ++} ++ ++void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ ++ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ saa716x_dmabuf_sgfree(dmabuf); ++ saa716x_free_ptable(dmabuf); ++} +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.h 2013-01-16 10:41:10.913798268 +0100 +@@ -0,0 +1,38 @@ ++#ifndef __SAA716x_DMA_H ++#define __SAA716x_DMA_H ++ ++#define SAA716x_PAGE_SIZE 4096 ++ ++enum saa716x_dma_type { ++ SAA716x_DMABUF_EXT_LIN, /* Linear external */ ++ SAA716x_DMABUF_EXT_SG, /* SG external */ ++ SAA716x_DMABUF_INT /* Linear internal */ ++}; ++ ++struct saa716x_dev; ++ ++struct saa716x_dmabuf { ++ enum saa716x_dma_type dma_type; ++ ++ void *mem_virt_noalign; ++ void *mem_virt; /* page aligned */ ++ dma_addr_t mem_ptab_phys; ++ void *mem_ptab_virt; ++ void *sg_list; /* SG list */ ++ ++ struct saa716x_dev *saa716x; ++ ++ int list_len; /* buffer len */ ++ int offset; /* page offset */ ++}; ++ ++extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf, ++ int size); ++extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf); ++ ++extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); ++extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); ++ ++#endif /* __SAA716x_DMA_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma_reg.h 2013-01-16 10:41:10.913798268 +0100 +@@ -0,0 +1,200 @@ ++#ifndef __SAA716x_DMA_REG_H ++#define __SAA716x_DMA_REG_H ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++#endif /* __SAA716x_DMA_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.c 2013-01-16 10:41:10.914798261 +0100 +@@ -0,0 +1,412 @@ ++#include ++ ++#include ++#include ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_phi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++ ++int sti7109_cmd_init(struct sti7109_dev *sti7109) ++{ ++ mutex_init(&sti7109->cmd_lock); ++ mutex_init(&sti7109->osd_cmd_lock); ++ mutex_init(&sti7109->data_lock); ++ ++ init_waitqueue_head(&sti7109->boot_finish_wq); ++ sti7109->boot_finished = 0; ++ ++ init_waitqueue_head(&sti7109->cmd_ready_wq); ++ sti7109->cmd_ready = 0; ++ ++ init_waitqueue_head(&sti7109->result_avail_wq); ++ sti7109->result_avail = 0; ++ ++ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); ++ sti7109->osd_cmd_ready = 0; ++ init_waitqueue_head(&sti7109->osd_result_avail_wq); ++ sti7109->osd_result_avail = 0; ++ ++ sti7109->data_handle = 0; ++ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); ++ init_waitqueue_head(&sti7109->data_ready_wq); ++ sti7109->data_ready = 0; ++ init_waitqueue_head(&sti7109->block_done_wq); ++ sti7109->block_done = 0; ++ return 0; ++} ++ ++static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, ++ sti7109->cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command ready"); ++ return -EIO; ++ } ++ ++ sti7109->cmd_ready = 0; ++ sti7109->result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, ++ sti7109->cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); ++ ++ if (sti7109->result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->result_avail_wq, ++ sti7109->result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { ++ sti7109->result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->result_len > sti7109->result_max_len) { ++ sti7109->result_len = sti7109->result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->cmd_len = cmd->cmd_len; ++ sti7109->result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->result_len; ++ if (sti7109->result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->result_data, ++ sti7109->result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, ++ sti7109->osd_cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command ready"); ++ return -EIO; ++ } ++ ++ sti7109->osd_cmd_ready = 0; ++ sti7109->osd_result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, ++ sti7109->osd_cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); ++ ++ if (sti7109->osd_result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->osd_result_avail_wq, ++ sti7109->osd_result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { ++ sti7109->osd_result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, ++ "osd result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { ++ sti7109->osd_result_len = sti7109->osd_result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->osd_cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->osd_cmd_len = cmd->cmd_len; ++ sti7109->osd_result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_osd_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->osd_result_len; ++ if (sti7109->osd_result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->osd_result_data, ++ sti7109->osd_result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->osd_cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ u16 blockSize; ++ u16 lastBlockSize; ++ u16 numBlocks; ++ u16 blockIndex; ++ u8 blockHeader[SIZE_BLOCK_HEADER]; ++ u8 * blockPtr; ++ int activeBlock; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, ++ sti7109->data_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); ++ return -EIO; ++ } ++ ++ sti7109->data_ready = 0; ++ ++ /* ++ * 8 bytes is the size of the block header. Block header structure is: ++ * 16 bit - block index ++ * 16 bit - number of blocks ++ * 16 bit - current block data size ++ * 16 bit - block handle. This is used to reference the data in the ++ * command that uses it. ++ */ ++ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; ++ numBlocks = data->data_length / blockSize; ++ lastBlockSize = data->data_length % blockSize; ++ if (lastBlockSize > 0) ++ numBlocks++; ++ ++ blockHeader[2] = (u8) (numBlocks >> 8); ++ blockHeader[3] = (u8) numBlocks; ++ blockHeader[6] = (u8) (sti7109->data_handle >> 8); ++ blockHeader[7] = (u8) sti7109->data_handle; ++ blockPtr = sti7109->data_buffer; ++ activeBlock = 0; ++ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { ++ u32 addr; ++ ++ if (lastBlockSize && (blockIndex == (numBlocks - 1))) ++ blockSize = lastBlockSize; ++ ++ blockHeader[0] = (uint8_t) (blockIndex >> 8); ++ blockHeader[1] = (uint8_t) blockIndex; ++ blockHeader[4] = (uint8_t) (blockSize >> 8); ++ blockHeader[5] = (uint8_t) blockSize; ++ ++ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); ++ saa716x_phi_write(saa716x, addr, blockHeader, ++ SIZE_BLOCK_HEADER); ++ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, ++ blockSize); ++ activeBlock = (activeBlock + 1) & 1; ++ if (blockIndex > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for block done"); ++ return -EIO; ++ } ++ } ++ sti7109->block_done = 0; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); ++ blockPtr += blockSize; ++ } ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); ++ return -EIO; ++ } ++ sti7109->block_done = 0; ++ ++ data->data_handle = sti7109->data_handle; ++ sti7109->data_handle++; ++ return 0; ++} ++ ++int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (data->data_length > MAX_DATA_LEN) { ++ dprintk(SAA716x_ERROR, 1, "data too big"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->data_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->data_buffer, ++ (void __user *)data->data_buffer, ++ data->data_length)) ++ goto out; ++ ++ err = sti7109_do_raw_data(sti7109, data); ++ if (err) ++ goto out; ++ ++out: ++ mutex_unlock(&sti7109->data_lock); ++ return err; ++} ++ ++int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x04; ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x00; ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x00; ++ sti7109->cmd_len = 6; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ *fw_version = (sti7109->result_data[6] << 16) ++ | (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ ++int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x05; /* command length */ ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x10; /* get video format info command */ ++ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ ++ sti7109->cmd_len = 7; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ vs->w = (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ vs->h = (sti7109->result_data[9] << 8) ++ | sti7109->result_data[10]; ++ vs->aspect_ratio = sti7109->result_data[11] >> 4; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.h 2013-01-16 10:41:10.914798261 +0100 +@@ -0,0 +1,16 @@ ++#ifndef __SAA716x_FF_CMD_H ++#define __SAA716x_FF_CMD_H ++ ++extern int sti7109_cmd_init(struct sti7109_dev *sti7109); ++extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_data(struct sti7109_dev * sti7109, ++ osd_raw_data_t * data); ++extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, ++ u32 *fw_version); ++extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, ++ video_size_t *vs); ++ ++#endif /* __SAA716x_FF_CMD_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff.h 2013-01-16 10:41:10.915798254 +0100 +@@ -0,0 +1,158 @@ ++#ifndef __SAA716x_FF_H ++#define __SAA716x_FF_H ++ ++#include "dvb_filter.h" ++#include "dvb_ringbuffer.h" ++ ++#define TECHNOTREND 0x13c2 ++#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 ++#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A ++ ++#define TT_PREMIUM_GPIO_POWER_ENABLE 27 ++#define TT_PREMIUM_GPIO_RESET_BACKEND 26 ++#define TT_PREMIUM_GPIO_FPGA_CS1 17 ++#define TT_PREMIUM_GPIO_FPGA_CS0 16 ++#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 ++#define TT_PREMIUM_GPIO_FPGA_DONE 14 ++#define TT_PREMIUM_GPIO_FPGA_INITN 13 ++ ++/* fpga interrupt register addresses */ ++#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ ++#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ ++#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ ++#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ ++#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ ++#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ ++#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ ++#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ ++ ++/* fpga TS router register addresses */ ++#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ ++#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ ++#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ ++#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ ++#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ ++#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ ++ ++#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ ++#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ ++#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ ++#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ ++#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ ++#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ ++ ++/* fpga TS FIFO register addresses */ ++#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ ++#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ ++ ++#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ ++ ++#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ ++ ++#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ ++#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ ++#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ ++#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ ++#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ ++#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ ++#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ ++#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ ++#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ ++#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ ++#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ ++#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ ++#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ ++#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ ++#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ ++#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ ++ ++#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ ++#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ ++#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ ++#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ ++#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ ++#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ ++#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ ++#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ ++#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ ++#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ ++ ++#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ ++#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ ++#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ ++#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ ++#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ ++ ++#define SIZE_BLOCK_HEADER 8 /* block header size */ ++ ++#define MAX_RESULT_LEN 256 ++#define MAX_DATA_LEN (1024 * 1024) ++ ++#define TSOUT_LEN (1024 * TS_SIZE) ++#define TSBUF_LEN (8 * 1024) ++ ++/* place to store all the necessary device information */ ++struct sti7109_dev { ++ struct saa716x_dev *dev; ++ struct dvb_device *osd_dev; ++ struct dvb_device *video_dev; ++ struct dvb_device *audio_dev; ++ ++ void *iobuf; /* memory for all buffers */ ++ struct dvb_ringbuffer tsout; /* buffer for TS output */ ++ u8 *tsbuf; /* temp ts buffer */ ++ ++ struct tasklet_struct fifo_tasklet; ++ ++ wait_queue_head_t boot_finish_wq; ++ int boot_finished; ++ ++ wait_queue_head_t cmd_ready_wq; ++ int cmd_ready; ++ u8 cmd_data[SIZE_CMD_DATA]; ++ u32 cmd_len; ++ ++ wait_queue_head_t result_avail_wq; ++ int result_avail; ++ u8 result_data[MAX_RESULT_LEN]; ++ u32 result_len; ++ u32 result_max_len; ++ ++ wait_queue_head_t osd_cmd_ready_wq; ++ int osd_cmd_ready; ++ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; ++ u32 osd_cmd_len; ++ ++ wait_queue_head_t osd_result_avail_wq; ++ int osd_result_avail; ++ u8 osd_result_data[MAX_RESULT_LEN]; ++ u32 osd_result_len; ++ u32 osd_result_max_len; ++ ++ u16 data_handle; ++ u8 *data_buffer; /* raw data transfer buffer */ ++ wait_queue_head_t data_ready_wq; ++ int data_ready; ++ wait_queue_head_t block_done_wq; ++ int block_done; ++ ++ struct mutex cmd_lock; ++ struct mutex osd_cmd_lock; ++ struct mutex data_lock; ++ ++ u64 audio_pts; ++ u64 video_pts; ++ u64 current_stc; ++ ++ u32 int_count_enable; ++ u32 total_int_count; ++ u32 fgpi_int_count[2]; ++ u32 i2c_int_count[2]; ++ u32 ext_int_total_count; ++ u32 ext_int_source_count[16]; ++ u32 last_int_ticks; ++ ++ u16 fpga_version; ++}; ++ ++#endif /* __SAA716x_FF_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_ir.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_ir.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_ir.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_ir.c 2013-01-16 10:41:10.915798254 +0100 +@@ -0,0 +1,265 @@ ++/* ++ * Driver for the remote control of the TT6400 DVB-S2 card ++ * ++ * Copyright (C) 2010 Oliver Endriss ++ * ++ * 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. ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++ ++ ++/* infrared remote control */ ++struct infrared { ++ u16 key_map[128]; ++ struct input_dev *input_dev; ++ char input_phys[32]; ++ struct timer_list keyup_timer; ++ struct tasklet_struct tasklet; ++ u32 command; ++ u32 device_mask; ++ u8 protocol; ++ u16 last_key; ++ u16 last_toggle; ++ bool delay_timer_finished; ++}; ++ ++#define IR_RC5 0 ++#define UP_TIMEOUT (HZ*7/25) ++ ++ ++/* key-up timer */ ++static void ir_emit_keyup(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) ++ return; ++ ++ input_report_key(ir->input_dev, ir->last_key, 0); ++ input_sync(ir->input_dev); ++} ++ ++ ++/* tasklet */ ++static void ir_emit_key(unsigned long parm) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; ++ struct infrared *ir = saa716x->ir_priv; ++ u32 ircom = ir->command; ++ u8 data; ++ u8 addr; ++ u16 toggle; ++ u16 keycode; ++ ++ /* extract device address and data */ ++ if (ircom & 0x80000000) { /* CEC remote command */ ++ addr = 0; ++ data = ircom & 0x7F; ++ toggle = 0; ++ } else { ++ switch (ir->protocol) { ++ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ ++ addr = (ircom >> 6) & 0x1f; ++ /* data bits 1..6 */ ++ data = ircom & 0x3f; ++ /* data bit 7 (inverted) */ ++ if (!(ircom & 0x1000)) ++ data |= 0x40; ++ toggle = ircom & 0x0800; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: invalid protocol %x\n", ++ __func__, ir->protocol); ++ return; ++ } ++ } ++ ++ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); ++ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); ++ ++ keycode = ir->key_map[data]; ++ ++ dprintk(SAA716x_DEBUG, 0, ++ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", ++ __func__, ircom, addr, data, keycode); ++ ++ /* check device address */ ++ if (!(ir->device_mask & (1 << addr))) ++ return; ++ ++ if (!keycode) { ++ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", ++ __func__, ircom, addr, data); ++ return; ++ } ++ ++ if (timer_pending(&ir->keyup_timer)) { ++ del_timer(&ir->keyup_timer); ++ if (ir->last_key != keycode || toggle != ir->last_toggle) { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } else if (ir->delay_timer_finished) { ++ input_event(ir->input_dev, EV_KEY, keycode, 2); ++ input_sync(ir->input_dev); ++ } ++ } else { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } ++ ++ ir->last_key = keycode; ++ ir->last_toggle = toggle; ++ ++ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; ++ add_timer(&ir->keyup_timer); ++ ++} ++ ++ ++/* register with input layer */ ++static void ir_register_keys(struct infrared *ir) ++{ ++ int i; ++ ++ set_bit(EV_KEY, ir->input_dev->evbit); ++ set_bit(EV_REP, ir->input_dev->evbit); ++ set_bit(EV_MSC, ir->input_dev->evbit); ++ ++ set_bit(MSC_RAW, ir->input_dev->mscbit); ++ set_bit(MSC_SCAN, ir->input_dev->mscbit); ++ ++ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); ++ ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { ++ if (ir->key_map[i] > KEY_MAX) ++ ir->key_map[i] = 0; ++ else if (ir->key_map[i] > KEY_RESERVED) ++ set_bit(ir->key_map[i], ir->input_dev->keybit); ++ } ++ ++ ir->input_dev->keycode = ir->key_map; ++ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); ++ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); ++} ++ ++ ++/* called by the input driver after rep[REP_DELAY] ms */ ++static void ir_repeat_key(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ ir->delay_timer_finished = true; ++} ++ ++ ++/* interrupt handler */ ++void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ if (!ir) ++ return; ++ ++ ir->command = ir_cmd; ++ tasklet_schedule(&ir->tasklet); ++} ++ ++ ++int saa716x_ir_init(struct saa716x_dev *saa716x) ++{ ++ struct input_dev *input_dev; ++ struct infrared *ir; ++ int rc; ++ int i; ++ ++ if (!saa716x) ++ return -ENOMEM; ++ ++ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); ++ if (!ir) ++ return -ENOMEM; ++ ++ init_timer(&ir->keyup_timer); ++ ir->keyup_timer.function = ir_emit_keyup; ++ ir->keyup_timer.data = (unsigned long) ir; ++ ++ input_dev = input_allocate_device(); ++ if (!input_dev) ++ goto err; ++ ++ ir->input_dev = input_dev; ++ input_dev->name = "TT6400 DVB IR receiver"; ++ snprintf(ir->input_phys, sizeof(ir->input_phys), ++ "pci-%s/ir0", pci_name(saa716x->pdev)); ++ input_dev->phys = ir->input_phys; ++ input_dev->id.bustype = BUS_PCI; ++ input_dev->id.version = 1; ++ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; ++ input_dev->id.product = saa716x->pdev->subsystem_device; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ input_dev->dev.parent = &saa716x->pdev->dev; ++#else ++ input_dev->cdev.dev = &saa716x->pdev->dev; ++#endif ++ rc = input_register_device(input_dev); ++ if (rc) ++ goto err; ++ ++ /* TODO: fix setup/keymap */ ++ ir->protocol = IR_RC5; ++ ir->device_mask = 0xffffffff; ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) ++ ir->key_map[i] = i+1; ++ ir_register_keys(ir); ++ ++ /* override repeat timer */ ++ input_dev->timer.function = ir_repeat_key; ++ input_dev->timer.data = (unsigned long) ir; ++ ++ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); ++ saa716x->ir_priv = ir; ++ ++ return 0; ++ ++err: ++ if (ir->input_dev) ++ input_free_device(ir->input_dev); ++ kfree(ir); ++ return -ENOMEM; ++} ++ ++ ++void saa716x_ir_exit(struct saa716x_dev *saa716x) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ saa716x->ir_priv = NULL; ++ tasklet_kill(&ir->tasklet); ++ del_timer_sync(&ir->keyup_timer); ++ input_unregister_device(ir->input_dev); ++ kfree(ir); ++} +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_main.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_main.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_main.c 2013-01-16 10:41:10.917798240 +0100 +@@ -0,0 +1,1535 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_dma_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_phi_reg.h" ++#include "saa716x_spi_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_vip.h" ++#include "saa716x_aip.h" ++#include "saa716x_msi.h" ++#include "saa716x_adap.h" ++#include "saa716x_gpio.h" ++#include "saa716x_phi.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "isl6423.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++unsigned int int_count_enable; ++module_param(int_count_enable, int, 0644); ++MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); ++ ++#define DRIVER_NAME "SAA716x FF" ++ ++static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ int fpgaInit; ++ int fpgaDone; ++ int rounds; ++ int ret; ++ const struct firmware *fw; ++ ++ /* request the FPGA firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," ++ " file not found: dvb-ttpremium-fpga-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ /* set FPGA PROGRAMN high */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN low to set it into configuration mode */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN high to start configuration process */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ ++ rounds = 0; ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ while (fpgaInit == 0 && rounds < 5000) { ++ //msleep(1); ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ rounds++; ++ } ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", ++ fpgaInit, rounds); ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); ++ ++ msleep(10); ++ ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); ++ saa716x_spi_write(saa716x, fw->data, fw->size); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ if (!fpgaDone) { ++ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " ++ "connect the power supply?\n"); ++ return -EINVAL; ++ } ++ ++ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); ++ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", ++ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); ++ ++ return 0; ++} ++ ++static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) ++{ ++ int i; ++ int length; ++ u32 requestedBlock; ++ u32 writtenBlock; ++ u32 numBlocks; ++ u32 blockSize; ++ u32 lastBlockSize; ++ u64 startTime; ++ u64 currentTime; ++ u64 waitTime; ++ int ret; ++ const struct firmware *fw; ++ u32 loaderVersion; ++ ++ /* request the st7109 loader, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," ++ " file not found: dvb-ttpremium-loader-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; ++ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", ++ loaderVersion >> 8, loaderVersion & 0xFF); ++ ++ saa716x_phi_write(saa716x, 0, fw->data, fw->size); ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ /* take ST out of reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); ++ ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == 1) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ return -1; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); ++ ++ /* request the st7109 firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," ++ " file not found: dvb-ttpremium-st7109-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); ++ writtenBlock = 0; ++ blockSize = 0x3c00; ++ length = fw->size; ++ numBlocks = length / blockSize; ++ lastBlockSize = length % blockSize; ++ for (i = 0; i < length; i += blockSize) { ++ writtenBlock++; ++ /* write one block (last may differ from blockSize) */ ++ if (lastBlockSize && writtenBlock == (numBlocks + 1)) ++ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); ++ else ++ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); ++ ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == (writtenBlock + 1)) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ release_firmware(fw); ++ return -1; ++ } ++ } ++ ++ /* disable frontend support through ST firmware */ ++ SAA716x_EPWR(PHI_1, 0x3ff4, 1); ++ ++ /* indicate end of transfer */ ++ writtenBlock++; ++ writtenBlock |= 0x80000000; ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); ++ ++ release_firmware(fw); ++ ++ return 0; ++} ++ ++static int saa716x_usercopy(struct dvb_device *dvbdev, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct dvb_device *dvbdev, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *) arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) ++ { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_osd_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_osd_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ int err = -EINVAL; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ if (cmd == OSD_RAW_CMD) { ++ osd_raw_cmd_t raw_cmd; ++ u8 hdr[4]; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_cmd, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) ++ goto out; ++ ++ if (hdr[3] == 4) ++ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); ++ else ++ err = sti7109_raw_cmd(sti7109, &raw_cmd); ++ ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ else if (cmd == OSD_RAW_DATA) { ++ osd_raw_data_t raw_data; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_data, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ err = sti7109_raw_data(sti7109, &raw_data); ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ ++out: ++ return err; ++} ++ ++static struct file_operations dvb_osd_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_osd_ioctl, ++#else ++ .unlocked_ioctl = dvb_osd_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_osd = { ++ .priv = NULL, ++ .users = 2, ++ .writers = 2, ++ .fops = &dvb_osd_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->osd_dev); ++ return 0; ++} ++ ++static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->osd_dev, ++ &dvbdev_osd, ++ sti7109, ++ DVB_DEVICE_OSD); ++ ++ return 0; ++} ++ ++static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ //struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case AUDIO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->audio_pts; ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_audio_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_audio_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); ++} ++ ++static struct file_operations dvb_audio_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_audio_ioctl, ++#else ++ .unlocked_ioctl = dvb_audio_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_audio_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->audio_dev); ++ return 0; ++} ++ ++static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->audio_dev, ++ &dvbdev_audio, ++ sti7109, ++ DVB_DEVICE_AUDIO); ++ ++ return 0; ++} ++ ++static void fifo_worker(unsigned long data) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ u32 fifoCtrl; ++ u32 fifoStat; ++ u16 fifoSize; ++ u16 fifoUsage; ++ u16 fifoFree; ++ int len; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); ++ fifoSize = (u16) (fifoStat >> 16); ++ fifoUsage = (u16) fifoStat; ++ fifoFree = fifoSize - fifoUsage; ++ spin_lock(&sti7109->tsout.lock); ++ len = dvb_ringbuffer_avail(&sti7109->tsout); ++ if (len > fifoFree) ++ len = fifoFree; ++ if (len >= TS_SIZE) ++ { ++ while (len >= TS_SIZE) ++ { ++ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); ++ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); ++ len -= TS_SIZE; ++ } ++ wake_up(&sti7109->tsout.queue); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ spin_unlock(&sti7109->tsout.lock); ++} ++ ++#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) ++ ++static ssize_t dvb_video_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ unsigned long todo = count; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ return -EPERM; ++/* ++ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) ++ return -EPERM; ++*/ ++ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) ++ return -EWOULDBLOCK; ++ ++ while (todo >= TS_SIZE) { ++ if (!FREE_COND_TS) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) ++ break; ++ } ++ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); ++ todo -= TS_SIZE; ++ buf += TS_SIZE; ++ } ++ ++ if (count > todo) { ++ u32 fifoCtrl; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ ++ return count - todo; ++} ++ ++static unsigned int dvb_video_poll(struct file *file, poll_table *wait) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ unsigned int mask = 0; ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) ++ poll_wait(file, &sti7109->tsout.queue, wait); ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { ++ if (1/*sti7109->playing*/) { ++ if (FREE_COND_TS) ++ mask |= (POLLOUT | POLLWRNORM); ++ } else /* if not playing: may play if asked for */ ++ mask |= (POLLOUT | POLLWRNORM); ++ } ++ ++ return mask; ++} ++ ++static int do_dvb_video_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case VIDEO_SELECT_SOURCE: ++ { ++ video_stream_source_t stream_source; ++ ++ stream_source = (video_stream_source_t) parg; ++ if (stream_source == VIDEO_SOURCE_DEMUX) { ++ /* stop and reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ } ++ else { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ /* reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ /* start FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); ++ } ++ break; ++ } ++ case VIDEO_CLEAR_BUFFER: ++ { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ break; ++ } ++ case VIDEO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->video_pts; ++ break; ++ } ++ case VIDEO_GET_SIZE: ++ { ++ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_video_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_video_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); ++} ++ ++static struct file_operations dvb_video_fops = { ++ .owner = THIS_MODULE, ++ .write = dvb_video_write, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_video_ioctl, ++#else ++ .unlocked_ioctl = dvb_video_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++ .poll = dvb_video_poll, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_video_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ tasklet_kill(&sti7109->fifo_tasklet); ++ dvb_unregister_device(sti7109->video_dev); ++ return 0; ++} ++ ++static int saa716x_ff_video_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); ++ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->video_dev, ++ &dvbdev_video, ++ sti7109, ++ DVB_DEVICE_VIDEO); ++ ++ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, ++ (unsigned long)saa716x); ++ ++ return 0; ++} ++ ++static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ struct sti7109_dev *sti7109; ++ int err = 0; ++ u32 value; ++ unsigned long timeout; ++ u32 fw_version; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ err = saa716x_phi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ /* prepare the sti7109 device struct */ ++ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); ++ if (!sti7109) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); ++ goto fail3; ++ } ++ ++ sti7109->dev = saa716x; ++ ++ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); ++ if (!sti7109->iobuf) ++ goto fail4; ++ ++ sti7109_cmd_init(sti7109); ++ ++ sti7109->int_count_enable = int_count_enable; ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ ++ saa716x->priv = sti7109; ++ ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ ++ /* hold ST in reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); ++ ++ /* enable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); ++ msleep(100); ++ ++ err = saa716x_ff_fpga_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); ++ goto fail5; ++ } ++ ++ /* configure TS muxer */ ++ if (sti7109->fpga_version < 0x110) { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); ++ } else { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); ++ } ++ ++ /* enable interrupts from ST7109 -> PC */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); ++ ++ value = SAA716x_EPRD(MSI, MSI_CONFIG33); ++ value &= 0xFCFFFFFF; ++ value |= MSI_INT_POL_EDGE_FALL; ++ SAA716x_EPWR(MSI, MSI_CONFIG33, value); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); ++ ++ /* enable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); ++ msleep(50); ++ /* disable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); ++ ++ err = saa716x_ff_st7109_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); ++ goto fail5; ++ } ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable FGPI2 and FGPI3 for TS inputs */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail6; ++ } ++ ++ /* wait a maximum of 10 seconds for the STi7109 to boot */ ++ timeout = 10 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, ++ sti7109->boot_finished == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ goto fail6; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); ++ err = -1; ++ goto fail6; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); ++ ++ err = saa716x_ff_video_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); ++ goto fail7; ++ } ++ ++ err = saa716x_ff_audio_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); ++ goto fail8; ++ } ++ ++ err = saa716x_ff_osd_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); ++ goto fail9; ++ } ++ ++ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); ++ if (!err) { ++ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", ++ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, ++ fw_version & 0xFF); ++ } ++ ++ err = saa716x_ir_init(saa716x); ++ if (err) ++ goto fail9; ++ ++ return 0; ++ ++fail9: ++ saa716x_ff_osd_exit(saa716x); ++fail8: ++ saa716x_ff_audio_exit(saa716x); ++fail7: ++ saa716x_ff_video_exit(saa716x); ++fail6: ++ saa716x_dvb_exit(saa716x); ++fail5: ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++fail4: ++ kfree(sti7109); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_ff_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ saa716x_ir_exit(saa716x); ++ ++ saa716x_ff_osd_exit(saa716x); ++ ++ saa716x_ff_audio_exit(saa716x); ++ ++ saa716x_ff_video_exit(saa716x); ++ ++ saa716x_dvb_exit(saa716x); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++ ++ saa716x->priv = NULL; ++ kfree(sti7109); ++ ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ struct sti7109_dev *sti7109; ++ u32 msiStatusL; ++ u32 msiStatusH; ++ u32 phiISR; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ sti7109 = saa716x->priv; ++ if (unlikely(sti7109 == NULL)) { ++ printk("%s: sti7109=NULL", __func__); ++ return IRQ_NONE; ++ } ++ if (sti7109->int_count_enable) ++ sti7109->total_int_count++; ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); ++ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); ++ ++ if (msiStatusL) { ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[0]++; ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[1]++; ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ if (msiStatusH) { ++ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); ++ } ++ ++ if (msiStatusH & MSI_INT_I2CINT_0) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[0]++; ++ saa716x->i2c[0].i2c_op = 0; ++ wake_up(&saa716x->i2c[0].i2c_wq); ++ } ++ if (msiStatusH & MSI_INT_I2CINT_1) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[1]++; ++ saa716x->i2c[1].i2c_op = 0; ++ wake_up(&saa716x->i2c[1].i2c_wq); ++ } ++ ++ if (msiStatusH & MSI_INT_EXTINT_0) { ++ ++ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); ++ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); ++ ++ if (sti7109->int_count_enable) { ++ int i; ++ sti7109->ext_int_total_count++; ++ for (i = 0; i < 16; i++) ++ if (phiISR & (1 << i)) ++ sti7109->ext_int_source_count[i]++; ++ } ++ ++ if (phiISR & ISR_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); ++ sti7109->result_len = length; ++ sti7109->result_avail = 1; ++ wake_up(&sti7109->result_avail_wq); ++ ++ phiISR &= ~ISR_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ ++ sti7109->cmd_ready = 1; ++ wake_up(&sti7109->cmd_ready_wq); ++ phiISR &= ~ISR_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); ++ sti7109->osd_result_len = length; ++ sti7109->osd_result_avail = 1; ++ wake_up(&sti7109->osd_result_avail_wq); ++ ++ phiISR &= ~ISR_OSD_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ ++ sti7109->osd_cmd_ready = 1; ++ wake_up(&sti7109->osd_cmd_ready_wq); ++ phiISR &= ~ISR_OSD_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); ++ } ++ ++ if (phiISR & ISR_BLOCK_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ ++ sti7109->block_done = 1; ++ wake_up(&sti7109->block_done_wq); ++ phiISR &= ~ISR_BLOCK_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); ++ } ++ ++ if (phiISR & ISR_DATA_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ ++ sti7109->data_ready = 1; ++ wake_up(&sti7109->data_ready_wq); ++ phiISR &= ~ISR_DATA_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); ++ } ++ ++ if (phiISR & ISR_BOOT_FINISH_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ ++ sti7109->boot_finished = 1; ++ wake_up(&sti7109->boot_finish_wq); ++ phiISR &= ~ISR_BOOT_FINISH_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); ++ } ++ ++ if (phiISR & ISR_AUDIO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); ++ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_AUDIO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ ++ } ++ ++ if (phiISR & ISR_VIDEO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); ++ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_VIDEO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ ++ } ++ ++ if (phiISR & ISR_CURRENT_STC_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); ++ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_CURRENT_STC_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ ++ } ++ ++ if (phiISR & ISR_REMOTE_EVENT_MASK) { ++ u8 data[4]; ++ u32 remote_event; ++ ++ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ remote_event = (data[3] << 24) ++ | (data[2] << 16) ++ | (data[1] << 8) ++ | (data[0]); ++ memset(data, 0, sizeof(data)); ++ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ ++ phiISR &= ~ISR_REMOTE_EVENT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); ++ ++ if (remote_event == 0) { ++ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); ++ } else { ++ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); ++ saa716x_ir_handler(saa716x, remote_event); ++ } ++ } ++ ++ if (phiISR & ISR_DVO_FORMAT_MASK) { ++ u8 data[4]; ++ u32 format; ++ ++ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); ++ format = (data[0] << 24) ++ | (data[1] << 16) ++ | (data[2] << 8) ++ | (data[3]); ++ ++ phiISR &= ~ISR_DVO_FORMAT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); ++ } ++ ++ if (phiISR & ISR_LOG_MESSAGE_MASK) { ++ char message[SIZE_LOG_MESSAGE_DATA]; ++ ++ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, ++ SIZE_LOG_MESSAGE_DATA); ++ ++ phiISR &= ~ISR_LOG_MESSAGE_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", ++ SIZE_LOG_MESSAGE_DATA, message); ++ } ++ ++ if (phiISR & ISR_FIFO1_EMPTY_MASK) { ++ u32 fifoCtrl; ++ ++ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl &= ~0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ tasklet_schedule(&sti7109->fifo_tasklet); ++ phiISR &= ~ISR_FIFO1_EMPTY_MASK; ++ } ++ ++ if (phiISR) { ++ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); ++ } ++ } ++ ++ if (sti7109->int_count_enable) { ++ if (jiffies - sti7109->last_int_ticks >= HZ) { ++ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," ++ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", ++ sti7109->total_int_count, ++ sti7109->fgpi_int_count[0], ++ sti7109->fgpi_int_count[1], ++ sti7109->i2c_int_count[0], ++ sti7109->i2c_int_count[1], ++ sti7109->ext_int_total_count, ++ sti7109->ext_int_source_count[0], ++ sti7109->ext_int_source_count[1], ++ sti7109->ext_int_source_count[2], ++ sti7109->ext_int_source_count[3], ++ sti7109->ext_int_source_count[4], ++ sti7109->ext_int_source_count[5], ++ sti7109->ext_int_source_count[6], ++ sti7109->ext_int_source_count[7], ++ sti7109->ext_int_source_count[8], ++ sti7109->ext_int_source_count[9], ++ sti7109->ext_int_source_count[10], ++ sti7109->ext_int_source_count[11], ++ sti7109->ext_int_source_count[12], ++ sti7109->ext_int_source_count[13], ++ sti7109->ext_int_source_count[14], ++ sti7109->ext_int_source_count[15]); ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" ++#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" ++ ++static struct stv090x_config tt6400_stv090x_config = { ++ .device = STV0900, ++ .demod_mode = STV090x_DUAL, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 13500000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts1_clk = 135000000, ++ .ts2_clk = 135000000, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static struct stv6110x_config tt6400_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 27000000, ++ .clk_div = 2, ++}; ++ ++static struct isl6423_config tt6400_isl6423_config[2] = { ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x09, ++ }, ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ } ++}; ++ ++ ++static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ if (count == 0 || count == 1) { ++ adapter->fe = dvb_attach(stv090x_attach, ++ &tt6400_stv090x_config, ++ i2c_adapter, ++ STV090x_DEMODULATOR_0 + count); ++ ++ if (adapter->fe) { ++ struct stv6110x_devctl *ctl; ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &tt6400_stv6110x_config, ++ i2c_adapter); ++ ++ tt6400_stv090x_config.tuner_init = ctl->tuner_init; ++ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ if (count == 1) { ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ /* The second tuner drives the STV0900 so ++ call it only for adapter 1 */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } ++ ++ dvb_attach(isl6423_attach, ++ adapter->fe, ++ i2c_adapter, ++ &tt6400_isl6423_config[count]); ++ ++ } ++ } ++ return 0; ++} ++ ++static struct saa716x_config saa716x_s26400_config = { ++ .model_name = SAA716x_MODEL_S2_6400_DUAL, ++ .dev_type = SAA716x_DEV_S2_6400_DUAL, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_s26400_frontend_attach, ++ .irq_handler = saa716x_ff_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ },{ ++ /* Adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++static struct pci_device_id saa716x_ff_pci_table[] = { ++ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); ++ ++static struct pci_driver saa716x_ff_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_ff_pci_table, ++ .probe = saa716x_ff_pci_probe, ++ .remove = saa716x_ff_pci_remove, ++}; ++ ++static int saa716x_ff_init(void) ++{ ++ return pci_register_driver(&saa716x_ff_pci_driver); ++} ++ ++static void saa716x_ff_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_ff_pci_driver); ++} ++ ++module_init(saa716x_ff_init); ++module_exit(saa716x_ff_exit); ++ ++MODULE_DESCRIPTION("SAA716x FF driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.c 2013-01-16 10:41:10.917798240 +0100 +@@ -0,0 +1,389 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static const u32 mmu_pta_base[] = { ++ MMU_PTA_BASE0, ++ MMU_PTA_BASE1, ++ MMU_PTA_BASE2, ++ MMU_PTA_BASE3, ++ MMU_PTA_BASE4, ++ MMU_PTA_BASE5, ++ MMU_PTA_BASE6, ++ MMU_PTA_BASE7, ++ MMU_PTA_BASE8, ++ MMU_PTA_BASE9, ++ MMU_PTA_BASE10, ++ MMU_PTA_BASE11, ++ MMU_PTA_BASE12, ++ MMU_PTA_BASE13, ++ MMU_PTA_BASE14, ++ MMU_PTA_BASE15, ++}; ++ ++static const u32 mmu_dma_cfg[] = { ++ MMU_DMA_CONFIG0, ++ MMU_DMA_CONFIG1, ++ MMU_DMA_CONFIG2, ++ MMU_DMA_CONFIG3, ++ MMU_DMA_CONFIG4, ++ MMU_DMA_CONFIG5, ++ MMU_DMA_CONFIG6, ++ MMU_DMA_CONFIG7, ++ MMU_DMA_CONFIG8, ++ MMU_DMA_CONFIG9, ++ MMU_DMA_CONFIG10, ++ MMU_DMA_CONFIG11, ++ MMU_DMA_CONFIG12, ++ MMU_DMA_CONFIG13, ++ MMU_DMA_CONFIG14, ++ MMU_DMA_CONFIG15, ++}; ++ ++static const u32 fgpi_ch[] = { ++ FGPI0, ++ FGPI1, ++ FGPI2, ++ FGPI3 ++}; ++ ++static const u32 bamdma_bufmode[] = { ++ BAM_FGPI0_DMA_BUF_MODE, ++ BAM_FGPI1_DMA_BUF_MODE, ++ BAM_FGPI2_DMA_BUF_MODE, ++ BAM_FGPI3_DMA_BUF_MODE ++}; ++ ++static const u32 msi_int_tagack[] = { ++ MSI_INT_TAGACK_FGPI_0, ++ MSI_INT_TAGACK_FGPI_1, ++ MSI_INT_TAGACK_FGPI_2, ++ MSI_INT_TAGACK_FGPI_3 ++}; ++ ++static const u32 msi_int_ovrflw[] = { ++ MSI_INT_OVRFLW_FGPI_0, ++ MSI_INT_OVRFLW_FGPI_1, ++ MSI_INT_OVRFLW_FGPI_2, ++ MSI_INT_OVRFLW_FGPI_3 ++}; ++ ++static const u32 msi_int_avint[] = { ++ MSI_INT_AVINT_FGPI_0, ++ MSI_INT_AVINT_FGPI_1, ++ MSI_INT_AVINT_FGPI_2, ++ MSI_INT_AVINT_FGPI_3 ++}; ++ ++void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port; ++ ++ fgpi_port = fgpi_ch[channel]; ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ ++ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); ++ ++int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) ++{ ++ u32 fgpi_base; ++ u32 buf_mode_reg; ++ u32 buf_mode; ++ ++ switch (fgpi_index) { ++ case 0: /* FGPI_0 */ ++ fgpi_base = FGPI0; ++ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; ++ break; ++ ++ case 1: /* FGPI_1 */ ++ fgpi_base = FGPI1; ++ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; ++ break; ++ ++ case 2: /* FGPI_2 */ ++ fgpi_base = FGPI2; ++ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; ++ break; ++ ++ case 3: /* FGPI_3 */ ++ fgpi_base = FGPI3; ++ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: unexpected fgpi %u\n", ++ __func__, fgpi_index); ++ return -1; ++ } ++ ++ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); ++ if (saa716x->revision < 2) { ++ /* workaround for revision 1: restore buffer numbers on BAM */ ++ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); ++ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); ++ } ++ return (buf_mode >> 3) & 0x7; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); ++ ++static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 config, i; ++ ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); ++ ++ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ ++ ++ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ ++ ++ return 0; ++} ++ ++int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, ++ struct fgpi_stream_params *stream_params, ++ int port) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port, buf_mode, val, mid; ++ u32 D1_XY_END, offst_1, offst_2; ++ int i = 0; ++ ++ fgpi_port = fgpi_ch[port]; ++ buf_mode = bamdma_bufmode[port]; ++ ++ /* Reset FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* Reset DMA channel */ ++ SAA716x_EPWR(BAM, buf_mode, 0x00000040); ++ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); ++ ++ ++ /* monitor BAM reset */ ++ val = SAA716x_EPRD(BAM, buf_mode); ++ while (val && (i < 100)) { ++ msleep(30); ++ val = SAA716x_EPRD(BAM, buf_mode); ++ i++; ++ } ++ ++ if (val) { ++ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); ++ return -EIO; ++ } ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); ++ ++ /* initialize all available address offsets */ ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); ++ ++ /* get module ID */ ++ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); ++ if (mid != 0x14b0100) ++ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); ++ ++ /* Initialize FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); ++ ++ offst_1 = 0; ++ offst_2 = 0; ++ switch (stream_params->stream_type) { ++ case FGPI_TRANSPORT_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_PROGRAM_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_VIDEO_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); ++ ++ if ((stream_params->stream_flags & FGPI_INTERLACED) && ++ (stream_params->stream_flags & FGPI_ODD_FIELD) && ++ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { ++ ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ ++ ++ D1_XY_END = (stream_params->samples << 16); ++ D1_XY_END |= (stream_params->lines / 2) + 2; ++ ++ if (stream_params->stream_flags & FGPI_PAL) ++ offst_1 = 768 * 2; ++ else ++ offst_2 = 768 * 2; ++ ++ } else { ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ ++ ++ D1_XY_END = stream_params->samples << 16; ++ D1_XY_END |= stream_params->lines + 2; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); ++ break; ++ ++ default: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ break; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params) ++{ ++ u32 fgpi_port; ++ u32 config; ++ u32 val; ++ u32 i; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); ++ msleep(10); ++ ++ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { ++ return -EIO; ++ } ++ ++ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ ++ ++ val = SAA716x_EPRD(MMU, config); ++ SAA716x_EPWR(MMU, config, val & ~0x40); ++ SAA716x_EPWR(MMU, config, val | 0x40); ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); ++ ++ val = SAA716x_EPRD(MMU, config); ++ i = 0; ++ while (i < 500) { ++ if (val & 0x80) ++ break; ++ msleep(10); ++ val = SAA716x_EPRD(MMU, config); ++ i++; ++ } ++ ++ if (!(val & 0x80)) { ++ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); ++ return -EIO; ++ } ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val |= 0x3000; ++ ++ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) ++{ ++ u32 fgpi_port; ++ u32 val; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val &= ~0x3000; ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)) ++{ ++ int i; ++ int ret; ++ ++ saa716x->fgpi[port].dma_channel = port + 6; ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ /* TODO: what is a good size for TS DMA buffer? */ ++ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ saa716x->fgpi[port].saa716x = saa716x; ++ tasklet_init(&saa716x->fgpi[port].tasklet, worker, ++ (unsigned long)&saa716x->fgpi[port]); ++ saa716x->fgpi[port].read_index = 0; ++ ++ return 0; ++} ++ ++int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) ++{ ++ int i; ++ ++ tasklet_kill(&saa716x->fgpi[port].tasklet); ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); ++ } ++ ++ return 0; ++} +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.h 2013-01-16 10:41:10.917798240 +0100 +@@ -0,0 +1,112 @@ ++#ifndef __SAA716x_FGPI_H ++#define __SAA716x_FGPI_H ++ ++#include ++ ++#define FGPI_BUFFERS 8 ++#define PTA_LSB(__mem) ((u32 ) (__mem)) ++#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) ++ ++#define BAM_DMA_BUF_MODE_BASE 0x0d8 ++#define BAM_DMA_BUF_MODE_OFFSET 0x24 ++ ++#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc ++#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 ++ ++#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 ++#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 ++#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 ++#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c ++#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 ++#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 ++#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 ++#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c ++ ++struct saa716x_dmabuf; ++ ++/* ++ * Port supported streams ++ * ++ * FGPI_AUDIO_STREAM ++ * FGPI_VIDEO_STREAM ++ * FGPI_VBI_STREAM ++ * FGPI_TRANSPORT_STREAM ++ * FGPI_PROGRAM_STREAM ++ */ ++enum fgpi_stream_type { ++ FGPI_AUDIO_STREAM = 0x01, ++ FGPI_VIDEO_STREAM = 0x02, ++ FGPI_VBI_STREAM = 0x04, ++ FGPI_TRANSPORT_STREAM = 0x08, ++ FGPI_PROGRAM_STREAM = 0x10 ++}; ++ ++/* ++ * Stream port flags ++ * ++ * FGPI_ODD_FIELD ++ * FGPI_EVEN_FIELD ++ * FGPI_HD_0 ++ * FGPI_HD_1 ++ * FGPI_PAL ++ * FGPI_NTSC ++ */ ++enum fgpi_stream_flags { ++ FGPI_ODD_FIELD = 0x0001, ++ FGPI_EVEN_FIELD = 0x0002, ++ FGPI_INTERLACED = 0x0004, ++ FGPI_HD0 = 0x0010, ++ FGPI_HD1 = 0x0020, ++ FGPI_PAL = 0x0040, ++ FGPI_NTSC = 0x0080, ++ FGPI_NO_SCALER = 0x0100, ++}; ++ ++/* ++ * Stream port parameters ++ * bits: Bits per sample ++ * samples: samples perline ++ * lines: number of lines ++ * pitch: stream pitch in bytes ++ * offset: offset to first valid line ++ */ ++struct fgpi_stream_params { ++ u32 bits; ++ u32 samples; ++ u32 lines; ++ ++ s32 pitch; ++ ++ u32 offset; ++ u32 page_tables; ++ ++ enum fgpi_stream_flags stream_flags; ++ enum fgpi_stream_type stream_type; ++}; ++ ++struct saa716x_dmabuf; ++ ++struct saa716x_fgpi_stream_port { ++ u8 dma_channel; ++ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; ++ struct saa716x_dev *saa716x; ++ struct tasklet_struct tasklet; ++ u8 read_index; ++}; ++ ++extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); ++extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, ++ u32 fgpi_index); ++extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params); ++extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); ++ ++extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)); ++extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); ++ ++#endif /* __SAA716x_FGPI_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi_reg.h 2013-01-16 10:41:10.918798233 +0100 +@@ -0,0 +1,74 @@ ++#ifndef __SAA716x_FGPI_REG_H ++#define __SAA716x_FGPI_REG_H ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++#endif /* __SAA716x_FGPI_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.c 2013-01-16 10:41:10.918798233 +0100 +@@ -0,0 +1,140 @@ ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++ ++#include "saa716x_gpio.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_gpio_init(struct saa716x_dev *saa716x) ++{ ++ spin_lock_init(&saa716x->gpio_lock); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_init); ++ ++int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) ++{ ++ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ ++ return 0; ++} ++ ++int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ reg &= ~mask; ++ reg |= (config & mask); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) ++{ ++ return SAA716x_EPRD(GPIO, GPIO_RD); ++} ++ ++void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) ++{ ++ SAA716x_EPWR(GPIO, GPIO_WR, data); ++} ++ ++void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_OEN); ++ reg &= mask; ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_OEN, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_WR); ++ reg &= ~bits; ++ /* TODO ! add maskable config bits in here */ ++ /* reg |= (config->mask & bits) */ ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_WR, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); ++ ++void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value |= 1 << gpio; ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); ++ ++void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ if (mode) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); ++ ++void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) ++{ ++ uint32_t value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ value = SAA716x_EPRD(GPIO, GPIO_WR); ++ if (set) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR, value); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_write); ++ ++int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_RD); ++ if (value & (1 << gpio)) ++ return 1; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_read); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.h 2013-01-16 10:41:10.918798233 +0100 +@@ -0,0 +1,26 @@ ++#ifndef __SAA716x_GPIO_H ++#define __SAA716x_GPIO_H ++ ++#define BOOT_MODE GPIO_31 | GPIO_30 ++#define AV_UNIT_B GPIO_25 ++#define AV_UNIT_A GPIO_24 ++#define AV_INTR_B GPIO_01 ++#define AV_INTR_A GPIO_00 ++ ++struct saa716x_dev; ++ ++extern void saa716x_gpio_init(struct saa716x_dev *saa716x); ++ ++extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); ++extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); ++extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); ++ ++extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); ++ ++extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); ++extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); ++extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); ++ ++#endif /* __SAA716x_GPIO_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio_reg.h 2013-01-16 10:41:10.919798225 +0100 +@@ -0,0 +1,47 @@ ++#ifndef __SAA716x_GPIO_REG_H ++#define __SAA716x_GPIO_REG_H ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++#endif /* __SAA716x_GPIO_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.c 2013-01-16 10:41:10.919798225 +0100 +@@ -0,0 +1,42 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_greg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static u32 g_save[12]; ++ ++void saa716x_greg_save(struct saa716x_dev *saa716x) ++{ ++ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); ++ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); ++ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); ++ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); ++ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); ++ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); ++ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); ++ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); ++ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); ++ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); ++ ++ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); ++} ++ ++void saa716x_greg_restore(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); ++ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); ++ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); ++ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); ++ ++ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); ++} +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.h 2013-01-16 10:41:10.919798225 +0100 +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_GREG_H ++#define __SAA716x_GREG_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_greg_save(struct saa716x_dev *saa716x); ++extern void saa716x_greg_restore(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_GREG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg_reg.h 2013-01-16 10:41:10.919798225 +0100 +@@ -0,0 +1,91 @@ ++#ifndef __SAA716x_GREG_REG_H ++#define __SAA716x_GREG_REG_H ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_GREG_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.c 2013-01-16 10:41:10.920798217 +0100 +@@ -0,0 +1,726 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_hybrid.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "zl10353.h" ++#include "mb86a16.h" ++#include "tda1004x.h" ++#include "tda827x.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Hybrid" ++ ++static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable decoders on 7162 */ ++ if (pdev->device == SAA7162) { ++ saa716x_gpio_set_output(saa716x, 24); ++ saa716x_gpio_set_output(saa716x, 25); ++ ++ saa716x_gpio_write(saa716x, 24, 0); ++ saa716x_gpio_write(saa716x, 25, 0); ++ ++ msleep(10); ++ ++ saa716x_gpio_write(saa716x, 24, 1); ++ saa716x_gpio_write(saa716x, 25, 1); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); ++ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++/* ++ * Twinhan/Azurewave VP-6090 ++ * DVB-S Frontend: 2x MB86A16 ++ * DVB-T Frontend: 2x TDA10046 + TDA8275 ++ */ ++#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" ++#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" ++ ++static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_vp6090_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_4M, ++ .agc_config = TDA10046_AGC_DEFAULT, ++ .if_freq = TDA10046_FREQ_3617, ++ .request_firmware = tda1004x_vp6090_request_firmware, ++}; ++ ++static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp6090_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp6090_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[count]; ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ saa716x_gpio_set_output(saa716x, 11); ++ saa716x_gpio_set_output(saa716x, 10); ++ saa716x_gpio_write(saa716x, 11, 1); ++ saa716x_gpio_write(saa716x, 10, 1); ++ msleep(100); ++#if 0 ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp6090_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++#endif ++ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_vp6090_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6090, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6090, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6090_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++/* ++ * NXP Reference design (Atlantis) ++ * 2x DVB-T Frontend: 2x TDA10046 ++ * Analog Decoder: 2x Internal ++ */ ++#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" ++#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" ++ ++static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_atlantis_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_atlantis_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_atlantis_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c; ++ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ ++ struct i2c_msg msg = { ++ .addr = 0x42 >> 1, ++ .flags = 0, ++ .buf = i2c_buf, ++ .len = sizeof(i2c_buf) ++ }; ++ ++ if (count < saa716x->config->adapters) { ++ u32 reset_gpio; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ if (count == 0) { ++ reset_gpio = 14; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ } else { ++ reset_gpio = 15; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ } ++ ++ /* activate the silent I2C bus */ ++ i2c_transfer(&i2c->i2c_adapter, &msg, 1); ++ ++ saa716x_gpio_set_output(saa716x, reset_gpio); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) ++ goto exit; ++ ++ dprintk(SAA716x_ERROR, 1, ++ "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_atlantis_config.demod_address); ++ ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_atlantis_config.tuner_address, ++ &i2c->i2c_adapter, &tda827x_atlantis_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_atlantis_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_atlantis_config = { ++ .model_name = SAA716x_MODEL_NXP_ATLANTIS, ++ .dev_type = SAA716x_DEV_NXP_ATLANTIS, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_atlantis_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* Adapter 1 */ ++ .ts_port = 0, /* using FGPI 0 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++/* ++ * NXP Reference design (NEMO) ++ * DVB-T Frontend: 1x TDA10046 + TDA8275 ++ * Analog Decoder: External SAA7136 ++ */ ++#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" ++#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" ++ ++static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_nemo_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_nemo_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_nemo_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ ++ ++ if (count == 0) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ /* GPIO 26 controls a +15dB gain */ ++ saa716x_gpio_set_output(saa716x, 26); ++ saa716x_gpio_write(saa716x, 26, 0); ++ ++ saa716x_gpio_set_output(saa716x, 14); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_nemo_config, ++ &demod_i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_nemo_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_nemo_config.tuner_address, ++ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_nemo_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_nemo_config = { ++ .model_name = SAA716x_MODEL_NXP_NEMO, ++ .dev_type = SAA716x_DEV_NXP_NEMO, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_nemo_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" ++#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" ++ ++#if 0 ++static struct zl10353_config saa716x_averhc82_zl10353_config = { ++ .demod_address = 0x1f, ++ .adc_clock = 450560, ++ .if2 = 361667, ++ .no_tuner = 1, ++ .parallel_ts = 1, ++}; ++#endif ++ ++static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); ++ ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_averhc82_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, ++ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averhc82_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" ++#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" ++ ++static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_averh788_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_H788, ++ .dev_type = SAA716x_DEV_AVERMEDIA_H788, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averh88_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++static struct pci_device_id saa716x_hybrid_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), ++ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); ++ ++static struct pci_driver saa716x_hybrid_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_hybrid_pci_table, ++ .probe = saa716x_hybrid_pci_probe, ++ .remove = saa716x_hybrid_pci_remove, ++}; ++ ++static int saa716x_hybrid_init(void) ++{ ++ return pci_register_driver(&saa716x_hybrid_pci_driver); ++} ++ ++static void saa716x_hybrid_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_hybrid_pci_driver); ++} ++ ++module_init(saa716x_hybrid_init); ++module_exit(saa716x_hybrid_exit); ++ ++MODULE_DESCRIPTION("SAA716x Hybrid driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.h 2013-01-16 10:41:10.920798217 +0100 +@@ -0,0 +1,13 @@ ++#ifndef __SAA716x_HYBRID_H ++#define __SAA716x_HYBRID_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define AVERMEDIA 0x1461 ++#define KWORLD 0x17DE ++ ++#define TWINHAN_VP_6090 0x0027 ++#define AVERMEDIA_HC82 0x2355 ++#define AVERMEDIA_H788 0x1455 ++#define KWORLD_DVB_T_PE310 0x7521 ++ ++#endif /* __SAA716x_HYBRID_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.c 2013-01-16 10:41:10.921798210 +0100 +@@ -0,0 +1,738 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_i2c_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_cgu_reg.h" ++ ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ ++ I2C_ACK_INTER_MTNA | \ ++ I2C_FAILURE_INTER_MAF) ++ ++#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ ++ I2C_TRANSMIT_PROG) ++ ++#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ ++ I2C_RECEIVE_CLEAR) ++ ++static const char* state[] = { ++ "Idle", ++ "DoneStop", ++ "Busy", ++ "TOscl", ++ "TOarb", ++ "DoneWrite", ++ "DoneRead", ++ "DoneWriteTO", ++ "DoneReadTO", ++ "NoDevice", ++ "NoACK", ++ "BUSErr", ++ "ArbLost", ++ "SEQErr", ++ "STErr" ++}; ++ ++int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) ++{ ++ u32 stat, mask; ++ u32 *I2C_DEV; ++ ++ BUG_ON(saa716x == NULL); ++ I2C_DEV = saa716x->I2C_DEV; ++ ++ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); ++ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); ++ saa716x->i2c[bus].i2c_stat = stat; ++ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", ++ bus, state[stat], stat, mask); ++ ++ if (!(stat & mask)) ++ return -1; ++ ++ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); ++ ++ if (stat & I2C_INTERRUPT_STFNF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTFNF) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_INTERRUPT_RFDA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPTE_RFF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_INTERRUPT_STDR) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MASTER_INTERRUPT_MTDR) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_ERROR_IBE) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MODE_CHANGE_INTER_MSMC) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_ACK_INTER_MTNA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_FAILURE_INTER_MAF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++ ++static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), ++ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); ++ ++ return IRQ_HANDLED; ++} ++ ++static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); ++ ++ return; ++} ++ ++static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ struct i2c_adapter *adapter = &i2c->i2c_adapter; ++ ++ int i, err = 0; ++ u32 reg; ++ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", ++ I2C_DEV, adapter->name); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Flush queue */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ /* Reset I2C Core and generate a delay */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); ++ ++ for (i = 0; i < 100; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); ++ if (reg == 0xc0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", ++ I2C_DEV, adapter->name); ++ break; ++ } ++ msleep(1); ++ ++ if (i == 99) ++ err = -EIO; ++ } ++ ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", ++ I2C_DEV, adapter->name); ++ ++ saa716x_term_xfer(i2c, I2C_DEV); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* I2C Rate Setup */ ++ switch (i2c->i2c_rate) { ++ case SAA716x_I2C_RATE_400: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); ++ break; ++ ++ case SAA716x_I2C_RATE_100: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); ++ break; ++ ++ default: ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", ++ adapter->name, ++ i2c->i2c_rate); ++ ++ break; ++ } ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Enabled interrupts: ++ * Master Transaction Done, ++ * Master Transaction Data Request ++ * (0x81) ++ */ ++ msleep(5); ++ ++ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, ++ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); ++ ++ /* Check interrupt enable status */ ++ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); ++ if (reg != 0x81) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%d) %s Interrupt enable failed, Exiting !", ++ i, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++ } ++ ++ /* Check status */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%02x) %s has bad state, Exiting !", ++ I2C_DEV, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++#if 0 ++ saa716x_add_irqvector(saa716x, ++ i2c_vec[i].vector, ++ i2c_vec[i].edge, ++ i2c_vec[i].handler, ++ SAA716x_I2C_ADAPTER(i)); ++#endif ++ reg = SAA716x_EPRD(CGU, CGU_SCR_3); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", ++ I2C_DEV, ++ (reg >> 1) & 0x01, ++ reg & 0x01); ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ return 0; ++ } ++ ++ /* Check FIFO status before TX */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ i2c->stat_tx_prior = reg; ++ if (reg & SAA716x_I2C_TXBUSY) { ++ for (i = 0; i < 100; i++) { ++ /* TODO! check for hotplug devices */ ++ msleep(10); ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ ++ if (reg & SAA716x_I2C_TXBUSY) { ++ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); ++ ++ err = saa716x_i2c_hwinit(i2c, I2C_DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto exit; ++ } ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ ++ /* Check for data write */ ++ for (i = 0; i < 1000; i++) { ++ /* TODO! check for hotplug devices */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (reg & I2C_TRANSMIT_CLEAR) { ++ break; ++ } ++ } ++ i2c->stat_tx_done = reg; ++ ++ if (!(reg & I2C_TRANSMIT_CLEAR)) { ++ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); ++ err = -EIO; ++ goto exit; ++ } ++ ++ return err; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); ++ return err; ++} ++ ++static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ /* Check FIFO status before RX */ ++ for (i = 0; i < 1000; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & SAA716x_I2C_RXBUSY)) { ++ break; ++ } ++ } ++ if (reg & SAA716x_I2C_RXBUSY) { ++ dprintk(SAA716x_INFO, 1, "FIFO empty"); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Read from FIFO */ ++ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); ++ return err; ++} ++ ++static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return; ++ ++ i2c->i2c_op = 1; ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ unsigned long timeout; ++ int err = 0; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return 0; ++ ++ timeout = HZ/100 + 1; /* 10ms */ ++ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); ++ if (timeout == -ERESTARTSYS || i2c->i2c_op) { ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ err = -ERESTARTSYS; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); ++ err = -EIO; ++ } ++ } ++ return err; ++} ++ ++static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1); ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now write the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = buf[i]; ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1) | 1; ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now read the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = 0x00; /* dummy write for reading */ ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ for (i = 0; i < bytes; i++) { ++ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data receive failed"); ++ goto exit; ++ } ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); ++ buf[i] = data; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) ++{ ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); ++ int i, j, err = 0; ++ int t; ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); ++ mutex_lock(&i2c->i2c_lock); ++ ++ for (t = 0; t < 3; t++) { ++ for (i = 0; i < num; i++) { ++ if (msgs[i].flags & I2C_M_RD) ++ err = saa716x_i2c_read_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ else ++ err = saa716x_i2c_write_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ if (err < 0) { ++ err = -EIO; ++ goto retry; ++ } ++ } ++ break; ++retry: ++ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); ++ for (i = 0; i < num; i++) { ++ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", ++ i, msgs[i].addr, msgs[i].len, msgs[i].flags); ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ for (j = 0; j < msgs[i].len; j++) { ++ dprintk(SAA716x_INFO, 1, " 0x%02x", ++ j, msgs[i].buf[j]); ++ } ++ } ++ } ++ err = saa716x_i2c_hwinit(i2c, DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto bail_out; ++ } ++ } ++ ++ mutex_unlock(&i2c->i2c_lock); ++ return num; ++ ++bail_out: ++ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); ++ mutex_unlock(&i2c->i2c_lock); ++ return err; ++} ++ ++static u32 saa716x_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm saa716x_algo = { ++ .master_xfer = saa716x_i2c_xfer, ++ .functionality = saa716x_i2c_func, ++}; ++ ++struct saa716x_i2cvec { ++ u32 vector; ++ enum saa716x_edge edge; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++static const struct saa716x_i2cvec i2c_vec[] = { ++ { ++ .vector = I2CINT_0, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ }, { ++ .vector = I2CINT_1, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ } ++}; ++ ++int saa716x_i2c_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ mutex_init(&i2c->i2c_lock); ++ ++ init_waitqueue_head(&i2c->i2c_wq); ++ i2c->i2c_op = 0; ++ ++ i2c->i2c_dev = i; ++ i2c->i2c_rate = saa716x->config->i2c_rate; ++ i2c->i2c_mode = saa716x->config->i2c_mode; ++ adapter = &i2c->i2c_adapter; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) ++ i2c->block_size = 8; ++ else ++ i2c->block_size = 1; ++ ++ if (adapter != NULL) { ++ ++ i2c_set_adapdata(adapter, i2c); ++ ++ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); ++ ++ adapter->owner = THIS_MODULE; ++ adapter->algo = &saa716x_algo; ++ adapter->algo_data = NULL; ++ adapter->timeout = 500; /* FIXME ! */ ++ adapter->retries = 3; /* FIXME ! */ ++ adapter->dev.parent = &pdev->dev; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", ++ i, ++ adapter->name); ++ ++ err = i2c_add_adapter(adapter); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); ++ goto exit; ++ } ++ ++ i2c->saa716x = saa716x; ++ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); ++ } ++ i2c++; ++ } ++ ++ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", ++ saa716x->pdev->device); ++ ++ return 0; ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_init); ++ ++int saa716x_i2c_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ adapter = &i2c->i2c_adapter; ++#if 0 ++ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); ++#endif ++ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); ++ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); ++ ++ err = i2c_del_adapter(adapter); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s remove failed", i, adapter->name); ++ goto exit; ++ } ++ i2c++; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); ++ ++ return 0; ++ ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_exit); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.h 2013-01-16 10:41:10.921798210 +0100 +@@ -0,0 +1,52 @@ ++#ifndef __SAA716x_I2C_H ++#define __SAA716x_I2C_H ++ ++#define SAA716x_I2C_ADAPTERS 2 ++ ++#define SAA716x_I2C_ADAPTER(__dev) (( \ ++ (__dev == 1) ? \ ++ "SAA716x I2C Core 1" : \ ++ "SAA716x I2C Core 0")) ++ ++#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) ++ ++#define SAA716x_I2C_BUS_A 0x01 ++#define SAA716x_I2C_BUS_B 0x00 ++ ++struct saa716x_dev; ++ ++enum saa716x_i2c_rate { ++ SAA716x_I2C_RATE_400 = 1, ++ SAA716x_I2C_RATE_100, ++}; ++ ++enum saa716x_i2c_mode { ++ SAA716x_I2C_MODE_POLLING = 0, ++ SAA716x_I2C_MODE_IRQ, ++ SAA716x_I2C_MODE_IRQ_BUFFERED ++}; ++ ++struct saa716x_i2c { ++ struct i2c_adapter i2c_adapter; ++ struct mutex i2c_lock; ++ struct saa716x_dev *saa716x; ++ u8 i2c_dev; ++ ++ enum saa716x_i2c_rate i2c_rate; /* run time */ ++ enum saa716x_i2c_mode i2c_mode; ++ u32 block_size; /* block size for buffered ++ mode, 1 otherwise */ ++ u32 i2c_stat; ++ ++ u32 stat_tx_prior; ++ u32 stat_tx_done; ++ wait_queue_head_t i2c_wq; ++ int i2c_op; ++}; ++ ++extern int saa716x_i2c_init(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); ++extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); ++ ++#endif /* __SAA716x_I2C_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c_reg.h 2013-01-16 10:41:10.922798203 +0100 +@@ -0,0 +1,145 @@ ++#ifndef __SAA716x_I2C_REG_H ++#define __SAA716x_I2C_REG_H ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_I2C_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_mod.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_mod.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_mod.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_mod.h 2013-01-16 10:41:10.922798203 +0100 +@@ -0,0 +1,50 @@ ++#ifndef __SAA716x_MOD_H ++#define __SAA716x_MOD_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++#define BAM 0x00008000 ++#define MMU 0x00009000 ++#define MSI 0x0000a000 ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++#define SPI 0x0000d000 ++#define GPIO 0x0000e000 ++#define PHI_0 0x0000f000 ++#define GREG 0x00012000 ++#define CGU 0x00013000 ++#define DCS 0x00014000 ++#define PHI_1 0x00020000 ++ ++#endif /* __SAA716x_MOD_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.c 2013-01-16 10:41:10.923798196 +0100 +@@ -0,0 +1,479 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_msi_reg.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++ ++#include "saa716x_priv.h" ++ ++#define SAA716x_MSI_VECTORS 50 ++ ++static const char *vector_name[] = { ++ "TAGACK_VI0_0", ++ "TAGACK_VI0_1", ++ "TAGACK_VI0_2", ++ "TAGACK_VI1_0", ++ "TAGACK_VI1_1", ++ "TAGACK_VI1_2", ++ "TAGACK_FGPI_0", ++ "TAGACK_FGPI_1", ++ "TAGACK_FGPI_2", ++ "TAGACK_FGPI_3", ++ "TAGACK_AI_0", ++ "TAGACK_AI_1", ++ "OVRFLW_VI0_0", ++ "OVRFLW_VI0_1", ++ "OVRFLW_VI0_2", ++ "OVRFLW_VI1_0", ++ "OVRFLW_VI1_1", ++ "OVRFLW_VI1_2", ++ "OVRFLW_FGPI_O", ++ "OVRFLW_FGPI_1", ++ "OVRFLW_FGPI_2", ++ "OVRFLW_FGPI_3", ++ "OVRFLW_AI_0", ++ "OVRFLW_AI_1", ++ "AVINT_VI0", ++ "AVINT_VI1", ++ "AVINT_FGPI_0", ++ "AVINT_FGPI_1", ++ "AVINT_FGPI_2", ++ "AVINT_FGPI_3", ++ "AVINT_AI_0", ++ "AVINT_AI_1", ++ "UNMAPD_TC_INT", ++ "EXTINT_0", ++ "EXTINT_1", ++ "EXTINT_2", ++ "EXTINT_3", ++ "EXTINT_4", ++ "EXTINT_5", ++ "EXTINT_6", ++ "EXTINT_7", ++ "EXTINT_8", ++ "EXTINT_9", ++ "EXTINT_10", ++ "EXTINT_11", ++ "EXTINT_12", ++ "EXTINT_13", ++ "EXTINT_14", ++ "EXTINT_15", ++ "I2CINT_0", ++ "I2CINT_1" ++}; ++ ++static u32 MSI_CONFIG_REG[51] = { ++ MSI_CONFIG0, ++ MSI_CONFIG1, ++ MSI_CONFIG2, ++ MSI_CONFIG3, ++ MSI_CONFIG4, ++ MSI_CONFIG5, ++ MSI_CONFIG6, ++ MSI_CONFIG7, ++ MSI_CONFIG8, ++ MSI_CONFIG9, ++ MSI_CONFIG10, ++ MSI_CONFIG11, ++ MSI_CONFIG12, ++ MSI_CONFIG13, ++ MSI_CONFIG14, ++ MSI_CONFIG15, ++ MSI_CONFIG16, ++ MSI_CONFIG17, ++ MSI_CONFIG18, ++ MSI_CONFIG19, ++ MSI_CONFIG20, ++ MSI_CONFIG21, ++ MSI_CONFIG22, ++ MSI_CONFIG23, ++ MSI_CONFIG24, ++ MSI_CONFIG25, ++ MSI_CONFIG26, ++ MSI_CONFIG27, ++ MSI_CONFIG28, ++ MSI_CONFIG29, ++ MSI_CONFIG30, ++ MSI_CONFIG31, ++ MSI_CONFIG32, ++ MSI_CONFIG33, ++ MSI_CONFIG34, ++ MSI_CONFIG35, ++ MSI_CONFIG36, ++ MSI_CONFIG37, ++ MSI_CONFIG38, ++ MSI_CONFIG39, ++ MSI_CONFIG40, ++ MSI_CONFIG41, ++ MSI_CONFIG42, ++ MSI_CONFIG43, ++ MSI_CONFIG44, ++ MSI_CONFIG45, ++ MSI_CONFIG46, ++ MSI_CONFIG47, ++ MSI_CONFIG48, ++ MSI_CONFIG49, ++ MSI_CONFIG50 ++}; ++ ++int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) ++{ ++ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); ++ ++ if (stat_l & MSI_INT_AVINT_VI0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); ++ ++ if (stat_l & MSI_INT_AVINT_VI1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); ++ ++ if (stat_h & MSI_INT_UNMAPD_TC_INT) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); ++ ++ if (stat_h & MSI_INT_EXTINT_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); ++ ++ if (stat_h & MSI_INT_EXTINT_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); ++ ++ if (stat_h & MSI_INT_EXTINT_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); ++ ++ if (stat_h & MSI_INT_EXTINT_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); ++ ++ if (stat_h & MSI_INT_EXTINT_4) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); ++ ++ if (stat_h & MSI_INT_EXTINT_5) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); ++ ++ if (stat_h & MSI_INT_EXTINT_6) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); ++ ++ if (stat_h & MSI_INT_EXTINT_7) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); ++ ++ if (stat_h & MSI_INT_EXTINT_8) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); ++ ++ if (stat_h & MSI_INT_EXTINT_9) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); ++ ++ if (stat_h & MSI_INT_EXTINT_10) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); ++ ++ if (stat_h & MSI_INT_EXTINT_11) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); ++ ++ if (stat_h & MSI_INT_EXTINT_12) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); ++ ++ if (stat_h & MSI_INT_EXTINT_13) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); ++ ++ if (stat_h & MSI_INT_EXTINT_14) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); ++ ++ if (stat_h & MSI_INT_EXTINT_15) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); ++ ++ if (stat_h & MSI_INT_I2CINT_0) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); ++ saa716x_i2c_irqevent(saa716x, 0); ++ } ++ ++ if (stat_h & MSI_INT_I2CINT_1) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); ++ saa716x_i2c_irqevent(saa716x, 1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_event); ++ ++int saa716x_msi_init(struct saa716x_dev *saa716x) ++{ ++ u32 ena_l, ena_h, sta_l, sta_h, mid; ++ int i; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); ++ saa716x->handlers = 0; ++ ++ /* get module id & version */ ++ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); ++ if (mid != 0x30100) ++ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); ++ ++ /* let HW take care of MSI race */ ++ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); ++ ++ /* INTA Polarity: Active High */ ++ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); ++ ++ /* ++ * IRQ Edge Rising: 25:24 = 0x01 ++ * Traffic Class: 18:16 = 0x00 ++ * MSI ID: 4:0 = 0x00 ++ */ ++ for (i = 0; i < SAA716x_MSI_VECTORS; i++) ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); ++ ++ /* get Status */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ /* disable and clear enabled and asserted IRQ's */ ++ if (sta_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); ++ ++ if (sta_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); ++ ++ if (ena_l) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); ++ ++ if (ena_h) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); ++ ++ msleep(5); ++ ++ /* Check IRQ's really disabled */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", ++ ena_l, ena_h, sta_l, sta_h); ++ ++ return 0; ++ } else { ++ dprintk(SAA716x_DEBUG, 1, "I/O error"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_init); ++ ++void saa716x_msiint_disable(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); ++} ++EXPORT_SYMBOL_GPL(saa716x_msiint_disable); ++ ++ ++/* Map the given vector Id to the hardware bitmask. */ ++static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) ++{ ++ u32 tmp = 1; ++ ++ if (vector < 32) { ++ /* Bits 0 - 31 */ ++ tmp <<= vector; ++ *mask_l = tmp; ++ *mask_h = 0; ++ } else { ++ /* Bits 32 - 48 */ ++ tmp <<= vector - 32; ++ *mask_l = 0; ++ *mask_h = tmp; ++ } ++} ++ ++int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc) ++{ ++ struct saa716x_msix_entry *msix_handler = NULL; ++ ++ u32 config, mask_l, mask_h, ena_l, ena_h; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(vector > SAA716x_MSI_VECTORS); ++ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); ++ ++ if ((vector > 32) && (vector < 49)) { ++ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); ++ config &= 0xfcffffff; /* clear polarity */ ++ ++ switch (edge) { ++ default: ++ case SAA716x_EDGE_RISING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); ++ break; ++ ++ case SAA716x_EDGE_FALLING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); ++ break; ++ ++ case SAA716x_EDGE_ANY: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); ++ break; ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* add callback */ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ strcpy(msix_handler->desc, desc); ++ msix_handler->vector = vector; ++ msix_handler->handler = handler; ++ saa716x->handlers++; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); ++ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); ++ ++ return 0; ++} ++ ++int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) ++{ ++ struct saa716x_msix_entry *msix_handler; ++ int i; ++ u32 mask_l, mask_h; ++ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ BUG_ON(msix_handler == NULL); ++ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); ++ ++ /* loop through the registered handlers */ ++ for (i = 0; i < saa716x->handlers; i++) { ++ ++ /* we found our vector */ ++ if (msix_handler->vector == vector) { ++ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ ++ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", ++ msix_handler->vector, ++ msix_handler->desc); ++ ++ /* check whether it is already released */ ++ if (msix_handler->handler) { ++ msix_handler->vector = 0; ++ msix_handler->handler = NULL; ++ saa716x->handlers--; ++ } ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* disable vector */ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); ++ ++ return 0; ++} +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.h 2013-01-16 10:41:10.923798196 +0100 +@@ -0,0 +1,87 @@ ++#ifndef __SAA716x_MSI_H ++#define __SAA716x_MSI_H ++ ++#define TAGACK_VI0_0 0x000 ++#define TAGACK_VI0_1 0x001 ++#define TAGACK_VI0_2 0x002 ++#define TAGACK_VI1_0 0x003 ++#define TAGACK_VI1_1 0x004 ++#define TAGACK_VI1_2 0x005 ++#define TAGACK_FGPI_0 0x006 ++#define TAGACK_FGPI_1 0x007 ++#define TAGACK_FGPI_2 0x008 ++#define TAGACK_FGPI_3 0x009 ++#define TAGACK_AI_0 0x00a ++#define TAGACK_AI_1 0x00b ++#define OVRFLW_VI0_0 0x00c ++#define OVRFLW_VI0_1 0x00d ++#define OVRFLW_VI0_2 0x00e ++#define OVRFLW_VI1_0 0x00f ++#define OVRFLW_VI1_1 0x010 ++#define OVRFLW_VI1_2 0x011 ++#define OVRFLW_FGPI_O 0x012 ++#define OVRFLW_FGPI_1 0x013 ++#define OVRFLW_FGPI_2 0x014 ++#define OVRFLW_FGPI_3 0x015 ++#define OVRFLW_AI_0 0x016 ++#define OVRFLW_AI_1 0x017 ++#define AVINT_VI0 0x018 ++#define AVINT_VI1 0x019 ++#define AVINT_FGPI_0 0x01a ++#define AVINT_FGPI_1 0x01b ++#define AVINT_FGPI_2 0x01c ++#define AVINT_FGPI_3 0x01d ++#define AVINT_AI_0 0x01e ++#define AVINT_AI_1 0x01f ++#define UNMAPD_TC_INT 0x020 ++#define EXTINT_0 0x021 ++#define EXTINT_1 0x022 ++#define EXTINT_2 0x023 ++#define EXTINT_3 0x024 ++#define EXTINT_4 0x025 ++#define EXTINT_5 0x026 ++#define EXTINT_6 0x027 ++#define EXTINT_7 0x028 ++#define EXTINT_8 0x029 ++#define EXTINT_9 0x02a ++#define EXTINT_10 0x02b ++#define EXTINT_11 0x02c ++#define EXTINT_12 0x02d ++#define EXTINT_13 0x02e ++#define EXTINT_14 0x02f ++#define EXTINT_15 0x030 ++#define I2CINT_0 0x031 ++#define I2CINT_1 0x032 ++ ++#define SAA716x_TC0 0x000 ++#define SAA716x_TC1 0x001 ++#define SAA716x_TC2 0x002 ++#define SAA716x_TC3 0x003 ++#define SAA716x_TC4 0x004 ++#define SAA716x_TC5 0x005 ++#define SAA716x_TC6 0x006 ++#define SAA716x_TC7 0x007 ++ ++ ++enum saa716x_edge { ++ SAA716x_EDGE_RISING = 1, ++ SAA716x_EDGE_FALLING = 2, ++ SAA716x_EDGE_ANY = 3 ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); ++ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc); ++ ++extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); ++ ++#endif /* __SAA716x_MSI_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi_reg.h 2013-01-16 10:41:10.923798196 +0100 +@@ -0,0 +1,143 @@ ++#ifndef __SAA716x_MSI_REG_H ++#define __SAA716x_MSI_REG_H ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++#endif /* __SAA716x_MSI_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_pci.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_pci.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_pci.c 2013-01-16 10:41:10.924798189 +0100 +@@ -0,0 +1,275 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_msi.h" ++#include "saa716x_priv.h" ++ ++#define DRIVER_NAME "SAA716x Core" ++ ++static irqreturn_t saa716x_msi_handler(int irq, void *dev_id) ++{ ++ return IRQ_HANDLED; ++} ++ ++static int saa716x_enable_msi(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err; ++ ++ err = pci_enable_msi(pdev); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static int saa716x_enable_msix(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, ret = 0; ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); ++ if (ret < 0) ++ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); ++ if (ret > 0) ++ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); ++ ++ return ret; ++} ++ ++static int saa716x_request_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_config *config = saa716x->config; ++ int i, ret = 0; ++ ++ if (saa716x->int_type == MODE_MSI) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); ++ ret = saa716x_enable_msi(saa716x); ++ } else if (saa716x->int_type == MODE_MSI_X) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); ++ ret = saa716x_enable_msix(saa716x); ++ } ++ ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); ++ saa716x->int_type = MODE_INTA; ++ } ++ ++ if (saa716x->int_type == MODE_MSI) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ 0, ++ DRIVER_NAME, ++ saa716x); ++ ++ if (ret) { ++ pci_disable_msi(pdev); ++ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); ++ ret = -EIO; ++ } ++ } ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { ++ ret = request_irq(saa716x->msix_entries[i].vector, ++ saa716x->saa716x_msix_handler[i].handler, ++ IRQF_SHARED, ++ saa716x->saa716x_msix_handler[i].desc, ++ saa716x); ++ ++ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); ++ return -1; ++ } ++ } ++ } ++ ++ if (saa716x->int_type == MODE_INTA) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ IRQF_SHARED, ++ DRIVER_NAME, ++ saa716x); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); ++ ret = -ENODEV; ++ } ++ } ++ ++ return ret; ++} ++ ++static void saa716x_free_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, vector; ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { ++ vector = saa716x->msix_entries[i].vector; ++ free_irq(vector, saa716x); ++ } ++ ++ pci_disable_msix(pdev); ++ ++ } else { ++ free_irq(pdev->irq, saa716x); ++ if (saa716x->int_type == MODE_MSI) ++ pci_disable_msi(pdev); ++ } ++} ++ ++int saa716x_pci_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; ++ u32 msi_cap; ++ u8 revision; ++ ++ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); ++ ++ err = pci_enable_device(pdev); ++ if (err != 0) { ++ ret = -ENODEV; ++ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); ++ goto fail0; ++ } ++ ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { ++ use_dac = 1; ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); ++ goto fail1; ++ } ++ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); ++ goto fail1; ++ } ++ ++ pci_set_master(pdev); ++ ++ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); ++ if (pm_cap == 0) { ++ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); ++ err = -EIO; ++ goto fail1; ++ } ++ ++ if (!request_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0), ++ DRIVER_NAME)) { ++ ++ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); ++ ret = -ENODEV; ++ goto fail1; ++ } ++ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++ if (!saa716x->mmio) { ++ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); ++ ret = -ENODEV; ++ goto fail2; ++ } ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ err = saa716x_request_irq(saa716x); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); ++ ret = -ENODEV; ++ goto fail3; ++ } ++ ++ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); ++ pci_read_config_dword(pdev, 0x40, &msi_cap); ++ ++ saa716x->revision = revision; ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", ++ saa716x->pdev->device, ++ revision, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 0, ++ "irq: %d,\n mmio: 0x%p\n", ++ saa716x->pdev->irq, ++ saa716x->mmio); ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", ++ saa716x->pdev->device, ++ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), ++ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), ++ (1 << ((msi_cap >> 17) & 0x07))); ++ ++ dprintk(SAA716x_ERROR, 0, "\n"); ++ ++ pci_set_drvdata(pdev, saa716x); ++ ++ return 0; ++ ++fail3: ++ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); ++ if (saa716x->mmio) ++ iounmap(saa716x->mmio); ++fail2: ++ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++fail1: ++ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); ++ pci_disable_device(pdev); ++ ++fail0: ++ pci_set_drvdata(pdev, NULL); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_init); ++ ++void saa716x_pci_exit(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ saa716x_free_irq(saa716x); ++ ++ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", ++ saa716x->pdev->device, ++ saa716x->mmio); ++ ++ if (saa716x->mmio) { ++ iounmap(saa716x->mmio); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ } ++ ++ pci_disable_device(pdev); ++ pci_set_drvdata(pdev, NULL); ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_exit); ++ ++MODULE_DESCRIPTION("SAA716x bridge driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.c 2013-01-16 10:41:10.924798189 +0100 +@@ -0,0 +1,152 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_spi.h" ++#include "saa716x_phi.h" ++#include "saa716x_priv.h" ++ ++u32 PHI_0_REGS[] = { ++ PHI_0_MODE, ++ PHI_0_0_CONFIG, ++ PHI_0_1_CONFIG, ++ PHI_0_2_CONFIG, ++ PHI_0_3_CONFIG ++}; ++ ++u32 PHI_1_REGS[] = { ++ PHI_1_MODE, ++ PHI_1_0_CONFIG, ++ PHI_1_1_CONFIG, ++ PHI_1_2_CONFIG, ++ PHI_1_3_CONFIG, ++ PHI_1_4_CONFIG, ++ PHI_1_5_CONFIG, ++ PHI_1_6_CONFIG, ++ PHI_1_7_CONFIG ++}; ++ ++#define PHI_BASE(__port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_BASE : \ ++ PHI_0_BASE \ ++)) ++ ++#define PHI_APERTURE(_port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_APERTURE: \ ++ PHI_0_APERTURE \ ++)) ++ ++#define PHI_REG(__port, __reg) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_REGS[__reg] : \ ++ PHI_0_REGS[__reg] \ ++)) ++ ++#define PHI_SLAVE(__port, __slave) (( \ ++ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ ++)) ++ ++/* // Read SAA716x registers ++ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) ++ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) ++ * ++ * // Read slave registers ++ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) ++ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) ++ */ ++ ++int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) ++{ ++ int i; ++ ++ /* Reset */ ++ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); ++ ++ for (i = 0; i < 20; i++) { ++ msleep(1); ++ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_phi_init(struct saa716x_dev *saa716x) ++{ ++ uint32_t value; ++ ++ /* init PHI 0 to FIFO mode */ ++ value = 0; ++ value |= PHI_FIFO_MODE; ++ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); ++ ++ value = 0; ++ value |= 0x02; /* chip select 1 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x06 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); ++ ++ /* init PHI 1 to SRAM mode, auto increment on */ ++ value = 0; ++ value |= PHI_AUTO_INCREMENT; ++ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); ++ ++ value = 0; ++ value |= 0x01; /* chip select 0 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x05 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); ++ ++ value = 0; ++ value |= PHI_ALE_POL; /* ALE is active high */ ++ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); ++ ++ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_init); ++ ++int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write); ++ ++int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_read); ++ ++int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.h 2013-01-16 10:41:10.924798189 +0100 +@@ -0,0 +1,39 @@ ++#ifndef __SAA716x_PHI_H ++#define __SAA716x_PHI_H ++ ++/* PHI SLAVE */ ++#define PHI_SLAVE_0 0 ++#define PHI_SLAVE_1 1 ++#define PHI_SLAVE_2 2 ++#define PHI_SLAVE_3 3 ++#define PHI_SLAVE_4 4 ++#define PHI_SLAVE_5 5 ++#define PHI_SLAVE_6 6 ++#define PHI_SLAVE_7 7 ++ ++/* PHI_REG */ ++#define PHI_MODE 0 ++#define PHI_CONFIG_0 1 ++#define PHI_CONFIG_1 2 ++#define PHI_CONFIG_2 3 ++#define PHI_CONFIG_3 4 ++#define PHI_CONFIG_4 5 ++#define PHI_CONFIG_5 6 ++#define PHI_CONFIG_6 7 ++#define PHI_CONFIG_7 8 ++ ++#define PHI_0_BASE 0x1000 ++#define PHI_0_APERTURE 0x0800 ++ ++#define PHI_1_BASE 0x0000 ++#define PHI_1_APERTURE 0xfffc ++ ++struct saa716x_dev; ++ ++extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); ++extern int saa716x_phi_init(struct saa716x_dev *saa716x); ++extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); ++extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); ++extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); ++ ++#endif /* __SAA716x_PHI_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi_reg.h 2013-01-16 10:41:10.925798182 +0100 +@@ -0,0 +1,100 @@ ++#ifndef __SAA716x_PHI_REG_H ++#define __SAA716x_PHI_REG_H ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++ ++/* BAR = 20 bits */ ++/* -------------- PHI1 Registers -------------- */ ++ ++ ++#endif /* __SAA716x_PHI_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_priv.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_priv.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_priv.h 2013-01-16 10:41:10.925798182 +0100 +@@ -0,0 +1,194 @@ ++#ifndef __SAA716x_PRIV_H ++#define __SAA716x_PRIV_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "saa716x_i2c.h" ++#include "saa716x_boot.h" ++#include "saa716x_cgu.h" ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++ ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dmxdev.h" ++#include "dvb_frontend.h" ++#include "dvb_net.h" ++ ++#define SAA716x_ERROR 0 ++#define SAA716x_NOTICE 1 ++#define SAA716x_INFO 2 ++#define SAA716x_DEBUG 3 ++ ++#define SAA716x_DEV (saa716x)->num ++#define SAA716x_VERBOSE (saa716x)->verbose ++#define SAA716x_MAX_ADAPTERS 4 ++ ++#define dprintk(__x, __y, __fmt, __arg...) do { \ ++ if (__y) { \ ++ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ } else { \ ++ if (SAA716x_VERBOSE > __x) \ ++ printk(__fmt , ##__arg); \ ++ } \ ++} while(0) ++ ++ ++#define NXP_SEMICONDUCTOR 0x1131 ++#define SAA7160 0x7160 ++#define SAA7161 0x7161 ++#define SAA7162 0x7162 ++ ++#define NXP_REFERENCE_BOARD 0x1131 ++ ++#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ ++ .vendor = NXP_SEMICONDUCTOR, \ ++ .device = (__chip), \ ++ .subvendor = (__subven), \ ++ .subdevice = (__subdev), \ ++ .driver_data = (unsigned long) (__configptr) \ ++} ++ ++#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++ ++#define SAA716x_MSI_MAX_VECTORS 16 ++ ++struct saa716x_msix_entry { ++ int vector; ++ u8 desc[32]; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++struct saa716x_dev; ++struct saa716x_adapter; ++struct saa716x_spi_config; ++ ++struct saa716x_adap_config { ++ u32 ts_port; ++ void (*worker)(unsigned long); ++}; ++ ++struct saa716x_config { ++ char *model_name; ++ char *dev_type; ++ ++ enum saa716x_boot_mode boot_mode; ++ ++ int adapters; ++ int frontends; ++ ++ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); ++ irqreturn_t (*irq_handler)(int irq, void *dev_id); ++ ++ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; ++ enum saa716x_i2c_rate i2c_rate; ++ enum saa716x_i2c_mode i2c_mode; ++}; ++ ++struct saa716x_adapter { ++ struct dvb_adapter dvb_adapter; ++ struct dvb_frontend *fe; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ struct dvb_net dvb_net; ++ ++ struct saa716x_dev *saa716x; ++ ++ u8 feeds; ++ u8 count; ++}; ++ ++struct saa716x_dev { ++ struct saa716x_config *config; ++ struct pci_dev *pdev; ++ ++ int num; /* device count */ ++ int verbose; ++ ++ u8 revision; ++ ++ /* PCI */ ++ void __iomem *mmio; ++ ++#define MODE_INTA 0 ++#define MODE_MSI 1 ++#define MODE_MSI_X 2 ++ u8 int_type; ++ ++ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; ++ struct saa716x_msix_entry saa716x_msix_handler[56]; ++ u8 handlers; /* no. of active handlers */ ++ ++ /* I2C */ ++ struct saa716x_i2c i2c[2]; ++ u32 i2c_rate; /* init time */ ++ u32 I2C_DEV[2]; ++ ++ struct saa716x_spi_state *saa716x_spi; ++ struct saa716x_spi_config spi_config; ++ ++ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; ++ struct mutex adap_lock; ++ struct saa716x_cgu cgu; ++ ++ spinlock_t gpio_lock; ++ /* DMA */ ++ ++ struct saa716x_fgpi_stream_port fgpi[4]; ++ ++ u32 id_offst; ++ u32 id_len; ++ void *priv; ++ ++ /* remote control */ ++ void *ir_priv; ++}; ++ ++/* PCI */ ++extern int saa716x_pci_init(struct saa716x_dev *saa716x); ++extern void saa716x_pci_exit(struct saa716x_dev *saa716x); ++ ++/* MSI */ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msi_exit(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++/* DMA */ ++extern int saa716x_dma_init(struct saa716x_dev *saa716x); ++extern void saa716x_dma_exit(struct saa716x_dev *saa716x); ++ ++/* AUDIO */ ++extern int saa716x_audio_init(struct saa716x_dev *saa716x); ++extern void saa716x_audio_exit(struct saa716x_dev *saa716x); ++ ++/* Boot */ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++ ++/* Remote control */ ++extern int saa716x_ir_init(struct saa716x_dev *saa716x); ++extern void saa716x_ir_exit(struct saa716x_dev *saa716x); ++extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); ++ ++#endif /* __SAA716x_PRIV_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_reg.h 2013-01-16 10:41:10.925798182 +0100 +@@ -0,0 +1,1279 @@ ++#ifndef __SAA716x_REG_H ++#define __SAA716x_REG_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++ ++ ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM 0x00008000 ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU 0x00009000 ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI 0x0000a000 ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI 0x0000d000 ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO 0x0000e000 ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0 0x0000f000 ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU 0x00013000 ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCS 0x00014000 ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG 0x00012000 ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++/* BAR = 20 bits */ ++ ++/* -------------- PHI1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++ ++ ++#endif /* __SAA716x_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.c 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,1071 @@ ++#include ++#include ++ ++#include "saa716x_rom.h" ++#include "saa716x_adap.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++int i; ++ ++static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ ++ u8 b0[] = { MSB(reg), LSB(reg) }; ++ int ret; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, ++ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } ++ }; ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ struct i2c_msg msg[2]; ++ ++ u8 b0[2]; ++ int ret, count; ++ ++ count = len / DUMP_BYTES; ++ if (len % DUMP_BYTES) ++ count++; ++ ++ count *= 2; ++ ++ for (i = 0; i < count; i += 2) { ++ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", ++ len, ++ count, ++ reg); ++ ++ b0[0] = MSB(reg); ++ b0[1] = LSB(reg); ++ ++ /* Write */ ++ msg[0].addr = 0x50; ++ msg[0].flags = 0; ++ msg[0].buf = b0; ++ msg[0].len = 2; ++ ++ /* Read */ ++ msg[1].addr = 0x50; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ ++ if (i == (count - 2)) { ++ /* last message */ ++ if (len % DUMP_BYTES) { ++ msg[1].len = len % DUMP_BYTES; ++ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ reg += DUMP_BYTES; ++ val += DUMP_BYTES; ++ } ++ ++ return 0; ++} ++ ++static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) ++{ ++ int i; ++ ++ *offset = 0; ++ for (i = 0; i < 256; i++) { ++ if (!(strncmp("START", buf + i, 5))) ++ break; ++ } ++ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); ++ *offset = i; ++ ++ return 0; ++} ++ ++static int saa716x_eeprom_header(struct saa716x_dev *saa716x, ++ struct saa716x_romhdr *rom_header, ++ u8 *buf, ++ u32 *offset) ++{ ++ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); ++ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ (int)sizeof (struct saa716x_romhdr), ++ rom_header->header_size); ++ ++ return -1; ++ } ++ *offset += sizeof (struct saa716x_romhdr); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", ++ saa716x->pdev->device, ++ rom_header->data_size); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", ++ saa716x->pdev->device, ++ rom_header->version); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", ++ saa716x->pdev->device, ++ rom_header->devices); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", ++ saa716x->pdev->device, ++ rom_header->compression); ++ ++ return 0; ++} ++ ++int saa716x_dump_eeprom(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ u8 buf[DUMP_BYTES]; ++ int i, err = 0; ++ u32 offset = 0; ++ ++ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); ++ return err; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", ++ saa716x->config->model_name); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", ++ saa716x->pdev->device, ++ DUMP_OFFST); ++ ++ for (i = 0; i < DUMP_BYTES; i++) { ++ if ((i % 16) == 0) { ++ dprintk(SAA716x_NOTICE, 0, "\n "); ++ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); ++ } ++ ++ if ((i % 8) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); ++ } ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", ++ saa716x->pdev->device); ++ ++ err = saa716x_get_offset(saa716x, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); ++ return err; ++ } ++ offset += 5; ++ saa716x->id_offst = offset; ++ /* Get header */ ++ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); ++ return -1; ++ } ++ saa716x->id_len = rom_header.data_size; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); ++ ++static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++static int saa716x_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext Data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_gpio_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_gpio_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_gpio_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_gpio_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pins=%d\n", ++ saa716x->pdev->device, ++ header.pins); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ ++ return 0; ++} ++ ++static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_video_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_video_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 0=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port0); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 1=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port1); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 2=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port2); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT ID=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_id); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_audio_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_audio_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_event_source_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_evsrc_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_evsrc_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_crossbar_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_xbar_hdr header; ++ struct saa716x_xbar_pair_info pair_info; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_xbar_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_xbar_hdr)); ++ ++ return -1; ++ } ++ ++ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pairs=%d\n", ++ saa716x->pdev->device, ++ header.pair_inputs); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); ++ return 0; ++} ++ ++static int saa716x_tuner_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_tuner_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_tuner_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_tuner_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_pll_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_pll_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_pll_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_pll_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_channel_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_channel_decoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_encoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_encoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_encoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_encoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_ir_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_ir_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_ir_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_ir_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_eeprom_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_eeprom_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_eeprom_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_filter_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_filter_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_filter_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_filter_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_streamdev_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_streamdev_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_streamdev_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 size; ++ u8 ext_size = 0; ++ ++ size = buf[*offset]; ++ if (size > 1) ++ ext_size = buf[*offset + size -1]; ++ ++ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ ext_size); ++ ++ *offset += size + ext_size; ++ return 0; ++} ++ ++ ++static void saa716x_device_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size, ++ u8 addr_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size + addr_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++ ++static int saa716x_device_info(struct saa716x_dev *saa716x, ++ struct saa716x_devinfo *device, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 address = 0; ++ ++ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); ++ if (device->struct_size != sizeof(struct saa716x_devinfo)) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", ++ device->struct_size, ++ (int)sizeof(struct saa716x_devinfo)); ++ ++ return -1; ++ } ++ ++ saa716x_device_dbg(saa716x, ++ buf, ++ offset, ++ device->struct_size, ++ device->extd_data_size, ++ device->addr_size); ++ ++ *offset += device->struct_size; ++ ++ if (device->addr_size) { ++ address = buf[*offset]; ++ address >>= 1; ++ *offset += device->addr_size; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", ++ saa716x->pdev->device, ++ address); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ device->struct_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_devid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_busid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_type); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->implem_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->path_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->gpio_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", ++ saa716x->pdev->device, ++ device->addr_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", ++ saa716x->pdev->device, ++ device->extd_data_size); ++ ++ if (device->extd_data_size) { ++ u32 mask; ++ ++ mask = 0x00000001; ++ while (mask) { ++ if (device->device_type & mask) { ++ switch (mask) { ++ case DECODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case GPIO_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found GPIO device\n", ++ saa716x->pdev->device); ++ ++ saa716x_gpio_info(saa716x, buf, offset); ++ break; ++ ++ case VIDEO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Video Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_video_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case AUDIO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Audio Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_audio_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case EVENT_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Event source\n", ++ saa716x->pdev->device); ++ ++ saa716x_event_source_info(saa716x, buf, offset); ++ break; ++ ++ case CROSSBAR: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Crossbar device\n", ++ saa716x->pdev->device); ++ ++ saa716x_crossbar_info(saa716x, buf, offset); ++ break; ++ ++ case TUNER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Tuner device\n", ++ saa716x->pdev->device); ++ ++ saa716x_tuner_info(saa716x, buf, offset); ++ break; ++ ++ case PLL_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found PLL device\n", ++ saa716x->pdev->device); ++ ++ saa716x_pll_info(saa716x, buf, offset); ++ break; ++ ++ case CHANNEL_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Channel Demodulator device\n", ++ saa716x->pdev->device); ++ ++ saa716x_channel_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case RDS_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found RDS Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case ENCODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Encoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_encoder_info(saa716x, buf, offset); ++ break; ++ ++ case IR_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found IR device\n", ++ saa716x->pdev->device); ++ ++ saa716x_ir_info(saa716x, buf, offset); ++ break; ++ ++ case EEPROM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found EEPROM device\n", ++ saa716x->pdev->device); ++ ++ saa716x_eeprom_info(saa716x, buf, offset); ++ break; ++ ++ case NOISE_FILTER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Noise filter device\n", ++ saa716x->pdev->device); ++ ++ saa716x_filter_info(saa716x, buf, offset); ++ break; ++ ++ case LNx_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found LNx device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case STREAM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found streaming device\n", ++ saa716x->pdev->device); ++ ++ saa716x_streamdev_info(saa716x, buf, offset); ++ break; ++ ++ case CONFIGSPACE_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Configspace device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ default: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found unknown device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ } ++ } ++ mask <<= 1; ++ } ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ ++ return 0; ++} ++ ++int saa716x_eeprom_data(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ struct saa716x_devinfo *device; ++ ++ u8 buf[1024]; ++ int i, ret = 0; ++ u32 offset = 0; ++ ++ /* dump */ ++ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); ++ goto err0; ++ } ++ ++ /* Get header */ ++ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); ++ goto err0; ++ } ++ ++ /* allocate for device info */ ++ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); ++ if (device == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); ++ goto err0; ++ } ++ ++ for (i = 0; i < rom_header.devices; i++) { ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", ++ saa716x->pdev->device, ++ i); ++ ++ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); ++ goto err1; ++ } ++ } ++ ++ kfree(device); ++ ++ return 0; ++ ++err1: ++ kfree(device); ++ ++err0: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_eeprom_data); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.h 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,253 @@ ++#ifndef __SAA716x_ROM_H ++#define __SAA716x_ROM_H ++ ++ ++#define MSB(__x) ((__x >> 8) & 0xff) ++#define LSB(__x) (__x & 0xff) ++ ++#define DUMP_BYTES 0xf0 ++#define DUMP_OFFST 0x000 ++ ++struct saa716x_dev; ++ ++struct saa716x_romhdr { ++ u16 header_size; ++ u8 compression; ++ u8 version; ++ u16 data_size; ++ u8 devices; ++ u8 checksum; ++} __attribute__((packed)); ++ ++struct saa716x_devinfo { ++ u8 struct_size; ++ u8 device_id; ++ u8 master_devid; ++ u8 master_busid; ++ u32 device_type; ++ u16 implem_id; ++ u8 path_id; ++ u8 gpio_id; ++ u16 addr_size; ++ u16 extd_data_size; ++} __attribute__((packed)); ++ ++enum saa716x_device_types { ++ DECODER_DEVICE = 0x00000001, ++ GPIO_SOURCE = 0x00000002, ++ VIDEO_DECODER = 0x00000004, ++ AUDIO_DECODER = 0x00000008, ++ EVENT_SOURCE = 0x00000010, ++ CROSSBAR = 0x00000020, ++ TUNER_DEVICE = 0x00000040, ++ PLL_DEVICE = 0x00000080, ++ CHANNEL_DECODER = 0x00000100, ++ RDS_DECODER = 0x00000200, ++ ENCODER_DEVICE = 0x00000400, ++ IR_DEVICE = 0x00000800, ++ EEPROM_DEVICE = 0x00001000, ++ NOISE_FILTER = 0x00002000, ++ LNx_DEVICE = 0x00004000, ++ STREAM_DEVICE = 0x00010000, ++ CONFIGSPACE_DEVICE = 0x80000000 ++}; ++ ++struct saa716x_decoder_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_decoder_info { ++ struct saa716x_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_gpio_hdr { ++ u8 size; ++ u8 pins; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_gpio_info { ++ struct saa716x_gpio_hdr gpio_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_video_decoder_hdr { ++ u8 size; ++ u8 video_port0; ++ u8 video_port1; ++ u8 video_port2; ++ u8 vbi_port_id; ++ u8 video_port_type; ++ u8 vbi_port_type; ++ u8 encoder_port_type; ++ u8 video_output; ++ u8 vbi_output; ++ u8 encoder_output; ++ u8 ext_data; ++}; ++ ++struct saa716x_video_decoder_info { ++ struct saa716x_video_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_audio_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 output; ++ u8 ext_data; ++}; ++ ++struct saa716x_audio_decoder_info { ++ struct saa716x_audio_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_evsrc_hdr { ++ u8 size; ++ u8 master_devid; ++ u16 condition_id; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_evsrc_info { ++ struct saa716x_evsrc_hdr evsrc_hdr; ++ u8 *ext_data; ++}; ++ ++enum saa716x_input_pair_type { ++ TUNER_SIF = 0x00, ++ TUNER_LINE = 0x01, ++ TUNER_SPDIF = 0x02, ++ TUNER_NONE = 0x03, ++ CVBS_LINE = 0x04, ++ CVBS_SPDIF = 0x05, ++ CVBS_NONE = 0x06, ++ YC_LINE = 0x07, ++ YC_SPDIF = 0x08, ++ YC_NONE = 0x09, ++ YPbPr_LINE = 0x0a, ++ YPbPr_SPDIF = 0x0b, ++ YPbPr_NONE = 0x0c, ++ NO_LINE = 0x0d, ++ NO_SPDIF = 0x0e, ++ RGB_LINE = 0x0f, ++ RGB_SPDIF = 0x10, ++ RGB_NONE = 0x11 ++}; ++ ++struct saa716x_xbar_pair_info { ++ u8 pair_input_type; ++ u8 video_input_id; ++ u8 audio_input_id; ++}; ++ ++struct saa716x_xbar_hdr { ++ u8 size; ++ u8 pair_inputs; ++ u8 pair_route_default; ++ u8 ext_data; ++}; ++ ++struct saa716x_xbar_info { ++ struct saa716x_xbar_hdr xbar_hdr; ++ struct saa716x_xbar_pair_info *pair_info; ++ u8 *ext_data; ++}; ++ ++struct saa716x_tuner_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_tuner_info { ++ struct saa716x_tuner_hdr tuner_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_pll_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_pll_info { ++ struct saa716x_pll_hdr pll_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_channel_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 ext_data; ++}; ++ ++struct saa716x_channel_decoder_info { ++ struct saa716x_channel_decoder_hdr channel_dec_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_encoder_hdr { ++ u8 size; ++ u8 stream_port0; ++ u8 stream_port1; ++ u8 ext_data; ++}; ++ ++struct saa716x_encoder_info { ++ struct saa716x_encoder_hdr encoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_ir_hdr { ++ u8 size; ++ u8 ir_caps; ++ u8 ext_data; ++}; ++ ++struct saa716x_ir_info { ++ struct saa716x_ir_hdr ir_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_eeprom_hdr { ++ u8 size; ++ u8 rel_device; ++ u8 ext_data; ++}; ++ ++struct saa716x_eeprom_info { ++ struct saa716x_eeprom_hdr eeprom_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_filter_hdr { ++ u8 size; ++ u8 video_decoder; ++ u8 audio_decoder; ++ u8 event_source; ++ u8 ext_data; ++}; ++ ++struct saa716x_filter_info { ++ struct saa716x_filter_hdr filter_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_streamdev_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_streamdev_info { ++ struct saa716x_streamdev_hdr streamdev_hdr; ++ u8 *ext_data; ++}; ++ ++extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); ++extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ROM_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.c 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,313 @@ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_spi_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#if 0 // not needed atm ++int saa716x_spi_irqevent(struct saa716x_dev *saa716x) ++{ ++ u32 stat, mask; ++ ++ BUG_ON(saa716x == NULL); ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; ++ if ((!stat && !mask)) ++ return -1; ++ ++ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++#endif ++ ++void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ int i; ++ u32 value; ++ int rounds; ++ ++ for (i = 0; i < length; i++) { ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ rounds = 0; ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ rounds++; ++ } ++ } ++} ++EXPORT_SYMBOL_GPL(saa716x_spi_write); ++ ++#if 0 // not needed atm ++static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) ++{ ++ u32 stat; ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); ++ ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); ++ ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); ++ ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); ++ ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); ++ ++ *status = stat; ++ ++ return 0; ++} ++ ++#define SPI_CYCLE_TIMEOUT 100 ++ ++static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) ++{ ++ u32 i, status = 0; ++ ++ /* write data and wait for completion */ ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { ++ msleep(10); ++ saa716x_spi_status(saa716x, &status); ++#if 0 ++ if (status & SPI_TRANSFER_FLAG) { ++ data = SAA716x_EPRD(SPI, SPI_DATA); ++ return 0; ++ } ++#endif ++ if (status & (SPI_WRITE_COLLISSION | ++ SPI_READ_OVERRUN | ++ SPI_MODE_FAULT | ++ SPI_SLAVE_ABORT)) ++ ++ return -EIO; ++ } ++ ++ return -EIO; ++} ++ ++#if 0 ++static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ struct saa716x_spi_config *config = saa716x->spi_config; ++ u32 gpio_mask; ++ int ret = 0; ++ ++ // protect against multiple access ++ spin_lock(&saa716x->gpio_lock); ++ ++ // configure the module ++ saa716x_spi_config(saa716x); ++ ++ // check input ++ ++ // change polarity of GPIO if active high ++ if (config->active_hi) { ++ select = 1; ++ release = 0; ++ } ++ ++ // configure GPIO, first set output register to low selected level ++ saa716x_gpio_write(saa716x, gpio, select); ++ ++ // set mode register to register controlled (0) ++ gpio_mask = (1 << gpio); ++ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); ++ ++ // configure bit as output (0) ++ saa716x_gpio_ctl(saa716x, gpio_mask, 0); ++ ++ // wait at least 500ns before sending a byte ++ msleep(1); ++ ++ // send command ++ for (i = 0; i < dwCommandSize; i++) { ++ ucData = 0; ++// dwStatus = TransferData(pucCommand[i], &ucData); ++ ret = saa716x_spi_xfer(saa716x); ++ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); ++ ++ /* If command length > 1, disable CS at the end of each command. ++ * But after the last command byte CS must be left active! ++ */ ++ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { ++ ++ saa716x_gpio_write(saa716x, gpio, release); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, select); ++ } ++ ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ ++ spin_unlock(&saa716x->spi_lock); ++ return ret; ++ } ++ ++ if (config->LSB_first) ++ dwTransferByte++; ++ else ++ dwTransferByte--; ++ } ++ ++// assume that the byte order is the same as the bit order ++ ++// send read address ++ ++// send data ++ ++// wait at least 500ns before releasing slave ++ ++// release GPIO pin ++ ++ // release spinlock ++ spin_unlock(&saa716x->gpio_lock); ++} ++#endif ++ ++#define MODEBITS (SPI_CPOL | SPI_CPHA) ++ ++static int saa716x_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ struct saa716x_spi_config *config = &saa716x->spi_config; ++ ++ u8 control = 0; ++ ++ if (spi->mode & ~MODEBITS) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", ++ spi->mode & ~MODEBITS); ++ ++ return -EINVAL; ++ } ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); ++ ++ control |= SPI_MODE_SELECT; /* SPI Master */ ++ ++ if (config->LSB_first) ++ control |= SPI_LSB_FIRST_ENABLE; ++ ++ if (config->clk_pol) ++ control |= SPI_CLOCK_POLARITY; ++ ++ if (config->clk_pha) ++ control |= SPI_CLOCK_PHASE; ++ ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); ++ ++ return 0; ++} ++ ++static void saa716x_spi_cleanup(struct spi_device *spi) ++{ ++ ++} ++ ++static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++#if 0 ++ if (saa716x_spi->run == QUEUE_STOPPED) { ++ spin_unlock_irqrestore(&saa716x_spi->lock, flags); ++ return -ESHUTDOWN; ++ } ++ ++ msg->actual_length = 0; ++ msg->status = -EINPROGRESS; ++ msg->state = START_STATE; ++ ++ list_add_tail(&msg->queue, &saa716x_spi->queue); ++ ++ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) ++ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); ++#endif ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++int saa716x_spi_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct spi_master *master; ++ struct saa716x_spi_state *saa716x_spi; ++ int ret; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); ++ if (master == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); ++ return -ENOMEM; ++ } ++ ++ saa716x_spi = spi_master_get_devdata(master); ++ saa716x_spi->master = master; ++ saa716x_spi->saa716x = saa716x; ++ saa716x->saa716x_spi = saa716x_spi; ++ ++ master->bus_num = pdev->bus->number; ++ master->num_chipselect = 1; /* TODO! use config */ ++ master->cleanup = saa716x_spi_cleanup; ++ master->setup = saa716x_spi_setup; ++ master->transfer = saa716x_spi_transfer; ++ ++ ret = spi_register_master(master); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); ++ goto err; ++ } ++err: ++ spi_master_put(master); ++ return ret; ++} ++EXPORT_SYMBOL(saa716x_spi_init); ++ ++void saa716x_spi_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; ++ ++ spi_unregister_master(saa716x_spi->master); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); ++} ++EXPORT_SYMBOL(saa716x_spi_exit); ++#endif ++ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.h 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,23 @@ ++#ifndef __SAA716x_SPI_H ++#define __SAA716x_SPI_H ++ ++struct saa716x_dev; ++ ++struct saa716x_spi_config { ++ u8 clk_count; ++ u8 clk_pol:1; ++ u8 clk_pha:1; ++ u8 LSB_first:1; ++}; ++ ++struct saa716x_spi_state { ++ struct spi_master *master; ++ struct saa716x_dev *saa716x; ++}; ++ ++extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); ++ ++extern int saa716x_spi_init(struct saa716x_dev *saa716x); ++extern void saa716x_spi_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_SPI_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi_reg.h 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,27 @@ ++#ifndef __SAA716x_SPI_REG_H ++#define __SAA716x_SPI_REG_H ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_SPI_REG_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.c +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.c 2013-01-16 10:41:10.926798175 +0100 +@@ -0,0 +1,23 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_vip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_vipint_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ ++ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++} ++EXPORT_SYMBOL_GPL(saa716x_vipint_disable); ++ ++void saa716x_vip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); ++ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_disable); +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.h 2013-01-16 10:41:10.927798168 +0100 +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_VIP_H ++#define __SAA716x_VIP_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); ++extern void saa716x_vip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_VIP_H */ +diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip_reg.h +--- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip_reg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip_reg.h 2013-01-16 10:41:10.927798168 +0100 +@@ -0,0 +1,127 @@ ++#ifndef __SAA716x_VIP_REG_H ++#define __SAA716x_VIP_REG_H ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++#endif /* __SAA716x_VIP_REG_H */ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/ds3103.h linux-3.7.2.patch/drivers/media/dvb-frontends/ds3103.h +--- linux-3.7.2/drivers/media/dvb-frontends/ds3103.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/ds3103.h 2013-01-16 10:41:10.927798168 +0100 +@@ -0,0 +1,47 @@ ++/* ++ Montage Technology DS3103 - DVBS/S2 Demodulator driver ++ ++ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef DS3103_H ++#define DS3103_H ++ ++#include ++ ++struct ds3103_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++ u8 ci_mode; ++ /* Set device param to start dma */ ++ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); ++}; ++ ++#if defined(CONFIG_DVB_DS3103) || \ ++ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline ++struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_DS3103 */ ++#endif /* DS3103_H */ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/ts2022.h linux-3.7.2.patch/drivers/media/dvb-frontends/ts2022.h +--- linux-3.7.2/drivers/media/dvb-frontends/ts2022.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/ts2022.h 2013-01-16 10:41:10.927798168 +0100 +@@ -0,0 +1,51 @@ ++ /* ++ Driver for Montage TS2022 DVBS/S2 Silicon tuner ++ ++ Copyright (C) 2012 Tomazzo Muzumici ++ ++ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++ */ ++ ++#ifndef __DVB_TS2022_H__ ++#define __DVB_TS2022_H__ ++ ++#include ++#include "dvb_frontend.h" ++ ++/** ++ * Attach a ts2022 tuner to the supplied frontend structure. ++ * ++ * @param fe Frontend to attach to. ++ * @param addr i2c address of the tuner. ++ * @param i2c i2c adapter to use. ++ * @return FE pointer on success, NULL on failure. ++ */ ++#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ ++ && defined(MODULE)) ++extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, ++ int addr, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_TS2022 */ ++ ++#endif /* __DVB_TS2022_H__ */ +diff -Naur linux-3.7.2/include/uapi/linux/dvb/osd.h linux-3.7.2.patch/include/uapi/linux/dvb/osd.h +--- linux-3.7.2/include/uapi/linux/dvb/osd.h 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/include/uapi/linux/dvb/osd.h 2013-01-16 10:41:21.992712972 +0100 +@@ -141,4 +141,20 @@ + #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) + #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) + ++typedef struct osd_raw_cmd_s { ++ const void __user *cmd_data; ++ int cmd_len; ++ void __user *result_data; ++ int result_len; ++} osd_raw_cmd_t; ++ ++typedef struct osd_raw_data_s { ++ const void __user *data_buffer; ++ int data_length; ++ int data_handle; ++} osd_raw_data_t; ++ ++#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) ++#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) ++ + #endif