mirror of
https://github.com/LibreELEC/LibreELEC.tv
synced 2025-09-24 19:46:01 +07:00
13032 lines
356 KiB
Diff
13032 lines
356 KiB
Diff
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
|
|
index b85f88c..238b2ed 100644
|
|
--- a/drivers/media/common/Kconfig
|
|
+++ b/drivers/media/common/Kconfig
|
|
@@ -22,4 +22,5 @@ config CYPRESS_FIRMWARE
|
|
|
|
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 --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
|
|
index d208de3..b3c373d 100644
|
|
--- a/drivers/media/common/Makefile
|
|
+++ b/drivers/media/common/Makefile
|
|
@@ -1,4 +1,4 @@
|
|
-obj-y += b2c2/ saa7146/ siano/
|
|
+obj-y += b2c2/ saa7146/ saa716x/ siano/
|
|
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
|
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
|
|
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
|
diff --git a/drivers/media/common/saa716x/Kconfig b/drivers/media/common/saa716x/Kconfig
|
|
new file mode 100644
|
|
index 0000000..e667a58
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/Kconfig
|
|
@@ -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 --git a/drivers/media/common/saa716x/Makefile b/drivers/media/common/saa716x/Makefile
|
|
new file mode 100644
|
|
index 0000000..c86f224
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/Makefile
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_adap.c b/drivers/media/common/saa716x/saa716x_adap.c
|
|
new file mode 100644
|
|
index 0000000..6d7346c
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_adap.c
|
|
@@ -0,0 +1,274 @@
|
|
+#include <linux/bitops.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_adap.h b/drivers/media/common/saa716x/saa716x_adap.h
|
|
new file mode 100644
|
|
index 0000000..7822e36
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_adap.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_aip.c b/drivers/media/common/saa716x/saa716x_aip.c
|
|
new file mode 100644
|
|
index 0000000..3bdb265
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_aip.c
|
|
@@ -0,0 +1,20 @@
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_aip.h b/drivers/media/common/saa716x/saa716x_aip.h
|
|
new file mode 100644
|
|
index 0000000..36277b7
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_aip.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_aip_reg.h b/drivers/media/common/saa716x/saa716x_aip_reg.h
|
|
new file mode 100644
|
|
index 0000000..3e0893a
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_aip_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_boot.c b/drivers/media/common/saa716x/saa716x_boot.c
|
|
new file mode 100644
|
|
index 0000000..21e59d0
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_boot.c
|
|
@@ -0,0 +1,319 @@
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_boot.h b/drivers/media/common/saa716x/saa716x_boot.h
|
|
new file mode 100644
|
|
index 0000000..8102853
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_boot.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_budget.c b/drivers/media/common/saa716x/saa716x_budget.c
|
|
new file mode 100644
|
|
index 0000000..6b52fc1
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_budget.c
|
|
@@ -0,0 +1,717 @@
|
|
+#include <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/mutex.h>
|
|
+
|
|
+#include <asm/io.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/page.h>
|
|
+#include <linux/kmod.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/device.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <linux/i2c.h>
|
|
+
|
|
+#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 = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0);
|
|
+ if (err < 0)
|
|
+ goto exit;
|
|
+ err = skystar2_stv090x_config.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 = skystar2_stv090x_config.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 --git a/drivers/media/common/saa716x/saa716x_budget.h b/drivers/media/common/saa716x/saa716x_budget.h
|
|
new file mode 100644
|
|
index 0000000..d6b8c46
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_budget.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_cgu.c b/drivers/media/common/saa716x/saa716x_cgu.c
|
|
new file mode 100644
|
|
index 0000000..a0ffb04
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_cgu.c
|
|
@@ -0,0 +1,539 @@
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_cgu.h b/drivers/media/common/saa716x/saa716x_cgu.h
|
|
new file mode 100644
|
|
index 0000000..5353cf2
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_cgu.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_cgu_reg.h b/drivers/media/common/saa716x/saa716x_cgu_reg.h
|
|
new file mode 100644
|
|
index 0000000..f7d82ae
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_cgu_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_dcs_reg.h b/drivers/media/common/saa716x/saa716x_dcs_reg.h
|
|
new file mode 100644
|
|
index 0000000..26dba68
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_dcs_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_dma.c b/drivers/media/common/saa716x/saa716x_dma.c
|
|
new file mode 100644
|
|
index 0000000..21d1dd8
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_dma.c
|
|
@@ -0,0 +1,306 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/scatterlist.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/pgtable.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_dma.h b/drivers/media/common/saa716x/saa716x_dma.h
|
|
new file mode 100644
|
|
index 0000000..f92d667
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_dma.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_dma_reg.h b/drivers/media/common/saa716x/saa716x_dma_reg.h
|
|
new file mode 100644
|
|
index 0000000..6037ca9
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_dma_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_ff.h b/drivers/media/common/saa716x/saa716x_ff.h
|
|
new file mode 100644
|
|
index 0000000..cb65929
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_ff.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_ff_cmd.c b/drivers/media/common/saa716x/saa716x_ff_cmd.c
|
|
new file mode 100644
|
|
index 0000000..81c1078
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.c
|
|
@@ -0,0 +1,412 @@
|
|
+#include <linux/types.h>
|
|
+
|
|
+#include <linux/dvb/video.h>
|
|
+#include <linux/dvb/osd.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_ff_cmd.h b/drivers/media/common/saa716x/saa716x_ff_cmd.h
|
|
new file mode 100644
|
|
index 0000000..fc79f08
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_ff_ir.c b/drivers/media/common/saa716x/saa716x_ff_ir.c
|
|
new file mode 100644
|
|
index 0000000..3562478
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_ff_ir.c
|
|
@@ -0,0 +1,265 @@
|
|
+/*
|
|
+ * Driver for the remote control of the TT6400 DVB-S2 card
|
|
+ *
|
|
+ * Copyright (C) 2010 Oliver Endriss <o.endriss@gmx.de>
|
|
+ *
|
|
+ * 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 <linux/types.h>
|
|
+#include <linux/input.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_ff_main.c b/drivers/media/common/saa716x/saa716x_ff_main.c
|
|
new file mode 100644
|
|
index 0000000..34093c2
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_ff_main.c
|
|
@@ -0,0 +1,1535 @@
|
|
+#include <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/mutex.h>
|
|
+
|
|
+#include <asm/io.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/byteorder.h>
|
|
+#include <linux/kmod.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/firmware.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <linux/i2c.h>
|
|
+
|
|
+#include <linux/dvb/video.h>
|
|
+#include <linux/dvb/audio.h>
|
|
+#include <linux/dvb/osd.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_fgpi.c b/drivers/media/common/saa716x/saa716x_fgpi.c
|
|
new file mode 100644
|
|
index 0000000..8bdb13d
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_fgpi.c
|
|
@@ -0,0 +1,389 @@
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_fgpi.h b/drivers/media/common/saa716x/saa716x_fgpi.h
|
|
new file mode 100644
|
|
index 0000000..225aff0
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_fgpi.h
|
|
@@ -0,0 +1,112 @@
|
|
+#ifndef __SAA716x_FGPI_H
|
|
+#define __SAA716x_FGPI_H
|
|
+
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_fgpi_reg.h b/drivers/media/common/saa716x/saa716x_fgpi_reg.h
|
|
new file mode 100644
|
|
index 0000000..1193016
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_fgpi_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_gpio.c b/drivers/media/common/saa716x/saa716x_gpio.c
|
|
new file mode 100644
|
|
index 0000000..62b6112
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_gpio.c
|
|
@@ -0,0 +1,140 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/spinlock.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_gpio.h b/drivers/media/common/saa716x/saa716x_gpio.h
|
|
new file mode 100644
|
|
index 0000000..a82580b
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_gpio.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_gpio_reg.h b/drivers/media/common/saa716x/saa716x_gpio_reg.h
|
|
new file mode 100644
|
|
index 0000000..f36184a
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_gpio_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_greg.c b/drivers/media/common/saa716x/saa716x_greg.c
|
|
new file mode 100644
|
|
index 0000000..d93a3b8
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_greg.c
|
|
@@ -0,0 +1,42 @@
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_greg.h b/drivers/media/common/saa716x/saa716x_greg.h
|
|
new file mode 100644
|
|
index 0000000..487595e
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_greg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_greg_reg.h b/drivers/media/common/saa716x/saa716x_greg_reg.h
|
|
new file mode 100644
|
|
index 0000000..052e8cd
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_greg_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_hybrid.c b/drivers/media/common/saa716x/saa716x_hybrid.c
|
|
new file mode 100644
|
|
index 0000000..27e5e71
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_hybrid.c
|
|
@@ -0,0 +1,726 @@
|
|
+#include <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/mutex.h>
|
|
+
|
|
+#include <asm/io.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/page.h>
|
|
+#include <linux/kmod.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/device.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <linux/i2c.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_hybrid.h b/drivers/media/common/saa716x/saa716x_hybrid.h
|
|
new file mode 100644
|
|
index 0000000..df34a59
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_hybrid.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_i2c.c b/drivers/media/common/saa716x/saa716x_i2c.c
|
|
new file mode 100644
|
|
index 0000000..91a091d
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_i2c.c
|
|
@@ -0,0 +1,734 @@
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <linux/i2c.h>
|
|
+
|
|
+#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, "<STFNF> ");
|
|
+
|
|
+ if (stat & I2C_INTERRUPT_MTFNF) {
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MTFNF> ");
|
|
+ }
|
|
+
|
|
+ if (stat & I2C_INTERRUPT_RFDA)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<RFDA> ");
|
|
+
|
|
+ if (stat & I2C_INTERRUPTE_RFF)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<RFF> ");
|
|
+
|
|
+ if (stat & I2C_SLAVE_INTERRUPT_STDR)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<STDR> ");
|
|
+
|
|
+ if (stat & I2C_MASTER_INTERRUPT_MTDR) {
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MTDR> ");
|
|
+ }
|
|
+
|
|
+ if (stat & I2C_ERROR_IBE)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<IBE> ");
|
|
+
|
|
+ if (stat & I2C_MODE_CHANGE_INTER_MSMC)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MSMC> ");
|
|
+
|
|
+ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<SRSD> ");
|
|
+
|
|
+ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<STSD> ");
|
|
+
|
|
+ if (stat & I2C_ACK_INTER_MTNA)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MTNA> ");
|
|
+
|
|
+ if (stat & I2C_FAILURE_INTER_MAF)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MAF> ");
|
|
+
|
|
+ if (stat & I2C_INTERRUPT_MTD)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<MTD> ");
|
|
+
|
|
+ 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, " <W %04x> 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, " <R %04x> 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, " <W %04x> 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);
|
|
+
|
|
+ i2c_del_adapter(adapter);
|
|
+ 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 --git a/drivers/media/common/saa716x/saa716x_i2c.h b/drivers/media/common/saa716x/saa716x_i2c.h
|
|
new file mode 100644
|
|
index 0000000..da767ac
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_i2c.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_i2c_reg.h b/drivers/media/common/saa716x/saa716x_i2c_reg.h
|
|
new file mode 100644
|
|
index 0000000..8fa992c
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_i2c_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_mod.h b/drivers/media/common/saa716x/saa716x_mod.h
|
|
new file mode 100644
|
|
index 0000000..273efdd
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_mod.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_msi.c b/drivers/media/common/saa716x/saa716x_msi.c
|
|
new file mode 100644
|
|
index 0000000..b0f05a2
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_msi.c
|
|
@@ -0,0 +1,479 @@
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_msi.h b/drivers/media/common/saa716x/saa716x_msi.h
|
|
new file mode 100644
|
|
index 0000000..8eb72d7
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_msi.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_msi_reg.h b/drivers/media/common/saa716x/saa716x_msi_reg.h
|
|
new file mode 100644
|
|
index 0000000..d9a12c7
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_msi_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_pci.c b/drivers/media/common/saa716x/saa716x_pci.c
|
|
new file mode 100644
|
|
index 0000000..7fa6bad
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_pci.c
|
|
@@ -0,0 +1,275 @@
|
|
+#include <asm/io.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/page.h>
|
|
+#include <linux/kmod.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_phi.c b/drivers/media/common/saa716x/saa716x_phi.c
|
|
new file mode 100644
|
|
index 0000000..7df9a98
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_phi.c
|
|
@@ -0,0 +1,152 @@
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_phi.h b/drivers/media/common/saa716x/saa716x_phi.h
|
|
new file mode 100644
|
|
index 0000000..ff5cda2
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_phi.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_phi_reg.h b/drivers/media/common/saa716x/saa716x_phi_reg.h
|
|
new file mode 100644
|
|
index 0000000..08f0aa7
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_phi_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_priv.h b/drivers/media/common/saa716x/saa716x_priv.h
|
|
new file mode 100644
|
|
index 0000000..1ad1d9c
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_priv.h
|
|
@@ -0,0 +1,194 @@
|
|
+#ifndef __SAA716x_PRIV_H
|
|
+#define __SAA716x_PRIV_H
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/mutex.h>
|
|
+
|
|
+#include <linux/pci.h>
|
|
+#include <linux/ioport.h>
|
|
+#include <linux/i2c.h>
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_reg.h b/drivers/media/common/saa716x/saa716x_reg.h
|
|
new file mode 100644
|
|
index 0000000..effd966
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_rom.c b/drivers/media/common/saa716x/saa716x_rom.c
|
|
new file mode 100644
|
|
index 0000000..7f8dbe1
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_rom.c
|
|
@@ -0,0 +1,1071 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/string.h>
|
|
+
|
|
+#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=0x%02x, ret=%i>", 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=0x%02x, ret=%i>", 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 --git a/drivers/media/common/saa716x/saa716x_rom.h b/drivers/media/common/saa716x/saa716x_rom.h
|
|
new file mode 100644
|
|
index 0000000..6bb317f
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_rom.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_spi.c b/drivers/media/common/saa716x/saa716x_spi.c
|
|
new file mode 100644
|
|
index 0000000..8859454
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_spi.c
|
|
@@ -0,0 +1,313 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/spinlock.h>
|
|
+#include <linux/io.h>
|
|
+
|
|
+#include <linux/spi/spi.h>
|
|
+
|
|
+#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, "<TXFER> ");
|
|
+ if (stat & SPI_WRITE_COLLISSION)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<WCOLL> ");
|
|
+ if (stat & SPI_READ_OVERRUN)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<ROFLW> ");
|
|
+ if (stat & SPI_MODE_FAULT)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<FAULT> ");
|
|
+ if (stat & SPI_SLAVE_ABORT)
|
|
+ dprintk(SAA716x_DEBUG, 0, "<ABORT> ");
|
|
+
|
|
+ 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 --git a/drivers/media/common/saa716x/saa716x_spi.h b/drivers/media/common/saa716x/saa716x_spi.h
|
|
new file mode 100644
|
|
index 0000000..0060c22
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_spi.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_spi_reg.h b/drivers/media/common/saa716x/saa716x_spi_reg.h
|
|
new file mode 100644
|
|
index 0000000..c51abce
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_spi_reg.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_vip.c b/drivers/media/common/saa716x/saa716x_vip.c
|
|
new file mode 100644
|
|
index 0000000..4cd4c81
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_vip.c
|
|
@@ -0,0 +1,23 @@
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#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 --git a/drivers/media/common/saa716x/saa716x_vip.h b/drivers/media/common/saa716x/saa716x_vip.h
|
|
new file mode 100644
|
|
index 0000000..55c6a1a
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_vip.h
|
|
@@ -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 --git a/drivers/media/common/saa716x/saa716x_vip_reg.h b/drivers/media/common/saa716x/saa716x_vip_reg.h
|
|
new file mode 100644
|
|
index 0000000..2d773bd
|
|
--- /dev/null
|
|
+++ b/drivers/media/common/saa716x/saa716x_vip_reg.h
|
|
@@ -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 --git a/drivers/media/dvb-frontends/ds3103.h b/drivers/media/dvb-frontends/ds3103.h
|
|
new file mode 100644
|
|
index 0000000..e52740c
|
|
--- /dev/null
|
|
+++ b/drivers/media/dvb-frontends/ds3103.h
|
|
@@ -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 <linux/dvb/frontend.h>
|
|
+
|
|
+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 --git a/drivers/media/dvb-frontends/ts2022.h b/drivers/media/dvb-frontends/ts2022.h
|
|
new file mode 100644
|
|
index 0000000..c894edb
|
|
--- /dev/null
|
|
+++ b/drivers/media/dvb-frontends/ts2022.h
|
|
@@ -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 <linux/i2c.h>
|
|
+#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 --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h
|
|
index 880e684..edd728c 100644
|
|
--- a/include/uapi/linux/dvb/osd.h
|
|
+++ b/include/uapi/linux/dvb/osd.h
|
|
@@ -141,4 +141,20 @@ typedef struct osd_cap_s {
|
|
#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
|