summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-10-25 19:30:53 +0300
committerIngo Molnar <mingo@elte.hu>2009-10-25 19:30:53 +0300
commit0b9e31e9264f1bad89856afb96da1688292f13b4 (patch)
tree7a9e9b6456dce993efeed8734de0a15a1f16ae94 /drivers/staging
parentcf82ff7ea7695b0e82ba07bc5e9f1bd03a74e1aa (diff)
parent964fe080d94db82a3268443e9b9ece4c60246414 (diff)
downloadlinux-0b9e31e9264f1bad89856afb96da1688292f13b4.tar.xz
Merge branch 'linus' into sched/core
Conflicts: fs/proc/array.c Merge reason: resolve conflict and queue up dependent patch. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig8
-rw-r--r--drivers/staging/Makefile4
-rw-r--r--drivers/staging/agnx/Kconfig5
-rw-r--r--drivers/staging/agnx/Makefile8
-rw-r--r--drivers/staging/agnx/TODO22
-rw-r--r--drivers/staging/agnx/agnx.h156
-rw-r--r--drivers/staging/agnx/debug.h416
-rw-r--r--drivers/staging/agnx/pci.c635
-rw-r--r--drivers/staging/agnx/phy.c960
-rw-r--r--drivers/staging/agnx/phy.h409
-rw-r--r--drivers/staging/agnx/rf.c893
-rw-r--r--drivers/staging/agnx/sta.c218
-rw-r--r--drivers/staging/agnx/sta.h222
-rw-r--r--drivers/staging/agnx/table.c168
-rw-r--r--drivers/staging/agnx/table.h10
-rw-r--r--drivers/staging/agnx/xmit.c836
-rw-r--r--drivers/staging/agnx/xmit.h250
-rw-r--r--drivers/staging/b3dfg/b3dfg.c1
-rw-r--r--drivers/staging/comedi/Kconfig2
-rw-r--r--drivers/staging/comedi/comedi_fops.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c8
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c18
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c12
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c22
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/s526.c109
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c1
-rw-r--r--drivers/staging/cowloop/Kconfig16
-rw-r--r--drivers/staging/cowloop/Makefile1
-rw-r--r--drivers/staging/cowloop/TODO11
-rw-r--r--drivers/staging/cowloop/cowloop.c2842
-rw-r--r--drivers/staging/cowloop/cowloop.h66
-rw-r--r--drivers/staging/cpc-usb/Kconfig4
-rw-r--r--drivers/staging/cpc-usb/Makefile3
-rw-r--r--drivers/staging/cpc-usb/TODO10
-rw-r--r--drivers/staging/cpc-usb/cpc-usb_drv.c1184
-rw-r--r--drivers/staging/cpc-usb/cpc.h417
-rw-r--r--drivers/staging/cpc-usb/cpc_int.h83
-rw-r--r--drivers/staging/cpc-usb/cpcusb.h86
-rw-r--r--drivers/staging/cpc-usb/sja2m16c.h41
-rw-r--r--drivers/staging/cpc-usb/sja2m16c_2.c452
-rw-r--r--drivers/staging/cx25821/Kconfig34
-rw-r--r--drivers/staging/cx25821/Makefile14
-rw-r--r--drivers/staging/cx25821/README6
-rw-r--r--drivers/staging/cx25821/cx25821-alsa.c789
-rw-r--r--drivers/staging/cx25821/cx25821-audio-upstream.c804
-rw-r--r--drivers/staging/cx25821/cx25821-audio-upstream.h57
-rw-r--r--drivers/staging/cx25821/cx25821-audio.h57
-rw-r--r--drivers/staging/cx25821/cx25821-audups11.c434
-rw-r--r--drivers/staging/cx25821/cx25821-biffuncs.h45
-rw-r--r--drivers/staging/cx25821/cx25821-cards.c70
-rw-r--r--drivers/staging/cx25821/cx25821-core.c1551
-rw-r--r--drivers/staging/cx25821/cx25821-gpio.c98
-rw-r--r--drivers/staging/cx25821/cx25821-gpio.h2
-rw-r--r--drivers/staging/cx25821/cx25821-i2c.c419
-rw-r--r--drivers/staging/cx25821/cx25821-medusa-defines.h51
-rw-r--r--drivers/staging/cx25821/cx25821-medusa-reg.h455
-rw-r--r--drivers/staging/cx25821/cx25821-medusa-video.c869
-rw-r--r--drivers/staging/cx25821/cx25821-medusa-video.h49
-rw-r--r--drivers/staging/cx25821/cx25821-reg.h1592
-rw-r--r--drivers/staging/cx25821/cx25821-sram.h261
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream-ch2.c835
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream-ch2.h101
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream.c894
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream.h109
-rw-r--r--drivers/staging/cx25821/cx25821-video.c1299
-rw-r--r--drivers/staging/cx25821/cx25821-video.h194
-rw-r--r--drivers/staging/cx25821/cx25821-video0.c451
-rw-r--r--drivers/staging/cx25821/cx25821-video1.c451
-rw-r--r--drivers/staging/cx25821/cx25821-video2.c452
-rw-r--r--drivers/staging/cx25821/cx25821-video3.c451
-rw-r--r--drivers/staging/cx25821/cx25821-video4.c450
-rw-r--r--drivers/staging/cx25821/cx25821-video5.c450
-rw-r--r--drivers/staging/cx25821/cx25821-video6.c450
-rw-r--r--drivers/staging/cx25821/cx25821-video7.c449
-rw-r--r--drivers/staging/cx25821/cx25821-videoioctl.c496
-rw-r--r--drivers/staging/cx25821/cx25821-vidups10.c435
-rw-r--r--drivers/staging/cx25821/cx25821-vidups9.c433
-rw-r--r--drivers/staging/cx25821/cx25821.h602
-rw-r--r--drivers/staging/dst/dcore.c9
-rw-r--r--drivers/staging/et131x/et1310_address_map.h2
-rw-r--r--drivers/staging/et131x/et1310_rx.c20
-rw-r--r--drivers/staging/go7007/Kconfig84
-rw-r--r--drivers/staging/go7007/Makefile15
-rw-r--r--drivers/staging/go7007/go7007-driver.c35
-rw-r--r--drivers/staging/go7007/go7007-fw.c3
-rw-r--r--drivers/staging/go7007/go7007-i2c.c12
-rw-r--r--drivers/staging/go7007/go7007-priv.h6
-rw-r--r--drivers/staging/go7007/go7007-usb.c58
-rw-r--r--drivers/staging/go7007/go7007-v4l2.c225
-rw-r--r--drivers/staging/go7007/go7007.txt176
-rw-r--r--drivers/staging/go7007/s2250-board.c107
-rw-r--r--drivers/staging/go7007/s2250-loader.c8
-rw-r--r--drivers/staging/go7007/snd-go7007.c2
-rw-r--r--drivers/staging/go7007/wis-tw9903.c3
-rw-r--r--drivers/staging/hv/osd.c1
-rw-r--r--drivers/staging/iio/Kconfig1
-rw-r--r--drivers/staging/iio/industrialio-core.c6
-rw-r--r--drivers/staging/iio/light/tsl2561.c4
-rw-r--r--drivers/staging/p9auth/p9auth.c14
-rw-r--r--drivers/staging/poch/poch.c1
-rw-r--r--drivers/staging/pohmelfs/config.c5
-rw-r--r--drivers/staging/rt2860/common/cmm_data_2860.c2
-rw-r--r--drivers/staging/rt2860/common/cmm_info.c1
-rw-r--r--drivers/staging/rt2860/rt_linux.c1
-rw-r--r--drivers/staging/rt2860/rtmp.h2
-rw-r--r--drivers/staging/rt3090/common/cmm_info.c1
-rw-r--r--drivers/staging/rt3090/rt_linux.c1
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c1
-rw-r--r--drivers/staging/sep/sep_driver.c1
-rw-r--r--drivers/staging/stlc45xx/stlc45xx.c1
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c1
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c1
-rw-r--r--drivers/staging/winbond/wbusb.c44
122 files changed, 17293 insertions, 10846 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 10d3fcffe91c..7df3ba4f1f4d 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -47,6 +47,8 @@ source "drivers/staging/slicoss/Kconfig"
source "drivers/staging/go7007/Kconfig"
+source "drivers/staging/cx25821/Kconfig"
+
source "drivers/staging/usbip/Kconfig"
source "drivers/staging/winbond/Kconfig"
@@ -57,8 +59,6 @@ source "drivers/staging/echo/Kconfig"
source "drivers/staging/poch/Kconfig"
-source "drivers/staging/agnx/Kconfig"
-
source "drivers/staging/otus/Kconfig"
source "drivers/staging/rt2860/Kconfig"
@@ -115,8 +115,6 @@ source "drivers/staging/vt6655/Kconfig"
source "drivers/staging/vt6656/Kconfig"
-source "drivers/staging/cpc-usb/Kconfig"
-
source "drivers/staging/udlfb/Kconfig"
source "drivers/staging/hv/Kconfig"
@@ -129,7 +127,5 @@ source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig"
-source "drivers/staging/cowloop/Kconfig"
-
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index c30093bae621..747571172269 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -6,12 +6,12 @@ obj-$(CONFIG_STAGING) += staging.o
obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_POCH) += poch/
-obj-$(CONFIG_AGNX) += agnx/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
obj-$(CONFIG_RT2870) += rt2870/
@@ -39,11 +39,9 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/
-obj-$(CONFIG_USB_CPC) += cpc-usb/
obj-$(CONFIG_FB_UDL) += udlfb/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_RAR_REGISTER) += rar/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
-obj-$(CONFIG_COWLOOP) += cowloop/
diff --git a/drivers/staging/agnx/Kconfig b/drivers/staging/agnx/Kconfig
deleted file mode 100644
index 7f43549e36dd..000000000000
--- a/drivers/staging/agnx/Kconfig
+++ /dev/null
@@ -1,5 +0,0 @@
-config AGNX
- tristate "Wireless Airgo AGNX support"
- depends on WLAN_80211 && MAC80211
- ---help---
- This is an experimental driver for Airgo AGNX00 wireless chip.
diff --git a/drivers/staging/agnx/Makefile b/drivers/staging/agnx/Makefile
deleted file mode 100644
index 1216564a312d..000000000000
--- a/drivers/staging/agnx/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-obj-$(CONFIG_AGNX) += agnx.o
-
-agnx-objs := rf.o \
- pci.o \
- xmit.o \
- table.o \
- sta.o \
- phy.o
diff --git a/drivers/staging/agnx/TODO b/drivers/staging/agnx/TODO
deleted file mode 100644
index 89bec74318aa..000000000000
--- a/drivers/staging/agnx/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-2008 7/18
-
-The RX has can't receive OFDM packet correctly,
-Guess it need be do RX calibrate.
-
-
-before 2008 3/1
-
-1: The RX get too much "CRC failed" pakets, it make the card work very unstable,
-2: After running a while, the card will get infinity "RX Frame" and "Error"
-interrupt, not know the root reason so far, try to fix it
-3: Using two tx queue txd and txm but not only txm.
-4: Set the hdr correctly.
-5: Try to do recalibrate correvtly
-6: To support G mode in future
-7: Fix the mac address can't be readed and set correctly in BE machine.
-8: Fix include and exclude FCS in promisous mode and manage mode
-9: Using sta_notify to notice sta change
-10: Turn on frame reception at the end of start
-11: Guess the card support HW_MULTICAST_FILTER
-12: The tx process should be implment atomic?
-13: Using mac80211 function to control the TX&RX LED.
diff --git a/drivers/staging/agnx/agnx.h b/drivers/staging/agnx/agnx.h
deleted file mode 100644
index 3963d2597a11..000000000000
--- a/drivers/staging/agnx/agnx.h
+++ /dev/null
@@ -1,156 +0,0 @@
-#ifndef AGNX_H_
-#define AGNX_H_
-
-#include <linux/io.h>
-
-#include "xmit.h"
-
-#define PFX KBUILD_MODNAME ": "
-
-static inline u32 agnx_read32(void __iomem *mem_region, u32 offset)
-{
- return ioread32(mem_region + offset);
-}
-
-static inline void agnx_write32(void __iomem *mem_region, u32 offset, u32 val)
-{
- iowrite32(val, mem_region + offset);
-}
-
-/* static const struct ieee80211_rate agnx_rates_80211b[] = { */
-/* { .rate = 10, */
-/* .val = 0xa, */
-/* .flags = IEEE80211_RATE_CCK }, */
-/* { .rate = 20, */
-/* .val = 0x14, */
-/* .hw_value = -0x14, */
-/* .flags = IEEE80211_RATE_CCK_2 }, */
-/* { .rate = 55, */
-/* .val = 0x37, */
-/* .val2 = -0x37, */
-/* .flags = IEEE80211_RATE_CCK_2 }, */
-/* { .rate = 110, */
-/* .val = 0x6e, */
-/* .val2 = -0x6e, */
-/* .flags = IEEE80211_RATE_CCK_2 } */
-/* }; */
-
-
-static const struct ieee80211_rate agnx_rates_80211g[] = {
-/* { .bitrate = 10, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
- { .bitrate = 10, .hw_value = 1, },
- { .bitrate = 20, .hw_value = 2, },
- { .bitrate = 55, .hw_value = 3, },
- { .bitrate = 110, .hw_value = 4,},
-
- { .bitrate = 60, .hw_value = 0xB, },
- { .bitrate = 90, .hw_value = 0xF, },
- { .bitrate = 120, .hw_value = 0xA },
- { .bitrate = 180, .hw_value = 0xE, },
-/* { .bitrate = 240, .hw_value = 0xd, }, */
- { .bitrate = 360, .hw_value = 0xD, },
- { .bitrate = 480, .hw_value = 0x8, },
- { .bitrate = 540, .hw_value = 0xC, },
-};
-
-static const struct ieee80211_channel agnx_channels[] = {
- { .center_freq = 2412, .hw_value = 1, },
- { .center_freq = 2417, .hw_value = 2, },
- { .center_freq = 2422, .hw_value = 3, },
- { .center_freq = 2427, .hw_value = 4, },
- { .center_freq = 2432, .hw_value = 5, },
- { .center_freq = 2437, .hw_value = 6, },
- { .center_freq = 2442, .hw_value = 7, },
- { .center_freq = 2447, .hw_value = 8, },
- { .center_freq = 2452, .hw_value = 9, },
- { .center_freq = 2457, .hw_value = 10, },
- { .center_freq = 2462, .hw_value = 11, },
- { .center_freq = 2467, .hw_value = 12, },
- { .center_freq = 2472, .hw_value = 13, },
- { .center_freq = 2484, .hw_value = 14, },
-};
-
-#define NUM_DRIVE_MODES 2
-/* Agnx operate mode */
-enum {
- AGNX_MODE_80211A,
- AGNX_MODE_80211A_OOB,
- AGNX_MODE_80211A_MIMO,
- AGNX_MODE_80211B_SHORT,
- AGNX_MODE_80211B_LONG,
- AGNX_MODE_80211G,
- AGNX_MODE_80211G_OOB,
- AGNX_MODE_80211G_MIMO,
-};
-
-enum {
- AGNX_UNINIT,
- AGNX_START,
- AGNX_STOP,
-};
-
-struct agnx_priv {
- struct pci_dev *pdev;
- struct ieee80211_hw *hw;
-
- spinlock_t lock;
- struct mutex mutex;
- unsigned int init_status;
-
- void __iomem *ctl; /* pointer to base ram address */
- void __iomem *data; /* pointer to mem region #2 */
-
- struct agnx_ring rx;
- struct agnx_ring txm;
- struct agnx_ring txd;
-
- /* Need volatile? */
- u32 irq_status;
-
- struct delayed_work periodic_work; /* Periodic tasks like recalibrate */
- struct ieee80211_low_level_stats stats;
-
- /* unsigned int phymode; */
- int mode;
- int channel;
- u8 bssid[ETH_ALEN];
-
- u8 mac_addr[ETH_ALEN];
- u8 revid;
-
- struct ieee80211_supported_band band;
-};
-
-
-#define AGNX_CHAINS_MAX 6
-#define AGNX_PERIODIC_DELAY 60000 /* unit: ms */
-#define LOCAL_STAID 0 /* the station entry for the card itself */
-#define BSSID_STAID 1 /* the station entry for the bsssid AP */
-#define spi_delay() udelay(40)
-#define eeprom_delay() udelay(40)
-#define routing_table_delay() udelay(50)
-
-/* PDU pool MEM region #2 */
-#define AGNX_PDUPOOL 0x40000 /* PDU pool */
-#define AGNX_PDUPOOL_SIZE 0x8000 /* PDU pool size*/
-#define AGNX_PDU_TX_WQ 0x41000 /* PDU list TX workqueue */
-#define AGNX_PDU_FREE 0x41800 /* Free Pool */
-#define PDU_SIZE 0x80 /* Free Pool node size */
-#define PDU_FREE_CNT 0xd0 /* Free pool node count */
-
-
-/* RF stuffs */
-extern void rf_chips_init(struct agnx_priv *priv);
-extern void spi_rc_write(void __iomem *mem_region, u32 chip_ids, u32 sw);
-extern void calibrate_oscillator(struct agnx_priv *priv);
-extern void do_calibration(struct agnx_priv *priv);
-extern void antenna_calibrate(struct agnx_priv *priv);
-extern void __antenna_calibrate(struct agnx_priv *priv);
-extern void print_offsets(struct agnx_priv *priv);
-extern int agnx_set_channel(struct agnx_priv *priv, unsigned int channel);
-
-
-#endif /* AGNX_H_ */
diff --git a/drivers/staging/agnx/debug.h b/drivers/staging/agnx/debug.h
deleted file mode 100644
index 7947f327a214..000000000000
--- a/drivers/staging/agnx/debug.h
+++ /dev/null
@@ -1,416 +0,0 @@
-#ifndef AGNX_DEBUG_H_
-#define AGNX_DEBUG_H_
-
-#include "agnx.h"
-#include "phy.h"
-#include "sta.h"
-#include "xmit.h"
-
-#define AGNX_TRACE printk(KERN_ERR PFX "function:%s line:%d\n", __func__, __LINE__)
-
-#define PRINTK_LE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", le16_to_cpu(var))
-#define PRINTK_LE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", le32_to_cpu(var))
-#define PRINTK_U8(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.2x\n", var)
-#define PRINTK_BE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", be16_to_cpu(var))
-#define PRINTK_BE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", be32_to_cpu(var))
-#define PRINTK_BITS(prefix, field) printk(KERN_DEBUG PFX #prefix ": " #field ": 0x%x\n", (reg & field) >> field##_SHIFT)
-
-static inline void agnx_bug(char *reason)
-{
- printk(KERN_ERR PFX "%s\n", reason);
- BUG();
-}
-
-static inline void agnx_print_desc(struct agnx_desc *desc)
-{
- u32 reg = be32_to_cpu(desc->frag);
-
- PRINTK_BITS(DESC, PACKET_LEN);
-
- if (reg & FIRST_FRAG) {
- PRINTK_BITS(DESC, FIRST_PACKET_MASK);
- PRINTK_BITS(DESC, FIRST_RESERV2);
- PRINTK_BITS(DESC, FIRST_TKIP_ERROR);
- PRINTK_BITS(DESC, FIRST_TKIP_PACKET);
- PRINTK_BITS(DESC, FIRST_RESERV1);
- PRINTK_BITS(DESC, FIRST_FRAG_LEN);
- } else {
- PRINTK_BITS(DESC, SUB_RESERV2);
- PRINTK_BITS(DESC, SUB_TKIP_ERROR);
- PRINTK_BITS(DESC, SUB_TKIP_PACKET);
- PRINTK_BITS(DESC, SUB_RESERV1);
- PRINTK_BITS(DESC, SUB_FRAG_LEN);
- }
-
- PRINTK_BITS(DESC, FIRST_FRAG);
- PRINTK_BITS(DESC, LAST_FRAG);
- PRINTK_BITS(DESC, OWNER);
-}
-
-
-static inline void dump_ieee80211b_phy_hdr(__be32 _11b0, __be32 _11b1)
-{
-
-}
-
-static inline void agnx_print_hdr(struct agnx_hdr *hdr)
-{
- u32 reg;
- int i;
-
- reg = be32_to_cpu(hdr->reg0);
- PRINTK_BITS(HDR, RTS);
- PRINTK_BITS(HDR, MULTICAST);
- PRINTK_BITS(HDR, ACK);
- PRINTK_BITS(HDR, TM);
- PRINTK_BITS(HDR, RELAY);
- PRINTK_BITS(HDR, REVISED_FCS);
- PRINTK_BITS(HDR, NEXT_BUFFER_ADDR);
-
- reg = be32_to_cpu(hdr->reg1);
- PRINTK_BITS(HDR, MAC_HDR_LEN);
- PRINTK_BITS(HDR, DURATION_OVERIDE);
- PRINTK_BITS(HDR, PHY_HDR_OVERIDE);
- PRINTK_BITS(HDR, CRC_FAIL);
- PRINTK_BITS(HDR, SEQUENCE_NUMBER);
- PRINTK_BITS(HDR, BUFF_HEAD_ADDR);
-
- reg = be32_to_cpu(hdr->reg2);
- PRINTK_BITS(HDR, PDU_COUNT);
- PRINTK_BITS(HDR, WEP_KEY);
- PRINTK_BITS(HDR, USES_WEP_KEY);
- PRINTK_BITS(HDR, KEEP_ALIVE);
- PRINTK_BITS(HDR, BUFF_TAIL_ADDR);
-
- reg = be32_to_cpu(hdr->reg3);
- PRINTK_BITS(HDR, CTS_11G);
- PRINTK_BITS(HDR, RTS_11G);
- PRINTK_BITS(HDR, FRAG_SIZE);
- PRINTK_BITS(HDR, PAYLOAD_LEN);
- PRINTK_BITS(HDR, FRAG_NUM);
-
- reg = be32_to_cpu(hdr->reg4);
- PRINTK_BITS(HDR, RELAY_STAID);
- PRINTK_BITS(HDR, STATION_ID);
- PRINTK_BITS(HDR, WORKQUEUE_ID);
-
- reg = be32_to_cpu(hdr->reg5);
- /* printf the route flag */
- PRINTK_BITS(HDR, ROUTE_HOST);
- PRINTK_BITS(HDR, ROUTE_CARD_CPU);
- PRINTK_BITS(HDR, ROUTE_ENCRYPTION);
- PRINTK_BITS(HDR, ROUTE_TX);
- PRINTK_BITS(HDR, ROUTE_RX1);
- PRINTK_BITS(HDR, ROUTE_RX2);
- PRINTK_BITS(HDR, ROUTE_COMPRESSION);
-
- PRINTK_BE32(HDR, hdr->_11g0);
- PRINTK_BE32(HDR, hdr->_11g1);
- PRINTK_BE32(HDR, hdr->_11b0);
- PRINTK_BE32(HDR, hdr->_11b1);
-
- dump_ieee80211b_phy_hdr(hdr->_11b0, hdr->_11b1);
-
- /* Fixme */
- for (i = 0; i < ARRAY_SIZE(hdr->mac_hdr); i++) {
- if (i == 0)
- printk(KERN_DEBUG PFX "IEEE80211 HDR: ");
- printk("%.2x ", hdr->mac_hdr[i]);
- if (i + 1 == ARRAY_SIZE(hdr->mac_hdr))
- printk("\n");
- }
-
- PRINTK_BE16(HDR, hdr->rts_duration);
- PRINTK_BE16(HDR, hdr->last_duration);
- PRINTK_BE16(HDR, hdr->sec_last_duration);
- PRINTK_BE16(HDR, hdr->other_duration);
- PRINTK_BE16(HDR, hdr->tx_other_duration);
- PRINTK_BE16(HDR, hdr->last_11g_len);
- PRINTK_BE16(HDR, hdr->other_11g_len);
- PRINTK_BE16(HDR, hdr->last_11b_len);
- PRINTK_BE16(HDR, hdr->other_11b_len);
-
- /* FIXME */
- reg = be16_to_cpu(hdr->reg6);
- PRINTK_BITS(HDR, MBF);
- PRINTK_BITS(HDR, RSVD4);
-
- PRINTK_BE16(HDR, hdr->rx_frag_stat);
-
- PRINTK_BE32(HDR, hdr->time_stamp);
- PRINTK_BE32(HDR, hdr->phy_stats_hi);
- PRINTK_BE32(HDR, hdr->phy_stats_lo);
- PRINTK_BE32(HDR, hdr->mic_key0);
- PRINTK_BE32(HDR, hdr->mic_key1);
-} /* agnx_print_hdr */
-
-
-static inline void agnx_print_rx_hdr(struct agnx_hdr *hdr)
-{
- agnx_print_hdr(hdr);
-
- PRINTK_BE16(HDR, hdr->rx.rx_packet_duration);
- PRINTK_BE16(HDR, hdr->rx.replay_cnt);
-
- PRINTK_U8(HDR, hdr->rx_channel);
-}
-
-static inline void agnx_print_tx_hdr(struct agnx_hdr *hdr)
-{
- agnx_print_hdr(hdr);
-
- PRINTK_U8(HDR, hdr->tx.long_retry_limit);
- PRINTK_U8(HDR, hdr->tx.short_retry_limit);
- PRINTK_U8(HDR, hdr->tx.long_retry_cnt);
- PRINTK_U8(HDR, hdr->tx.short_retry_cnt);
-
- PRINTK_U8(HDR, hdr->rx_channel);
-}
-
-static inline void
-agnx_print_sta_power(struct agnx_priv *priv, unsigned int sta_idx)
-{
- struct agnx_sta_power power;
- u32 reg;
-
- get_sta_power(priv, &power, sta_idx);
-
- reg = le32_to_cpu(power.reg);
- PRINTK_BITS(STA_POWER, SIGNAL);
- PRINTK_BITS(STA_POWER, RATE);
- PRINTK_BITS(STA_POWER, TIFS);
- PRINTK_BITS(STA_POWER, EDCF);
- PRINTK_BITS(STA_POWER, CHANNEL_BOND);
- PRINTK_BITS(STA_POWER, PHY_MODE);
- PRINTK_BITS(STA_POWER, POWER_LEVEL);
- PRINTK_BITS(STA_POWER, NUM_TRANSMITTERS);
-}
-
-static inline void
-agnx_print_sta_tx_wq(struct agnx_priv *priv, unsigned int sta_idx, unsigned int wq_idx)
-{
- struct agnx_sta_tx_wq tx_wq;
- u32 reg;
-
- get_sta_tx_wq(priv, &tx_wq, sta_idx, wq_idx);
-
- reg = le32_to_cpu(tx_wq.reg0);
- PRINTK_BITS(STA_TX_WQ, TAIL_POINTER);
- PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_LOW);
-
- reg = le32_to_cpu(tx_wq.reg3);
- PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_HIGH);
- PRINTK_BITS(STA_TX_WQ, ACK_POINTER_LOW);
-
- reg = le32_to_cpu(tx_wq.reg1);
- PRINTK_BITS(STA_TX_WQ, ACK_POINTER_HIGH);
- PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_TAIL_PACK_CNT);
- PRINTK_BITS(STA_TX_WQ, ACK_TIMOUT_TAIL_PACK_CNT);
-
- reg = le32_to_cpu(tx_wq.reg2);
- PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_BYTE_CNT);
- PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_FRAG_CNT);
- PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_ACK_TYPE);
- PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_VALID);
-}
-
-static inline void agnx_print_sta_traffic(struct agnx_sta_traffic *traffic)
-{
- u32 reg;
-
- reg = le32_to_cpu(traffic->reg0);
- PRINTK_BITS(STA_TRAFFIC, ACK_TIMOUT_CNT);
- PRINTK_BITS(STA_TRAFFIC, TRAFFIC_ACK_TYPE);
- PRINTK_BITS(STA_TRAFFIC, NEW_PACKET);
- PRINTK_BITS(STA_TRAFFIC, TRAFFIC_VALID);
- PRINTK_BITS(STA_TRAFFIC, RX_HDR_DESC_POINTER);
-
- reg = le32_to_cpu(traffic->reg1);
- PRINTK_BITS(STA_TRAFFIC, RX_PACKET_TIMESTAMP);
- PRINTK_BITS(STA_TRAFFIC, TRAFFIC_RESERVED);
- PRINTK_BITS(STA_TRAFFIC, SV);
- PRINTK_BITS(STA_TRAFFIC, RX_SEQUENCE_NUM);
-
- PRINTK_LE32(STA_TRAFFIC, traffic->tx_replay_cnt_low);
-
- PRINTK_LE16(STA_TRAFFIC, traffic->tx_replay_cnt_high);
- PRINTK_LE16(STA_TRAFFIC, traffic->rx_replay_cnt_high);
-
- PRINTK_LE32(STA_TRAFFIC, traffic->rx_replay_cnt_low);
-}
-
-static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
-{
- struct agnx_sta station;
- struct agnx_sta *sta = &station;
- u32 reg;
- unsigned int i;
-
- get_sta(priv, sta, sta_idx);
-
- for (i = 0; i < 4; i++)
- PRINTK_LE32(STA, sta->tx_session_keys[i]);
- for (i = 0; i < 4; i++)
- PRINTK_LE32(STA, sta->rx_session_keys[i]);
-
- reg = le32_to_cpu(sta->reg);
- PRINTK_BITS(STA, ID_1);
- PRINTK_BITS(STA, ID_0);
- PRINTK_BITS(STA, ENABLE_CONCATENATION);
- PRINTK_BITS(STA, ENABLE_DECOMPRESSION);
- PRINTK_BITS(STA, STA_RESERVED);
- PRINTK_BITS(STA, EAP);
- PRINTK_BITS(STA, ED_NULL);
- PRINTK_BITS(STA, ENCRYPTION_POLICY);
- PRINTK_BITS(STA, DEFINED_KEY_ID);
- PRINTK_BITS(STA, FIXED_KEY);
- PRINTK_BITS(STA, KEY_VALID);
- PRINTK_BITS(STA, STATION_VALID);
-
- PRINTK_LE32(STA, sta->tx_aes_blks_unicast);
- PRINTK_LE32(STA, sta->rx_aes_blks_unicast);
-
- PRINTK_LE16(STA, sta->aes_format_err_unicast_cnt);
- PRINTK_LE16(STA, sta->aes_replay_unicast);
-
- PRINTK_LE16(STA, sta->aes_decrypt_err_unicast);
- PRINTK_LE16(STA, sta->aes_decrypt_err_default);
-
- PRINTK_LE16(STA, sta->single_retry_packets);
- PRINTK_LE16(STA, sta->failed_tx_packets);
-
- PRINTK_LE16(STA, sta->muti_retry_packets);
- PRINTK_LE16(STA, sta->ack_timeouts);
-
- PRINTK_LE16(STA, sta->frag_tx_cnt);
- PRINTK_LE16(STA, sta->rts_brq_sent);
-
- PRINTK_LE16(STA, sta->tx_packets);
- PRINTK_LE16(STA, sta->cts_back_timeout);
-
- PRINTK_LE32(STA, sta->phy_stats_high);
- PRINTK_LE32(STA, sta->phy_stats_low);
-
- /* for (i = 0; i < 8; i++) */
- agnx_print_sta_traffic(sta->traffic + 0);
-
- PRINTK_LE16(STA, sta->traffic_class0_frag_success);
- PRINTK_LE16(STA, sta->traffic_class1_frag_success);
- PRINTK_LE16(STA, sta->traffic_class2_frag_success);
- PRINTK_LE16(STA, sta->traffic_class3_frag_success);
- PRINTK_LE16(STA, sta->traffic_class4_frag_success);
- PRINTK_LE16(STA, sta->traffic_class5_frag_success);
- PRINTK_LE16(STA, sta->traffic_class6_frag_success);
- PRINTK_LE16(STA, sta->traffic_class7_frag_success);
-
- PRINTK_LE16(STA, sta->num_frag_non_prime_rates);
- PRINTK_LE16(STA, sta->ack_timeout_non_prime_rates);
-}
-
-
-static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
-{
- u16 fctl;
- int hdrlen;
-
- fctl = le16_to_cpu(hdr->frame_control);
- switch (fctl & IEEE80211_FCTL_FTYPE) {
- case IEEE80211_FTYPE_DATA:
- printk(PFX "%s DATA ", tag);
- break;
- case IEEE80211_FTYPE_CTL:
- printk(PFX "%s CTL ", tag);
- break;
- case IEEE80211_FTYPE_MGMT:
- printk(PFX "%s MGMT ", tag);
- switch (fctl & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_ASSOC_REQ:
- printk("SubType: ASSOC_REQ ");
- break;
- case IEEE80211_STYPE_ASSOC_RESP:
- printk("SubType: ASSOC_RESP ");
- break;
- case IEEE80211_STYPE_REASSOC_REQ:
- printk("SubType: REASSOC_REQ ");
- break;
- case IEEE80211_STYPE_REASSOC_RESP:
- printk("SubType: REASSOC_RESP ");
- break;
- case IEEE80211_STYPE_PROBE_REQ:
- printk("SubType: PROBE_REQ ");
- break;
- case IEEE80211_STYPE_PROBE_RESP:
- printk("SubType: PROBE_RESP ");
- break;
- case IEEE80211_STYPE_BEACON:
- printk("SubType: BEACON ");
- break;
- case IEEE80211_STYPE_ATIM:
- printk("SubType: ATIM ");
- break;
- case IEEE80211_STYPE_DISASSOC:
- printk("SubType: DISASSOC ");
- break;
- case IEEE80211_STYPE_AUTH:
- printk("SubType: AUTH ");
- break;
- case IEEE80211_STYPE_DEAUTH:
- printk("SubType: DEAUTH ");
- break;
- case IEEE80211_STYPE_ACTION:
- printk("SubType: ACTION ");
- break;
- default:
- printk("SubType: Unknow\n");
- }
- break;
- default:
- printk(PFX "%s Packet type: Unknow\n", tag);
- }
-
- hdrlen = ieee80211_hdrlen(fctl);
-
- if (hdrlen >= 4)
- printk("FC=0x%04x DUR=0x%04x",
- fctl, le16_to_cpu(hdr->duration_id));
- if (hdrlen >= 10)
- printk(" A1=%pM", hdr->addr1);
- if (hdrlen >= 16)
- printk(" A2=%pM", hdr->addr2);
- if (hdrlen >= 24)
- printk(" A3=%pM", hdr->addr3);
- if (hdrlen >= 30)
- printk(" A4=%pM", hdr->addr4);
- printk("\n");
-}
-
-static inline void dump_txm_registers(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
- for (i = 0; i <= 0x1e8; i += 4)
- printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
-}
-static inline void dump_rxm_registers(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
- for (i = 0; i <= 0x108; i += 4)
- printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
-}
-static inline void dump_bm_registers(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
- for (i = 0; i <= 0x90; i += 4)
- printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
-}
-static inline void dump_cir_registers(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
- for (i = 0; i <= 0xb8; i += 4)
- printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
-}
-
-#endif /* AGNX_DEBUG_H_ */
diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c
deleted file mode 100644
index 32b5489456a8..000000000000
--- a/drivers/staging/agnx/pci.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/etherdevice.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "agnx.h"
-#include "debug.h"
-#include "xmit.h"
-#include "phy.h"
-
-MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
-MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id agnx_pci_id_tbl[] __devinitdata = {
- { PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
- { PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, agnx_pci_id_tbl);
-
-
-static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- if (*reason & AGNX_STAT_RX) {
- /* Mark complete RX */
- reg = ioread32(ctl + AGNX_CIR_RXCTL);
- reg |= 0x4;
- iowrite32(reg, ctl + AGNX_CIR_RXCTL);
- /* disable Rx interrupt */
- }
- if (*reason & AGNX_STAT_TX) {
- reg = ioread32(ctl + AGNX_CIR_TXDCTL);
- if (reg & 0x4) {
- iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
- *reason |= AGNX_STAT_TXD;
- }
- reg = ioread32(ctl + AGNX_CIR_TXMCTL);
- if (reg & 0x4) {
- iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
- *reason |= AGNX_STAT_TXM;
- }
- }
-#if 0
- if (*reason & AGNX_STAT_X) {
- reg = ioread32(ctl + AGNX_INT_STAT);
- iowrite32(reg, ctl + AGNX_INT_STAT);
- /* FIXME reinit interrupt mask */
- reg = 0xc390bf9 & ~IRQ_TX_BEACON;
- reg &= ~IRQ_TX_DISABLE;
- iowrite32(reg, ctl + AGNX_INT_MASK);
- iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
- }
-#endif
-} /* agnx_interrupt_ack */
-
-static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
-{
- struct ieee80211_hw *dev = dev_id;
- struct agnx_priv *priv = dev->priv;
- void __iomem *ctl = priv->ctl;
- irqreturn_t ret = IRQ_NONE;
- u32 irq_reason;
-
- spin_lock(&priv->lock);
-
-/* printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */
-
- if (priv->init_status != AGNX_START)
- goto out;
-
- /* FiXME Here has no lock, Is this will lead to race? */
- irq_reason = ioread32(ctl + AGNX_CIR_BLKCTL);
- if (!(irq_reason & 0x7))
- goto out;
-
- ret = IRQ_HANDLED;
- priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
-
-/* printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */
- /* Make sure the txm and txd flags don't conflict with other unknown
- interrupt flag, maybe is not necessary */
- irq_reason &= 0xF;
-
- disable_rx_interrupt(priv);
- /* TODO Make sure the card finished initialized */
- agnx_interrupt_ack(priv, &irq_reason);
-
- if (irq_reason & AGNX_STAT_RX)
- handle_rx_irq(priv);
- if (irq_reason & AGNX_STAT_TXD)
- handle_txd_irq(priv);
- if (irq_reason & AGNX_STAT_TXM)
- handle_txm_irq(priv);
- if (irq_reason & AGNX_STAT_X)
- handle_other_irq(priv);
-
- enable_rx_interrupt(priv);
-out:
- spin_unlock(&priv->lock);
- return ret;
-} /* agnx_interrupt_handler */
-
-
-/* FIXME */
-static int agnx_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- AGNX_TRACE;
- return _agnx_tx(dev->priv, skb);
-} /* agnx_tx */
-
-
-static int agnx_get_mac_address(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- /* Attention! directly read the MAC or other date from EEPROM will
- lead to cardbus(WGM511) lock up when write to PM PLL register */
- reg = agnx_read32(ctl, 0x3544);
- udelay(40);
- reg = agnx_read32(ctl, 0x354c);
- udelay(50);
- /* Get the mac address */
- reg = agnx_read32(ctl, 0x3544);
- udelay(40);
-
- /* HACK */
- reg = cpu_to_le32(reg);
- priv->mac_addr[0] = ((u8 *)&reg)[2];
- priv->mac_addr[1] = ((u8 *)&reg)[3];
- reg = agnx_read32(ctl, 0x3548);
- udelay(50);
- *((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
-
- if (!is_valid_ether_addr(priv->mac_addr)) {
- printk(KERN_WARNING PFX "read mac %pM\n", priv->mac_addr);
- printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
- random_ether_addr(priv->mac_addr);
- }
-
- return 0;
-} /* agnx_get_mac_address */
-
-static int agnx_alloc_rings(struct agnx_priv *priv)
-{
- unsigned int len;
- AGNX_TRACE;
-
- /* Allocate RX/TXM/TXD rings info */
- priv->rx.size = AGNX_RX_RING_SIZE;
- priv->txm.size = AGNX_TXM_RING_SIZE;
- priv->txd.size = AGNX_TXD_RING_SIZE;
-
- len = priv->rx.size + priv->txm.size + priv->txd.size;
-
-/* priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */
- priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
- if (!priv->rx.info)
- return -ENOMEM;
- priv->txm.info = priv->rx.info + priv->rx.size;
- priv->txd.info = priv->txm.info + priv->txm.size;
-
- /* Allocate RX/TXM/TXD descriptors */
- priv->rx.desc = pci_alloc_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
- &priv->rx.dma);
- if (!priv->rx.desc) {
- kfree(priv->rx.info);
- return -ENOMEM;
- }
-
- priv->txm.desc = priv->rx.desc + priv->rx.size;
- priv->txm.dma = priv->rx.dma + sizeof(struct agnx_desc) * priv->rx.size;
- priv->txd.desc = priv->txm.desc + priv->txm.size;
- priv->txd.dma = priv->txm.dma + sizeof(struct agnx_desc) * priv->txm.size;
-
- return 0;
-} /* agnx_alloc_rings */
-
-static void rings_free(struct agnx_priv *priv)
-{
- unsigned int len = priv->rx.size + priv->txm.size + priv->txd.size;
- unsigned long flags;
- AGNX_TRACE;
-
- spin_lock_irqsave(&priv->lock, flags);
- kfree(priv->rx.info);
- pci_free_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
- priv->rx.desc, priv->rx.dma);
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-#if 0
-static void agnx_periodic_work_handler(struct work_struct *work)
-{
- struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
-/* unsigned long flags; */
- unsigned long delay;
-
- /* fixme: using mutex?? */
-/* spin_lock_irqsave(&priv->lock, flags); */
-
- /* TODO Recalibrate*/
-/* calibrate_oscillator(priv); */
-/* antenna_calibrate(priv); */
-/* agnx_send_packet(priv, 997); */
- /* FIXME */
-/* if (debug == 3) */
-/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
-/* else */
- delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
-/* delay = round_jiffies(HZ * 15); */
-
- queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
-
-/* spin_unlock_irqrestore(&priv->lock, flags); */
-}
-#endif
-
-static int agnx_start(struct ieee80211_hw *dev)
-{
- struct agnx_priv *priv = dev->priv;
- /* unsigned long delay; */
- int err = 0;
- AGNX_TRACE;
-
- err = agnx_alloc_rings(priv);
- if (err) {
- printk(KERN_ERR PFX "Can't alloc RX/TXM/TXD rings\n");
- goto out;
- }
- err = request_irq(priv->pdev->irq, &agnx_interrupt_handler,
- IRQF_SHARED, "agnx_pci", dev);
- if (err) {
- printk(KERN_ERR PFX "Failed to register IRQ handler\n");
- rings_free(priv);
- goto out;
- }
-
-/* mdelay(500); */
-
- might_sleep();
- agnx_hw_init(priv);
-
-/* mdelay(500); */
- might_sleep();
-
- priv->init_status = AGNX_START;
-/* INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
-/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
-/* queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
-out:
- return err;
-} /* agnx_start */
-
-static void agnx_stop(struct ieee80211_hw *dev)
-{
- struct agnx_priv *priv = dev->priv;
- AGNX_TRACE;
-
- priv->init_status = AGNX_STOP;
- /* make sure hardware will not generate irq */
- agnx_hw_reset(priv);
- free_irq(priv->pdev->irq, dev);
-/* flush_workqueue(priv->hw->workqueue); */
-/* cancel_delayed_work_sync(&priv->periodic_work); */
- unfill_rings(priv);
- rings_free(priv);
-}
-
-static int agnx_config(struct ieee80211_hw *dev, u32 changed)
-{
- struct agnx_priv *priv = dev->priv;
- struct ieee80211_conf *conf = &dev->conf;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
- AGNX_TRACE;
-
- spin_lock(&priv->lock);
- /* FIXME need priv lock? */
- if (channel != priv->channel) {
- priv->channel = channel;
- agnx_set_channel(priv, priv->channel);
- }
-
- spin_unlock(&priv->lock);
- return 0;
-}
-
-static void agnx_bss_info_changed(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf,
- u32 changed)
-{
- struct agnx_priv *priv = dev->priv;
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
- if (!(changed & BSS_CHANGED_BSSID))
- return;
-
- spin_lock(&priv->lock);
-
- if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
- agnx_set_bssid(priv, conf->bssid);
- memcpy(priv->bssid, conf->bssid, ETH_ALEN);
- hash_write(priv, conf->bssid, BSSID_STAID);
- sta_init(priv, BSSID_STAID);
- /* FIXME needed? */
- sta_power_init(priv, BSSID_STAID);
- agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
- }
- spin_unlock(&priv->lock);
-} /* agnx_bss_info_changed */
-
-
-static void agnx_configure_filter(struct ieee80211_hw *dev,
- unsigned int changed_flags,
- unsigned int *total_flags,
- int mc_count, struct dev_mc_list *mclist)
-{
- unsigned int new_flags = 0;
-
- *total_flags = new_flags;
- /* TODO */
-}
-
-static int agnx_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
-{
- struct agnx_priv *priv = dev->priv;
- AGNX_TRACE;
-
- spin_lock(&priv->lock);
- /* FIXME */
- if (priv->mode != NL80211_IFTYPE_MONITOR)
- return -EOPNOTSUPP;
-
- switch (conf->type) {
- case NL80211_IFTYPE_STATION:
- priv->mode = conf->type;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- spin_unlock(&priv->lock);
-
- return 0;
-}
-
-static void agnx_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
-{
- struct agnx_priv *priv = dev->priv;
- AGNX_TRACE;
-
- /* TODO */
- priv->mode = NL80211_IFTYPE_MONITOR;
-}
-
-static int agnx_get_stats(struct ieee80211_hw *dev,
- struct ieee80211_low_level_stats *stats)
-{
- struct agnx_priv *priv = dev->priv;
- AGNX_TRACE;
- spin_lock(&priv->lock);
- /* TODO !! */
- memcpy(stats, &priv->stats, sizeof(*stats));
- spin_unlock(&priv->lock);
-
- return 0;
-}
-
-static u64 agnx_get_tsft(struct ieee80211_hw *dev)
-{
- void __iomem *ctl = ((struct agnx_priv *)dev->priv)->ctl;
- u32 tsftl;
- u64 tsft;
- AGNX_TRACE;
-
- /* FIXME */
- tsftl = ioread32(ctl + AGNX_TXM_TIMESTAMPLO);
- tsft = ioread32(ctl + AGNX_TXM_TIMESTAMPHI);
- tsft <<= 32;
- tsft |= tsftl;
-
- return tsft;
-}
-
-static int agnx_get_tx_stats(struct ieee80211_hw *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
- struct agnx_priv *priv = dev->priv;
- AGNX_TRACE;
-
- /* FIXME now we just using txd queue, but should using txm queue too */
- stats[0].len = (priv->txd.idx - priv->txd.idx_sent) / 2;
- stats[0].limit = priv->txd.size - 2;
- stats[0].count = priv->txd.idx / 2;
-
- return 0;
-}
-
-static struct ieee80211_ops agnx_ops = {
- .tx = agnx_tx,
- .start = agnx_start,
- .stop = agnx_stop,
- .add_interface = agnx_add_interface,
- .remove_interface = agnx_remove_interface,
- .config = agnx_config,
- .bss_info_changed = agnx_bss_info_changed,
- .configure_filter = agnx_configure_filter,
- .get_stats = agnx_get_stats,
- .get_tx_stats = agnx_get_tx_stats,
- .get_tsf = agnx_get_tsft
-};
-
-static void __devexit agnx_pci_remove(struct pci_dev *pdev)
-{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- struct agnx_priv *priv;
- AGNX_TRACE;
-
- if (!dev)
- return;
- priv = dev->priv;
- ieee80211_unregister_hw(dev);
- pci_iounmap(pdev, priv->ctl);
- pci_iounmap(pdev, priv->data);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
-
- ieee80211_free_hw(dev);
-}
-
-static int __devinit agnx_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- struct ieee80211_hw *dev;
- struct agnx_priv *priv;
- int err;
-
- err = pci_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "can't enable pci device\n");
- return err;
- }
-
- err = pci_request_regions(pdev, "agnx-pci");
- if (err) {
- dev_err(&pdev->dev, "can't reserve PCI resources\n");
- return err;
- }
-
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
- pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
- dev_err(&pdev->dev, "no suitable DMA available\n");
- err = -EIO;
- goto err_free_reg;
- }
-
- pci_set_master(pdev);
-
- dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
- if (!dev) {
- dev_err(&pdev->dev, "ieee80211 alloc failed\n");
- err = -ENOMEM;
- goto err_free_reg;
- }
- priv = dev->priv;
- memset(priv, 0, sizeof(*priv));
- priv->mode = NL80211_IFTYPE_MONITOR;
- priv->pdev = pdev;
- priv->hw = dev;
- spin_lock_init(&priv->lock);
- priv->init_status = AGNX_UNINIT;
-
- priv->ctl = pci_iomap(pdev, 0, 0);
-/* dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */
- if (!priv->ctl) {
- dev_err(&pdev->dev, "can't map device memory\n");
- err = -ENOMEM;
- goto err_free_dev;
- }
- priv->data = pci_iomap(pdev, 1, 0);
- if (!priv->data) {
- dev_err(&pdev->dev, "can't map device memory\n");
- err = -ENOMEM;
- goto err_iounmap2;
- }
-
- pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid);
-
- priv->band.channels = (struct ieee80211_channel *)agnx_channels;
- priv->band.n_channels = ARRAY_SIZE(agnx_channels);
- priv->band.bitrates = (struct ieee80211_rate *)agnx_rates_80211g;
- priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g);
-
- /* Init ieee802.11 dev */
- SET_IEEE80211_DEV(dev, &pdev->dev);
- pci_set_drvdata(pdev, dev);
- dev->extra_tx_headroom = sizeof(struct agnx_hdr);
-
- /* FIXME It only include FCS in promious mode but not manage mode */
-/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */
- dev->channel_change_time = 5000;
- dev->max_signal = 100;
- /* FIXME */
- dev->queues = 1;
-
- agnx_get_mac_address(priv);
-
- SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
-
-/* /\* FIXME *\/ */
-/* for (i = 1; i < NUM_DRIVE_MODES; i++) { */
-/* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
-/* if (err) { */
-/* printk(KERN_ERR PFX "Can't register hwmode\n"); */
-/* goto err_iounmap; */
-/* } */
-/* } */
-
- priv->channel = 1;
- dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-
- err = ieee80211_register_hw(dev);
- if (err) {
- dev_err(&pdev->dev, "can't register hardware\n");
- goto err_iounmap;
- }
-
- agnx_hw_reset(priv);
-
- dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n",
- wiphy_name(dev->wiphy),
- dev->wiphy->perm_addr, priv->revid);
- return 0;
-
- err_iounmap:
- pci_iounmap(pdev, priv->data);
-
- err_iounmap2:
- pci_iounmap(pdev, priv->ctl);
-
- err_free_dev:
- pci_set_drvdata(pdev, NULL);
- ieee80211_free_hw(dev);
-
- err_free_reg:
- pci_release_regions(pdev);
-
- pci_disable_device(pdev);
- return err;
-} /* agnx_pci_probe*/
-
-#ifdef CONFIG_PM
-
-static int agnx_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- AGNX_TRACE;
-
- ieee80211_stop_queues(dev);
- agnx_stop(dev);
-
- pci_save_state(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return 0;
-}
-
-static int agnx_pci_resume(struct pci_dev *pdev)
-{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- AGNX_TRACE;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-
- agnx_start(dev);
- ieee80211_wake_queues(dev);
-
- return 0;
-}
-
-#else
-
-#define agnx_pci_suspend NULL
-#define agnx_pci_resume NULL
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver agnx_pci_driver = {
- .name = "agnx-pci",
- .id_table = agnx_pci_id_tbl,
- .probe = agnx_pci_probe,
- .remove = __devexit_p(agnx_pci_remove),
- .suspend = agnx_pci_suspend,
- .resume = agnx_pci_resume,
-};
-
-static int __init agnx_pci_init(void)
-{
- AGNX_TRACE;
- return pci_register_driver(&agnx_pci_driver);
-}
-
-static void __exit agnx_pci_exit(void)
-{
- AGNX_TRACE;
- pci_unregister_driver(&agnx_pci_driver);
-}
-
-
-module_init(agnx_pci_init);
-module_exit(agnx_pci_exit);
diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c
deleted file mode 100644
index ec1ca86fa0c4..000000000000
--- a/drivers/staging/agnx/phy.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/etherdevice.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-#include "table.h"
-#include "sta.h"
-#include "xmit.h"
-
-u8 read_from_eeprom(struct agnx_priv *priv, u16 address)
-{
- void __iomem *ctl = priv->ctl;
- struct agnx_eeprom cmd;
- u32 reg;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;
- cmd.address = address;
- /* Verify that the Status bit is clear */
- /* Read Command and Address are written to the Serial Interface */
- iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);
- /* Wait for the Status bit to clear again */
- eeprom_delay();
- /* Read from Data */
- reg = ioread32(ctl + AGNX_CIR_SERIALITF);
-
- cmd = *(struct agnx_eeprom *)&reg;
-
- return cmd.data;
-}
-
-static int card_full_reset(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
- agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);
- reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
- return 0;
-}
-
-inline void enable_power_saving(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg &= ~0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-}
-
-inline void disable_power_saving(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-}
-
-
-void disable_receiver(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
- /* FIXME Disable the receiver */
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
- /* Set gain control reset */
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
- /* Reset gain control reset */
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-}
-
-
-/* Fixme this shoule be disable RX, above is enable RX */
-void enable_receiver(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
- /* Set adaptive gain control discovery mode */
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
- /* Set gain control reset */
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
- /* Clear gain control reset */
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-}
-
-static void mac_address_set(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u8 *mac_addr = priv->mac_addr;
- u32 reg;
-
- /* FIXME */
- reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
- iowrite32(reg, ctl + AGNX_RXM_MACHI);
- reg = (mac_addr[4] << 8) | mac_addr[5];
- iowrite32(reg, ctl + AGNX_RXM_MACLO);
-}
-
-static void receiver_bssid_set(struct agnx_priv *priv, const u8 *bssid)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- disable_receiver(priv);
- /* FIXME */
- reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
- iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
- reg = (bssid[4] << 8) | bssid[5];
- iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
-
- /* Enable the receiver */
- enable_receiver(priv);
-
- /* Clear the TSF */
-/* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
-/* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
- /* Clear the TBTT */
- agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);
- agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);
- disable_receiver(priv);
-} /* receiver_bssid_set */
-
-static void band_management_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- void __iomem *data = priv->data;
- u32 reg;
- int i;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ);
- agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
- memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE);
- agnx_write32(ctl, AGNX_BM_BMCTL, 0x200);
-
- agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40);
- agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2);
- agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0);
- agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22);
-
- /* FIXME Initialize the Free Pool Linked List */
- /* 1. Write the Address of the Next Node ((0x41800 + node*size)/size)
- to the first word of each node. */
- for (i = 0; i < PDU_FREE_CNT; i++) {
- iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE,
- data + AGNX_PDU_FREE + (PDU_SIZE * i));
- /* The last node should be set to 0x0 */
- if ((i + 1) == PDU_FREE_CNT)
- memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i),
- 0x0, PDU_SIZE);
- }
-
- /* Head is First Pool address (0x41800) / size (0x80) */
- agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE);
- /* Tail is Last Pool Address (0x47f80) / size (0x80) */
- agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE);
- /* Count is Number of Nodes in the Pool (0xd0) */
- agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT);
-
- /* Start all workqueue */
- agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000);
- agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000);
-
- /* Enable the Band Management */
- reg = agnx_read32(ctl, AGNX_BM_BMCTL);
- reg |= 0x1;
- agnx_write32(ctl, AGNX_BM_BMCTL, reg);
-} /* band_managment_init */
-
-
-static void system_itf_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0);
- agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a);
-
- if (priv->revid == 0) {
- reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
- reg |= 0x11;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
- }
- /* ??? What is that means? it should difference for differice type
- of cards */
- agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006);
-
- agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000);
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
- reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
-}
-
-static void encryption_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0);
- agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0);
- agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0);
- agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0);
- agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8);
-}
-
-static void tx_management_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- void __iomem *data = priv->data;
- u32 reg;
- AGNX_TRACE;
-
- /* Fill out the ComputationalEngineLookupTable
- * starting at memory #2 offset 0x800
- */
- tx_engine_lookup_tbl_init(priv);
- memset_io(data + 0x1000, 0, 0xfe0);
- /* Enable Transmission Management Functions */
- agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff);
- /* Write 0x3f to Transmission Template */
- agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f);
-
- if (priv->revid >= 2)
- agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b);
- else
- agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b);
-
- reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
- reg &= 0xff00;
- reg |= 0xb;
- agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
- reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
- reg &= 0xffff00ff;
- reg |= 0xa00;
- agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
- /* Enable TIFS */
- agnx_write32(ctl, AGNX_TXM_CTL, 0x40000);
-
- reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
- reg &= 0xff00ffff;
- reg |= 0x510000;
- agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
- reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
- reg &= 0xff00ffff;
- agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
- reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
- reg &= 0x00ffffff;
- reg |= 0x1c000000;
- agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
- reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
- reg &= 0x00ffffff;
- reg |= 0x01000000;
- agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
-
- /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */
- agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d);
- agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d);
- agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d);
- agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d);
-
- /* Max Ack timeout limit */
- agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19);
- /* Max RX Data Timeout count, */
- reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME);
- reg &= 0xffff0000;
- reg |= 0xff;
- agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg);
-
- /* CF poll RX Timeout count */
- reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
- reg &= 0xffff;
- reg |= 0xff0000;
- agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
-
- /* Max Timeout Exceeded count, */
- reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT);
- reg &= 0xff00ffff;
- reg |= 0x190000;
- agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg);
-
- /* CF ack timeout limit for 11b */
- reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B);
- reg &= 0xff00;
- reg |= 0x1e;
- agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg);
-
- /* Max CF Poll Timeout Count */
- reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
- reg &= 0xffff0000;
- reg |= 0x19;
- agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
- /* CF Poll RX Timeout Count */
- reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
- reg &= 0xffff0000;
- reg |= 0x1e;
- agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
-
- /* # write default to */
- /* 1. Schedule Empty Count */
- agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5);
- /* 2. CFP Period Count */
- agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1);
- /* 3. CFP MDV */
- agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000);
-
- /* Probe Delay */
- reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
- reg &= 0xffff0000;
- reg |= 0x400;
- agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
-
- /* Max CCA count Slot */
- reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT);
- reg &= 0xffff00ff;
- reg |= 0x900;
- agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg);
-
- /* Slot limit/1 msec Limit */
- reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT);
- reg &= 0xff00ffff;
- reg |= 0x140077;
- agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg);
-
- /* # Set CW #(0-7) to default */
- agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007);
- agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007);
-
- /* # Set Short/Long limit #(0-7) to default */
- agnx_write32(ctl, AGNX_TXM_SLBEALIM0, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM1, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM2, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM3, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM4, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM5, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM6, 0xa000a);
- agnx_write32(ctl, AGNX_TXM_SLBEALIM7, 0xa000a);
-
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
- reg |= 0x1400;
- agnx_write32(ctl, AGNX_TXM_CTL, reg);
- /* Wait for bit 0 in Control Reg to clear */
- udelay(80);
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
- /* Or 0x18000 to Control reg */
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
- reg |= 0x18000;
- agnx_write32(ctl, AGNX_TXM_CTL, reg);
- /* Wait for bit 0 in Control Reg to clear */
- udelay(80);
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
-
- /* Set Listen Interval Count to default */
- agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1);
- /* Set DTIM period count to default */
- agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000);
-} /* tx_management_init */
-
-static void rx_management_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
- /* Initialize the Routing Table */
- routing_table_init(priv);
-
- if (priv->revid >= 3) {
- agnx_write32(ctl, 0x2074, 0x1f171710);
- agnx_write32(ctl, 0x2078, 0x10100d0d);
- agnx_write32(ctl, 0x207c, 0x11111010);
- } else {
- agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
- }
- agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
-}
-
-
-static void agnx_timer_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- AGNX_TRACE;
-
-/* /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */
-/* agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */
-/* /\* Write 0xe2 to Timer 1 Control *\/ */
-/* agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */
-
- /* Write 0x249f00 (tick duration?) to Timer 1 */
- agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0);
- /* Write 0xe2 to Timer 1 Control */
- agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0);
-
- iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL);
-}
-
-static void power_manage_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f);
- agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg &= 0xf00f;
- reg |= 0xa0;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
- if (priv->revid >= 3) {
- reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
- reg |= 0x18;
- agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
- }
-} /* power_manage_init */
-
-
-static void gain_ctlcnt_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119);
- agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118);
- agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg &= ~0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
- agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
-
- /* FIXME Write the initial Station Descriptor for the card */
- sta_init(priv, LOCAL_STAID);
- sta_init(priv, BSSID_STAID);
-
- /* Enable staion 0 and 1 can do TX */
- /* It seemed if we set other bit to 1 the bit 0 will
- be auto change to 0 */
- agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
-/* agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */
-} /* gain_ctlcnt_init */
-
-
-static void phy_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- void __iomem *data = priv->data;
- u32 reg;
- AGNX_TRACE;
-
- /* Load InitialGainTable */
- gain_table_init(priv);
-
- agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
-
- /* Clear the following offsets in Memory Range #2: */
- memset_io(data + 0x5040, 0, 0xa * 4);
- memset_io(data + 0x5080, 0, 0xa * 4);
- memset_io(data + 0x50c0, 0, 0xa * 4);
- memset_io(data + 0x5400, 0, 0x80 * 4);
- memset_io(data + 0x6000, 0, 0x280 * 4);
- memset_io(data + 0x7000, 0, 0x280 * 4);
- memset_io(data + 0x8000, 0, 0x280 * 4);
-
- /* Initialize the Following Registers According to PCI Revision ID */
- if (priv->revid == 0) {
- /* fixme the part hasn't been update but below has been update
- based on WGM511 */
- agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x1d);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x3);
- agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
- agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
- agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
- agnx_write32(ctl, AGNX_GCR_THD0AL, 0x4b);
- agnx_write32(ctl, AGNX_GCR_THD0B, 0x4b);
- agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
- agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
- agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
- agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
- agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
- agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
- agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
- agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
- agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
- agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
- reg = agnx_read32(ctl, AGNX_GCR_CWDETEC);
- reg |= 0x1;
- agnx_write32(ctl, AGNX_GCR_CWDETEC, reg);
- agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
- agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
- agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x0);
- agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
- agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1);
- agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0x1);
- agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
- agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x78);
- agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x1c);
- agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
- agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x1);
- agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
- agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
- agnx_write32(ctl, AGNX_GCR_THJUMP, 0x14);
- agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
- agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x30);
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x32);
- agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
- agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
- agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
- agnx_write32(ctl, 0x9400, 0x0);
- agnx_write32(ctl, 0x940c, 0x6ff);
- agnx_write32(ctl, 0x9428, 0xa0);
- agnx_write32(ctl, 0x9434, 0x0);
- agnx_write32(ctl, 0x9c04, 0x15);
- agnx_write32(ctl, 0x9c0c, 0x7f);
- agnx_write32(ctl, 0x9c34, 0x0);
- agnx_write32(ctl, 0xc000, 0x38d);
- agnx_write32(ctl, 0x14018, 0x0);
- agnx_write32(ctl, 0x16000, 0x1);
- agnx_write32(ctl, 0x11004, 0x0);
- agnx_write32(ctl, 0xec54, 0xa);
- agnx_write32(ctl, 0xec1c, 0x5);
- } else if (priv->revid > 0) {
- agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
- agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
- agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
- agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
- agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
- agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
- agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
- agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
- agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
- agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
- agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
- agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
- agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
- agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
- agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
-/* agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
- agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
- agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x32);
- agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x32);
- agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x32);
- agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
- agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1ad);
- agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0xa10);
- agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
- agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
- agnx_write32(ctl, AGNX_GCR_THCS, 0x0);
- agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x4);
- agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
- agnx_write32(ctl, AGNX_GCR_THJUMP, 0x1e);
- agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
- agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x2a);
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
- agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
- agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
- agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
- agnx_write32(ctl, AGNX_GCR_WATCHDOG, 0x37);
- agnx_write32(ctl, 0x9400, 0x0);
- agnx_write32(ctl, 0x940c, 0x6ff);
- agnx_write32(ctl, 0x9428, 0xa0);
- agnx_write32(ctl, 0x9434, 0x0);
- agnx_write32(ctl, 0x9c04, 0x15);
- agnx_write32(ctl, 0x9c0c, 0x7f);
- agnx_write32(ctl, 0x9c34, 0x0);
- agnx_write32(ctl, 0xc000, 0x38d);
- agnx_write32(ctl, 0x14014, 0x1000);
- agnx_write32(ctl, 0x14018, 0x0);
- agnx_write32(ctl, 0x16000, 0x1);
- agnx_write32(ctl, 0x11004, 0x0);
- agnx_write32(ctl, 0xec54, 0xa);
- agnx_write32(ctl, 0xec1c, 0x50);
- } else if (priv->revid > 1) {
- reg = agnx_read32(ctl, 0xec18);
- reg |= 0x8;
- agnx_write32(ctl, 0xec18, reg);
- }
-
- /* Write the TX Fir Coefficient Table */
- tx_fir_table_init(priv);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg &= ~0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
- reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
- reg |= 0x1;
- agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
-/* reg = agnx_read32(ctl, 0x1a030); */
-/* reg &= ~0x4; */
-/* agnx_write32(ctl, 0x1a030, reg); */
-
- agnx_write32(ctl, AGNX_GCR_TRACNT4, 0x113);
-} /* phy_init */
-
-static void chip_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- band_management_init(priv);
-
- rf_chips_init(priv);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
- /* Initialize the PHY */
- phy_init(priv);
-
- encryption_init(priv);
-
- tx_management_init(priv);
-
- rx_management_init(priv);
-
- power_manage_init(priv);
-
- /* Initialize the Timers */
- agnx_timer_init(priv);
-
- /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */
- reg = 0xc390bf9 & ~IRQ_TX_BEACON;
- reg &= ~IRQ_TX_DISABLE;
- agnx_write32(ctl, AGNX_INT_MASK, reg);
-
- reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
- reg |= 0x800;
- agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
-
- /* set it when need get multicast enable? */
- agnx_write32(ctl, AGNX_BM_MTSM, 0xff);
-} /* chip_init */
-
-
-static inline void set_promis_and_managed(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
-}
-static inline void set_learn_mode(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x8);
-}
-static inline void set_scan_mode(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x20);
-}
-static inline void set_promiscuous_mode(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10);
-}
-static inline void set_managed_mode(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x2);
-}
-static inline void set_adhoc_mode(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x0);
-}
-
-#if 0
-static void unknow_register_write(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
-
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x0, 0x3e);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4, 0xb2);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x8, 0x140);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0xc, 0x1C0);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x10, 0x1FF);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x14, 0x1DD);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x18, 0x15F);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x1c, 0xA1);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x20, 0x3E7);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x24, 0x36B);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x28, 0x348);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x2c, 0x37D);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x30, 0x3DE);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x34, 0x36);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x38, 0x64);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x3c, 0x57);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x40, 0x23);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x44, 0x3ED);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x48, 0x3C9);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4c, 0x3CA);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x50, 0x3E7);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x54, 0x8);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x58, 0x1F);
- agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x5c, 0x1a);
-}
-#endif
-
-static void card_interface_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u32 reg;
- unsigned int i;
- AGNX_TRACE;
-
- might_sleep();
- /* Clear RX Control and Enable RX queues */
- agnx_write32(ctl, AGNX_CIR_RXCTL, 0x8);
-
- might_sleep();
- /* Do a full reset of the card */
- card_full_reset(priv);
- might_sleep();
-
- /* Check and set Card Endianness */
- reg = ioread32(priv->ctl + AGNX_CIR_ENDIAN);
- /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */
- printk(KERN_INFO PFX "CIR_ENDIAN is %x\n", reg);
-
-
- /* Config the eeprom */
- agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x7000086);
- udelay(10);
- reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-
-
- agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
- reg = agnx_read32(ctl, 0xec50);
- reg |= 0xf;
- agnx_write32(ctl, 0xec50, reg);
- agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
-
-
- reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
- udelay(10);
- reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-
- /* Dump the eeprom */
- do {
- char eeprom[0x100000/0x100];
-
- for (i = 0; i < 0x100000; i += 0x100) {
- agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x3000000 + i);
- udelay(13);
- reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
- udelay(70);
- reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
- eeprom[i/0x100] = reg & 0xFF;
- udelay(10);
- }
- print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
- ARRAY_SIZE(eeprom));
- } while (0);
-
- spi_rc_write(ctl, RF_CHIP0, 0x26);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
- /* Initialize the system interface */
- system_itf_init(priv);
-
- might_sleep();
- /* Chip Initialization (Polaris) */
- chip_init(priv);
- might_sleep();
-
- /* Calibrate the antennae */
- antenna_calibrate(priv);
-
- reg = agnx_read32(ctl, 0xec50);
- reg &= ~0x40;
- agnx_write32(ctl, 0xec50, reg);
- agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
- agnx_write32(ctl, AGNX_PM_PLLCTL, 0x1);
-
- reg = agnx_read32(ctl, AGNX_BM_BMCTL);
- reg |= 0x8000;
- agnx_write32(ctl, AGNX_BM_BMCTL, reg);
- enable_receiver(priv);
- reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
- reg |= 0x200;
- agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
- enable_receiver(priv);
-
- might_sleep();
- /* Initialize Gain Control Counts */
- gain_ctlcnt_init(priv);
-
- /* Write Initial Station Power Template for this station(#0) */
- sta_power_init(priv, LOCAL_STAID);
-
- might_sleep();
- /* Initialize the rx,td,tm rings, for each node in the ring */
- fill_rings(priv);
-
- might_sleep();
-
-
- agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
- agnx_write32(ctl, 0xec50, 0xc);
- agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
-
- /* FIXME Initialize the transmit control register */
- agnx_write32(ctl, AGNX_TXM_CTL, 0x194c1);
-
- enable_receiver(priv);
-
- might_sleep();
- /* FIXME Set the Receive Control Mac Address to card address */
- mac_address_set(priv);
- enable_receiver(priv);
- might_sleep();
-
- /* Set the recieve request rate */
- /* FIXME Enable the request */
- /* Check packet length */
- /* Set maximum packet length */
-/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
-/* enable_receiver(priv); */
-
- /* Set the Receiver BSSID */
- receiver_bssid_set(priv, bssid);
-
- /* FIXME Set to managed mode */
- set_managed_mode(priv);
-/* set_promiscuous_mode(priv); */
-/* set_scan_mode(priv); */
-/* set_learn_mode(priv); */
-/* set_promis_and_managed(priv); */
-/* set_adhoc_mode(priv); */
-
- /* Set the recieve request rate */
- /* Check packet length */
- agnx_write32(ctl, AGNX_RXM_REQRATE, 0x08000000);
- reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
- /* Set maximum packet length */
- reg |= 0x00195e00;
- agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
-
- /* Configure the RX and TX interrupt */
- reg = ENABLE_RX_INTERRUPT | RX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
- agnx_write32(ctl, AGNX_CIR_RXCFG, reg);
- /* FIXME */
- reg = ENABLE_TX_INTERRUPT | TX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
- agnx_write32(ctl, AGNX_CIR_TXCFG, reg);
-
- /* Enable RX TX Interrupts */
- agnx_write32(ctl, AGNX_CIR_RXCTL, 0x80);
- agnx_write32(ctl, AGNX_CIR_TXMCTL, 0x80);
- agnx_write32(ctl, AGNX_CIR_TXDCTL, 0x80);
-
- /* FIXME Set the master control interrupt in block control */
- agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x800);
-
- /* Enable RX and TX queues */
- reg = agnx_read32(ctl, AGNX_CIR_RXCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_CIR_RXCTL, reg);
- reg = agnx_read32(ctl, AGNX_CIR_TXMCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_CIR_TXMCTL, reg);
- reg = agnx_read32(ctl, AGNX_CIR_TXDCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_CIR_TXDCTL, reg);
-
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
- /* FIXME */
- /* unknow_register_write(priv); */
- /* Update local card hash entry */
- hash_write(priv, priv->mac_addr, LOCAL_STAID);
-
- might_sleep();
-
- /* FIXME */
- agnx_set_channel(priv, 1);
- might_sleep();
-} /* agnx_card_interface_init */
-
-
-void agnx_hw_init(struct agnx_priv *priv)
-{
- AGNX_TRACE;
- might_sleep();
- card_interface_init(priv);
-}
-
-int agnx_hw_reset(struct agnx_priv *priv)
-{
- return card_full_reset(priv);
-}
-
-int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len)
-{
- AGNX_TRACE;
- return 0;
-}
-
-void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid)
-{
- receiver_bssid_set(priv, bssid);
-}
diff --git a/drivers/staging/agnx/phy.h b/drivers/staging/agnx/phy.h
deleted file mode 100644
index a955f05361e7..000000000000
--- a/drivers/staging/agnx/phy.h
+++ /dev/null
@@ -1,409 +0,0 @@
-#ifndef AGNX_PHY_H_
-#define AGNX_PHY_H_
-
-#include "agnx.h"
-
-/* Transmission Managment Registers */
-#define AGNX_TXM_BASE 0x0000
-#define AGNX_TXM_CTL 0x0000 /* control register */
-#define AGNX_TXM_ETMF 0x0004 /* enable transmission management functions */
-#define AGNX_TXM_TXTEMP 0x0008 /* transmission template */
-#define AGNX_TXM_RETRYSTAID 0x000c /* Retry Station ID */
-#define AGNX_TXM_TIMESTAMPLO 0x0010 /* Timestamp Lo */
-#define AGNX_TXM_TIMESTAMPHI 0x0014 /* Timestamp Hi */
-#define AGNX_TXM_TXDELAY 0x0018 /* tx delay */
-#define AGNX_TXM_TBTTLO 0x0020 /* tbtt Lo */
-#define AGNX_TXM_TBTTHI 0x0024 /* tbtt Hi */
-#define AGNX_TXM_BEAINTER 0x0028 /* Beacon Interval */
-#define AGNX_TXM_NAV 0x0030 /* NAV */
-#define AGNX_TXM_CFPMDV 0x0034 /* CFP MDV */
-#define AGNX_TXM_CFPERCNT 0x0038 /* CFP period count */
-#define AGNX_TXM_PROBDELAY 0x003c /* probe delay */
-#define AGNX_TXM_LISINTERCNT 0x0040 /* listen interval count */
-#define AGNX_TXM_DTIMPERICNT 0x004c /* DTIM period count */
-
-#define AGNX_TXM_BEACON_CTL 0x005c /* beacon control */
-
-#define AGNX_TXM_SCHEMPCNT 0x007c /* schedule empty count */
-#define AGNX_TXM_MAXTIMOUT 0x0084 /* max timeout exceed count */
-#define AGNX_TXM_MAXCFPTIM 0x0088 /* max CF poll timeout count */
-#define AGNX_TXM_MAXRXTIME 0x008c /* max RX timeout count */
-#define AGNX_TXM_MAXACKTIM 0x0090 /* max ACK timeout count */
-#define AGNX_TXM_DIF01 0x00a0 /* DIF 0-1 */
-#define AGNX_TXM_DIF23 0x00a4 /* DIF 2-3 */
-#define AGNX_TXM_DIF45 0x00a8 /* DIF 4-5 */
-#define AGNX_TXM_DIF67 0x00ac /* DIF 6-7 */
-#define AGNX_TXM_SIFSPIFS 0x00b0 /* SIFS/PIFS */
-#define AGNX_TXM_TIFSEIFS 0x00b4 /* TIFS/EIFS */
-#define AGNX_TXM_MAXCCACNTSLOT 0x00b8 /* max CCA count slot */
-#define AGNX_TXM_SLOTLIMIT 0x00bc /* slot limit/1 msec limit */
-#define AGNX_TXM_CFPOLLRXTIM 0x00f0 /* CF poll RX timeout count */
-#define AGNX_TXM_CFACKT11B 0x00f4 /* CF ack timeout limit for 11b */
-#define AGNX_TXM_CW0 0x0100 /* CW 0 */
-#define AGNX_TXM_SLBEALIM0 0x0108 /* short/long beacon limit 0 */
-#define AGNX_TXM_CW1 0x0120 /* CW 1 */
-#define AGNX_TXM_SLBEALIM1 0x0128 /* short/long beacon limit 1 */
-#define AGNX_TXM_CW2 0x0140 /* CW 2 */
-#define AGNX_TXM_SLBEALIM2 0x0148 /* short/long beacon limit 2 */
-#define AGNX_TXM_CW3 0x0160 /* CW 3 */
-#define AGNX_TXM_SLBEALIM3 0x0168 /* short/long beacon limit 3 */
-#define AGNX_TXM_CW4 0x0180 /* CW 4 */
-#define AGNX_TXM_SLBEALIM4 0x0188 /* short/long beacon limit 4 */
-#define AGNX_TXM_CW5 0x01a0 /* CW 5 */
-#define AGNX_TXM_SLBEALIM5 0x01a8 /* short/long beacon limit 5 */
-#define AGNX_TXM_CW6 0x01c0 /* CW 6 */
-#define AGNX_TXM_SLBEALIM6 0x01c8 /* short/long beacon limit 6 */
-#define AGNX_TXM_CW7 0x01e0 /* CW 7 */
-#define AGNX_TXM_SLBEALIM7 0x01e8 /* short/long beacon limit 7 */
-#define AGNX_TXM_BEACONTEMP 0x1000 /* beacon template */
-#define AGNX_TXM_STAPOWTEMP 0x1a00 /* Station Power Template */
-
-/* Receive Management Control Registers */
-#define AGNX_RXM_BASE 0x2000
-#define AGNX_RXM_REQRATE 0x2000 /* requested rate */
-#define AGNX_RXM_MACHI 0x2004 /* first 4 bytes of mac address */
-#define AGNX_RXM_MACLO 0x2008 /* last 2 bytes of mac address */
-#define AGNX_RXM_BSSIDHI 0x200c /* bssid hi */
-#define AGNX_RXM_BSSIDLO 0x2010 /* bssid lo */
-#define AGNX_RXM_HASH_CMD_FLAG 0x2014 /* Flags for the RX Hash Command Default:0 */
-#define AGNX_RXM_HASH_CMD_HIGH 0x2018 /* The High half of the Hash Command */
-#define AGNX_RXM_HASH_CMD_LOW 0x201c /* The Low half of the Hash Command */
-#define AGNX_RXM_ROUTAB 0x2020 /* routing table */
-#define ROUTAB_SUBTYPE_SHIFT 24
-#define ROUTAB_TYPE_SHIFT 28
-#define ROUTAB_STATUS_SHIFT 30
-#define ROUTAB_RW_SHIFT 31
-#define ROUTAB_ROUTE_DROP 0xf00000 /* Drop */
-#define ROUTAB_ROUTE_CPU 0x400000 /* CPU */
-#define ROUTAB_ROUTE_ENCRY 0x500800 /* Encryption */
-#define ROUTAB_ROUTE_RFP 0x800000 /* RFP */
-
-#define ROUTAB_TYPE_MANAG 0x0 /* Management */
-#define ROUTAB_TYPE_CTL 0x1 /* Control */
-#define ROUTAB_TYPE_DATA 0x2 /* Data */
-
-#define ROUTAB_SUBTYPE_DATA 0x0
-#define ROUTAB_SUBTYPE_DATAACK 0x1
-#define ROUTAB_SUBTYPE_DATAPOLL 0x2
-#define ROUTAB_SUBTYPE_DATAPOLLACK 0x3
-#define ROUTAB_SUBTYPE_NULL 0x4 /* NULL */
-#define ROUTAB_SUBTYPE_NULLACK 0x5
-#define ROUTAB_SUBTYPE_NULLPOLL 0x6
-#define ROUTAB_SUBTYPE_NULLPOLLACK 0x7
-#define ROUTAB_SUBTYPE_QOSDATA 0x8 /* QOS DATA */
-#define ROUTAB_SUBTYPE_QOSDATAACK 0x9
-#define ROUTAB_SUBTYPE_QOSDATAPOLL 0xa
-#define ROUTAB_SUBTYPE_QOSDATAACKPOLL 0xb
-#define ROUTAB_SUBTYPE_QOSNULL 0xc
-#define ROUTAB_SUBTYPE_QOSNULLACK 0xd
-#define ROUTAB_SUBTYPE_QOSNULLPOLL 0xe
-#define ROUTAB_SUBTYPE_QOSNULLPOLLACK 0xf
-#define AGNX_RXM_DELAY11 0x2024 /* delay 11(AB) */
-#define AGNX_RXM_SOF_CNT 0x2028 /* SOF Count */
-#define AGNX_RXM_FRAG_CNT 0x202c /* Fragment Count*/
-#define AGNX_RXM_FCS_CNT 0x2030 /* FCS Count */
-#define AGNX_RXM_BSSID_MISS_CNT 0x2034 /* BSSID Miss Count */
-#define AGNX_RXM_PDU_ERR_CNT 0x2038 /* PDU Error Count */
-#define AGNX_RXM_DEST_MISS_CNT 0x203C /* Destination Miss Count */
-#define AGNX_RXM_DROP_CNT 0x2040 /* Drop Count */
-#define AGNX_RXM_ABORT_CNT 0x2044 /* Abort Count */
-#define AGNX_RXM_RELAY_CNT 0x2048 /* Relay Count */
-#define AGNX_RXM_HASH_MISS_CNT 0x204c /* Hash Miss Count */
-#define AGNX_RXM_SA_HI 0x2050 /* Address of received packet Hi */
-#define AGNX_RXM_SA_LO 0x2054 /* Address of received packet Lo */
-#define AGNX_RXM_HASH_DUMP_LST 0x2100 /* Contains Hash Data */
-#define AGNX_RXM_HASH_DUMP_MST 0x2104 /* Contains Hash Data */
-#define AGNX_RXM_HASH_DUMP_DATA 0x2108 /* The Station ID to dump */
-
-
-/* Encryption Managment */
-#define AGNX_ENCRY_BASE 0x2400
-#define AGNX_ENCRY_WEPKEY0 0x2440 /* wep key #0 */
-#define AGNX_ENCRY_WEPKEY1 0x2444 /* wep key #1 */
-#define AGNX_ENCRY_WEPKEY2 0x2448 /* wep key #2 */
-#define AGNX_ENCRY_WEPKEY3 0x244c /* wep key #3 */
-#define AGNX_ENCRY_CCMRECTL 0x2460 /* ccm replay control */
-
-
-/* Band Management Registers */
-#define AGNX_BM_BASE 0x2c00
-#define AGNX_BM_BMCTL 0x2c00 /* band management control */
-#define AGNX_BM_TXWADDR 0x2c18 /* tx workqueue address start */
-#define AGNX_BM_TXTOPEER 0x2c24 /* transmit to peers */
-#define AGNX_BM_FPLHP 0x2c2c /* free pool list head pointer */
-#define AGNX_BM_FPLTP 0x2c30 /* free pool list tail pointer */
-#define AGNX_BM_FPCNT 0x2c34 /* free pool count */
-#define AGNX_BM_CIPDUWCNT 0x2c38 /* card interface pdu workqueue count */
-#define AGNX_BM_SPPDUWCNT 0x2c3c /* sp pdu workqueue count */
-#define AGNX_BM_RFPPDUWCNT 0x2c40 /* rfp pdu workqueue count */
-#define AGNX_BM_RHPPDUWCNT 0x2c44 /* rhp pdu workqueue count */
-#define AGNX_BM_CIWQCTL 0x2c48 /* Card Interface WorkQueue Control */
-#define AGNX_BM_CPUTXWCTL 0x2c50 /* cpu tx workqueue control */
-#define AGNX_BM_CPURXWCTL 0x2c58 /* cpu rx workqueue control */
-#define AGNX_BM_CPULWCTL 0x2c60 /* cpu low workqueue control */
-#define AGNX_BM_CPUHWCTL 0x2c68 /* cpu high workqueue control */
-#define AGNX_BM_SPTXWCTL 0x2c70 /* sp tx workqueue control */
-#define AGNX_BM_SPRXWCTL 0x2c78 /* sp rx workqueue control */
-#define AGNX_BM_RFPWCTL 0x2c80 /* RFP workqueue control */
-#define AGNX_BM_MTSM 0x2c90 /* Multicast Transmit Station Mask */
-
-/* Card Interface Registers (32bits) */
-#define AGNX_CIR_BASE 0x3000
-#define AGNX_CIR_BLKCTL 0x3000 /* block control*/
-#define AGNX_STAT_TX 0x1
-#define AGNX_STAT_RX 0x2
-#define AGNX_STAT_X 0x4
-/* Below two interrupt flags will be set by our but not CPU or the card */
-#define AGNX_STAT_TXD 0x10
-#define AGNX_STAT_TXM 0x20
-
-#define AGNX_CIR_ADDRWIN 0x3004 /* Addressable Windows*/
-#define AGNX_CIR_ENDIAN 0x3008 /* card endianness */
-#define AGNX_CIR_SERIALITF 0x3020 /* serial interface */
-#define AGNX_CIR_RXCFG 0x3040 /* receive config */
-#define ENABLE_RX_INTERRUPT 0x20
-#define RX_CACHE_LINE 0x8
-/* the RX fragment length */
-#define FRAG_LEN_256 0x0 /* 256B */
-#define FRAG_LEN_512 0x1
-#define FRAG_LEN_1024 0x2
-#define FRAG_LEN_2048 0x3
-#define FRAG_BE 0x10
-#define AGNX_CIR_RXCTL 0x3050 /* receive control */
-/* memory address, chipside */
-#define AGNX_CIR_RXCMSTART 0x3054 /* receive client memory start */
-#define AGNX_CIR_RXCMEND 0x3058 /* receive client memory end */
-/* memory address, pci */
-#define AGNX_CIR_RXHOSTADDR 0x3060 /* receive hostside address */
-/* memory address, chipside */
-#define AGNX_CIR_RXCLIADDR 0x3064 /* receive clientside address */
-#define AGNX_CIR_RXDMACTL 0x3068 /* receive dma control */
-#define AGNX_CIR_TXCFG 0x3080 /* transmit config */
-#define AGNX_CIR_TXMCTL 0x3090 /* Transmit Management Control */
-#define ENABLE_TX_INTERRUPT 0x20
-#define TX_CACHE_LINE 0x8
-#define AGNX_CIR_TXMSTART 0x3094 /* Transmit Management Start */
-#define AGNX_CIR_TXMEND 0x3098 /* Transmit Management End */
-#define AGNX_CIR_TXDCTL 0x30a0 /* transmit data control */
-/* memeory address, chipset */
-#define AGNX_CIR_TXDSTART 0x30a4 /* transmit data start */
-#define AGNX_CIR_TXDEND 0x30a8 /* transmit data end */
-#define AGNX_CIR_TXMHADDR 0x30b0 /* Transmit Management Hostside Address */
-#define AGNX_CIR_TXMCADDR 0x30b4 /* Transmit Management Clientside Address */
-#define AGNX_CIR_TXDMACTL 0x30b8 /* transmit dma control */
-
-
-/* Power Managment Unit */
-#define AGNX_PM_BASE 0x3c00
-#define AGNX_PM_PMCTL 0x3c00 /* PM Control*/
-#define AGNX_PM_MACMSW 0x3c08 /* MAC Manual Slow Work Enable */
-#define AGNX_PM_RFCTL 0x3c0c /* RF Control */
-#define AGNX_PM_PHYMW 0x3c14 /* Phy Mannal Work */
-#define AGNX_PM_SOFTRST 0x3c18 /* PMU Soft Reset */
-#define AGNX_PM_PLLCTL 0x3c1c /* PMU PLL control*/
-#define AGNX_PM_TESTPHY 0x3c24 /* PMU Test Phy */
-
-
-/* Interrupt Control interface */
-#define AGNX_INT_BASE 0x4000
-#define AGNX_INT_STAT 0x4000 /* interrupt status */
-#define AGNX_INT_MASK 0x400c /* interrupt mask */
-/* FIXME */
-#define IRQ_TX_BEACON 0x1 /* TX Beacon */
-#define IRQ_TX_RETRY 0x8 /* TX Retry Interrupt */
-#define IRQ_TX_ACTIVITY 0x10 /* TX Activity */
-#define IRQ_RX_ACTIVITY 0x20 /* RX Activity */
-/* FIXME I guess that instead RX a none exist staion's packet or
- the station hasn't been init */
-#define IRQ_RX_X 0x40
-#define IRQ_RX_Y 0x80 /* RX ? */
-#define IRQ_RX_HASHHIT 0x100 /* RX Hash Hit */
-#define IRQ_RX_FRAME 0x200 /* RX Frame */
-#define IRQ_ERR_INT 0x400 /* Error Interrupt */
-#define IRQ_TX_QUE_FULL 0x800 /* TX Workqueue Full */
-#define IRQ_BANDMAN_ERR 0x10000 /* Bandwidth Management Error */
-#define IRQ_TX_DISABLE 0x20000 /* TX Disable */
-#define IRQ_RX_IVASESKEY 0x80000 /* RX Invalid Session Key */
-#define IRQ_RX_KEYIDMIS 0x100000 /* RX key ID Mismatch */
-#define IRQ_REP_THHIT 0x200000 /* Replay Threshold Hit */
-#define IRQ_TIMER1 0x4000000 /* Timer1 */
-#define IRQ_TIMER_CNT 0x10000000 /* Timer Count */
-#define IRQ_PHY_FASTINT 0x20000000 /* Phy Fast Interrupt */
-#define IRQ_PHY_SLOWINT 0x40000000 /* Phy Slow Interrupt */
-#define IRQ_OTHER 0x80000000 /* Unknow interrupt */
-#define AGNX_IRQ_ALL 0xffffffff
-
-/* System Interface */
-#define AGNX_SYSITF_BASE 0x4400
-#define AGNX_SYSITF_SYSMODE 0x4400 /* system mode */
-#define AGNX_SYSITF_GPIOIN 0x4410 /* GPIO In */
-/* PIN lines for leds? */
-#define AGNX_SYSITF_GPIOUT 0x4414 /* GPIO Out */
-
-/* Timer Control */
-#define AGNX_TIMCTL_TIMER1 0x4800 /* Timer 1 */
-#define AGNX_TIMCTL_TIM1CTL 0x4808 /* Timer 1 Control */
-
-
-/* Antenna Calibration Interface */
-#define AGNX_ACI_BASE 0x5000
-#define AGNX_ACI_MODE 0x5000 /* Mode */
-#define AGNX_ACI_MEASURE 0x5004 /* Measure */
-#define AGNX_ACI_SELCHAIN 0x5008 /* Select Chain */
-#define AGNX_ACI_LEN 0x500c /* Length */
-#define AGNX_ACI_TIMER1 0x5018 /* Timer 1 */
-#define AGNX_ACI_TIMER2 0x501c /* Timer 2 */
-#define AGNX_ACI_OFFSET 0x5020 /* Offset */
-#define AGNX_ACI_STATUS 0x5030 /* Status */
-#define CALI_IDLE 0x0
-#define CALI_DONE 0x1
-#define CALI_BUSY 0x2
-#define CALI_ERR 0x3
-#define AGNX_ACI_AICCHA0OVE 0x5034 /* AIC Channel 0 Override */
-#define AGNX_ACI_AICCHA1OVE 0x5038 /* AIC Channel 1 Override */
-
-/* Gain Control Registers */
-#define AGNX_GCR_BASE 0x9000
-/* threshold of primary antenna */
-#define AGNX_GCR_THD0A 0x9000 /* threshold? D0 A */
-/* low threshold of primary antenna */
-#define AGNX_GCR_THD0AL 0x9004 /* threshold? D0 A low */
-/* threshold of secondary antenna */
-#define AGNX_GCR_THD0B 0x9008 /* threshold? D0_B */
-#define AGNX_GCR_DUNSAT 0x900c /* d unsaturated */
-#define AGNX_GCR_DSAT 0x9010 /* d saturated */
-#define AGNX_GCR_DFIRCAL 0x9014 /* D Fir/Cal */
-#define AGNX_GCR_DGCTL11A 0x9018 /* d gain control 11a */
-#define AGNX_GCR_DGCTL11B 0x901c /* d gain control 11b */
-/* strength of gain */
-#define AGNX_GCR_GAININIT 0x9020 /* gain initialization */
-#define AGNX_GCR_THNOSIG 0x9024 /* threhold no signal */
-#define AGNX_GCR_COARSTEP 0x9028 /* coarse stepping */
-#define AGNX_GCR_SIFST11A 0x902c /* sifx time 11a */
-#define AGNX_GCR_SIFST11B 0x9030 /* sifx time 11b */
-#define AGNX_GCR_CWDETEC 0x9034 /* cw detection */
-#define AGNX_GCR_0X38 0x9038 /* ???? */
-#define AGNX_GCR_BOACT 0x903c /* BO Active */
-#define AGNX_GCR_BOINACT 0x9040 /* BO Inactive */
-#define AGNX_GCR_BODYNA 0x9044 /* BO dynamic */
-/* 802.11 mode(a,b,g) */
-#define AGNX_GCR_DISCOVMOD 0x9048 /* discovery mode */
-#define AGNX_GCR_NLISTANT 0x904c /* number of listening antenna */
-#define AGNX_GCR_NACTIANT 0x9050 /* number of active antenna */
-#define AGNX_GCR_NMEASANT 0x9054 /* number of measuring antenna */
-#define AGNX_GCR_NCAPTANT 0x9058 /* number of capture antenna */
-#define AGNX_GCR_THCAP11A 0x905c /* threshold capture 11a */
-#define AGNX_GCR_THCAP11B 0x9060 /* threshold capture 11b */
-#define AGNX_GCR_THCAPRX11A 0x9064 /* threshold capture rx 11a */
-#define AGNX_GCR_THCAPRX11B 0x9068 /* threshold capture rx 11b */
-#define AGNX_GCR_THLEVDRO 0x906c /* threshold level drop */
-#define AGNX_GCR_GAINSET0 0x9070 /* Gainset 0 */
-#define AGNX_GCR_GAINSET1 0x9074 /* Gainset 1 */
-#define AGNX_GCR_GAINSET2 0x9078 /* Gainset 2 */
-#define AGNX_GCR_MAXRXTIME11A 0x907c /* maximum rx time 11a */
-#define AGNX_GCR_MAXRXTIME11B 0x9080 /* maximum rx time 11b */
-#define AGNX_GCR_CORRTIME 0x9084 /* correction time */
-/* reset the subsystem, 0 = disable, 1 = enable */
-#define AGNX_GCR_RSTGCTL 0x9088 /* reset gain control */
-/* channel receiving */
-#define AGNX_GCR_RXCHANEL 0x908c /* receive channel */
-#define AGNX_GCR_NOISE0 0x9090 /* Noise 0 */
-#define AGNX_GCR_NOISE1 0x9094 /* Noise 1 */
-#define AGNX_GCR_NOISE2 0x9098 /* Noise 2 */
-#define AGNX_GCR_SIGHTH 0x909c /* Signal High Threshold */
-#define AGNX_GCR_SIGLTH 0x90a0 /* Signal Low Threshold */
-#define AGNX_GCR_CORRDROP 0x90a4 /* correction drop */
-/* threshold of tertiay antenna */
-#define AGNX_GCR_THCD 0x90a8 /* threshold? CD */
-#define AGNX_GCR_THCS 0x90ac /* threshold? CS */
-#define AGNX_GCR_MAXPOWDIFF 0x90b8 /* maximum power difference */
-#define AGNX_GCR_TRACNT4 0x90ec /* Transition Count 4 */
-#define AGNX_GCR_TRACNT5 0x90f0 /* transition count 5 */
-#define AGNX_GCR_TRACNT6 0x90f4 /* transition count 6 */
-#define AGNX_GCR_TRACNT7 0x90f8 /* transition coutn 7 */
-#define AGNX_GCR_TESTBUS 0x911c /* test bus */
-#define AGNX_GCR_CHAINNUM 0x9120 /* Number of Chains */
-#define AGNX_GCR_ANTCFG 0x9124 /* Antenna Config */
-#define AGNX_GCR_THJUMP 0x912c /* threhold jump */
-#define AGNX_GCR_THPOWER 0x9130 /* threshold power */
-#define AGNX_GCR_THPOWCLIP 0x9134 /* threshold power clip*/
-#define AGNX_GCR_FORCECTLCLK 0x9138 /* Force Gain Control Clock */
-#define AGNX_GCR_GAINSETWRITE 0x913c /* Gainset Write */
-#define AGNX_GCR_THD0BTFEST 0x9140 /* threshold d0 b tf estimate */
-#define AGNX_GCR_THRX11BPOWMIN 0x9144 /* threshold rx 11b power minimum */
-#define AGNX_GCR_0X14c 0x914c /* ?? */
-#define AGNX_GCR_0X150 0x9150 /* ?? */
-#define AGNX_GCR_RXOVERIDE 0x9194 /* recieve override */
-#define AGNX_GCR_WATCHDOG 0x91b0 /* watchdog timeout */
-
-
-/* Spi Interface */
-#define AGNX_SPI_BASE 0xdc00
-#define AGNX_SPI_CFG 0xdc00 /* spi configuration */
-/* Only accept 16 bits */
-#define AGNX_SPI_WMSW 0xdc04 /* write most significant word */
-/* Only accept 16 bits */
-#define AGNX_SPI_WLSW 0xdc08 /* write least significant word */
-#define AGNX_SPI_CTL 0xdc0c /* spi control */
-#define AGNX_SPI_RMSW 0xdc10 /* read most significant word */
-#define AGNX_SPI_RLSW 0xdc14 /* read least significant word */
-/* SPI Control Mask */
-#define SPI_READ_CTL 0x4000 /* read control */
-#define SPI_BUSY_CTL 0x8000 /* busy control */
-/* RF and synth chips in spi */
-#define RF_CHIP0 0x400
-#define RF_CHIP1 0x800
-#define RF_CHIP2 0x1000
-#define SYNTH_CHIP 0x2000
-
-/* Unknown register */
-#define AGNX_UNKNOWN_BASE 0x7800
-
-/* FIXME MonitorGain */
-#define AGNX_MONGCR_BASE 0x12000
-
-/* Gain Table */
-#define AGNX_GAIN_TABLE 0x12400
-
-/* The initial FIR coefficient table */
-#define AGNX_FIR_BASE 0x19804
-
-#define AGNX_ENGINE_LOOKUP_TBL 0x800
-
-/* eeprom commands */
-#define EEPROM_CMD_NULL 0x0 /* NULL */
-#define EEPROM_CMD_WRITE 0x2 /* write */
-#define EEPROM_CMD_READ 0x3 /* read */
-#define EEPROM_CMD_STATUSREAD 0x5 /* status register read */
-#define EEPROM_CMD_WRITEENABLE 0x6 /* write enable */
-#define EEPROM_CMD_CONFIGURE 0x7 /* configure */
-
-#define EEPROM_DATAFORCOFIGURE 0x6 /* ??? */
-
-/* eeprom address */
-#define EEPROM_ADDR_SUBVID 0x0 /* Sub Vendor ID */
-#define EEPROM_ADDR_SUBSID 0x2 /* Sub System ID */
-#define EEPROM_ADDR_MACADDR 0x146 /* MAC Address */
-#define EEPROM_ADDR_LOTYPE 0x14f /* LO type */
-
-struct agnx_eeprom {
- u8 data; /* date */
- u16 address; /* address in EEPROM */
- u8 cmd; /* command, unknown, status */
-} __attribute__((__packed__));
-
-#define AGNX_EEPROM_COMMAND_SHIFT 5
-#define AGNX_EEPROM_COMMAND_STAT 0x01
-
-void disable_receiver(struct agnx_priv *priv);
-void enable_receiver(struct agnx_priv *priv);
-u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
-void agnx_hw_init(struct agnx_priv *priv);
-int agnx_hw_reset(struct agnx_priv *priv);
-int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
-void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid);
-void enable_power_saving(struct agnx_priv *priv);
-void disable_power_saving(struct agnx_priv *priv);
-void calibrate_antenna_period(unsigned long data);
-
-#endif /* AGNX_PHY_H_ */
diff --git a/drivers/staging/agnx/rf.c b/drivers/staging/agnx/rf.c
deleted file mode 100644
index 42e457a1844f..000000000000
--- a/drivers/staging/agnx/rf.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- */
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-#include "table.h"
-
-/* FIXME! */
-static inline void spi_write(void __iomem *region, u32 chip_ids, u32 sw,
- u16 size, u32 control)
-{
- u32 reg;
- u32 lsw = sw & 0xffff; /* lower 16 bits of sw*/
- u32 msw = sw >> 16; /* high 16 bits of sw */
-
- /* FIXME Write Most Significant Word of the 32bit data to MSW */
- /* FIXME And Least Significant Word to LSW */
- iowrite32((lsw), region + AGNX_SPI_WLSW);
- iowrite32((msw), region + AGNX_SPI_WMSW);
- reg = chip_ids | size | control;
- /* Write chip id(s), write size and busy control to Control Register */
- iowrite32((reg), region + AGNX_SPI_CTL);
- /* Wait for Busy control to clear */
- spi_delay();
-}
-
-/*
- * Write to SPI Synth register
- */
-static inline void spi_sy_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
- /* FIXME the size 0x15 is a magic value*/
- spi_write(region, chip_ids, sw, 0x15, SPI_BUSY_CTL);
-}
-
-/*
- * Write to SPI RF register
- */
-static inline void spi_rf_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
- /* FIXME the size 0xd is a magic value*/
- spi_write(region, chip_ids, sw, 0xd, SPI_BUSY_CTL);
-} /* spi_rf_write */
-
-/*
- * Write to SPI with Read Control bit set
- */
-inline void spi_rc_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
- /* FIXME the size 0xe5 is a magic value */
- spi_write(region, chip_ids, sw, 0xe5, SPI_BUSY_CTL|SPI_READ_CTL);
-}
-
-/* Get the active chains's count */
-static int get_active_chains(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int num = 0;
- u32 reg;
- AGNX_TRACE;
-
- spi_rc_write(ctl, RF_CHIP0, 0x21);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (reg == 1)
- num++;
-
- spi_rc_write(ctl, RF_CHIP1, 0x21);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (reg == 1)
- num++;
-
- spi_rc_write(ctl, RF_CHIP2, 0x21);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (reg == 1)
- num++;
-
- spi_rc_write(ctl, RF_CHIP0, 0x26);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (0x33 != reg)
- printk(KERN_WARNING PFX "Unmatched rf chips result\n");
-
- return num;
-} /* get_active_chains */
-
-void rf_chips_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- int num;
- AGNX_TRACE;
-
- if (priv->revid == 1) {
- reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
- }
-
- /* Set SPI clock speed to 200NS */
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xF;
- reg |= 0x3;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
- /* Set SPI clock speed to 50NS */
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xF;
- reg |= 0x1;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1101);
-
- num = get_active_chains(priv);
- printk(KERN_INFO PFX "Active chains are %d\n", num);
-
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xF;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1908);
-} /* rf_chips_init */
-
-
-static u32 channel_tbl[15][9] = {
- {0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {1, 0x00, 0x00, 0x624, 0x00, 0x1a4, 0x28, 0x00, 0x1e},
- {2, 0x00, 0x00, 0x615, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
- {3, 0x00, 0x00, 0x61a, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
- {4, 0x00, 0x00, 0x61f, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
- {5, 0x00, 0x00, 0x624, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
- {6, 0x00, 0x00, 0x61f, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
- {7, 0x00, 0x00, 0x624, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
- {8, 0x00, 0x00, 0x629, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
- {9, 0x00, 0x00, 0x624, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
- {10, 0x00, 0x00, 0x629, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
- {11, 0x00, 0x00, 0x62e, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
- {12, 0x00, 0x00, 0x633, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
- {13, 0x00, 0x00, 0x628, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
- {14, 0x00, 0x00, 0x644, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-};
-
-
-static inline void
-channel_tbl_write(struct agnx_priv *priv, unsigned int channel, unsigned int reg_num)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- reg = channel_tbl[channel][reg_num];
- reg <<= 4;
- reg |= reg_num;
- spi_sy_write(ctl, SYNTH_CHIP, reg);
-}
-
-static void synth_freq_set(struct agnx_priv *priv, unsigned int channel)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-
- /* Set the Clock bits to 50NS */
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xF;
- reg |= 0x1;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
- /* Write 0x00c0 to LSW and 0x3 to MSW of Synth Chip */
- spi_sy_write(ctl, SYNTH_CHIP, 0x300c0);
-
- spi_sy_write(ctl, SYNTH_CHIP, 0x32);
-
- /* # Write to Register 1 on the Synth Chip */
- channel_tbl_write(priv, channel, 1);
- /* # Write to Register 3 on the Synth Chip */
- channel_tbl_write(priv, channel, 3);
- /* # Write to Register 6 on the Synth Chip */
- channel_tbl_write(priv, channel, 6);
- /* # Write to Register 5 on the Synth Chip */
- channel_tbl_write(priv, channel, 5);
- /* # Write to register 8 on the Synth Chip */
- channel_tbl_write(priv, channel, 8);
-
- /* FIXME Clear the clock bits */
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xf;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-} /* synth_chip_init */
-
-
-static void antenna_init(struct agnx_priv *priv, int num_antenna)
-{
- void __iomem *ctl = priv->ctl;
-
- switch (num_antenna) {
- case 1:
- agnx_write32(ctl, AGNX_GCR_NLISTANT, 1);
- agnx_write32(ctl, AGNX_GCR_NMEASANT, 1);
- agnx_write32(ctl, AGNX_GCR_NACTIANT, 1);
- agnx_write32(ctl, AGNX_GCR_NCAPTANT, 1);
-
- agnx_write32(ctl, AGNX_GCR_ANTCFG, 7);
- agnx_write32(ctl, AGNX_GCR_BOACT, 34);
- agnx_write32(ctl, AGNX_GCR_BOINACT, 34);
- agnx_write32(ctl, AGNX_GCR_BODYNA, 30);
-
- agnx_write32(ctl, AGNX_GCR_THD0A, 125);
- agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
- agnx_write32(ctl, AGNX_GCR_THD0B, 90);
-
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 80);
- agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
- agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
- break;
- case 2:
- agnx_write32(ctl, AGNX_GCR_NLISTANT, 2);
- agnx_write32(ctl, AGNX_GCR_NMEASANT, 2);
- agnx_write32(ctl, AGNX_GCR_NACTIANT, 2);
- agnx_write32(ctl, AGNX_GCR_NCAPTANT, 2);
- agnx_write32(ctl, AGNX_GCR_ANTCFG, 15);
- agnx_write32(ctl, AGNX_GCR_BOACT, 36);
- agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
- agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
- agnx_write32(ctl, AGNX_GCR_THD0A, 120);
- agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
- agnx_write32(ctl, AGNX_GCR_THD0B, 80);
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
- agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
- agnx_write32(ctl, AGNX_GCR_SIGLTH, 32);
- break;
- case 3:
- agnx_write32(ctl, AGNX_GCR_NLISTANT, 3);
- agnx_write32(ctl, AGNX_GCR_NMEASANT, 3);
- agnx_write32(ctl, AGNX_GCR_NACTIANT, 3);
- agnx_write32(ctl, AGNX_GCR_NCAPTANT, 3);
- agnx_write32(ctl, AGNX_GCR_ANTCFG, 31);
- agnx_write32(ctl, AGNX_GCR_BOACT, 36);
- agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
- agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
- agnx_write32(ctl, AGNX_GCR_THD0A, 100);
- agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
- agnx_write32(ctl, AGNX_GCR_THD0B, 70);
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
- agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
- agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
-/* agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */
- break;
- default:
- printk(KERN_WARNING PFX "Unknow antenna number\n");
- }
-} /* antenna_init */
-
-static void chain_update(struct agnx_priv *priv, u32 chain)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- spi_rc_write(ctl, RF_CHIP0, 0x20);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
- if (reg == 0x4)
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
- else if (reg != 0x0)
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
- else {
- if (chain == 3 || chain == 6) {
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
- } else if (chain == 2 || chain == 4) {
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
- spi_rf_write(ctl, RF_CHIP2, 0x1005);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x824);
- } else if (chain == 1) {
- spi_rf_write(ctl, RF_CHIP0, reg|0x1000);
- spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1004);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xc36);
- }
- }
-
- spi_rc_write(ctl, RF_CHIP0, 0x22);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
- switch (reg) {
- case 0:
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
- break;
- case 1:
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
- break;
- case 2:
- if (chain == 6 || chain == 4) {
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1202);
- spi_rf_write(ctl, RF_CHIP2, 0x1005);
- } else if (chain < 3) {
- spi_rf_write(ctl, RF_CHIP0, 0x1202);
- spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1005);
- }
- break;
- default:
- if (chain == 3) {
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
- spi_rf_write(ctl, RF_CHIP2, 0x1201);
- } else if (chain == 2) {
- spi_rf_write(ctl, RF_CHIP0, 0x1203);
- spi_rf_write(ctl, RF_CHIP2, 0x1200);
- spi_rf_write(ctl, RF_CHIP1, 0x1201);
- } else if (chain == 1) {
- spi_rf_write(ctl, RF_CHIP0, 0x1203);
- spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1200);
- } else if (chain == 4) {
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
- spi_rf_write(ctl, RF_CHIP2, 0x1201);
- } else {
- spi_rf_write(ctl, RF_CHIP0, 0x1203);
- spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1201);
- }
- }
-} /* chain_update */
-
-static void antenna_config(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- /* Write 0x0 to the TX Management Control Register Enable bit */
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
- reg &= ~0x1;
- agnx_write32(ctl, AGNX_TXM_CTL, reg);
-
- /* FIXME */
- /* Set initial value based on number of Antennae */
- antenna_init(priv, 3);
-
- /* FIXME Update Power Templates for current valid Stations */
- /* sta_power_init(priv, 0);*/
-
- /* FIXME the number of chains should get from eeprom*/
- chain_update(priv, AGNX_CHAINS_MAX);
-} /* antenna_config */
-
-void calibrate_oscillator(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
- reg |= 0x10;
- agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
-
- agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 1);
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 1);
-
- agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
- /* (Residual DC Calibration) to Calibration Mode */
- agnx_write32(ctl, AGNX_ACI_MODE, 0x2);
-
- spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1004);
- agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
- /* (TX LO Calibration) to Calibration Mode */
- agnx_write32(ctl, AGNX_ACI_MODE, 0x4);
-
- do {
- u32 reg1, reg2, reg3;
- /* Enable Power Saving Control */
- enable_power_saving(priv);
- /* Save the following registers to restore */
- reg1 = ioread32(ctl + 0x11000);
- reg2 = ioread32(ctl + 0xec50);
- reg3 = ioread32(ctl + 0xec54);
- wmb();
-
- agnx_write32(ctl, 0x11000, 0xcfdf);
- agnx_write32(ctl, 0xec50, 0x70);
- /* Restore the registers */
- agnx_write32(ctl, 0x11000, reg1);
- agnx_write32(ctl, 0xec50, reg2);
- agnx_write32(ctl, 0xec54, reg3);
- /* Disable Power Saving Control */
- disable_power_saving(priv);
- } while (0);
-
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0);
-} /* calibrate_oscillator */
-
-
-static void radio_channel_set(struct agnx_priv *priv, unsigned int channel)
-{
- void __iomem *ctl = priv->ctl;
- unsigned int freq = priv->band.channels[channel - 1].center_freq;
- u32 reg;
- AGNX_TRACE;
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
- /* Set SPI Clock to 50 Ns */
- reg = agnx_read32(ctl, AGNX_SPI_CFG);
- reg &= ~0xF;
- reg |= 0x1;
- agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
- /* Clear the Disable Tx interrupt bit in Interrupt Mask */
-/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
-/* reg &= ~IRQ_TX_DISABLE; */
-/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
-
- /* Band Selection */
- reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
-
- /* FIXME Set the SiLabs Chip Frequency */
- synth_freq_set(priv, channel);
-
- reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
- reg |= 0x80100030;
- agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
- reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
- reg |= 0x20009;
- agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1100);
-
- /* Load the MonitorGain Table */
- monitor_gain_table_init(priv);
-
- /* Load the TX Fir table */
- tx_fir_table_init(priv);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg |= 0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
- spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x22);
- udelay(80);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
-
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff);
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
- reg = agnx_read32(ctl, 0xec50);
- reg |= 0x4f;
- agnx_write32(ctl, 0xec50, reg);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
- agnx_write32(ctl, 0x11008, 0x1);
- agnx_write32(ctl, 0x1100c, 0x0);
- agnx_write32(ctl, 0x11008, 0x0);
- agnx_write32(ctl, 0xec50, 0xc);
-
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
- agnx_write32(ctl, 0x11010, 0x6e);
- agnx_write32(ctl, 0x11014, 0x6c);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-
- /* Calibrate the Antenna */
- /* antenna_calibrate(priv); */
- /* Calibrate the TxLocalOscillator */
- calibrate_oscillator(priv);
-
- reg = agnx_read32(ctl, AGNX_PM_PMCTL);
- reg &= ~0x8;
- agnx_write32(ctl, AGNX_PM_PMCTL, reg);
- agnx_write32(ctl, AGNX_GCR_GAININIT, 0xa);
- agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
-
- agnx_write32(ctl, 0x11018, 0xb);
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
-
- /* Write Frequency to Gain Control Channel */
- agnx_write32(ctl, AGNX_GCR_RXCHANEL, freq);
- /* Write 0x140000/Freq to 0x9c08 */
- reg = 0x140000/freq;
- agnx_write32(ctl, 0x9c08, reg);
-
- reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
- reg &= ~0x80100030;
- agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
-
- reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
- reg &= ~0x20009;
- reg |= 0x1;
- agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
- agnx_write32(ctl, AGNX_ACI_MODE, 0x0);
-
-/* FIXME According to Number of Chains: */
-
-/* 1. 1: */
-/* 1. Write 0x1203 to RF Chip 0 */
-/* 2. Write 0x1200 to RF Chips 1 +2 */
-/* 2. 2: */
-/* 1. Write 0x1203 to RF Chip 0 */
-/* 2. Write 0x1200 to RF Chip 2 */
-/* 3. Write 0x1201 to RF Chip 1 */
-/* 3. 3: */
-/* 1. Write 0x1203 to RF Chip 0 */
-/* 2. Write 0x1201 to RF Chip 1 + 2 */
-/* 4. 4: */
-/* 1. Write 0x1203 to RF Chip 0 + 1 */
-/* 2. Write 0x1200 to RF Chip 2 */
-
-/* 5. 6: */
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
- spi_rf_write(ctl, RF_CHIP2, 0x1201);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
- /* FIXME Set the Disable Tx interrupt bit in Interrupt Mask
- (Or 0x20000 to Interrupt Mask) */
-/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
-/* reg |= IRQ_TX_DISABLE; */
-/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
-
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
- /* Configure the Antenna */
- antenna_config(priv);
-
- /* Write 0x0 to Discovery Mode Enable detect G, B, A packet? */
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0);
-
- reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
- reg |= 0x80000000;
- agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
- /* enable radio on and the power LED */
- reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
- reg &= ~0x1;
- reg |= 0x2;
- agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
-
- reg = agnx_read32(ctl, AGNX_TXM_CTL);
- reg |= 0x1;
- agnx_write32(ctl, AGNX_TXM_CTL, reg);
-} /* radio_channel_set */
-
-static void base_band_filter_calibrate(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1001);
- agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x0);
- spi_rc_write(ctl, RF_CHIP0, 0x27);
- spi_rc_write(ctl, RF_CHIP1, 0x27);
- spi_rc_write(ctl, RF_CHIP2, 0x27);
- agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x1);
-}
-
-static void print_offset(struct agnx_priv *priv, u32 chain)
-{
- void __iomem *ctl = priv->ctl;
- u32 offset;
-
- iowrite32((chain), ctl + AGNX_ACI_SELCHAIN);
- udelay(10);
- offset = (ioread32(ctl + AGNX_ACI_OFFSET));
- printk(PFX "Chain is 0x%x, Offset is 0x%x\n", chain, offset);
-}
-
-void print_offsets(struct agnx_priv *priv)
-{
- print_offset(priv, 0);
- print_offset(priv, 4);
- print_offset(priv, 1);
- print_offset(priv, 5);
- print_offset(priv, 2);
- print_offset(priv, 6);
-}
-
-
-struct chains {
- u32 cali; /* calibrate value*/
-
-#define NEED_CALIBRATE 0
-#define SUCCESS_CALIBRATE 1
- int status;
-};
-
-static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
- unsigned int num)
-{
- void __iomem *ctl = priv->ctl;
- u32 calibra = chains[num].cali;
-
- if (num < 3)
- calibra |= 0x1400;
- else
- calibra |= 0x1500;
-
- switch (num) {
- case 0:
- case 4:
- spi_rf_write(ctl, RF_CHIP0, calibra);
- break;
- case 1:
- case 5:
- spi_rf_write(ctl, RF_CHIP1, calibra);
- break;
- case 2:
- case 6:
- spi_rf_write(ctl, RF_CHIP2, calibra);
- break;
- default:
- BUG();
- }
-} /* chain_calibrate */
-
-static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
- unsigned int num)
-{
- void __iomem *ctl = priv->ctl;
- u32 offset;
-
- iowrite32((num), ctl + AGNX_ACI_SELCHAIN);
- /* FIXME */
- udelay(10);
- offset = (ioread32(ctl + AGNX_ACI_OFFSET));
-
- if (offset < 0xf) {
- chains[num].status = SUCCESS_CALIBRATE;
- return;
- }
-
- if (num == 0 || num == 1 || num == 2) {
- if (0 == chains[num].cali)
- chains[num].cali = 0xff;
- else
- chains[num].cali--;
- } else
- chains[num].cali++;
-
- chains[num].status = NEED_CALIBRATE;
-}
-
-static inline void calibra_delay(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- unsigned int i = 100;
-
- wmb();
- while (--i) {
- reg = (ioread32(ctl + AGNX_ACI_STATUS));
- if (reg == 0x4000)
- break;
- udelay(10);
- }
- if (!i)
- printk(PFX "calibration failed\n");
-}
-
-void do_calibration(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- struct chains chains[7];
- unsigned int i, j;
- AGNX_TRACE;
-
- for (i = 0; i < 7; i++) {
- if (i == 3)
- continue;
-
- chains[i].cali = 0x7f;
- chains[i].status = NEED_CALIBRATE;
- }
-
- /* FIXME 0x300 is a magic number */
- for (j = 0; j < 0x300; j++) {
- if (chains[0].status == SUCCESS_CALIBRATE &&
- chains[1].status == SUCCESS_CALIBRATE &&
- chains[2].status == SUCCESS_CALIBRATE &&
- chains[4].status == SUCCESS_CALIBRATE &&
- chains[5].status == SUCCESS_CALIBRATE &&
- chains[6].status == SUCCESS_CALIBRATE)
- break;
-
- /* Attention, there is no chain 3 */
- for (i = 0; i < 7; i++) {
- if (i == 3)
- continue;
- if (chains[i].status == NEED_CALIBRATE)
- chain_calibrate(priv, chains, i);
- }
- /* Write 0x1 to Calibration Measure */
- iowrite32((0x1), ctl + AGNX_ACI_MEASURE);
- calibra_delay(priv);
-
- for (i = 0; i < 7; i++) {
- if (i == 3)
- continue;
-
- get_calibrete_value(priv, chains, i);
- }
- }
- printk(PFX "Clibrate times is %d\n", j);
- print_offsets(priv);
-} /* do_calibration */
-
-void antenna_calibrate(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
- AGNX_TRACE;
-
- agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
- agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
-
- agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
- agnx_write32(ctl, AGNX_GCR_BOACT, 0x24);
- agnx_write32(ctl, AGNX_GCR_BOINACT, 0x24);
- agnx_write32(ctl, AGNX_GCR_BODYNA, 0x20);
- agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
- agnx_write32(ctl, AGNX_GCR_THD0AL, 0x64);
- agnx_write32(ctl, AGNX_GCR_THD0B, 0x46);
- agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
- agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x64);
- agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x30);
-
- spi_rc_write(ctl, RF_CHIP0, 0x20);
- /* Fixme */
- udelay(80);
- /* 1. Should read 0x0 */
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (0x0 != reg)
- printk(KERN_WARNING PFX "Unmatched rf chips result\n");
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
-
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
- spi_rc_write(ctl, RF_CHIP0, 0x22);
- udelay(80);
- reg = agnx_read32(ctl, AGNX_SPI_RLSW);
- if (0x0 != reg)
- printk(KERN_WARNING PFX "Unmatched rf chips result\n");
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
-
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
- agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
- reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
- reg |= 0x1c000032;
- agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
- reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
- reg |= 0x0003f07;
- agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
- reg = agnx_read32(ctl, 0xec50);
- reg |= 0x40;
- agnx_write32(ctl, 0xec50, reg);
-
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff8);
- agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
- agnx_write32(ctl, AGNX_GCR_CHAINNUM, 0x6);
- agnx_write32(ctl, 0x19874, 0x0);
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
-
- /* Calibrate the BaseBandFilter */
- base_band_filter_calibrate(priv);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
-
- agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
- agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
- agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
- agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
-
- agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
- agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
-
- /* Measure Calibration */
- agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
- calibra_delay(priv);
-
- /* do calibration */
- do_calibration(priv);
-
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
- agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
-
- agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
- disable_receiver(priv);
-} /* antenna_calibrate */
-
-void __antenna_calibrate(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- /* Calibrate the BaseBandFilter */
- /* base_band_filter_calibrate(priv); */
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
-
-
- agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
- agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
- agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
-
- agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
-
- agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
- agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
-
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
- spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
- /* Measure Calibration */
- agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
- calibra_delay(priv);
- do_calibration(priv);
- agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
- agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
- agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-
- agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
- reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
- reg &= 0xf;
- agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
-
-
- agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
-
- /* Write 0x3 Gain Control Discovery Mode */
- enable_receiver(priv);
-}
-
-int agnx_set_channel(struct agnx_priv *priv, unsigned int channel)
-{
- AGNX_TRACE;
-
- printk(KERN_ERR PFX "Channel is %d %s\n", channel, __func__);
- radio_channel_set(priv, channel);
- return 0;
-}
diff --git a/drivers/staging/agnx/sta.c b/drivers/staging/agnx/sta.c
deleted file mode 100644
index 3e7db5e2811a..000000000000
--- a/drivers/staging/agnx/sta.c
+++ /dev/null
@@ -1,218 +0,0 @@
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include "phy.h"
-#include "sta.h"
-#include "debug.h"
-
-void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
-{
- void __iomem *ctl = priv->ctl;
-
- reglo &= 0xFFFF;
- reglo |= 0x30000000;
- reglo |= 0x40000000; /* Set status busy */
- reglo |= sta_id << 16;
-
- iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
- iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
- iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-
- reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
- reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
- printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
-}
-
-void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id)
-{
- void __iomem *ctl = priv->ctl;
- u32 reghi, reglo;
-
- if (!is_valid_ether_addr(mac_addr))
- printk(KERN_WARNING PFX "Update hash table: Invalid hwaddr!\n");
-
- reghi = mac_addr[0] << 24 | mac_addr[1] << 16 | mac_addr[2] << 8 | mac_addr[3];
- reglo = mac_addr[4] << 8 | mac_addr[5];
- reglo |= 0x10000000; /* Set hash commmand */
- reglo |= 0x40000000; /* Set status busy */
- reglo |= sta_id << 16;
-
- iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
- iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
- iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-
- reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
- if (!(reglo & 0x80000000))
- printk(KERN_WARNING PFX "Update hash table failed\n");
-}
-
-void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
-{
- void __iomem *ctl = priv->ctl;
-
- reglo &= 0xFFFF;
- reglo |= 0x20000000;
- reglo |= 0x40000000; /* Set status busy */
- reglo |= sta_id << 16;
-
- iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
- iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
- iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
- reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
-
- reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
- printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
-
-}
-
-void hash_dump(struct agnx_priv *priv, u8 sta_id)
-{
- void __iomem *ctl = priv->ctl;
- u32 reghi, reglo;
-
- reglo = 0x40000000; /* status bit */
- iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
- iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
-
- udelay(80);
-
- reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
- reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
- printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
- reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
- printk(PFX "hash flag is : %.8x\n", reghi);
- reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_MST);
- reglo = ioread32(ctl + AGNX_RXM_HASH_DUMP_LST);
- printk(PFX "hash dump mst lst: %.8x%.8x\n", reghi, reglo);
- reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_DATA);
- printk(PFX "hash dump data: %.8x\n", reghi);
-}
-
-void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
-{
- void __iomem *ctl = priv->ctl;
- memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
- sizeof(*power));
-}
-
-inline void
-set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
-{
- void __iomem *ctl = priv->ctl;
- /* FIXME 2. Write Template to offset + station number */
- memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
- power, sizeof(*power));
-}
-
-
-void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
- unsigned int sta_idx, unsigned int wq_idx)
-{
- void __iomem *data = priv->data;
- memcpy_fromio(tx_wq, data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
- sizeof(*tx_wq) * wq_idx, sizeof(*tx_wq));
-
-}
-
-inline void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
- unsigned int sta_idx, unsigned int wq_idx)
-{
- void __iomem *data = priv->data;
- memcpy_toio(data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
- sizeof(*tx_wq) * wq_idx, tx_wq, sizeof(*tx_wq));
-}
-
-
-void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
-{
- void __iomem *data = priv->data;
-
- memcpy_fromio(sta, data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
- sizeof(*sta));
-}
-
-inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
-{
- void __iomem *data = priv->data;
-
- memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
- sta, sizeof(*sta));
-}
-
-/* FIXME */
-void sta_power_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
- struct agnx_sta_power power;
- u32 reg;
- AGNX_TRACE;
-
- memset(&power, 0, sizeof(power));
- reg = agnx_set_bits(EDCF, EDCF_SHIFT, 0x1);
- power.reg = cpu_to_le32(reg);
- set_sta_power(priv, &power, sta_idx);
- udelay(40);
-} /* add_power_template */
-
-
-/* @num: The #number of station that is visible to the card */
-static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
- struct agnx_sta_tx_wq tx_wq;
- u32 reg;
- unsigned int i;
-
- memset(&tx_wq, 0, sizeof(tx_wq));
-
- reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
- reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
-/* reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */
- tx_wq.reg2 |= cpu_to_le32(reg);
-
- /* Suppose all 8 traffic class are used */
- for (i = 0; i < STA_TX_WQ_NUM; i++)
- set_sta_tx_wq(priv, &tx_wq, sta_idx, i);
-} /* sta_tx_workqueue_init */
-
-
-static void sta_traffic_init(struct agnx_sta_traffic *traffic)
-{
- u32 reg;
- memset(traffic, 0, sizeof(*traffic));
-
- reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
- reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
-/* reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */
- traffic->reg0 = cpu_to_le32(reg);
-
- /* 3. setting RX Sequence Number to 4095 */
- reg = agnx_set_bits(RX_SEQUENCE_NUM, RX_SEQUENCE_NUM_SHIFT, 4095);
- traffic->reg1 = cpu_to_le32(reg);
-}
-
-
-/* @num: The #number of station that is visible to the card */
-void sta_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
- /* FIXME the length of sta is 256 bytes Is that
- * dangerous to stack overflow? */
- struct agnx_sta sta;
- u32 reg;
- int i;
-
- memset(&sta, 0, sizeof(sta));
- /* Set valid to 1 */
- reg = agnx_set_bits(STATION_VALID, STATION_VALID_SHIFT, 1);
- /* Set Enable Concatenation to 0 (?) */
- reg |= agnx_set_bits(ENABLE_CONCATENATION, ENABLE_CONCATENATION_SHIFT, 0);
- /* Set Enable Decompression to 0 (?) */
- reg |= agnx_set_bits(ENABLE_DECOMPRESSION, ENABLE_DECOMPRESSION_SHIFT, 0);
- sta.reg = cpu_to_le32(reg);
-
- /* Initialize each of the Traffic Class Structures by: */
- for (i = 0; i < 8; i++)
- sta_traffic_init(sta.traffic + i);
-
- set_sta(priv, &sta, sta_idx);
- sta_tx_workqueue_init(priv, sta_idx);
-} /* sta_descriptor_init */
-
-
diff --git a/drivers/staging/agnx/sta.h b/drivers/staging/agnx/sta.h
deleted file mode 100644
index fd504e3f3870..000000000000
--- a/drivers/staging/agnx/sta.h
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef AGNX_STA_H_
-#define AGNX_STA_H_
-
-#define STA_TX_WQ_NUM 8 /* The number of TX workqueue one STA has */
-
-struct agnx_hash_cmd {
- __be32 cmdhi;
-#define MACLO 0xFFFF0000
-#define MACLO_SHIFT 16
-#define STA_ID 0x0000FFF0
-#define STA_ID_SHIFT 4
-#define CMD 0x0000000C
-#define CMD_SHIFT 2
-#define STATUS 0x00000002
-#define STATUS_SHIFT 1
-#define PASS 0x00000001
-#define PASS_SHIFT 1
- __be32 cmdlo;
-} __attribute__((__packed__));
-
-
-/*
- * Station Power Template
- * FIXME Just for agn100 yet
- */
-struct agnx_sta_power {
- __le32 reg;
-#define SIGNAL 0x000000FF /* signal */
-#define SIGNAL_SHIFT 0
-#define RATE 0x00000F00
-#define RATE_SHIFT 8
-#define TIFS 0x00001000
-#define TIFS_SHIFT 12
-#define EDCF 0x00002000
-#define EDCF_SHIFT 13
-#define CHANNEL_BOND 0x00004000
-#define CHANNEL_BOND_SHIFT 14
-#define PHY_MODE 0x00038000
-#define PHY_MODE_SHIFT 15
-#define POWER_LEVEL 0x007C0000
-#define POWER_LEVEL_SHIFT 18
-#define NUM_TRANSMITTERS 0x00800000
-#define NUM_TRANSMITTERS_SHIFT 23
-} __attribute__((__packed__));
-
-/*
- * TX Workqueue Descriptor
- */
-struct agnx_sta_tx_wq {
- __le32 reg0;
-#define HEAD_POINTER_LOW 0xFF000000 /* Head pointer low */
-#define HEAD_POINTER_LOW_SHIFT 24
-#define TAIL_POINTER 0x00FFFFFF /* Tail pointer */
-#define TAIL_POINTER_SHIFT 0
-
- __le32 reg3;
-#define ACK_POINTER_LOW 0xFFFF0000 /* ACK pointer low */
-#define ACK_POINTER_LOW_SHIFT 16
-#define HEAD_POINTER_HIGH 0x0000FFFF /* Head pointer high */
-#define HEAD_POINTER_HIGH_SHIFT 0
-
- __le32 reg1;
-/* ACK timeout tail packet count */
-#define ACK_TIMOUT_TAIL_PACK_CNT 0xFFF00000
-#define ACK_TIMOUT_TAIL_PACK_CNT_SHIFT 20
-/* Head timeout tail packet count */
-#define HEAD_TIMOUT_TAIL_PACK_CNT 0x000FFF00
-#define HEAD_TIMOUT_TAIL_PACK_CNT_SHIFT 8
-#define ACK_POINTER_HIGH 0x000000FF /* ACK pointer high */
-#define ACK_POINTER_HIGH_SHIFT 0
-
- __le32 reg2;
-#define WORK_QUEUE_VALID 0x80000000 /* valid */
-#define WORK_QUEUE_VALID_SHIFT 31
-#define WORK_QUEUE_ACK_TYPE 0x40000000 /* ACK type */
-#define WORK_QUEUE_ACK_TYPE_SHIFT 30
-/* Head timeout window limit fragmentation count */
-#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT 0x3FFF0000
-#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT_SHIFT 16
-/* Head timeout window limit byte count */
-#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT 0x0000FFFF
-#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT_SHIFT 0
-} __attribute__((__packed__));
-
-
-/*
- * Traffic Class Structure
- */
-struct agnx_sta_traffic {
- __le32 reg0;
-#define ACK_TIMOUT_CNT 0xFF800000 /* ACK Timeout Counts */
-#define ACK_TIMOUT_CNT_SHIFT 23
-#define TRAFFIC_ACK_TYPE 0x00600000 /* ACK Type */
-#define TRAFFIC_ACK_TYPE_SHIFT 21
-#define NEW_PACKET 0x00100000 /* New Packet */
-#define NEW_PACKET_SHIFT 20
-#define TRAFFIC_VALID 0x00080000 /* Valid */
-#define TRAFFIC_VALID_SHIFT 19
-#define RX_HDR_DESC_POINTER 0x0007FFFF /* RX Header Descripter pointer */
-#define RX_HDR_DESC_POINTER_SHIFT 0
-
- __le32 reg1;
-#define RX_PACKET_TIMESTAMP 0xFFFF0000 /* RX Packet Timestamp */
-#define RX_PACKET_TIMESTAMP_SHIFT 16
-#define TRAFFIC_RESERVED 0x0000E000 /* Reserved */
-#define TRAFFIC_RESERVED_SHIFT 13
-#define SV 0x00001000 /* sv */
-#define SV_SHIFT 12
-#define RX_SEQUENCE_NUM 0x00000FFF /* RX Sequence Number */
-#define RX_SEQUENCE_NUM_SHIFT 0
-
- __le32 tx_replay_cnt_low; /* TX Replay Counter Low */
-
- __le16 tx_replay_cnt_high; /* TX Replay Counter High */
- __le16 rx_replay_cnt_high; /* RX Replay Counter High */
-
- __be32 rx_replay_cnt_low; /* RX Replay Counter Low */
-} __attribute__((__packed__));
-
-/*
- * Station Descriptors
- */
-struct agnx_sta {
- __le32 tx_session_keys[4]; /* Transmit Session Key (0-3) */
- __le32 rx_session_keys[4]; /* Receive Session Key (0-3) */
-
- __le32 reg;
-#define ID_1 0xC0000000 /* id 1 */
-#define ID_1_SHIFT 30
-#define ID_0 0x30000000 /* id 0 */
-#define ID_0_SHIFT 28
-#define ENABLE_CONCATENATION 0x0FF00000 /* Enable concatenation */
-#define ENABLE_CONCATENATION_SHIFT 20
-#define ENABLE_DECOMPRESSION 0x000FF000 /* Enable decompression */
-#define ENABLE_DECOMPRESSION_SHIFT 12
-#define STA_RESERVED 0x00000C00 /* Reserved */
-#define STA_RESERVED_SHIFT 10
-#define EAP 0x00000200 /* EAP */
-#define EAP_SHIFT 9
-#define ED_NULL 0x00000100 /* ED NULL */
-#define ED_NULL_SHIFT 8
-#define ENCRYPTION_POLICY 0x000000E0 /* Encryption Policy */
-#define ENCRYPTION_POLICY_SHIFT 5
-#define DEFINED_KEY_ID 0x00000018 /* Defined Key ID */
-#define DEFINED_KEY_ID_SHIFT 3
-#define FIXED_KEY 0x00000004 /* Fixed Key */
-#define FIXED_KEY_SHIFT 2
-#define KEY_VALID 0x00000002 /* Key Valid */
-#define KEY_VALID_SHIFT 1
-#define STATION_VALID 0x00000001 /* Station Valid */
-#define STATION_VALID_SHIFT 0
-
- __le32 tx_aes_blks_unicast; /* TX AES Blks Unicast */
- __le32 rx_aes_blks_unicast; /* RX AES Blks Unicast */
-
- __le16 aes_format_err_unicast_cnt; /* AES Format Error Unicast Counts */
- __le16 aes_replay_unicast; /* AES Replay Unicast */
-
- __le16 aes_decrypt_err_unicast; /* AES Decrypt Error Unicast */
- __le16 aes_decrypt_err_default; /* AES Decrypt Error default */
-
- __le16 single_retry_packets; /* Single Retry Packets */
- __le16 failed_tx_packets; /* Failed Tx Packets */
-
- __le16 muti_retry_packets; /* Multiple Retry Packets */
- __le16 ack_timeouts; /* ACK Timeouts */
-
- __le16 frag_tx_cnt; /* Fragment TX Counts */
- __le16 rts_brq_sent; /* RTS Brq Sent */
-
- __le16 tx_packets; /* TX Packets */
- __le16 cts_back_timeout; /* CTS Back Timeout */
-
- __le32 phy_stats_high; /* PHY Stats High */
- __le32 phy_stats_low; /* PHY Stats Low */
-
- struct agnx_sta_traffic traffic[8]; /* Traffic Class Structure (8) */
-
- __le16 traffic_class0_frag_success; /* Traffic Class 0 Fragment Success */
- __le16 traffic_class1_frag_success; /* Traffic Class 1 Fragment Success */
- __le16 traffic_class2_frag_success; /* Traffic Class 2 Fragment Success */
- __le16 traffic_class3_frag_success; /* Traffic Class 3 Fragment Success */
- __le16 traffic_class4_frag_success; /* Traffic Class 4 Fragment Success */
- __le16 traffic_class5_frag_success; /* Traffic Class 5 Fragment Success */
- __le16 traffic_class6_frag_success; /* Traffic Class 6 Fragment Success */
- __le16 traffic_class7_frag_success; /* Traffic Class 7 Fragment Success */
-
- __le16 num_frag_non_prime_rates; /* number of Fragments for non-prime rates */
- __le16 ack_timeout_non_prime_rates; /* ACK Timeout for non-prime rates */
-
-} __attribute__((__packed__));
-
-
-struct agnx_beacon_hdr {
- struct agnx_sta_power power; /* Tx Station Power Template */
- u8 phy_hdr[6]; /* PHY Hdr */
- u8 frame_len_lo; /* Frame Length Lo */
- u8 frame_len_hi; /* Frame Length Hi */
- u8 mac_hdr[24]; /* MAC Header */
- /* FIXME */
- /* 802.11(abg) beacon */
-} __attribute__((__packed__));
-
-void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id);
-void hash_dump(struct agnx_priv *priv, u8 sta_id);
-void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
-void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
-
-void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx);
-void set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power,
- unsigned int sta_idx);
-void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
- unsigned int sta_idx, unsigned int wq_idx);
-void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
- unsigned int sta_idx, unsigned int wq_idx);
-void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
-void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
-
-void sta_power_init(struct agnx_priv *priv, unsigned int num);
-void sta_init(struct agnx_priv *priv, unsigned int num);
-
-#endif /* AGNX_STA_H_ */
diff --git a/drivers/staging/agnx/table.c b/drivers/staging/agnx/table.c
deleted file mode 100644
index b52fef9db0e3..000000000000
--- a/drivers/staging/agnx/table.c
+++ /dev/null
@@ -1,168 +0,0 @@
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-
-static const u32
-tx_fir_table[] = { 0x19, 0x5d, 0xce, 0x151, 0x1c3, 0x1ff, 0x1ea, 0x17c, 0xcf,
- 0x19, 0x38e, 0x350, 0x362, 0x3ad, 0x5, 0x44, 0x59, 0x49,
- 0x21, 0x3f7, 0x3e0, 0x3e3, 0x3f3, 0x0 };
-
-void tx_fir_table_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(tx_fir_table); i++)
- iowrite32(tx_fir_table[i], ctl + AGNX_FIR_BASE + i*4);
-} /* fir_table_setup */
-
-
-static const u32
-gain_table[] = { 0x8, 0x8, 0xf, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b,
- 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4b, 0x4f,
- 0x53, 0x57, 0x5b, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
- 0x5f, 0x5f, 0x5f, 0x5f };
-
-void gain_table_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(gain_table); i++) {
- iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4);
- iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4 + 0x80);
- }
-} /* gain_table_init */
-
-void monitor_gain_table_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- unsigned int i;
-
- for (i = 0; i < 0x44; i += 4) {
- iowrite32(0x61, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0x61, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0x44; i < 0x64; i += 4) {
- iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0x64; i < 0x94; i += 4) {
- iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0x94; i < 0xdc; i += 4) {
- iowrite32(0x87, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0x87, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0xdc; i < 0x148; i += 4) {
- iowrite32(0x95, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0x95, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0x148; i < 0x1e8; i += 4) {
- iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
- for (i = 0x1e8; i <= 0x1fc; i += 4) {
- iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + i);
- iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + 0x200 + i);
- }
-} /* monitor_gain_table_init */
-
-
-void routing_table_init(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- unsigned int type, subtype;
- u32 reg;
-
- disable_receiver(priv);
-
- for (type = 0; type < 0x3; type++) {
- for (subtype = 0; subtype < 0x10; subtype++) {
- /* 1. Set Routing table to R/W and to Return status on Read */
- reg = (type << ROUTAB_TYPE_SHIFT) |
- (subtype << ROUTAB_SUBTYPE_SHIFT);
- reg |= (1 << ROUTAB_RW_SHIFT) | (1 << ROUTAB_STATUS_SHIFT);
- if (type == ROUTAB_TYPE_DATA) {
- /* NULL goes to RFP */
- if (subtype == ROUTAB_SUBTYPE_NULL)
-/* reg |= ROUTAB_ROUTE_RFP; */
- reg |= ROUTAB_ROUTE_CPU;
- /* QOS NULL goes to CPU */
- else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
- reg |= ROUTAB_ROUTE_CPU;
- /* All Data and QOS data subtypes go to Encryption */
- else if ((subtype == ROUTAB_SUBTYPE_DATA) ||
- (subtype == ROUTAB_SUBTYPE_DATAACK) ||
- (subtype == ROUTAB_SUBTYPE_DATAPOLL) ||
- (subtype == ROUTAB_SUBTYPE_DATAPOLLACK) ||
- (subtype == ROUTAB_SUBTYPE_QOSDATA) ||
- (subtype == ROUTAB_SUBTYPE_QOSDATAACK) ||
- (subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
- (subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
- reg |= ROUTAB_ROUTE_ENCRY;
-/* reg |= ROUTAB_ROUTE_CPU; */
- /*Drop NULL and QOS NULL ack, poll and poll ack*/
- else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
- (subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
- (subtype == ROUTAB_SUBTYPE_NULLPOLL) ||
- (subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
- (subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
- (subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
-/* reg |= ROUTAB_ROUTE_DROP; */
- reg |= ROUTAB_ROUTE_CPU;
- } else {
- reg |= (ROUTAB_ROUTE_CPU);
- }
- iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
- /* Check to verify that the status bit cleared */
- routing_table_delay();
- }
- }
- enable_receiver(priv);
-} /* routing_table_init */
-
-void tx_engine_lookup_tbl_init(struct agnx_priv *priv)
-{
- void __iomem *data = priv->data;
- unsigned int i;
-
- for (i = 0; i <= 28; i += 4)
- iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
- for (i = 32; i <= 120; i += 8) {
- iowrite32(0x1e58, data + AGNX_ENGINE_LOOKUP_TBL + i);
- iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
- }
-
- for (i = 128; i <= 156; i += 4)
- iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
- for (i = 160; i <= 248; i += 8) {
- iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i);
- iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
- }
-
- for (i = 256; i <= 284; i += 4)
- iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
- for (i = 288; i <= 376; i += 8) {
- iowrite32(0x1a58, data + AGNX_ENGINE_LOOKUP_TBL + i);
- iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
- }
-
- for (i = 512; i <= 540; i += 4)
- iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
- for (i = 544; i <= 632; i += 8) {
- iowrite32(0x2058, data + AGNX_ENGINE_LOOKUP_TBL + i);
- iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
- }
-
- for (i = 640; i <= 668; i += 4)
- iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i);
- for (i = 672; i <= 764; i += 8) {
- iowrite32(0x2258, data + AGNX_ENGINE_LOOKUP_TBL + i);
- iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
- }
-}
-
diff --git a/drivers/staging/agnx/table.h b/drivers/staging/agnx/table.h
deleted file mode 100644
index f0626b5ee86b..000000000000
--- a/drivers/staging/agnx/table.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef AGNX_TABLE_H_
-#define AGNX_TABLE_H_
-
-void tx_fir_table_init(struct agnx_priv *priv);
-void gain_table_init(struct agnx_priv *priv);
-void monitor_gain_table_init(struct agnx_priv *priv);
-void routing_table_init(struct agnx_priv *priv);
-void tx_engine_lookup_tbl_init(struct agnx_priv *priv);
-
-#endif /* AGNX_TABLE_H_ */
diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c
deleted file mode 100644
index 42db41070cf0..000000000000
--- a/drivers/staging/agnx/xmit.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-
-unsigned int rx_frame_cnt;
-/* unsigned int local_tx_sent_cnt = 0; */
-
-static inline void disable_rx_engine(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- iowrite32(0x100, ctl + AGNX_CIR_RXCTL);
- /* Wait for RX Control to have the Disable Rx Interrupt (0x100) set */
- ioread32(ctl + AGNX_CIR_RXCTL);
-}
-
-static inline void enable_rx_engine(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- iowrite32(0x80, ctl + AGNX_CIR_RXCTL);
- ioread32(ctl + AGNX_CIR_RXCTL);
-}
-
-inline void disable_rx_interrupt(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- disable_rx_engine(priv);
- reg = ioread32(ctl + AGNX_CIR_RXCFG);
- reg &= ~0x20;
- iowrite32(reg, ctl + AGNX_CIR_RXCFG);
- ioread32(ctl + AGNX_CIR_RXCFG);
-}
-
-inline void enable_rx_interrupt(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- reg = ioread32(ctl + AGNX_CIR_RXCFG);
- reg |= 0x20;
- iowrite32(reg, ctl + AGNX_CIR_RXCFG);
- ioread32(ctl + AGNX_CIR_RXCFG);
- enable_rx_engine(priv);
-}
-
-static inline void rx_desc_init(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_desc *desc = priv->rx.desc + idx;
- struct agnx_info *info = priv->rx.info + idx;
-
- memset(info, 0, sizeof(*info));
-
- info->dma_len = IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct agnx_hdr);
- info->skb = dev_alloc_skb(info->dma_len);
- if (info->skb == NULL)
- agnx_bug("refill err");
-
- info->mapping = pci_map_single(priv->pdev, skb_tail_pointer(info->skb),
- info->dma_len, PCI_DMA_FROMDEVICE);
- memset(desc, 0, sizeof(*desc));
- desc->dma_addr = cpu_to_be32(info->mapping);
- /* Set the owner to the card */
- desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
-}
-
-static inline void rx_desc_reinit(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_info *info = priv->rx.info + idx;
-
- /* Cause ieee80211 will free the skb buffer, so we needn't to free it again?! */
- pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
- rx_desc_init(priv, idx);
-}
-
-static inline void rx_desc_reusing(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_desc *desc = priv->rx.desc + idx;
- struct agnx_info *info = priv->rx.info + idx;
-
- memset(desc, 0, sizeof(*desc));
- desc->dma_addr = cpu_to_be32(info->mapping);
- /* Set the owner to the card */
- desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
-}
-
-static void rx_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_desc *desc = priv->rx.desc + idx;
- struct agnx_info *info = priv->rx.info + idx;
-
- BUG_ON(!desc || !info);
- if (info->mapping)
- pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
- if (info->skb)
- dev_kfree_skb(info->skb);
- memset(info, 0, sizeof(*info));
- memset(desc, 0, sizeof(*desc));
-}
-
-static inline void __tx_desc_free(struct agnx_priv *priv,
- struct agnx_desc *desc, struct agnx_info *info)
-{
- BUG_ON(!desc || !info);
- /* TODO make sure mapping, skb and len are consistency */
- if (info->mapping)
- pci_unmap_single(priv->pdev, info->mapping,
- info->dma_len, PCI_DMA_TODEVICE);
- if (info->type == PACKET)
- dev_kfree_skb(info->skb);
-
- memset(info, 0, sizeof(*info));
- memset(desc, 0, sizeof(*desc));
-}
-
-static void txm_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_desc *desc = priv->txm.desc + idx;
- struct agnx_info *info = priv->txm.info + idx;
-
- __tx_desc_free(priv, desc, info);
-}
-
-static void txd_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
- struct agnx_desc *desc = priv->txd.desc + idx;
- struct agnx_info *info = priv->txd.info + idx;
-
- __tx_desc_free(priv, desc, info);
-}
-
-int fill_rings(struct agnx_priv *priv)
-{
- void __iomem *ctl = priv->ctl;
- unsigned int i;
- u32 reg;
- AGNX_TRACE;
-
- priv->txd.idx_sent = priv->txm.idx_sent = 0;
- priv->rx.idx = priv->txm.idx = priv->txd.idx = 0;
-
- for (i = 0; i < priv->rx.size; i++)
- rx_desc_init(priv, i);
- for (i = 0; i < priv->txm.size; i++) {
- memset(priv->txm.desc + i, 0, sizeof(struct agnx_desc));
- memset(priv->txm.info + i, 0, sizeof(struct agnx_info));
- }
- for (i = 0; i < priv->txd.size; i++) {
- memset(priv->txd.desc + i, 0, sizeof(struct agnx_desc));
- memset(priv->txd.info + i, 0, sizeof(struct agnx_info));
- }
-
- /* FIXME Set the card RX TXM and TXD address */
- agnx_write32(ctl, AGNX_CIR_RXCMSTART, priv->rx.dma);
- agnx_write32(ctl, AGNX_CIR_RXCMEND, priv->txm.dma);
-
- agnx_write32(ctl, AGNX_CIR_TXMSTART, priv->txm.dma);
- agnx_write32(ctl, AGNX_CIR_TXMEND, priv->txd.dma);
-
- agnx_write32(ctl, AGNX_CIR_TXDSTART, priv->txd.dma);
- agnx_write32(ctl, AGNX_CIR_TXDEND, priv->txd.dma +
- sizeof(struct agnx_desc) * priv->txd.size);
-
- /* FIXME Relinquish control of rings to card */
- reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
- reg &= ~0x800;
- agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
- return 0;
-} /* fill_rings */
-
-void unfill_rings(struct agnx_priv *priv)
-{
- unsigned long flags;
- unsigned int i;
- AGNX_TRACE;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- for (i = 0; i < priv->rx.size; i++)
- rx_desc_free(priv, i);
- for (i = 0; i < priv->txm.size; i++)
- txm_desc_free(priv, i);
- for (i = 0; i < priv->txd.size; i++)
- txd_desc_free(priv, i);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Extract the bitrate out of a CCK PLCP header.
- copy from bcm43xx driver */
-static inline u8 agnx_plcp_get_bitrate_cck(__be32 *phyhdr_11b)
-{
- /* FIXME */
- switch (*(u8 *)phyhdr_11b) {
- case 0x0A:
- return 0;
- case 0x14:
- return 1;
- case 0x37:
- return 2;
- case 0x6E:
- return 3;
- }
- agnx_bug("Wrong plcp rate");
- return 0;
-}
-
-/* FIXME */
-static inline u8 agnx_plcp_get_bitrate_ofdm(__be32 *phyhdr_11g)
-{
- u8 rate = *(u8 *)phyhdr_11g & 0xF;
-
- printk(PFX "G mode rate is 0x%x\n", rate);
- return rate;
-}
-
-/* FIXME */
-static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
- struct ieee80211_rx_status *stat)
-{
- void __iomem *ctl = priv->ctl;
- u8 *rssi;
- u32 noise;
- /* FIXME just for test */
- int snr = 40; /* signal-to-noise ratio */
-
- memset(stat, 0, sizeof(*stat));
- /* RSSI */
- rssi = (u8 *)&hdr->phy_stats_lo;
-/* stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; */
- /* Noise */
- noise = ioread32(ctl + AGNX_GCR_NOISE0);
- noise += ioread32(ctl + AGNX_GCR_NOISE1);
- noise += ioread32(ctl + AGNX_GCR_NOISE2);
- stat->noise = noise / 3;
- /* Signal quality */
-/* snr = stat->ssi - stat->noise; */
- if (snr >= 0 && snr < 40)
- stat->signal = 5 * snr / 2;
- else if (snr >= 40)
- stat->signal = 100;
- else
- stat->signal = 0;
-
-
- if (hdr->_11b0 && !hdr->_11g0) {
- stat->rate_idx = agnx_plcp_get_bitrate_cck(&hdr->_11b0);
- } else if (!hdr->_11b0 && hdr->_11g0) {
- printk(PFX "RX: Found G mode packet\n");
- stat->rate_idx = agnx_plcp_get_bitrate_ofdm(&hdr->_11g0);
- } else
- agnx_bug("Unknown packets type");
-
-
- stat->band = IEEE80211_BAND_2GHZ;
- stat->freq = agnx_channels[priv->channel - 1].center_freq;
-/* stat->antenna = 3;
- stat->mactime = be32_to_cpu(hdr->time_stamp);
- stat->channel = priv->channel; */
-}
-
-static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
- struct sk_buff *skb)
-{
- u16 fctl;
- unsigned int hdrlen;
-
- fctl = le16_to_cpu(ieeehdr->frame_control);
- hdrlen = ieee80211_hdrlen(fctl);
- /* FIXME */
- if (hdrlen < (2+2+6)/*minimum hdr*/ ||
- hdrlen > sizeof(struct ieee80211_mgmt)) {
- printk(KERN_ERR PFX "hdr len is %d\n", hdrlen);
- agnx_bug("Wrong ieee80211 hdr detected");
- }
- skb_push(skb, hdrlen);
- memcpy(skb->data, ieeehdr, hdrlen);
-} /* combine_hdr_frag */
-
-static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
- unsigned packet_len)
-{
- if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1) {
- printk(PFX "RX: CRC check fail\n");
- goto drop;
- }
- if (packet_len > 2048) {
- printk(PFX "RX: Too long packet detected\n");
- goto drop;
- }
-
- /* FIXME Just usable for Promious Mode, for Manage mode exclude FCS */
-/* if (packet_len - sizeof(*agnxhdr) < FCS_LEN) { */
-/* printk(PFX "RX: Too short packet detected\n"); */
-/* goto drop; */
-/* } */
- return 0;
-drop:
- priv->stats.dot11FCSErrorCount++;
- return -1;
-}
-
-void handle_rx_irq(struct agnx_priv *priv)
-{
- struct ieee80211_rx_status status;
- unsigned int len;
-/* AGNX_TRACE; */
-
- do {
- struct agnx_desc *desc;
- u32 frag;
- struct agnx_info *info;
- struct agnx_hdr *hdr;
- struct sk_buff *skb;
- unsigned int i = priv->rx.idx % priv->rx.size;
-
- desc = priv->rx.desc + i;
- frag = be32_to_cpu(desc->frag);
- if (frag & OWNER)
- break;
-
- info = priv->rx.info + i;
- skb = info->skb;
- hdr = (struct agnx_hdr *)(skb->data);
-
- len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
- if (agnx_packet_check(priv, hdr, len) == -1) {
- rx_desc_reusing(priv, i);
- continue;
- }
- skb_put(skb, len);
-
- do {
- u16 fctl;
- fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
- if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)/* && !(fctl & IEEE80211_STYPE_BEACON)) */
- dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
- } while (0);
-
- if (hdr->_11b0 && !hdr->_11g0) {
-/* int j;
- u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)
- ->frame_control);
- if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
- agnx_print_rx_hdr(hdr);
- agnx_print_sta(priv, BSSID_STAID);
- for (j = 0; j < 8; j++)
- agnx_print_sta_tx_wq(priv, BSSID_STAID, j);
- } */
-
- get_rx_stats(priv, hdr, &status);
- skb_pull(skb, sizeof(*hdr));
- combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
- } else if (!hdr->_11b0 && hdr->_11g0) {
-/* int j; */
- agnx_print_rx_hdr(hdr);
- agnx_print_sta(priv, BSSID_STAID);
-/* for (j = 0; j < 8; j++) */
- agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
-
- print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
- skb->data, skb->len + 8);
-
-/* if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) */
- get_rx_stats(priv, hdr, &status);
- skb_pull(skb, sizeof(*hdr));
- combine_hdr_frag((struct ieee80211_hdr *)
- ((void *)&hdr->mac_hdr), skb);
-/* dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */
- } else
- agnx_bug("Unknown packets type");
- memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
- ieee80211_rx_irqsafe(priv->hw, skb);
- rx_desc_reinit(priv, i);
-
- } while (priv->rx.idx++);
-} /* handle_rx_irq */
-
-static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
-{
- struct agnx_desc *desc;
- struct agnx_info *info;
- unsigned int idx;
-
- for (idx = ring->idx_sent; idx < ring->idx; idx++) {
- unsigned int i = idx % ring->size;
- u32 frag;
-
- desc = ring->desc + i;
- info = ring->info + i;
-
- frag = be32_to_cpu(desc->frag);
- if (frag & OWNER) {
- if (info->type == HEADER)
- break;
- else
- agnx_bug("TX error");
- }
-
- pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
-
- do {
-/* int j; */
- size_t len;
- len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
-/* if (len == 614) { */
-/* agnx_print_desc(desc); */
- if (info->type == PACKET) {
-/* agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */
-/* agnx_print_sta_power(priv, LOCAL_STAID); */
-/* agnx_print_sta(priv, LOCAL_STAID); */
-/* for (j = 0; j < 8; j++) */
-/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
-/* agnx_print_sta_power(priv, BSSID_STAID); */
-/* agnx_print_sta(priv, BSSID_STAID); */
-/* for (j = 0; j < 8; j++) */
-/* agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */
- }
-/* } */
- } while (0);
-
- if (info->type == PACKET) {
-/* dump_txm_registers(priv);
- dump_rxm_registers(priv);
- dump_bm_registers(priv);
- dump_cir_registers(priv); */
- }
-
- if (info->type == PACKET) {
-/* struct ieee80211_hdr *hdr; */
- struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
-
- skb_pull(info->skb, sizeof(struct agnx_hdr));
- memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
-
-/* dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); */
-/* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
-/* info->skb->data, info->skb->len); */
-
- if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK))
- txi->flags |= IEEE80211_TX_STAT_ACK;
-
- ieee80211_tx_status_irqsafe(priv->hw, info->skb);
-
-
-/* info->tx_status.queue_number = (ring->size - i) / 2; */
-/* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
-/* } else */
-/* dev_kfree_skb_irq(info->skb); */
- }
- memset(desc, 0, sizeof(*desc));
- memset(info, 0, sizeof(*info));
- }
-
- ring->idx_sent = idx;
- /* TODO fill the priv->low_level_stats */
-
- /* ieee80211_wake_queue(priv->hw, 0); */
-}
-
-void handle_txm_irq(struct agnx_priv *priv)
-{
- handle_tx_irq(priv, &priv->txm);
-}
-
-void handle_txd_irq(struct agnx_priv *priv)
-{
- handle_tx_irq(priv, &priv->txd);
-}
-
-void handle_other_irq(struct agnx_priv *priv)
-{
-/* void __iomem *ctl = priv->ctl; */
- u32 status = priv->irq_status;
- void __iomem *ctl = priv->ctl;
- u32 reg;
-
- if (status & IRQ_TX_BEACON) {
- iowrite32(IRQ_TX_BEACON, ctl + AGNX_INT_STAT);
- printk(PFX "IRQ: TX Beacon control is 0X%.8X\n", ioread32(ctl + AGNX_TXM_BEACON_CTL));
- printk(PFX "IRQ: TX Beacon rx frame num: %d\n", rx_frame_cnt);
- }
- if (status & IRQ_TX_RETRY) {
- reg = ioread32(ctl + AGNX_TXM_RETRYSTAID);
- printk(PFX "IRQ: TX Retry, RETRY STA ID is %x\n", reg);
- }
- if (status & IRQ_TX_ACTIVITY)
- printk(PFX "IRQ: TX Activity\n");
- if (status & IRQ_RX_ACTIVITY)
- printk(PFX "IRQ: RX Activity\n");
- if (status & IRQ_RX_X)
- printk(PFX "IRQ: RX X\n");
- if (status & IRQ_RX_Y) {
- reg = ioread32(ctl + AGNX_INT_MASK);
- reg &= ~IRQ_RX_Y;
- iowrite32(reg, ctl + AGNX_INT_MASK);
- iowrite32(IRQ_RX_Y, ctl + AGNX_INT_STAT);
- printk(PFX "IRQ: RX Y\n");
- }
- if (status & IRQ_RX_HASHHIT) {
- reg = ioread32(ctl + AGNX_INT_MASK);
- reg &= ~IRQ_RX_HASHHIT;
- iowrite32(reg, ctl + AGNX_INT_MASK);
- iowrite32(IRQ_RX_HASHHIT, ctl + AGNX_INT_STAT);
- printk(PFX "IRQ: RX Hash Hit\n");
-
- }
- if (status & IRQ_RX_FRAME) {
- reg = ioread32(ctl + AGNX_INT_MASK);
- reg &= ~IRQ_RX_FRAME;
- iowrite32(reg, ctl + AGNX_INT_MASK);
- iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
- printk(PFX "IRQ: RX Frame\n");
- rx_frame_cnt++;
- }
- if (status & IRQ_ERR_INT) {
- iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
-/* agnx_hw_reset(priv); */
- printk(PFX "IRQ: Error Interrupt\n");
- }
- if (status & IRQ_TX_QUE_FULL)
- printk(PFX "IRQ: TX Workqueue Full\n");
- if (status & IRQ_BANDMAN_ERR)
- printk(PFX "IRQ: Bandwidth Management Error\n");
- if (status & IRQ_TX_DISABLE)
- printk(PFX "IRQ: TX Disable\n");
- if (status & IRQ_RX_IVASESKEY)
- printk(PFX "IRQ: RX Invalid Session Key\n");
- if (status & IRQ_REP_THHIT)
- printk(PFX "IRQ: Replay Threshold Hit\n");
- if (status & IRQ_TIMER1)
- printk(PFX "IRQ: Timer1\n");
- if (status & IRQ_TIMER_CNT)
- printk(PFX "IRQ: Timer Count\n");
- if (status & IRQ_PHY_FASTINT)
- printk(PFX "IRQ: Phy Fast Interrupt\n");
- if (status & IRQ_PHY_SLOWINT)
- printk(PFX "IRQ: Phy Slow Interrupt\n");
- if (status & IRQ_OTHER)
- printk(PFX "IRQ: 0x80000000\n");
-} /* handle_other_irq */
-
-
-static inline void route_flag_set(struct agnx_hdr *txhdr)
-{
-/* u32 reg = 0; */
-
- /* FIXME */
-/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
-/* txhdr->reg5 = cpu_to_be32(reg); */
- txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
-/* txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */
-/* txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */
-}
-
-/* Return 0 if no match */
-static inline unsigned int get_power_level(unsigned int rate, unsigned int antennas_num)
-{
- unsigned int power_level;
-
- switch (rate) {
- case 10:
- case 20:
- case 55:
- case 60:
- case 90:
- case 120:
- power_level = 22;
- break;
-
- case 180:
- power_level = 19;
- break;
-
- case 240:
- power_level = 18;
- break;
-
- case 360:
- power_level = 16;
- break;
-
- case 480:
- power_level = 15;
- break;
-
- case 540:
- power_level = 14;
- break;
- default:
- agnx_bug("Error rate setting\n");
- }
-
- if (power_level && (antennas_num == 2))
- power_level -= 3;
-
- return power_level;
-}
-
-static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_info)
-{
- struct agnx_hdr *txhdr = (struct agnx_hdr *)tx_info->skb->data;
- size_t len;
- u16 fc = le16_to_cpu(*(__le16 *)&tx_info->hdr);
- u32 reg;
-
- memset(txhdr, 0, sizeof(*txhdr));
-
-/* reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); */
- reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
- reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
- txhdr->reg4 = cpu_to_be32(reg);
-
- /* Set the Hardware Sequence Number to 1? */
- reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0);
-/* reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); */
- reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
- txhdr->reg1 = cpu_to_be32(reg);
- /* Set the agnx_hdr's MAC header */
- memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
-
- reg = agnx_set_bits(ACK, ACK_SHIFT, 1);
-/* reg = agnx_set_bits(ACK, ACK_SHIFT, 0); */
- reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0);
-/* reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); */
- reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0);
- reg |= agnx_set_bits(TM, TM_SHIFT, 0);
- txhdr->reg0 = cpu_to_be32(reg);
-
- /* Set the long and short retry limits */
- txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
- txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
-
- /* FIXME */
- len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
- if (fc & IEEE80211_FCTL_PROTECTED)
- len += 8;
- len = 2398;
- reg = agnx_set_bits(FRAG_SIZE, FRAG_SIZE_SHIFT, len);
- len = tx_info->skb->len - sizeof(*txhdr);
- reg |= agnx_set_bits(PAYLOAD_LEN, PAYLOAD_LEN_SHIFT, len);
- txhdr->reg3 = cpu_to_be32(reg);
-
- route_flag_set(txhdr);
-} /* fill_hdr */
-
-static void txm_power_set(struct agnx_priv *priv,
- struct ieee80211_tx_info *txi)
-{
- struct agnx_sta_power power;
- u32 reg;
-
- /* FIXME */
- if (txi->control.rates[0].idx < 0) {
- /* For B mode Short Preamble */
- reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
-/* control->tx_rate = -control->tx_rate; */
- } else
- reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
-/* reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); */
- reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB);
- reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB);
-/* reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); */
- reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
- /* if rate < 11M set it to 0 */
- reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
-/* reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */
-/* reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */
-
- power.reg = reg;
-/* power.reg = cpu_to_le32(reg); */
-
-/* set_sta_power(priv, &power, LOCAL_STAID); */
- set_sta_power(priv, &power, BSSID_STAID);
-}
-
-static inline int tx_packet_check(struct sk_buff *skb)
-{
- unsigned int ieee_len = ieee80211_get_hdrlen_from_skb(skb);
- if (skb->len > 2048) {
- printk(KERN_ERR PFX "length is %d\n", skb->len);
- agnx_bug("Too long TX skb");
- return -1;
- }
- /* FIXME */
- if (skb->len == ieee_len) {
- printk(PFX "A strange TX packet\n");
- return -1;
- /* tx_faile_irqsafe(); */
- }
- return 0;
-}
-
-static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
- struct agnx_ring *ring)
-{
- struct agnx_desc *hdr_desc, *frag_desc;
- struct agnx_info *hdr_info, *frag_info;
- struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
- unsigned long flags;
- unsigned int i;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* The RX interrupt need be Disable until this TX packet
- is handled in the next tx interrupt */
- disable_rx_interrupt(priv);
-
- i = ring->idx;
- ring->idx += 2;
-/* if (priv->txm_idx - priv->txm_idx_sent == AGNX_TXM_RING_SIZE - 2) */
-/* ieee80211_stop_queue(priv->hw, 0); */
-
- /* Set agnx header's info and desc */
- i %= ring->size;
- hdr_desc = ring->desc + i;
- hdr_info = ring->info + i;
- hdr_info->hdr_len = ieee80211_get_hdrlen_from_skb(skb);
- memcpy(&hdr_info->hdr, skb->data, hdr_info->hdr_len);
-
- /* Add the agnx header to the front of the SKB */
- skb_push(skb, sizeof(struct agnx_hdr) - hdr_info->hdr_len);
-
- hdr_info->txi = txi;
- hdr_info->dma_len = sizeof(struct agnx_hdr);
- hdr_info->skb = skb;
- hdr_info->type = HEADER;
- fill_agnx_hdr(priv, hdr_info);
- hdr_info->mapping = pci_map_single(priv->pdev, skb->data,
- hdr_info->dma_len, PCI_DMA_TODEVICE);
- do {
- u32 frag = 0;
- frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 1);
- frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 0);
- frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
- frag |= agnx_set_bits(FIRST_FRAG_LEN, FIRST_FRAG_LEN_SHIFT, 1);
- frag |= agnx_set_bits(OWNER, OWNER_SHIFT, 1);
- hdr_desc->frag = cpu_to_be32(frag);
- } while (0);
- hdr_desc->dma_addr = cpu_to_be32(hdr_info->mapping);
-
-
- /* Set Frag's info and desc */
- i = (i + 1) % ring->size;
- frag_desc = ring->desc + i;
- frag_info = ring->info + i;
- memcpy(frag_info, hdr_info, sizeof(struct agnx_info));
- frag_info->type = PACKET;
- frag_info->dma_len = skb->len - hdr_info->dma_len;
- frag_info->mapping = pci_map_single(priv->pdev, skb->data + hdr_info->dma_len,
- frag_info->dma_len, PCI_DMA_TODEVICE);
- do {
- u32 frag = 0;
- frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 0);
- frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 1);
- frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
- frag |= agnx_set_bits(SUB_FRAG_LEN, SUB_FRAG_LEN_SHIFT, frag_info->dma_len);
- frag_desc->frag = cpu_to_be32(frag);
- } while (0);
- frag_desc->dma_addr = cpu_to_be32(frag_info->mapping);
-
- txm_power_set(priv, txi);
-
-/* do { */
-/* int j; */
-/* size_t len; */
-/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
-/* if (len == 614) { */
-/* agnx_print_desc(hdr_desc); */
-/* agnx_print_desc(frag_desc); */
-/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
-/* agnx_print_sta_power(priv, LOCAL_STAID); */
-/* agnx_print_sta(priv, LOCAL_STAID); */
-/* for (j = 0; j < 8; j++) */
-/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
-/* agnx_print_sta_power(priv, BSSID_STAID); */
-/* agnx_print_sta(priv, BSSID_STAID); */
-/* for (j = 0; j < 8; j++) */
-/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
-/* } */
-/* } while (0); */
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* FIXME ugly code */
- /* Trigger TXM */
- do {
- u32 reg;
- reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
- reg |= 0x8;
- iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
- } while (0);
-
- /* Trigger TXD */
- do {
- u32 reg;
- reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
- reg |= 0x8;
- iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
- } while (0);
-
- return 0;
-}
-
-int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
-{
- u16 fctl;
-
- if (tx_packet_check(skb))
- return 0;
-
-/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
-/* skb->data, skb->len); */
-
- fctl = le16_to_cpu(*((__le16 *)skb->data));
-
- if ((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
- return __agnx_tx(priv, skb, &priv->txd);
- else
- return __agnx_tx(priv, skb, &priv->txm);
-}
diff --git a/drivers/staging/agnx/xmit.h b/drivers/staging/agnx/xmit.h
deleted file mode 100644
index 93ac4157e697..000000000000
--- a/drivers/staging/agnx/xmit.h
+++ /dev/null
@@ -1,250 +0,0 @@
-#ifndef AGNX_XMIT_H_
-#define AGNX_XMIT_H_
-
-#include <net/mac80211.h>
-
-struct agnx_priv;
-
-static inline u32 agnx_set_bits(u32 mask, u8 shift, u32 value)
-{
- return (value << shift) & mask;
-}
-
-static inline u32 agnx_get_bits(u32 mask, u8 shift, u32 value)
-{
- return (value & mask) >> shift;
-}
-
-
-struct agnx_rx {
- __be16 rx_packet_duration; /* RX Packet Duration */
- __be16 replay_cnt; /* Replay Count */
-} __attribute__((__packed__));
-
-
-struct agnx_tx {
- u8 long_retry_limit; /* Long Retry Limit */
- u8 short_retry_limit; /* Short Retry Limit */
- u8 long_retry_cnt; /* Long Retry Count */
- u8 short_retry_cnt; /* Short Retry Count */
-} __attribute__((__packed__));
-
-
-/* Copy from bcm43xx */
-#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
-#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
-#define PAD_BYTES(nr_bytes) P4D_BYTES(__LINE__, nr_bytes)
-
-#define P4D_BIT3S(magic, nr_bits) __be32 __padding##magic:nr_bits
-#define P4D_BITS(line, nr_bits) P4D_BIT3S(line, nr_bits)
-#define PAD_BITS(nr_bits) P4D_BITS(__LINE__, nr_bits)
-
-
-struct agnx_hdr {
- __be32 reg0;
-#define RTS 0x80000000 /* RTS */
-#define RTS_SHIFT 31
-#define MULTICAST 0x40000000 /* multicast */
-#define MULTICAST_SHIFT 30
-#define ACK 0x30000000 /* ACK */
-#define ACK_SHIFT 28
-#define TM 0x08000000 /* TM */
-#define TM_SHIFT 27
-#define RELAY 0x04000000 /* Relay */
-#define RELAY_SHIFT 26
-/* PAD_BITS(4); */
-#define REVISED_FCS 0x00380000 /* revised FCS */
-#define REVISED_FCS_SHIFT 19
-#define NEXT_BUFFER_ADDR 0x0007FFFF /* Next Buffer Address */
-#define NEXT_BUFFER_ADDR_SHIFT 0
-
- __be32 reg1;
-#define MAC_HDR_LEN 0xFC000000 /* MAC Header Length */
-#define MAC_HDR_LEN_SHIFT 26
-#define DURATION_OVERIDE 0x02000000 /* Duration Override */
-#define DURATION_OVERIDE_SHIFT 25
-#define PHY_HDR_OVERIDE 0x01000000 /* PHY Header Override */
-#define PHY_HDR_OVERIDE_SHIFT 24
-#define CRC_FAIL 0x00800000 /* CRC fail */
-#define CRC_FAIL_SHIFT 23
-/* PAD_BITS(1); */
-#define SEQUENCE_NUMBER 0x00200000 /* Sequence Number */
-#define SEQUENCE_NUMBER_SHIFT 21
-/* PAD_BITS(2); */
-#define BUFF_HEAD_ADDR 0x0007FFFF /* Buffer Head Address */
-#define BUFF_HEAD_ADDR_SHIFT 0
-
- __be32 reg2;
-#define PDU_COUNT 0xFC000000 /* PDU Count */
-#define PDU_COUNT_SHIFT 26
-/* PAD_BITS(3); */
-#define WEP_KEY 0x00600000 /* WEP Key # */
-#define WEP_KEY_SHIFT 21
-#define USES_WEP_KEY 0x00100000 /* Uses WEP Key */
-#define USES_WEP_KEY_SHIFT 20
-#define KEEP_ALIVE 0x00080000 /* Keep alive */
-#define KEEP_ALIVE_SHIFT 19
-#define BUFF_TAIL_ADDR 0x0007FFFF /* Buffer Tail Address */
-#define BUFF_TAIL_ADDR_SHIFT 0
-
- __be32 reg3;
-#define CTS_11G 0x80000000 /* CTS in 11g */
-#define CTS_11G_SHIFT 31
-#define RTS_11G 0x40000000 /* RTS in 11g */
-#define RTS_11G_SHIFT 30
-/* PAD_BITS(2); */
-#define FRAG_SIZE 0x0FFF0000 /* fragment size */
-#define FRAG_SIZE_SHIFT 16
-#define PAYLOAD_LEN 0x0000FFF0 /* payload length */
-#define PAYLOAD_LEN_SHIFT 4
-#define FRAG_NUM 0x0000000F /* number of frags */
-#define FRAG_NUM_SHIFT 0
-
- __be32 reg4;
-/* PAD_BITS(4); */
-#define RELAY_STAID 0x0FFF0000 /* relayStald */
-#define RELAY_STAID_SHIFT 16
-#define STATION_ID 0x0000FFF0 /* Station ID */
-#define STATION_ID_SHIFT 4
-#define WORKQUEUE_ID 0x0000000F /* Workqueue ID */
-#define WORKQUEUE_ID_SHIFT 0
-
- /* FIXME this register maybe is LE? */
- __be32 reg5;
-/* PAD_BITS(4); */
-#define ROUTE_HOST 0x0F000000
-#define ROUTE_HOST_SHIFT 24
-#define ROUTE_CARD_CPU 0x00F00000
-#define ROUTE_CARD_CPU_SHIFT 20
-#define ROUTE_ENCRYPTION 0x000F0000
-#define ROUTE_ENCRYPTION_SHIFT 16
-#define ROUTE_TX 0x0000F000
-#define ROUTE_TX_SHIFT 12
-#define ROUTE_RX1 0x00000F00
-#define ROUTE_RX1_SHIFT 8
-#define ROUTE_RX2 0x000000F0
-#define ROUTE_RX2_SHIFT 4
-#define ROUTE_COMPRESSION 0x0000000F
-#define ROUTE_COMPRESSION_SHIFT 0
-
- __be32 _11g0; /* 11g */
- __be32 _11g1; /* 11g */
- __be32 _11b0; /* 11b */
- __be32 _11b1; /* 11b */
- u8 mac_hdr[32]; /* MAC header */
-
- __be16 rts_duration; /* RTS duration */
- __be16 last_duration; /* Last duration */
- __be16 sec_last_duration; /* Second to Last duration */
- __be16 other_duration; /* Other duration */
- __be16 tx_last_duration; /* TX Last duration */
- __be16 tx_other_duration; /* TX Other Duration */
- __be16 last_11g_len; /* Length of last 11g */
- __be16 other_11g_len; /* Lenght of other 11g */
-
- __be16 last_11b_len; /* Length of last 11b */
- __be16 other_11b_len; /* Lenght of other 11b */
-
-
- __be16 reg6;
-#define MBF 0xF000 /* mbf */
-#define MBF_SHIFT 12
-#define RSVD4 0x0FFF /* rsvd4 */
-#define RSVD4_SHIFT 0
-
- __be16 rx_frag_stat; /* RX fragmentation status */
-
- __be32 time_stamp; /* TimeStamp */
- __be32 phy_stats_hi; /* PHY stats hi */
- __be32 phy_stats_lo; /* PHY stats lo */
- __be32 mic_key0; /* MIC key 0 */
- __be32 mic_key1; /* MIC key 1 */
-
- union { /* RX/TX Union */
- struct agnx_rx rx;
- struct agnx_tx tx;
- };
-
- u8 rx_channel; /* Recieve Channel */
- PAD_BYTES(3);
-
- u8 reserved[4];
-} __attribute__((__packed__));
-
-
-struct agnx_desc {
-#define PACKET_LEN 0xFFF00000
-#define PACKET_LEN_SHIFT 20
-/* ------------------------------------------------ */
-#define FIRST_PACKET_MASK 0x00080000
-#define FIRST_PACKET_MASK_SHIFT 19
-#define FIRST_RESERV2 0x00040000
-#define FIRST_RESERV2_SHIFT 18
-#define FIRST_TKIP_ERROR 0x00020000
-#define FIRST_TKIP_ERROR_SHIFT 17
-#define FIRST_TKIP_PACKET 0x00010000
-#define FIRST_TKIP_PACKET_SHIFT 16
-#define FIRST_RESERV1 0x0000F000
-#define FIRST_RESERV1_SHIFT 12
-#define FIRST_FRAG_LEN 0x00000FF8
-#define FIRST_FRAG_LEN_SHIFT 3
-/* ------------------------------------------------ */
-#define SUB_RESERV2 0x000c0000
-#define SUB_RESERV2_SHIFT 18
-#define SUB_TKIP_ERROR 0x00020000
-#define SUB_TKIP_ERROR_SHIFT 17
-#define SUB_TKIP_PACKET 0x00010000
-#define SUB_TKIP_PACKET_SHIFT 16
-#define SUB_RESERV1 0x00008000
-#define SUB_RESERV1_SHIFT 15
-#define SUB_FRAG_LEN 0x00007FF8
-#define SUB_FRAG_LEN_SHIFT 3
-/* ------------------------------------------------ */
-#define FIRST_FRAG 0x00000004
-#define FIRST_FRAG_SHIFT 2
-#define LAST_FRAG 0x00000002
-#define LAST_FRAG_SHIFT 1
-#define OWNER 0x00000001
-#define OWNER_SHIFT 0
- __be32 frag;
- __be32 dma_addr;
-} __attribute__((__packed__));
-
-enum {HEADER, PACKET};
-
-struct agnx_info {
- struct sk_buff *skb;
- dma_addr_t mapping;
- u32 dma_len; /* dma buffer len */
- /* Below fields only usful for tx */
- u32 hdr_len; /* ieee80211 header length */
- unsigned int type;
- struct ieee80211_tx_info *txi;
- struct ieee80211_hdr hdr;
-};
-
-
-struct agnx_ring {
- struct agnx_desc *desc;
- dma_addr_t dma;
- struct agnx_info *info;
- /* Will lead to overflow when sent packet number enough? */
- unsigned int idx;
- unsigned int idx_sent; /* only usful for txd and txm */
- unsigned int size;
-};
-
-#define AGNX_RX_RING_SIZE 128
-#define AGNX_TXD_RING_SIZE 256
-#define AGNX_TXM_RING_SIZE 128
-
-void disable_rx_interrupt(struct agnx_priv *priv);
-void enable_rx_interrupt(struct agnx_priv *priv);
-int fill_rings(struct agnx_priv *priv);
-void unfill_rings(struct agnx_priv *priv);
-void handle_rx_irq(struct agnx_priv *priv);
-void handle_txd_irq(struct agnx_priv *priv);
-void handle_txm_irq(struct agnx_priv *priv);
-void handle_other_irq(struct agnx_priv *priv);
-int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb);
-#endif /* AGNX_XMIT_H_ */
diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c
index 94c5d27d24d7..cda26bb493b3 100644
--- a/drivers/staging/b3dfg/b3dfg.c
+++ b/drivers/staging/b3dfg/b3dfg.c
@@ -36,6 +36,7 @@
#include <linux/wait.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
+#include <linux/sched.h>
static unsigned int b3dfg_nbuf = 2;
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index af723cb9d08f..d63c889ce557 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -1,7 +1,7 @@
config COMEDI
tristate "Data acquisition support (comedi)"
default N
- depends on m
+ depends on m && (PCI || PCMCIA || PCCARD || USB)
---help---
Enable support a wide range of data acquisition devices
for Linux.
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index f54bb9b3ee37..aaad76e0a76a 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2337,7 +2337,7 @@ static int resize_async_buffer(struct comedi_device *dev,
}
DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
- dev->minor, s - dev->subdevices, async->prealloc_bufsz);
+ dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 12d12b43a6f1..80c0df8656f3 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -744,7 +744,7 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
/* Initialize the pcmcia_device structure */
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 4d10bc31d461..09e6e3bdfb3e 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -53,7 +53,8 @@ Passing a zero for an option is the same as leaving it unspecified.
* Some drivers use arrays such as this, other do not.
*/
struct pcidio_board {
- const char *name; /* anme of the board */
+ const char *name; /* name of the board */
+ int dev_id;
int n_8255; /* number of 8255 chips on board */
/* indices of base address regions */
@@ -64,18 +65,21 @@ struct pcidio_board {
static const struct pcidio_board pcidio_boards[] = {
{
.name = "pci-dio24",
+ .dev_id = 0x0028,
.n_8255 = 1,
.pcicontroler_badrindex = 1,
.dioregs_badrindex = 2,
},
{
.name = "pci-dio24h",
+ .dev_id = 0x0014,
.n_8255 = 1,
.pcicontroler_badrindex = 1,
.dioregs_badrindex = 2,
},
{
.name = "pci-dio48h",
+ .dev_id = 0x000b,
.n_8255 = 2,
.pcicontroler_badrindex = 0,
.dioregs_badrindex = 1,
@@ -206,7 +210,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
continue;
/* loop through cards supported by this driver */
for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
- if (pcidio_pci_table[index].device != pcidev->device)
+ if (pcidio_boards[index].dev_id != pcidev->device)
continue;
/* was a particular bus/slot requested? */
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 14bf29bf5781..0d2c2eb23b23 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -515,6 +515,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
{
struct poll_delay_t result = poll_delay_min_max(1000, 2000);
struct jr3_pci_subdev_private *p = s->private;
+ int i;
if (p) {
volatile struct jr3_channel *channel = p->channel;
@@ -570,18 +571,11 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
p->serial_no);
/* Transformation all zeros */
- transf.link[0].link_type =
- (enum link_types)0;
- transf.link[0].link_amount = 0;
- transf.link[1].link_type =
- (enum link_types)0;
- transf.link[1].link_amount = 0;
- transf.link[2].link_type =
- (enum link_types)0;
- transf.link[2].link_amount = 0;
- transf.link[3].link_type =
- (enum link_types)0;
- transf.link[3].link_amount = 0;
+ for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
+ transf.link[i].link_type =
+ (enum link_types)0;
+ transf.link[i].link_amount = 0;
+ }
set_transforms(channel, transf, 0);
use_transform(channel, 0);
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 2cda7ad1d32f..80e192d2e77e 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -51,6 +51,7 @@ from http://www.comedi.org
*/
#include <linux/interrupt.h>
+#include <linux/sched.h>
#include "../comedidev.h"
#include "comedi_pci.h"
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 6b118c15b49e..bbf75eb6d7f2 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -418,15 +418,15 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
return -EINVAL;
base_bitfield_channel = CR_CHAN(insn->chanspec);
for (j = 0; j < max_ports_per_bitfield; ++j) {
+ const unsigned port_offset = ni_65xx_port_by_channel(base_bitfield_channel) + j;
const unsigned port =
- sprivate(s)->base_port +
- ni_65xx_port_by_channel(base_bitfield_channel) + j;
+ sprivate(s)->base_port + port_offset;
unsigned base_port_channel;
unsigned port_mask, port_data, port_read_bits;
int bitshift;
if (port >= ni_65xx_total_num_ports(board(dev)))
break;
- base_port_channel = port * ni_65xx_channels_per_port;
+ base_port_channel = port_offset * ni_65xx_channels_per_port;
port_mask = data[0];
port_data = data[1];
bitshift = base_port_channel - base_bitfield_channel;
@@ -457,6 +457,12 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
port_read_bits =
readb(private(dev)->mite->daq_io_addr + Port_Data(port));
/* printk("read 0x%x from port %i\n", port_read_bits, port); */
+ if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
+ /* Outputs inverted, so invert value read back from
+ * DO subdevice. (Does not apply to boards with DIO
+ * subdevice.) */
+ port_read_bits ^= 0xFF;
+ }
if (bitshift > 0) {
port_read_bits <<= bitshift;
} else {
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 6a7797604c97..ec31a3970664 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -520,7 +520,7 @@ static int dio700_cs_attach(struct pcmcia_device *link)
link->priv = local;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index b06e81c526e8..0700a8bddd1e 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -271,7 +271,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)
link->priv = local;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 57aecfa883c7..a3053b8da1c6 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -246,7 +246,7 @@ static int labpc_cs_attach(struct pcmcia_device *link)
link->priv = local;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE;
link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID;
link->irq.Handler = NULL;
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index e3ffb067ead1..753ee0512342 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -62,6 +62,7 @@
/* #define DEBUG_STATUS_B */
#include <linux/interrupt.h>
+#include <linux/sched.h>
#include "8255.h"
#include "mite.h"
#include "comedi_fc.h"
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index b7322963cf78..9aef87fc81dc 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -273,7 +273,7 @@ static int cs_attach(struct pcmcia_device *link)
{
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
link->io.NumPorts1 = 16;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 52b2eca9e73d..d544698f2414 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -70,6 +70,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
/* #define DEBUG_FLAGS */
#include <linux/interrupt.h>
+#include <linux/sched.h>
#include "../comedidev.h"
#include "mite.h"
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 19d87553d906..24c8b8ed5b4c 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -29,7 +29,7 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E,
PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
- PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225,
+ PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, PXI-6225,
PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259,
PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
PCI-6711, PXI-6711, PCI-6713, PXI-6713,
@@ -179,6 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = {
PCI_VENDOR_ID_NATINST, 0x70f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x710d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x716c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+ PCI_VENDOR_ID_NATINST, 0x716d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x717f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x71bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x717d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -953,6 +954,25 @@ static const struct ni_board_struct ni_boards[] = {
.has_8255 = 0,
},
{
+ .device_id = 0x716d,
+ .name = "pxi-6225",
+ .n_adchan = 80,
+ .adbits = 16,
+ .ai_fifo_depth = 4095,
+ .gainlkup = ai_gain_622x,
+ .ai_speed = 4000,
+ .n_aochan = 2,
+ .aobits = 16,
+ .ao_fifo_depth = 8191,
+ .ao_range_table = &range_ni_M_622x_ao,
+ .reg_type = ni_reg_622x,
+ .ao_unipolar = 0,
+ .ao_speed = 1200,
+ .num_p0_dio_channels = 32,
+ .caldac = {caldac_none},
+ .has_8255 = 0,
+ },
+ {
.device_id = 0x70aa,
.name = "pci-6229",
.n_adchan = 32,
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index f63bdc35cffd..344b82353e08 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1079,7 +1079,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
link->priv = local;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = daqp_interrupt;
link->irq.Instance = local;
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index b89e1ec267c5..07c21e686f27 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -43,6 +43,7 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
#include "../comedidev.h"
#include <linux/ioport.h>
+#include <asm/byteorder.h>
#define S526_SIZE 64
@@ -113,6 +114,7 @@ static const int s526_ports[] = {
};
struct counter_mode_register_t {
+#if defined (__LITTLE_ENDIAN_BITFIELD)
unsigned short coutSource:1;
unsigned short coutPolarity:1;
unsigned short autoLoadResetRcap:3;
@@ -124,12 +126,27 @@ struct counter_mode_register_t {
unsigned short outputRegLatchCtrl:1;
unsigned short preloadRegSel:1;
unsigned short reserved:1;
+ #elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned short reserved:1;
+ unsigned short preloadRegSel:1;
+ unsigned short outputRegLatchCtrl:1;
+ unsigned short countDirCtrl:1;
+ unsigned short countDir:1;
+ unsigned short clockSource:2;
+ unsigned short ctEnableCtrl:2;
+ unsigned short hwCtEnableSource:2;
+ unsigned short autoLoadResetRcap:3;
+ unsigned short coutPolarity:1;
+ unsigned short coutSource:1;
+#else
+#error Unknown bit field order
+#endif
};
-union {
+union cmReg {
struct counter_mode_register_t reg;
unsigned short value;
-} cmReg;
+};
#define MAX_GPCT_CONFIG_DATA 6
@@ -285,6 +302,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int i, n;
/* short value; */
/* int subdev_channel = 0; */
+ union cmReg cmReg;
printk("comedi%d: s526: ", dev->minor);
@@ -375,7 +393,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (thisboard->have_dio) {
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 2;
+ s->n_chan = 8;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = s526_dio_insn_bits;
@@ -435,11 +453,11 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
udelay(1000);
printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
- /* Load the pre-laod register high word */
+ /* Load the pre-load register high word */
/* value = (short) (0x55); */
/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
- /* Load the pre-laod register low word */
+ /* Load the pre-load register low word */
/* value = (short)(0xaa55); */
/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
@@ -516,6 +534,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
int i;
short value;
+ union cmReg cmReg;
/* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */
@@ -568,19 +587,8 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
#if 1
/* Set Counter Mode Register */
- cmReg.reg.coutSource = 0; /* out RCAP */
- cmReg.reg.coutPolarity = 0; /* Polarity inverted */
- cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */
- cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */
- cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */
- cmReg.reg.clockSource = 3; /* x4 */
- cmReg.reg.countDir = 0; /* up */
- cmReg.reg.countDirCtrl = 0; /* quadrature */
- cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
- cmReg.reg.preloadRegSel = 0; /* PR0 */
- cmReg.reg.reserved = 0;
+ cmReg.value = insn->data[1] & 0xFFFF;
- /* Set Counter Mode Register */
/* printk("s526: Counter Mode register=%x\n", cmReg.value); */
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
@@ -615,11 +623,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.value = (short)(insn->data[1] & 0xFFFF);
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
- /* Load the pre-laod register high word */
+ /* Load the pre-load register high word */
value = (short)((insn->data[2] >> 16) & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- /* Load the pre-laod register low word */
+ /* Load the pre-load register low word */
value = (short)(insn->data[2] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
@@ -653,11 +661,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.preloadRegSel = 0; /* PR0 */
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
- /* Load the pre-laod register 0 high word */
+ /* Load the pre-load register 0 high word */
value = (short)((insn->data[2] >> 16) & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- /* Load the pre-laod register 0 low word */
+ /* Load the pre-load register 0 low word */
value = (short)(insn->data[2] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
@@ -666,17 +674,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.preloadRegSel = 1; /* PR1 */
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
- /* Load the pre-laod register 1 high word */
+ /* Load the pre-load register 1 high word */
value = (short)((insn->data[3] >> 16) & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- /* Load the pre-laod register 1 low word */
+ /* Load the pre-load register 1 low word */
value = (short)(insn->data[3] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
/* Write the Counter Control Register */
- if (insn->data[3] != 0) {
- value = (short)(insn->data[3] & 0xFFFF);
+ if (insn->data[4] != 0) {
+ value = (short)(insn->data[4] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
}
break;
@@ -698,11 +706,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.preloadRegSel = 0; /* PR0 */
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
- /* Load the pre-laod register 0 high word */
+ /* Load the pre-load register 0 high word */
value = (short)((insn->data[2] >> 16) & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- /* Load the pre-laod register 0 low word */
+ /* Load the pre-load register 0 low word */
value = (short)(insn->data[2] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
@@ -711,17 +719,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.preloadRegSel = 1; /* PR1 */
outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
- /* Load the pre-laod register 1 high word */
+ /* Load the pre-load register 1 high word */
value = (short)((insn->data[3] >> 16) & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- /* Load the pre-laod register 1 low word */
+ /* Load the pre-load register 1 low word */
value = (short)(insn->data[3] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
/* Write the Counter Control Register */
- if (insn->data[3] != 0) {
- value = (short)(insn->data[3] & 0xFFFF);
+ if (insn->data[4] != 0) {
+ value = (short)(insn->data[4] & 0xFFFF);
outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
}
break;
@@ -741,6 +749,7 @@ static int s526_gpct_winsn(struct comedi_device *dev,
{
int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
short value;
+ union cmReg cmReg;
printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
@@ -775,9 +784,8 @@ static int s526_gpct_winsn(struct comedi_device *dev,
(devpriv->s526_gpct_config[subdev_channel]).data[1] =
insn->data[1];
} else {
- printk("%d \t %d\n", insn->data[1], insn->data[2]);
- printk
- ("s526: INSN_WRITE: PTG: Problem with Pulse params\n");
+ printk("s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
+ insn->data[0], insn->data[1]);
return -EINVAL;
}
@@ -949,7 +957,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */
/* or we could just return the software copy of the output values if
* it was a purely digital output subdevice */
- /* data[1]=s->state; */
+ /* data[1]=s->state & 0xFF; */
return 2;
}
@@ -959,28 +967,33 @@ static int s526_dio_insn_config(struct comedi_device *dev,
struct comedi_insn *insn, unsigned int *data)
{
int chan = CR_CHAN(insn->chanspec);
- short value;
+ int group, mask;
printk("S526 DIO insn_config\n");
- if (insn->n != 1)
- return -EINVAL;
-
- value = inw(ADDR_REG(REG_DIO));
-
/* The input or output configuration of each digital line is
* configured by a special insn_config instruction. chanspec
* contains the channel to be changed, and data[0] contains the
* value COMEDI_INPUT or COMEDI_OUTPUT. */
- if (data[0] == COMEDI_OUTPUT) {
- value |= 1 << (chan + 10); /* bit 10/11 set the group 1/2's mode */
- s->io_bits |= (0xF << chan);
- } else {
- value &= ~(1 << (chan + 10)); /* 1 is output, 0 is input. */
- s->io_bits &= ~(0xF << chan);
+ group = chan >> 2;
+ mask = 0xF << (group << 2);
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->state |= 1 << (group + 10); // bit 10/11 set the group 1/2's mode
+ s->io_bits |= mask;
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
+ s->io_bits &= ~mask;
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ default:
+ return -EINVAL;
}
- outw(value, ADDR_REG(REG_DIO));
+ outw(s->state, ADDR_REG(REG_DIO));
return 1;
}
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index a21967983942..82aa86e718b2 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -35,6 +35,7 @@ Status: in development
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/sched.h>
#include <asm/termios.h>
#include <asm/ioctls.h>
diff --git a/drivers/staging/cowloop/Kconfig b/drivers/staging/cowloop/Kconfig
deleted file mode 100644
index 58d2a23bd2c1..000000000000
--- a/drivers/staging/cowloop/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-config COWLOOP
- tristate "copy-on-write pseudo Block Driver"
- depends on BLOCK
- default n
- ---help---
- Cowloop is a "copy-on-write" pseudo block driver. It can be
- stacked on top of a "real" block driver, and catches all write
- operations on their way from the file systems layer above to
- the real driver below, effectively shielding the lower driver
- from those write accesses. The requests are then diverted to
- an ordinary file, located somewhere else (configurable). Later
- read requests are checked to see whether they can be serviced
- by the "real" block driver below, or must be pulled in from
- the diverted location. More information and userspace tools to
- use the driver are on the project's website
- http://www.ATComputing.nl/cowloop/
diff --git a/drivers/staging/cowloop/Makefile b/drivers/staging/cowloop/Makefile
deleted file mode 100644
index 2b6b81a63d21..000000000000
--- a/drivers/staging/cowloop/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_COWLOOP) += cowloop.o
diff --git a/drivers/staging/cowloop/TODO b/drivers/staging/cowloop/TODO
deleted file mode 100644
index 9399d1c16e15..000000000000
--- a/drivers/staging/cowloop/TODO
+++ /dev/null
@@ -1,11 +0,0 @@
-TODO:
- - checkpatch.pl cleanups
- - run sparse to ensure clean
- - fix up 32/64bit ioctl issues
- - move proc file usage to debugfs
- - audit ioctls
- - add documentation
- - get linux-fsdevel to review it
-
-Please send patches to "H.J. Thomassen" <hjt@ATComputing.nl> and
-Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/cowloop/cowloop.c b/drivers/staging/cowloop/cowloop.c
deleted file mode 100644
index a71c743a1196..000000000000
--- a/drivers/staging/cowloop/cowloop.c
+++ /dev/null
@@ -1,2842 +0,0 @@
-/*
-** COWLOOP block device driver (2.6 kernel compliant)
-** =======================================================================
-** Read-write loop-driver with copy-on-write functionality.
-**
-** Synopsis:
-**
-** modprobe cowloop [maxcows=..] [rdofile=..... cowfile=.... [option=r]]
-**
-** Definition of number of configured cowdevices:
-** maxcows= number of configured cowdevices (default: 16)
-** (do not confuse this with MAXCOWS: absolute maximum as compiled)
-**
-** One pair of filenames can be supplied during insmod/modprobe to open
-** the first cowdevice:
-** rdofile= read-only file (or filesystem)
-** cowfile= storage-space for modified blocks of read-only file(system)
-** option=r repair cowfile automatically if it appears to be dirty
-**
-** Other cowdevices can be activated via the command "cowdev"
-** whenever the cowloop-driver is loaded.
-**
-** The read-only file may be of type 'regular' or 'block-device'.
-**
-** The cowfile must be of type 'regular'.
-** If an existing regular file is used as cowfile, its contents will be
-** used again for the current read-only file. When the cowfile has not been
-** closed properly during a previous session (i.e. rmmod cowloop), the
-** cowloop-driver refuses to open it unless the parameter "option=r" is
-** specified.
-**
-** Layout of cowfile:
-**
-** +-----------------------------+
-** | cow head block | MAPUNIT bytes
-** |-----------------------------|
-** | | MAPUNIT bytes
-** |--- ---|
-** | | MAPUNIT bytes
-** |--- ---|
-** | used-block bitmap | MAPUNIT bytes
-** |-----------------------------|
-** | gap to align start-offset |
-** | to 4K multiple |
-** |-----------------------------| <---- start-offset cow blocks
-** | |
-** | written cow blocks | MAPUNIT bytes
-** | ..... |
-**
-** cowhead block:
-** - contains general info about the rdofile which is related
-** to this cowfile
-**
-** used-block bitmap:
-** - contains one bit per block with a size of MAPUNIT bytes
-** - bit-value '1' = block has been written on cow
-** '0' = block unused on cow
-** - total bitmap rounded to multiples of MAPUNIT
-**
-** ============================================================================
-** Author: Gerlof Langeveld - AT Computing (March 2003)
-** Current maintainer: Hendrik-Jan Thomassen - AT Computing (Summer 2006)
-** Email: hjt@ATComputing.nl
-** ----------------------------------------------------------------------------
-** Copyright (C) 2003-2009 AT Consultancy
-**
-** 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, 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
-** ----------------------------------------------------------------------------
-**
-** Major modifications:
-**
-** 200405 Ported to kernel-version 2.6 Hendrik-Jan Thomassen
-** 200405 Added cowhead to cowfile to garantee
-** consistency with read-only file Gerlof Langeveld
-** 200405 Postponed flushing of bitmaps to improve
-** performance. Gerlof Langeveld
-** 200405 Inline recovery for dirty cowfiles. Gerlof Langeveld
-** 200502 Redesign to support more cowdevices. Gerlof Langeveld
-** 200502 Support devices/file > 2 Gbytes. Gerlof Langeveld
-** 200507 Check for free space to expand cowfile. Gerlof Langeveld
-** 200902 Upgrade for kernel 2.6.28 Hendrik-Jan Thomassen
-**
-** Inspired by
-** loop.c by Theodore Ts'o and
-** cloop.c by Paul `Rusty' Russell & Klaus Knopper.
-**
-** Design-considerations:
-**
-** For the first experiments with the cowloop-driver, the request-queue
-** made use of the do_generic_file_read() which worked fine except
-** in combination with the cloop-driver; that combination
-** resulted in a non-interruptible hangup of the system during
-** heavy load. Other experiments using the `make_request' interface also
-** resulted in unpredictable system hangups (with proper use of spinlocks).
-**
-** To overcome these problems, the cowloop-driver starts a kernel-thread
-** for every active cowdevice.
-** All read- and write-request on the read-only file and copy-on-write file
-** are handled in the context of that thread.
-** A scheme has been designed to wakeup the kernel-thread as
-** soon as I/O-requests are available in the request-queue; this thread
-** handles the requests one-by-one by calling the proper read- or
-** write-function related to the open read-only file or copy-on-write file.
-** When all pending requests have been handled, the kernel-thread goes
-** back to sleep-state.
-** This approach requires some additional context-switches; however the
-** performance loss during heavy I/O is less than 3%.
-**
-** -------------------------------------------------------------------------*/
-/* The following is the cowloop package version number. It must be
- identical to the content of the include-file "version.h" that is
- used in all supporting utilities: */
-char revision[] = "$Revision: 3.1 $"; /* cowlo_init_module() has
- assumptions about this string's format */
-
-/* Note that the following numbers are *not* the cowloop package version
- numbers, but separate revision history numbers to track the
- modifications of this particular source file: */
-/* $Log: cowloop.c,v $
-**
-** Revision 1.30 2009/02/08 hjt
-** Integrated earlier fixes
-** Upgraded to kernel 2.6.28 (thanks Jerome Poulin)
-**
-** Revision 1.29 2006/12/03 22:12:00 hjt
-** changed 'cowdevlock' from spinlock to semaphore, to avoid
-** "scheduling while atomic". Contributed by Juergen Christ.
-** Added version.h again
-**
-** Revision 1.28 2006/08/16 16:00:00 hjt
-** malloc each individual cowloopdevice struct separately
-**
-** Revision 1.27 2006/03/14 14:57:03 root
-** Removed include version.h
-**
-** Revision 1.26 2005/08/08 11:22:48 root
-** Implement possibility to close a cow file or reopen a cowfile read-only.
-**
-** Revision 1.25 2005/08/03 14:00:39 root
-** Added modinfo info to driver.
-**
-** Revision 1.24 2005/07/21 06:14:53 root
-** Cosmetic changes source code.
-**
-** Revision 1.23 2005/07/20 13:07:32 root
-** Supply ioctl to write watchdog program to react on lack of cowfile space.
-**
-** Revision 1.22 2005/07/20 07:53:34 root
-** Regular verification of free space in filesystem holding the cowfile
-** (give warnings whenever space is almost exhausted).
-** Terminology change: checksum renamed to fingerprint.
-**
-** Revision 1.21 2005/07/19 09:21:52 root
-** Removing maximum limit of 16 Gb per cowdevice.
-**
-** Revision 1.20 2005/07/19 07:50:33 root
-** Minor bugfixes and cosmetic changes.
-**
-** Revision 1.19 2005/06/10 12:29:55 root
-** Removed lock/unlock operation from cowlo_open().
-**
-** Revision 1.18 2005/05/09 12:56:26 root
-** Allow a cowdevice to be open more than once
-** (needed for support of ReiserFS and XFS).
-**
-** Revision 1.17 2005/03/17 14:36:16 root
-** Fixed some license issues.
-**
-** Revision 1.16 2005/03/07 14:42:05 root
-** Only allow one parallel open per cowdevice.
-**
-** Revision 1.15 2005/02/18 11:52:04 gerlof
-** Redesign to support more than one cowdevice > 2 Gb space.
-**
-** Revision 1.14 2004/08/17 14:19:16 gerlof
-** Modified output of /proc/cowloop.
-**
-** Revision 1.13 2004/08/16 07:21:10 gerlof
-** Separate statistical counter for read on rdofile and cowfile.
-**
-** Revision 1.12 2004/08/11 06:52:11 gerlof
-** Modified messages.
-**
-** Revision 1.11 2004/08/11 06:44:11 gerlof
-** Modified log messages.
-**
-** Revision 1.10 2004/08/10 12:27:27 gerlof
-** Cosmetic changes.
-**
-** Revision 1.9 2004/08/09 11:43:37 gerlof
-** Removed double definition of major number (COWMAJOR).
-**
-** Revision 1.8 2004/08/09 08:03:39 gerlof
-** Cleanup of messages.
-**
-** Revision 1.7 2004/05/27 06:37:33 gerlof
-** Modified /proc message.
-**
-** Revision 1.6 2004/05/26 21:23:28 gerlof
-** Modified /proc output.
-**
-** Revision 1.5 2004/05/26 13:23:34 gerlof
-** Support cowsync to force flushing the bitmaps and cowhead.
-**
-** Revision 1.4 2004/05/26 11:11:10 gerlof
-** Updated the comment to the actual situation.
-**
-** Revision 1.3 2004/05/26 10:50:00 gerlof
-** Implemented recovery-option.
-**
-** Revision 1.2 2004/05/25 15:14:41 gerlof
-** Modified bitmap flushing strategy.
-**
-*/
-
-#define COWMAJOR 241
-
-// #define COWDEBUG
-
-#ifdef COWDEBUG
-#define DEBUGP printk
-#define DCOW KERN_ALERT
-#else
-#define DEBUGP(format, x...)
-#endif
-
-#include <linux/types.h>
-#include <linux/autoconf.h>
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/semaphore.h>
-#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
-#include <linux/blkdev.h>
-#include <linux/buffer_head.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/statfs.h>
-
-#include "cowloop.h"
-
-MODULE_LICENSE("GPL");
-/* MODULE_AUTHOR("Gerlof Langeveld <gerlof@ATComputing.nl>"); obsolete address */
-MODULE_AUTHOR("Hendrik-Jan Thomassen <hjt@ATComputing.nl>"); /* current maintainer */
-MODULE_DESCRIPTION("Copy-on-write loop driver");
-MODULE_PARM_DESC(maxcows, " Number of configured cowdevices (default 16)");
-MODULE_PARM_DESC(rdofile, " Read-only file for /dev/cow/0");
-MODULE_PARM_DESC(cowfile, " Cowfile for /dev/cow/0");
-MODULE_PARM_DESC(option, " Repair cowfile if inconsistent: option=r");
-
-#define DEVICE_NAME "cow"
-
-#define DFLCOWS 16 /* default cowloop devices */
-
-static int maxcows = DFLCOWS;
-module_param(maxcows, int, 0);
-static char *rdofile = "";
-module_param(rdofile, charp, 0);
-static char *cowfile = "";
-module_param(cowfile, charp, 0);
-static char *option = "";
-module_param(option, charp, 0);
-
-/*
-** per cowdevice several bitmap chunks are allowed of MAPCHUNKSZ each
-**
-** each bitmap chunk can describe MAPCHUNKSZ * 8 * MAPUNIT bytes of data
-** suppose:
-** MAPCHUNKSZ 4096 and MAPUNIT 1024 --> 4096 * 8 * 1024 = 32 Mb per chunk
-*/
-#define MAPCHUNKSZ 4096 /* #bytes per bitmap chunk (do not change) */
-
-#define SPCMINBLK 100 /* space threshold to give warning messages */
-#define SPCDFLINTVL 16 /* once every SPCDFLINTVL writes to cowfile, */
- /* available space in filesystem is checked */
-
-#define CALCMAP(x) ((x)/(MAPCHUNKSZ*8))
-#define CALCBYTE(x) (((x)%(MAPCHUNKSZ*8))>>3)
-#define CALCBIT(x) ((x)&7)
-
-#define ALLCOW 1
-#define ALLRDO 2
-#define MIXEDUP 3
-
-static char allzeroes[MAPUNIT];
-
-/*
-** administration per cowdevice (pair of cowfile/rdofile)
-*/
-
-/* bit-values for state */
-#define COWDEVOPEN 0x01 /* cowdevice opened */
-#define COWRWCOWOPEN 0x02 /* cowfile opened read-write */
-#define COWRDCOWOPEN 0x04 /* cowfile opened read-only */
-#define COWWATCHDOG 0x08 /* ioctl for watchdog cowfile space active */
-
-#define COWCOWOPEN (COWRWCOWOPEN|COWRDCOWOPEN)
-
-struct cowloop_device
-{
- /*
- ** current status
- */
- int state; /* bit-values (see above) */
- int opencnt; /* # opens for cowdevice */
-
- /*
- ** open file pointers
- */
- struct file *rdofp, *cowfp; /* open file pointers */
- char *rdoname, *cowname; /* file names */
-
- /*
- ** request queue administration
- */
- struct request_queue *rqueue;
- spinlock_t rqlock;
- struct gendisk *gd;
-
- /*
- ** administration about read-only file
- */
- unsigned int numblocks; /* # blocks input file in MAPUNIT */
- unsigned int blocksz; /* minimum unit to access this dev */
- unsigned long fingerprint; /* fingerprint of current rdofile */
- struct block_device *belowdev; /* block device below us */
- struct gendisk *belowgd; /* gendisk for blk dev below us */
- struct request_queue *belowq; /* req. queue of blk dev below us */
-
- /*
- ** bitmap administration to register which blocks are modified
- */
- long int mapsize; /* total size of bitmap (bytes) */
- long int mapremain; /* remaining bytes in last bitmap */
- int mapcount; /* number of bitmaps in use */
- char **mapcache; /* area with pointers to bitmaps */
-
- char *iobuf; /* databuffer of MAPUNIT bytes */
- struct cowhead *cowhead; /* buffer containing cowhead */
-
- /*
- ** administration for interface with the kernel-thread
- */
- int pid; /* pid==0: no thread available */
- struct request *req; /* request to be handled now */
- wait_queue_head_t waitq; /* wait-Q: thread waits for work */
- char closedown; /* boolean: thread exit required */
- char qfilled; /* boolean: I/O request pending */
- char iobusy; /* boolean: req under treatment */
-
- /*
- ** administration to keep track of free space in cowfile filesystem
- */
- unsigned long blksize; /* block size of fs (bytes) */
- unsigned long blktotal; /* recent total space in fs (blocks) */
- unsigned long blkavail; /* recent free space in fs (blocks) */
-
- wait_queue_head_t watchq; /* wait-Q: watcher awaits threshold */
- unsigned long watchthresh; /* threshold of watcher (blocks) */
-
- /*
- ** statistical counters
- */
- unsigned long rdoreads; /* number of read-actions rdo */
- unsigned long cowreads; /* number of read-actions cow */
- unsigned long cowwrites; /* number of write-actions */
- unsigned long nrcowblocks; /* number of blocks in use on cow */
-};
-
-static struct cowloop_device **cowdevall; /* ptr to ptrs to all cowdevices */
-static struct semaphore cowdevlock; /* generic lock for cowdevs */
-
-static struct gendisk *cowctlgd; /* gendisk control channel */
-static spinlock_t cowctlrqlock; /* for req.q. of ctrl. channel */
-
-/*
-** private directory /proc/cow
-*/
-struct proc_dir_entry *cowlo_procdir;
-
-/*
-** function prototypes
-*/
-static long int cowlo_do_request (struct request *req);
-static void cowlo_sync (void);
-static int cowlo_checkio (struct cowloop_device *, int, loff_t);
-static int cowlo_readmix (struct cowloop_device *, void *, int, loff_t);
-static int cowlo_writemix (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readrdo (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readcow (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readcowraw (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_writecow (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_writecowraw(struct cowloop_device *, void *, int, loff_t);
-static int cowlo_ioctl (struct block_device *, fmode_t,
- unsigned int, unsigned long);
-static int cowlo_makepair (struct cowpair __user *);
-static int cowlo_removepair (unsigned long __user *);
-static int cowlo_watch (struct cowpair __user *);
-static int cowlo_cowctl (unsigned long __user *, int);
-static int cowlo_openpair (char *, char *, int, int);
-static int cowlo_closepair (struct cowloop_device *);
-static int cowlo_openrdo (struct cowloop_device *, char *);
-static int cowlo_opencow (struct cowloop_device *, char *, int);
-static void cowlo_undo_openrdo(struct cowloop_device *);
-static void cowlo_undo_opencow(struct cowloop_device *);
-
-/*****************************************************************************/
-/* System call handling */
-/*****************************************************************************/
-
-/*
-** handle system call open()/mount()
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int cowlo_open(struct block_device *bdev, fmode_t mode)
-{
- struct inode *inode = bdev->bd_inode;
-
- if (!inode)
- return -EINVAL;
-
- if (imajor(inode) != COWMAJOR) {
- printk(KERN_WARNING
- "cowloop - unexpected major %d\n", imajor(inode));
- return -ENODEV;
- }
-
- switch (iminor(inode)) {
- case COWCTL:
- DEBUGP(DCOW"cowloop - open %d control\n", COWCTL);
- break;
-
- default:
- DEBUGP(DCOW"cowloop - open minor %d\n", iminor(inode));
-
- if ( iminor(inode) >= maxcows )
- return -ENODEV;
-
- if ( !((cowdevall[iminor(inode)])->state & COWDEVOPEN) )
- return -ENODEV;
-
- (cowdevall[iminor(inode)])->opencnt++;
- }
-
- return 0;
-}
-
-/*
-** handle system call close()/umount()
-**
-** returns:
-** 0 - okay
-*/
-static int cowlo_release(struct gendisk *gd, fmode_t mode)
-{
- struct block_device *bdev;
- struct inode *inode;
-
- bdev = bdget_disk(gd, 0);
- inode = bdev->bd_inode;
- if (!inode)
- return 0;
-
- DEBUGP(DCOW"cowloop - release (close) minor %d\n", iminor(inode));
-
- if ( iminor(inode) != COWCTL)
- (cowdevall[iminor(inode)])->opencnt--;
-
- return 0;
-}
-
-/*
-** handle system call ioctl()
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int cowlo_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- struct hd_geometry geo;
- struct inode *inode = bdev->bd_inode;
-
- DEBUGP(DCOW "cowloop - ioctl cmd %x\n", cmd);
-
- switch ( iminor(inode) ) {
-
- /*
- ** allowed via control device only
- */
- case COWCTL:
- switch (cmd) {
- /*
- ** write all bitmap chunks and cowheaders to cowfiles
- */
- case COWSYNC:
- down(&cowdevlock);
- cowlo_sync();
- up(&cowdevlock);
- return 0;
-
- /*
- ** open a new cowdevice (pair of rdofile/cowfile)
- */
- case COWMKPAIR:
- return cowlo_makepair((void __user *)arg);
-
- /*
- ** close a cowdevice (pair of rdofile/cowfile)
- */
- case COWRMPAIR:
- return cowlo_removepair((void __user *)arg);
-
- /*
- ** watch free space of filesystem containing cowfile
- */
- case COWWATCH:
- return cowlo_watch((void __user *)arg);
-
- /*
- ** close cowfile for active device
- */
- case COWCLOSE:
- return cowlo_cowctl((void __user *)arg, COWCLOSE);
-
- /*
- ** reopen cowfile read-only for active device
- */
- case COWRDOPEN:
- return cowlo_cowctl((void __user *)arg, COWRDOPEN);
-
- default:
- return -EINVAL;
- } /* end of switch on command */
-
- /*
- ** allowed for any other cowdevice
- */
- default:
- switch (cmd) {
- /*
- ** HDIO_GETGEO must be supported for fdisk, etc
- */
- case HDIO_GETGEO:
- geo.cylinders = 0;
- geo.heads = 0;
- geo.sectors = 0;
-
- if (copy_to_user((void __user *)arg, &geo, sizeof geo))
- return -EFAULT;
- return 0;
-
- default:
- return -EINVAL;
- } /* end of switch on ioctl-cmd code parameter */
- } /* end of switch on minor number */
-}
-
-static struct block_device_operations cowlo_fops =
-{
- .owner = THIS_MODULE,
- .open = cowlo_open, /* called upon open */
- .release = cowlo_release, /* called upon close */
- .ioctl = cowlo_ioctl, /* called upon ioctl */
-};
-
-/*
-** handle ioctl-command COWMKPAIR:
-** open a new cowdevice (pair of rdofile/cowfile) on-the-fly
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_makepair(struct cowpair __user *arg)
-{
- int i, rv=0;
- struct cowpair cowpair;
- unsigned char *cowpath;
- unsigned char *rdopath;
-
- /*
- ** retrieve info about pathnames
- */
- if ( copy_from_user(&cowpair, arg, sizeof cowpair) )
- return -EFAULT;
-
- if ( (MAJOR(cowpair.device) != COWMAJOR) && (cowpair.device != ANYDEV) )
- return -EINVAL;
-
- if ( (MINOR(cowpair.device) >= maxcows) && (cowpair.device != ANYDEV) )
- return -EINVAL;
-
- /*
- ** retrieve pathname strings
- */
- if ( (cowpair.cowflen > PATH_MAX) || (cowpair.rdoflen > PATH_MAX) )
- return -ENAMETOOLONG;
-
- if ( !(cowpath = kmalloc(cowpair.cowflen+1, GFP_KERNEL)) )
- return -ENOMEM;
-
- if ( copy_from_user(cowpath, (void __user *)cowpair.cowfile,
- cowpair.cowflen) ) {
- kfree(cowpath);
- return -EFAULT;
- }
- *(cowpath+cowpair.cowflen) = 0;
-
- if ( !(rdopath = kmalloc(cowpair.rdoflen+1, GFP_KERNEL)) ) {
- kfree(cowpath);
- return -ENOMEM;
- }
-
- if ( copy_from_user(rdopath, (void __user *)cowpair.rdofile,
- cowpair.rdoflen) ) {
- kfree(rdopath);
- kfree(cowpath);
- return -EFAULT;
- }
- *(rdopath+cowpair.rdoflen) = 0;
-
- /*
- ** open new cowdevice
- */
- if ( cowpair.device == ANYDEV) {
- /*
- ** search first unused minor
- */
- for (i=0, rv=-EBUSY; i < maxcows; i++) {
- if ( !((cowdevall[i])->state & COWDEVOPEN) ) {
- rv = cowlo_openpair(rdopath, cowpath, 0, i);
- break;
- }
- }
-
- if (rv) { /* open failed? */
- kfree(rdopath);
- kfree(cowpath);
- return rv;
- }
-
- /*
- ** return newly allocated cowdevice to user space
- */
- cowpair.device = MKDEV(COWMAJOR, i);
-
- if ( copy_to_user(arg, &cowpair, sizeof cowpair)) {
- kfree(rdopath);
- kfree(cowpath);
- return -EFAULT;
- }
- } else { /* specific minor requested */
- if ( (rv = cowlo_openpair(rdopath, cowpath, 0,
- MINOR(cowpair.device)))) {
- kfree(rdopath);
- kfree(cowpath);
- return rv;
- }
- }
-
- return 0;
-}
-
-/*
-** handle ioctl-command COWRMPAIR:
-** deactivate an existing cowdevice (pair of rdofile/cowfile) on-the-fly
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_removepair(unsigned long __user *arg)
-{
- unsigned long cowdevice;
- struct cowloop_device *cowdev;
-
- /*
- ** retrieve info about device to be removed
- */
- if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
- return -EFAULT;
-
- /*
- ** verify major-minor number
- */
- if ( MAJOR(cowdevice) != COWMAJOR)
- return -EINVAL;
-
- if ( MINOR(cowdevice) >= maxcows)
- return -EINVAL;
-
- cowdev = cowdevall[MINOR(cowdevice)];
-
- if ( !(cowdev->state & COWDEVOPEN) )
- return -ENODEV;
-
- /*
- ** synchronize bitmaps and close cowdevice
- */
- if (cowdev->state & COWRWCOWOPEN) {
- down(&cowdevlock);
- cowlo_sync();
- up(&cowdevlock);
- }
-
- return cowlo_closepair(cowdev);
-}
-
-/*
-** handle ioctl-command COWWATCH:
-** watch the free space of the filesystem containing a cowfile
-** of an open cowdevice
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_watch(struct cowpair __user *arg)
-{
- struct cowloop_device *cowdev;
- struct cowwatch cowwatch;
-
- /*
- ** retrieve structure holding info
- */
- if ( copy_from_user(&cowwatch, arg, sizeof cowwatch))
- return -EFAULT;
-
- /*
- ** verify if cowdevice exists and is currently open
- */
- if ( MINOR(cowwatch.device) >= maxcows)
- return -EINVAL;
-
- cowdev = cowdevall[MINOR(cowwatch.device)];
-
- if ( !(cowdev->state & COWDEVOPEN) )
- return -ENODEV;
-
- /*
- ** if the WATCHWAIT-option is set, wait until the indicated
- ** threshold is reached (only one waiter allowed)
- */
- if (cowwatch.flags & WATCHWAIT) {
- /*
- ** check if already another waiter active
- ** for this cowdevice
- */
- if (cowdev->state & COWWATCHDOG)
- return -EAGAIN;
-
- cowdev->state |= COWWATCHDOG;
-
- cowdev->watchthresh = (unsigned long long)
- cowwatch.threshold /
- (cowdev->blksize / 1024);
-
- if (wait_event_interruptible(cowdev->watchq,
- cowdev->watchthresh >= cowdev->blkavail)) {
- cowdev->state &= ~COWWATCHDOG;
- return EINTR;
- }
-
- cowdev->state &= ~COWWATCHDOG;
- }
-
- cowwatch.totalkb = (unsigned long long)cowdev->blktotal *
- cowdev->blksize / 1024;
- cowwatch.availkb = (unsigned long long)cowdev->blkavail *
- cowdev->blksize / 1024;
-
- if ( copy_to_user(arg, &cowwatch, sizeof cowwatch))
- return -EFAULT;
-
- return 0;
-}
-
-/*
-** handle ioctl-commands COWCLOSE and COWRDOPEN:
-** COWCLOSE - close the cowfile while the cowdevice remains open;
-** this allows an unmount of the filesystem on which
-** the cowfile resides
-** COWRDOPEN - close the cowfile and reopen it for read-only;
-** this allows a remount read-ony of the filesystem
-** on which the cowfile resides
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_cowctl(unsigned long __user *arg, int cmd)
-{
- struct cowloop_device *cowdev;
- unsigned long cowdevice;
-
- /*
- ** retrieve info about device to be removed
- */
- if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
- return -EFAULT;
-
- /*
- ** verify major-minor number
- */
- if ( MAJOR(cowdevice) != COWMAJOR)
- return -EINVAL;
-
- if ( MINOR(cowdevice) >= maxcows)
- return -EINVAL;
-
- cowdev = cowdevall[MINOR(cowdevice)];
-
- if ( !(cowdev->state & COWDEVOPEN) )
- return -ENODEV;
-
- /*
- ** synchronize bitmaps and close cowfile
- */
- if (cowdev->state & COWRWCOWOPEN) {
- down(&cowdevlock);
- cowlo_sync();
- up(&cowdevlock);
- }
-
- /*
- ** handle specific ioctl-command
- */
- switch (cmd) {
- case COWRDOPEN:
- /*
- ** if the cowfile is still opened read-write
- */
- if (cowdev->state & COWRWCOWOPEN) {
- /*
- ** close the cowfile
- */
- if (cowdev->cowfp)
- filp_close(cowdev->cowfp, 0);
-
- cowdev->state &= ~COWRWCOWOPEN;
-
- /*
- ** open again for read-only
- */
- cowdev->cowfp = filp_open(cowdev->cowname,
- O_RDONLY|O_LARGEFILE, 0600);
-
- if ( (cowdev->cowfp == NULL) || IS_ERR(cowdev->cowfp) ) {
- printk(KERN_ERR
- "cowloop - failed to reopen cowfile %s\n",
- cowdev->cowname);
- return -EINVAL;
- }
-
- /*
- ** mark cowfile open for read-only
- */
- cowdev->state |= COWRDCOWOPEN;
- } else {
- return -EINVAL;
- }
- break;
-
- case COWCLOSE:
- /*
- ** if the cowfile is still open
- */
- if (cowdev->state & COWCOWOPEN) {
- /*
- ** close the cowfile
- */
- if (cowdev->cowfp)
- filp_close(cowdev->cowfp, 0);
-
- cowdev->state &= ~COWCOWOPEN;
- }
- }
-
- return 0;
-}
-
-
-/*****************************************************************************/
-/* Handling of I/O-requests for a cowdevice */
-/*****************************************************************************/
-
-/*
-** function to be called by core-kernel to handle the I/O-requests
-** in the queue
-*/
-static void cowlo_request(struct request_queue *q)
-{
- struct request *req;
- struct cowloop_device *cowdev;
-
- DEBUGP(DCOW "cowloop - request function called....\n");
-
- while((req = blk_peek_request(q)) != NULL) {
- DEBUGP(DCOW "cowloop - got next request\n");
-
- if (! blk_fs_request(req)) {
- /* this is not a normal file system request */
- __blk_end_request_cur(req, -EIO);
- continue;
- }
- cowdev = req->rq_disk->private_data;
-
- if (cowdev->iobusy)
- return;
- else
- cowdev->iobusy = 1;
-
- /*
- ** when no kernel-thread is available, the request will
- ** produce an I/O-error
- */
- if (!cowdev->pid) {
- printk(KERN_ERR"cowloop - no thread available\n");
- __blk_end_request_cur(req, -EIO); /* request failed */
- cowdev->iobusy = 0;
- continue;
- }
-
- /*
- ** handle I/O-request in the context of the kernel-thread
- */
- cowdev->req = req;
- cowdev->qfilled = 1;
-
- wake_up_interruptible_sync(&cowdev->waitq);
-
- /*
- ** get out of this function now while the I/O-request is
- ** under treatment of the kernel-thread; this function
- ** will be called again after the current I/O-request has
- ** been finished by the thread
- */
- return;
- }
-}
-
-/*
-** daemon-process (kernel-thread) executes this function
-*/
-static int
-cowlo_daemon(struct cowloop_device *cowdev)
-{
- int rv;
- int minor;
- char myname[16];
-
- for (minor = 0; minor < maxcows; minor++) {
- if (cowdev == cowdevall[minor]) break;
- }
- sprintf(myname, "cowloopd%d", minor);
-
- daemonize(myname);
-
- while (!cowdev->closedown) {
- /*
- ** sleep while waiting for an I/O request;
- ** note that no non-interruptible wait has been used
- ** because the non-interruptible version of
- ** a *synchronous* wake_up does not exist (any more)
- */
- if (wait_event_interruptible(cowdev->waitq, cowdev->qfilled)){
- flush_signals(current); /* ignore signal-based wakeup */
- continue;
- }
-
- if (cowdev->closedown) /* module will be unloaded ? */{
- cowdev->pid = 0;
- return 0;
- }
-
- /*
- ** woken up by the I/O-request handler: treat requested I/O
- */
- cowdev->qfilled = 0;
-
- rv = cowlo_do_request(cowdev->req);
-
- /*
- ** reacquire the queue-spinlock for manipulating
- ** the request-queue and dequeue the request
- */
- spin_lock_irq(&cowdev->rqlock);
-
- __blk_end_request_cur(cowdev->req, rv);
- cowdev->iobusy = 0;
-
- /*
- ** initiate the next request from the queue
- */
- cowlo_request(cowdev->rqueue);
-
- spin_unlock_irq(&cowdev->rqlock);
- }
- return 0;
-}
-
-/*
-** function to be called in the context of the kernel thread
-** to handle the queued I/O-requests
-**
-** returns:
-** 0 - fail
-** 1 - success
-*/
-static long int
-cowlo_do_request(struct request *req)
-{
- unsigned long len;
- long int rv;
- loff_t offset;
- struct cowloop_device *cowdev = req->rq_disk->private_data;
-
- /*
- ** calculate some variables which are needed later on
- */
- len = blk_rq_cur_sectors(req) << 9;
- offset = (loff_t) blk_rq_pos(req) << 9;
-
- DEBUGP(DCOW"cowloop - req cmd=%d offset=%lld len=%lu addr=%p\n",
- *(req->cmd), offset, len, req->buffer);
-
- /*
- ** handle READ- or WRITE-request
- */
- switch (rq_data_dir(req)) {
- /**********************************************************/
- case READ:
- switch ( cowlo_checkio(cowdev, len, offset) ) {
- case ALLCOW:
- rv = cowlo_readcow(cowdev, req->buffer, len, offset);
- break;
-
- case ALLRDO:
- rv = cowlo_readrdo(cowdev, req->buffer, len, offset);
- break;
-
- case MIXEDUP:
- rv = cowlo_readmix(cowdev, req->buffer, len, offset);
- break;
-
- default:
- rv = 0; /* never happens */
- }
- break;
-
- /**********************************************************/
- case WRITE:
- switch ( cowlo_checkio(cowdev, len, offset) ) {
- case ALLCOW:
- /*
- ** straight-forward write will do...
- */
- DEBUGP(DCOW"cowloop - write straight ");
-
- rv = cowlo_writecow(cowdev, req->buffer, len, offset);
- break; /* from switch */
-
- case ALLRDO:
- if ( (len & MUMASK) == 0) {
- DEBUGP(DCOW"cowloop - write straight ");
-
- rv = cowlo_writecow(cowdev, req->buffer,
- len, offset);
- break;
- }
-
- case MIXEDUP:
- rv = cowlo_writemix(cowdev, req->buffer, len, offset);
- break;
-
- default:
- rv = 0; /* never happens */
- }
- break;
-
- default:
- printk(KERN_ERR
- "cowloop - unrecognized command %d\n", *(req->cmd));
- rv = 0;
- }
-
- return (rv <= 0 ? 0 : 1);
-}
-
-/*
-** check for a given I/O-request if all underlying blocks
-** (with size MAPUNIT) are either in the read-only file or in
-** the cowfile (or a combination of the two)
-**
-** returns:
-** ALLRDO - all underlying blocks in rdofile
-** ALLCOW - all underlying blocks in cowfile
-** MIXEDUP - underlying blocks partly in rdofile and partly in cowfile
-*/
-static int
-cowlo_checkio(struct cowloop_device *cowdev, int len, loff_t offset)
-{
- unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
- long int totcnt, cowcnt;
- char *mc;
-
- /*
- ** notice that the requested block might cross
- ** a blocksize boundary while one of the concerned
- ** blocks resides in the read-only file and another
- ** one in the copy-on-write file; in that case the
- ** request will be broken up into pieces
- */
- if ( (len <= MAPUNIT) &&
- (MAPUNIT - (offset & MUMASK) <= len) ) {
- /*
- ** easy situation:
- ** requested data-block entirely fits within
- ** the mapunit used for the bitmap
- ** check if that block is located in rdofile or
- ** cowfile
- */
- blocknr = offset >> MUSHIFT;
-
- mapnum = CALCMAP (blocknr);
- bytenum = CALCBYTE(blocknr);
- bitnum = CALCBIT (blocknr);
-
- if (*(*(cowdev->mapcache+mapnum)+bytenum)&(1<<bitnum))
- return ALLCOW;
- else
- return ALLRDO;
- }
-
- /*
- ** less easy situation:
- ** the requested data-block does not fit within the mapunit
- ** used for the bitmap
- ** check if *all* underlying blocks involved reside on the rdofile
- ** or the cowfile (so still no breakup required)
- */
- for (cowcnt=totcnt=0; len > 0; len-=partlen, offset+=partlen, totcnt++){
- /*
- ** calculate blocknr of involved block
- */
- blocknr = offset >> MUSHIFT;
-
- /*
- ** calculate partial length for this transfer
- */
- partlen = MAPUNIT - (offset & MUMASK);
- if (partlen > len)
- partlen = len;
-
- /*
- ** is this block located in the cowfile
- */
- mapnum = CALCMAP (blocknr);
- bytenum = CALCBYTE(blocknr);
- bitnum = CALCBIT (blocknr);
-
- mc = *(cowdev->mapcache+mapnum);
-
- if (*(mc+bytenum)&(1<<bitnum))
- cowcnt++;;
-
- DEBUGP(DCOW
- "cowloop - check %lu - map %lu, byte %lu, bit %lu, "
- "cowcnt %ld, totcnt %ld %02x %p\n",
- blocknr, mapnum, bytenum, bitnum, cowcnt, totcnt,
- *(mc+bytenum), mc);
- }
-
- if (cowcnt == 0) /* all involved blocks on rdofile? */
- return ALLRDO;
-
- if (cowcnt == totcnt) /* all involved blocks on cowfile? */
- return ALLCOW;
-
- /*
- ** situation somewhat more complicated:
- ** involved underlying blocks spread over both files
- */
- return MIXEDUP;
-}
-
-/*
-** read requested chunk partly from rdofile and partly from cowfile
-**
-** returns:
-** 0 - fail
-** 1 - success
-*/
-static int
-cowlo_readmix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
- unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
- long int rv;
- char *mc;
-
- /*
- ** complicated approach: breakup required of read-request
- */
- for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
- /*
- ** calculate blocknr of entire block
- */
- blocknr = offset >> MUSHIFT;
-
- /*
- ** calculate partial length for this transfer
- */
- partlen = MAPUNIT - (offset & MUMASK);
- if (partlen > len)
- partlen = len;
-
- /*
- ** is this block located in the cowfile
- */
- mapnum = CALCMAP (blocknr);
- bytenum = CALCBYTE(blocknr);
- bitnum = CALCBIT (blocknr);
- mc = *(cowdev->mapcache+mapnum);
-
- if (*(mc+bytenum)&(1<<bitnum)) {
- /*
- ** read (partial) block from cowfile
- */
- DEBUGP(DCOW"cowloop - split read "
- "cow partlen=%ld off=%lld\n", partlen, offset);
-
- if (cowlo_readcow(cowdev, buf, partlen, offset) <= 0)
- rv = 0;
- } else {
- /*
- ** read (partial) block from rdofile
- */
- DEBUGP(DCOW"cowloop - split read "
- "rdo partlen=%ld off=%lld\n", partlen, offset);
-
- if (cowlo_readrdo(cowdev, buf, partlen, offset) <= 0)
- rv = 0;
- }
- }
-
- return rv;
-}
-
-/*
-** chunk to be written to the cowfile needs pieces to be
-** read from the rdofile
-**
-** returns:
-** 0 - fail
-** 1 - success
-*/
-static int
-cowlo_writemix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
- unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
- long int rv;
- char *mc;
-
- /*
- ** somewhat more complicated stuff is required:
- ** if the request is larger than one underlying
- ** block or is spread over two underlying blocks,
- ** split the request into pieces; if a block does not
- ** start at a block boundary, take care that
- ** surrounding data is read first (if needed),
- ** fit the new data in and write it as a full block
- */
- for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
- /*
- ** calculate partial length for this transfer
- */
- partlen = MAPUNIT - (offset & MUMASK);
- if (partlen > len)
- partlen = len;
-
- /*
- ** calculate blocknr of entire block
- */
- blocknr = offset >> MUSHIFT;
-
- /*
- ** has this block been written before?
- */
- mapnum = CALCMAP (blocknr);
- bytenum = CALCBYTE(blocknr);
- bitnum = CALCBIT (blocknr);
- mc = *(cowdev->mapcache+mapnum);
-
- if (*(mc+bytenum)&(1<<bitnum)) {
- /*
- ** block has been written before;
- ** write transparantly to cowfile
- */
- DEBUGP(DCOW
- "cowloop - splitwr transp\n");
-
- if (cowlo_writecow(cowdev, buf, partlen, offset) <= 0)
- rv = 0;
- } else {
- /*
- ** block has never been written before,
- ** so read entire block from
- ** read-only file first, unless
- ** a full block is requested to
- ** be written
- */
- if (partlen < MAPUNIT) {
- if (cowlo_readrdo(cowdev, cowdev->iobuf,
- MAPUNIT, (loff_t)blocknr << MUSHIFT) <= 0)
- rv = 0;
- }
-
- /*
- ** transfer modified part into
- ** the block just read
- */
- memcpy(cowdev->iobuf + (offset & MUMASK), buf, partlen);
-
- /*
- ** write entire block to cowfile
- */
- DEBUGP(DCOW"cowloop - split "
- "partlen=%ld off=%lld\n",
- partlen, (loff_t)blocknr << MUSHIFT);
-
- if (cowlo_writecow(cowdev, cowdev->iobuf, MAPUNIT,
- (loff_t)blocknr << MUSHIFT) <= 0)
- rv = 0;
- }
- }
-
- return rv;
-}
-
-/*****************************************************************************/
-/* I/O-support for read-only file and copy-on-write file */
-/*****************************************************************************/
-
-/*
-** read data from the read-only file
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readrdo(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
- long int rv;
- mm_segment_t old_fs;
- loff_t saveoffset = offset;
-
- DEBUGP(DCOW"cowloop - readrdo called\n");
-
- old_fs = get_fs();
- set_fs( get_ds() );
- rv = cowdev->rdofp->f_op->read(cowdev->rdofp, buf, len, &offset);
- set_fs(old_fs);
-
- if (rv < len) {
- printk(KERN_WARNING "cowloop - read-failure %ld on rdofile"
- "- offset=%lld len=%d\n",
- rv, saveoffset, len);
- }
-
- cowdev->rdoreads++;
- return rv;
-}
-
-/*
-** read cowfile from a modified offset, i.e. skipping the bitmap and cowhead
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readcow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
- DEBUGP(DCOW"cowloop - readcow called\n");
-
- offset += cowdev->cowhead->doffset;
-
- return cowlo_readcowraw(cowdev, buf, len, offset);
-}
-
-/*
-** read cowfile from an absolute offset
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readcowraw(struct cowloop_device *cowdev,
- void *buf, int len, loff_t offset)
-{
- long int rv;
- mm_segment_t old_fs;
- loff_t saveoffset = offset;
-
- DEBUGP(DCOW"cowloop - readcowraw called\n");
-
- /*
- ** be sure that cowfile is opened for read-write
- */
- if ( !(cowdev->state & COWCOWOPEN) ) {
- printk(KERN_WARNING
- "cowloop - read request from cowfile refused\n");
-
- return -EBADF;
- }
-
- /*
- ** issue low level read
- */
- old_fs = get_fs();
- set_fs( get_ds() );
- rv = cowdev->cowfp->f_op->read(cowdev->cowfp, buf, len, &offset);
- set_fs(old_fs);
-
- if (rv < len) {
- printk(KERN_WARNING
- "cowloop - read-failure %ld on cowfile"
- "- offset=%lld len=%d\n", rv, saveoffset, len);
- }
-
- cowdev->cowreads++;
- return rv;
-}
-
-/*
-** write cowfile from a modified offset, i.e. skipping the bitmap and cowhead
-**
-** if a block is written for the first time while its contents consists
-** of binary zeroes only, the concerning bitmap is flushed to the cowfile
-**
-** return-value: similar to user-mode write
-*/
-static long int
-cowlo_writecow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
- long int rv;
- unsigned long mapnum=0, mapbyte=0, mapbit=0, cowblock=0, partlen;
- char *tmpptr, *mapptr = NULL;
- loff_t tmpoffset, mapoffset = 0;
-
- DEBUGP(DCOW"cowloop - writecow called\n");
-
- /*
- ** be sure that cowfile is opened for read-write
- */
- if ( !(cowdev->state & COWRWCOWOPEN) ) {
- printk(KERN_WARNING
- "cowloop - Write request to cowfile refused\n");
-
- return -EBADF;
- }
-
- /*
- ** write the entire block to the cowfile
- */
- tmpoffset = offset + cowdev->cowhead->doffset;
-
- rv = cowlo_writecowraw(cowdev, buf, len, tmpoffset);
-
- /*
- ** verify if enough space available on filesystem holding
- ** the cowfile
- ** - when the last write failed (might be caused by lack of space)
- ** - when a watcher is active (to react adequatly)
- ** - when the previous check indicated fs was almost full
- ** - with regular intervals
- */
- if ( (rv <= 0) ||
- (cowdev->state & COWWATCHDOG) ||
- (cowdev->blkavail / 2 < SPCDFLINTVL) ||
- (cowdev->cowwrites % SPCDFLINTVL == 0) ) {
- struct kstatfs ks;
-
- if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0){
- if (ks.f_bavail <= SPCMINBLK) {
- switch (ks.f_bavail) {
- case 0:
- case 1:
- case 2:
- case 3:
- printk(KERN_ALERT
- "cowloop - "
- "ALERT: cowfile full!\n");
- break;
-
- default:
- printk(KERN_WARNING
- "cowloop - cowfile almost "
- "full (only %llu Kb free)\n",
- (unsigned long long)
- ks.f_bsize * ks.f_bavail /1024);
- }
- }
-
- cowdev->blktotal = ks.f_blocks;
- cowdev->blkavail = ks.f_bavail;
-
- /*
- ** wakeup watcher if threshold has been reached
- */
- if ( (cowdev->state & COWWATCHDOG) &&
- (cowdev->watchthresh >= cowdev->blkavail) ) {
- wake_up_interruptible(&cowdev->watchq);
- }
- }
- }
-
- if (rv <= 0)
- return rv;
-
- DEBUGP(DCOW"cowloop - block written\n");
-
- /*
- ** check if block(s) is/are written to the cowfile
- ** for the first time; if so, adapt the bitmap
- */
- for (; len > 0; len-=partlen, offset+=partlen, buf+=partlen) {
- /*
- ** calculate partial length for this transfer
- */
- partlen = MAPUNIT - (offset & MUMASK);
- if (partlen > len)
- partlen = len;
-
- /*
- ** calculate bitnr of written chunk of cowblock
- */
- cowblock = offset >> MUSHIFT;
-
- mapnum = CALCMAP (cowblock);
- mapbyte = CALCBYTE(cowblock);
- mapbit = CALCBIT (cowblock);
-
- if (*(*(cowdev->mapcache+mapnum)+mapbyte) & (1<<mapbit))
- continue; /* already written before */
-
- /*
- ** if the block is written for the first time,
- ** the corresponding bit should be set in the bitmap
- */
- *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
-
- cowdev->nrcowblocks++;
-
- DEBUGP(DCOW"cowloop - bitupdate blk=%ld map=%ld "
- "byte=%ld bit=%ld\n",
- cowblock, mapnum, mapbyte, mapbit);
-
- /*
- ** check if the cowhead in the cowfile is currently
- ** marked clean; if so, mark it dirty and flush it
- */
- if ( !(cowdev->cowhead->flags &= COWDIRTY)) {
- cowdev->cowhead->flags |= COWDIRTY;
-
- cowlo_writecowraw(cowdev, cowdev->cowhead,
- MAPUNIT, (loff_t)0);
- }
-
- /*
- ** if the written datablock contained binary zeroes,
- ** the bitmap block should be marked to be flushed to disk
- ** (blocks containing all zeroes cannot be recovered by
- ** the cowrepair-program later on if cowloop is not properly
- ** removed via rmmod)
- */
- if ( memcmp(buf, allzeroes, partlen) ) /* not all zeroes? */
- continue; /* no flush needed */
-
- /*
- ** calculate positions of bitmap block to be flushed
- ** - pointer of bitmap block in memory
- ** - offset of bitmap block in cowfile
- */
- tmpptr = *(cowdev->mapcache+mapnum) + (mapbyte & (~MUMASK));
- tmpoffset = (loff_t) MAPUNIT + mapnum * MAPCHUNKSZ +
- (mapbyte & (~MUMASK));
-
- /*
- ** flush a bitmap block at the moment that all bits have
- ** been set in that block, i.e. at the moment that we
- ** switch to another bitmap block
- */
- if ( (mapoffset != 0) && (mapoffset != tmpoffset) ) {
- if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT,
- mapoffset) < 0) {
- printk(KERN_WARNING
- "cowloop - write-failure on bitmap - "
- "blk=%ld map=%ld byte=%ld bit=%ld\n",
- cowblock, mapnum, mapbyte, mapbit);
- }
-
- DEBUGP(DCOW"cowloop - bitmap blk written %lld\n",
- mapoffset);
- }
-
- /*
- ** remember offset in cowfile and offset in memory
- ** for bitmap to be flushed; flushing will be done
- ** as soon as all updates in this bitmap block have
- ** been done
- */
- mapoffset = tmpoffset;
- mapptr = tmpptr;
- }
-
- /*
- ** any new block written containing binary zeroes?
- */
- if (mapoffset) {
- if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT, mapoffset) < 0) {
- printk(KERN_WARNING
- "cowloop - write-failure on bitmap - "
- "blk=%ld map=%ld byte=%ld bit=%ld\n",
- cowblock, mapnum, mapbyte, mapbit);
- }
-
- DEBUGP(DCOW"cowloop - bitmap block written %lld\n", mapoffset);
- }
-
- return rv;
-}
-
-/*
-** write cowfile from an absolute offset
-**
-** return-value: similar to user-mode write
-*/
-static long int
-cowlo_writecowraw(struct cowloop_device *cowdev,
- void *buf, int len, loff_t offset)
-{
- long int rv;
- mm_segment_t old_fs;
- loff_t saveoffset = offset;
-
- DEBUGP(DCOW"cowloop - writecowraw called\n");
-
- /*
- ** be sure that cowfile is opened for read-write
- */
- if ( !(cowdev->state & COWRWCOWOPEN) ) {
- printk(KERN_WARNING
- "cowloop - write request to cowfile refused\n");
-
- return -EBADF;
- }
-
- /*
- ** issue low level write
- */
- old_fs = get_fs();
- set_fs( get_ds() );
- rv = cowdev->cowfp->f_op->write(cowdev->cowfp, buf, len, &offset);
- set_fs(old_fs);
-
- if (rv < len) {
- printk(KERN_WARNING
- "cowloop - write-failure %ld on cowfile"
- "- offset=%lld len=%d\n", rv, saveoffset, len);
- }
-
- cowdev->cowwrites++;
- return rv;
-}
-
-
-/*
-** readproc-function: called when the corresponding /proc-file is read
-*/
-static int
-cowlo_readproc(char *buf, char **start, off_t pos, int cnt, int *eof, void *p)
-{
- struct cowloop_device *cowdev = p;
-
- revision[sizeof revision - 3] = '\0';
-
- return sprintf(buf,
- " cowloop version: %9s\n\n"
- " device state: %s%s%s%s\n"
- " number of opens: %9d\n"
- " pid of thread: %9d\n\n"
- " read-only file: %9s\n"
- " rdoreads: %9lu\n\n"
- "copy-on-write file: %9s\n"
- " state cowfile: %9s\n"
- " bitmap-blocks: %9lu (of %d bytes)\n"
- " cowblocks in use: %9lu (of %d bytes)\n"
- " cowreads: %9lu\n"
- " cowwrites: %9lu\n",
- &revision[11],
-
- cowdev->state & COWDEVOPEN ? "devopen " : "",
- cowdev->state & COWRWCOWOPEN ? "cowopenrw " : "",
- cowdev->state & COWRDCOWOPEN ? "cowopenro " : "",
- cowdev->state & COWWATCHDOG ? "watchdog " : "",
-
- cowdev->opencnt,
- cowdev->pid,
- cowdev->rdoname,
- cowdev->rdoreads,
- cowdev->cowname,
- cowdev->cowhead->flags & COWDIRTY ? "dirty":"clean",
- cowdev->mapsize >> MUSHIFT, MAPUNIT,
- cowdev->nrcowblocks, MAPUNIT,
- cowdev->cowreads,
- cowdev->cowwrites);
-}
-
-/*****************************************************************************/
-/* Setup and destroy cowdevices */
-/*****************************************************************************/
-
-/*
-** open and prepare a cowdevice (rdofile and cowfile) and allocate bitmaps
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_openpair(char *rdof, char *cowf, int autorecover, int minor)
-{
- long int rv;
- struct cowloop_device *cowdev = cowdevall[minor];
- struct kstatfs ks;
-
- down(&cowdevlock);
-
- /*
- ** requested device exists?
- */
- if (minor >= maxcows) {
- up(&cowdevlock);
- return -ENODEV;
- }
-
- /*
- ** requested device already assigned to cowdevice?
- */
- if (cowdev->state & COWDEVOPEN) {
- up(&cowdevlock);
- return -EBUSY;
- }
-
- /*
- ** initialize administration
- */
- memset(cowdev, 0, sizeof *cowdev);
-
- spin_lock_init (&cowdev->rqlock);
- init_waitqueue_head(&cowdev->waitq);
- init_waitqueue_head(&cowdev->watchq);
-
- /*
- ** open the read-only file
- */
- DEBUGP(DCOW"cowloop - call openrdo....\n");
-
- if ( (rv = cowlo_openrdo(cowdev, rdof)) ) {
- cowlo_undo_openrdo(cowdev);
- up(&cowdevlock);
- return rv;
- }
-
- /*
- ** open the cowfile
- */
- DEBUGP(DCOW"cowloop - call opencow....\n");
-
- if ( (rv = cowlo_opencow(cowdev, cowf, autorecover)) ) {
- cowlo_undo_openrdo(cowdev);
- cowlo_undo_opencow(cowdev);
- up(&cowdevlock);
- return rv;
- }
-
- /*
- ** administer total and available size of filesystem holding cowfile
- */
- if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0) {
- cowdev->blksize = ks.f_bsize;
- cowdev->blktotal = ks.f_blocks;
- cowdev->blkavail = ks.f_bavail;
- } else {
- cowdev->blksize = 1024; /* avoid division by zero */
- }
-
- /*
- ** flush the (recovered) bitmaps and cowhead to the cowfile
- */
- DEBUGP(DCOW"cowloop - call cowsync....\n");
-
- cowlo_sync();
-
- /*
- ** allocate gendisk for the cow device
- */
- DEBUGP(DCOW"cowloop - alloc disk....\n");
-
- if ((cowdev->gd = alloc_disk(1)) == NULL) {
- printk(KERN_WARNING
- "cowloop - unable to alloc_disk for cowloop\n");
-
- cowlo_undo_openrdo(cowdev);
- cowlo_undo_opencow(cowdev);
- up(&cowdevlock);
- return -ENOMEM;
- }
-
- cowdev->gd->major = COWMAJOR;
- cowdev->gd->first_minor = minor;
- cowdev->gd->minors = 1;
- cowdev->gd->fops = &cowlo_fops;
- cowdev->gd->private_data = cowdev;
- sprintf(cowdev->gd->disk_name, "%s%d", DEVICE_NAME, minor);
-
- /* in .5 Kb units */
- set_capacity(cowdev->gd, (cowdev->numblocks*(MAPUNIT/512)));
-
- DEBUGP(DCOW"cowloop - init request queue....\n");
-
- if ((cowdev->rqueue = blk_init_queue(cowlo_request, &cowdev->rqlock))
- == NULL) {
- printk(KERN_WARNING
- "cowloop - unable to get request queue for cowloop\n");
-
- del_gendisk(cowdev->gd);
- cowlo_undo_openrdo(cowdev);
- cowlo_undo_opencow(cowdev);
- up(&cowdevlock);
- return -EINVAL;
- }
-
- blk_queue_logical_block_size(cowdev->rqueue, cowdev->blocksz);
- cowdev->gd->queue = cowdev->rqueue;
-
- /*
- ** start kernel thread to handle requests
- */
- DEBUGP(DCOW"cowloop - kickoff daemon....\n");
-
- cowdev->pid = kernel_thread((int (*)(void *))cowlo_daemon, cowdev, 0);
-
- /*
- ** create a file below directory /proc/cow for this new cowdevice
- */
- if (cowlo_procdir) {
- char tmpname[64];
-
- sprintf(tmpname, "%d", minor);
-
- create_proc_read_entry(tmpname, 0 , cowlo_procdir,
- cowlo_readproc, cowdev);
- }
-
- cowdev->state |= COWDEVOPEN;
-
- cowdev->rdoname = rdof;
- cowdev->cowname = cowf;
-
- /*
- ** enable the new disk; this triggers the first request!
- */
- DEBUGP(DCOW"cowloop - call add_disk....\n");
-
- add_disk(cowdev->gd);
-
- up(&cowdevlock);
- return 0;
-}
-
-/*
-** close a cowdevice (pair of rdofile/cowfile) and release memory
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_closepair(struct cowloop_device *cowdev)
-{
- int minor;
-
- down(&cowdevlock);
-
- /*
- ** if cowdevice is not activated at all, refuse
- */
- if ( !(cowdev->state & COWDEVOPEN) ) {
- up(&cowdevlock);
- return -ENODEV;
- }
-
- /*
- ** if this cowdevice is still open, refuse
- */
- if (cowdev->opencnt > 0) {
- up(&cowdevlock);
- return -EBUSY;
- }
-
- up(&cowdevlock);
-
- /*
- ** wakeup watcher (if any)
- */
- if (cowdev->state & COWWATCHDOG) {
- cowdev->watchthresh = cowdev->blkavail;
- wake_up_interruptible(&cowdev->watchq);
- }
-
- /*
- ** wakeup kernel-thread to be able to exit
- ** and wait until it has exited
- */
- cowdev->closedown = 1;
- cowdev->qfilled = 1;
- wake_up_interruptible(&cowdev->waitq);
-
- while (cowdev->pid)
- schedule();
-
- del_gendisk(cowdev->gd); /* revert the alloc_disk() */
- put_disk(cowdev->gd); /* revert the add_disk() */
-
- if (cowlo_procdir) {
- char tmpname[64];
-
- for (minor = 0; minor < maxcows; minor++) {
- if (cowdev == cowdevall[minor]) break;
- }
- sprintf(tmpname, "%d", minor);
-
- remove_proc_entry(tmpname, cowlo_procdir);
- }
-
- blk_cleanup_queue(cowdev->rqueue);
-
- /*
- ** release memory for filenames if these names have
- ** been allocated dynamically
- */
- if ( (cowdev->cowname) && (cowdev->cowname != cowfile))
- kfree(cowdev->cowname);
-
- if ( (cowdev->rdoname) && (cowdev->rdoname != rdofile))
- kfree(cowdev->rdoname);
-
- cowlo_undo_openrdo(cowdev);
- cowlo_undo_opencow(cowdev);
-
- cowdev->state &= ~COWDEVOPEN;
-
- return 0;
-}
-
-/*
-** open the read-only file
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_openrdo(struct cowloop_device *cowdev, char *rdof)
-{
- struct file *f;
- struct inode *inode;
- long int i, nrval;
-
- DEBUGP(DCOW"cowloop - openrdo called\n");
-
- /*
- ** open the read-only file
- */
- if(*rdof == '\0') {
- printk(KERN_ERR
- "cowloop - specify name for read-only file\n\n");
- return -EINVAL;
- }
-
- f = filp_open(rdof, O_RDONLY|O_LARGEFILE, 0);
-
- if ( (f == NULL) || IS_ERR(f) ) {
- printk(KERN_ERR
- "cowloop - open of rdofile %s failed\n", rdof);
- return -EINVAL;
- }
-
- cowdev->rdofp = f;
-
- inode = f->f_dentry->d_inode;
-
- if ( !S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode) ) {
- printk(KERN_ERR
- "cowloop - %s not regular file or blockdev\n", rdof);
- return -EINVAL;
- }
-
- DEBUGP(DCOW"cowloop - determine size rdo....\n");
-
- /*
- ** determine block-size and total size of read-only file
- */
- if (S_ISREG(inode->i_mode)) {
- /*
- ** read-only file is a regular file
- */
- cowdev->blocksz = 512; /* other value fails */
- cowdev->numblocks = inode->i_size >> MUSHIFT;
-
- if (inode->i_size & MUMASK) {
- printk(KERN_WARNING
- "cowloop - rdofile %s truncated to multiple "
- "of %d bytes\n", rdof, MAPUNIT);
- }
-
- DEBUGP(DCOW"cowloop - RO=regular: numblocks=%d, blocksz=%d\n",
- cowdev->numblocks, cowdev->blocksz);
- } else {
- /*
- ** read-only file is a block device
- */
- cowdev->belowdev = inode->i_bdev;
- cowdev->belowgd = cowdev->belowdev->bd_disk; /* gendisk */
-
- if (cowdev->belowdev->bd_part) {
- cowdev->numblocks = cowdev->belowdev->bd_part->nr_sects
- / (MAPUNIT/512);
- }
-
- if (cowdev->belowgd) {
- cowdev->belowq = cowdev->belowgd->queue;
-
- if (cowdev->numblocks == 0) {
- cowdev->numblocks = get_capacity(cowdev->belowgd)
- / (MAPUNIT/512);
- }
- }
-
-
- if (cowdev->belowq)
- cowdev->blocksz = queue_logical_block_size(cowdev->belowq);
-
- if (cowdev->blocksz == 0)
- cowdev->blocksz = BLOCK_SIZE; /* default 2^10 */
-
- DEBUGP(DCOW"cowloop - numblocks=%d, "
- "blocksz=%d, belowgd=%p, belowq=%p\n",
- cowdev->numblocks, cowdev->blocksz,
- cowdev->belowgd, cowdev->belowq);
-
- DEBUGP(DCOW"cowloop - belowdev.bd_block_size=%d\n",
- cowdev->belowdev->bd_block_size);
- }
-
- if (cowdev->numblocks == 0) {
- printk(KERN_ERR "cowloop - %s has no contents\n", rdof);
- return -EINVAL;
- }
-
- /*
- ** reserve space in memory as generic I/O buffer
- */
- cowdev->iobuf = kmalloc(MAPUNIT, GFP_KERNEL);
-
- if (!cowdev->iobuf) {
- printk(KERN_ERR
- "cowloop - cannot get space for buffer %d\n", MAPUNIT);
- return -ENOMEM;
- }
-
- DEBUGP(DCOW"cowloop - determine fingerprint rdo....\n");
-
- /*
- ** determine fingerprint for read-only file
- ** calculate fingerprint from first four datablocks
- ** which do not contain binary zeroes
- */
- for (i=0, cowdev->fingerprint=0, nrval=0;
- (nrval < 4)&&(i < cowdev->numblocks); i++) {
- int j;
- unsigned char cs;
-
- /*
- ** read next block
- */
- if (cowlo_readrdo(cowdev, cowdev->iobuf, MAPUNIT,
- (loff_t)i << MUSHIFT) < 1)
- break;
-
- /*
- ** calculate fingerprint by adding all byte-values
- */
- for (j=0, cs=0; j < MAPUNIT; j++)
- cs += *(cowdev->iobuf+j);
-
- if (cs == 0) /* block probably contained zeroes */
- continue;
-
- /*
- ** shift byte-value to proper place in final fingerprint
- */
- cowdev->fingerprint |= cs << (nrval*8);
- nrval++;
- }
-
- return 0;
-}
-
-/*
-** undo memory allocs and file opens issued so far
-** related to the read-only file
-*/
-static void
-cowlo_undo_openrdo(struct cowloop_device *cowdev)
-{
- if(cowdev->iobuf);
- kfree(cowdev->iobuf);
-
- if (cowdev->rdofp)
- filp_close(cowdev->rdofp, 0);
-}
-
-/*
-** open the cowfile
-**
-** returns:
-** 0 - okay
-** < 0 - error value
-*/
-static int
-cowlo_opencow(struct cowloop_device *cowdev, char *cowf, int autorecover)
-{
- long int i, rv;
- int minor;
- unsigned long nb;
- struct file *f;
- struct inode *inode;
- loff_t offset;
- struct cowloop_device *cowtmp;
-
- DEBUGP(DCOW"cowloop - opencow called\n");
-
- /*
- ** open copy-on-write file (read-write)
- */
- if (cowf[0] == '\0') {
- printk(KERN_ERR
- "cowloop - specify name of copy-on-write file\n\n");
- return -EINVAL;
- }
-
- f = filp_open(cowf, O_RDWR|O_LARGEFILE, 0600);
-
- if ( (f == NULL) || IS_ERR(f) ) {
- /*
- ** non-existing cowfile: try to create
- */
- f = filp_open(cowf, O_RDWR|O_CREAT|O_LARGEFILE, 0600);
-
- if ( (f == NULL) || IS_ERR(f) ) {
- printk(KERN_ERR
- "cowloop - failed to open file %s for read-write\n\n",
- cowf);
- return -EINVAL;
- }
- }
-
- cowdev->cowfp = f;
-
- inode = f->f_dentry->d_inode;
-
- if (!S_ISREG(inode->i_mode)) {
- printk(KERN_ERR "cowloop - %s is not regular file\n", cowf);
- return -EINVAL;
- }
-
- /*
- ** check if this cowfile is already in use for another cowdevice
- */
- for (minor = 0; minor < maxcows; minor++) {
-
- cowtmp = cowdevall[minor];
-
- if ( !(cowtmp->state & COWDEVOPEN) )
- continue;
-
- if (cowtmp == cowdev)
- continue;
-
- if (cowtmp->cowfp->f_dentry->d_inode == f->f_dentry->d_inode) {
- printk(KERN_ERR
- "cowloop - %s: already in use as cow\n", cowf);
- return -EBUSY;
- }
- }
-
- /*
- ** mark cowfile open for read-write
- */
- cowdev->state |= COWRWCOWOPEN;
-
- /*
- ** calculate size (in bytes) for total bitmap in cowfile;
- ** when the size of the cowhead block is added, the start-offset
- ** for the modified data blocks can be found
- */
- nb = cowdev->numblocks;
-
- if (nb%8) /* transform #bits to #bytes */
- nb+=8; /* rounded if necessary */
- nb /= 8;
-
- if (nb & MUMASK) /* round up #bytes to MAPUNIT chunks */
- cowdev->mapsize = ( (nb>>MUSHIFT) +1) << MUSHIFT;
- else
- cowdev->mapsize = nb;
-
- /*
- ** reserve space in memory for the cowhead
- */
- cowdev->cowhead = kmalloc(MAPUNIT, GFP_KERNEL);
-
- if (!cowdev->cowhead) {
- printk(KERN_ERR "cowloop - cannot get space for cowhead %d\n",
- MAPUNIT);
- return -ENOMEM;
- }
-
- memset(cowdev->cowhead, 0, MAPUNIT);
-
- DEBUGP(DCOW"cowloop - prepare cowhead....\n");
-
- /*
- ** check if the cowfile exists or should be created
- */
- if (inode->i_size != 0) {
- /*
- ** existing cowfile: read the cow head
- */
- if (inode->i_size < MAPUNIT) {
- printk(KERN_ERR
- "cowloop - existing cowfile %s too small\n",
- cowf);
- return -EINVAL;
- }
-
- cowlo_readcowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
-
- /*
- ** verify if the existing file is really a cowfile
- */
- if (cowdev->cowhead->magic != COWMAGIC) {
- printk(KERN_ERR
- "cowloop - cowfile %s has incorrect format\n",
- cowf);
- return -EINVAL;
- }
-
- /*
- ** verify the cowhead version of the cowfile
- */
- if (cowdev->cowhead->version > COWVERSION) {
- printk(KERN_ERR
- "cowloop - cowfile %s newer than this driver\n",
- cowf);
- return -EINVAL;
- }
-
- /*
- ** make sure that this is not a packed cowfile
- */
- if (cowdev->cowhead->flags & COWPACKED) {
- printk(KERN_ERR
- "cowloop - packed cowfile %s not accepted\n", cowf);
- return -EINVAL;
- }
-
- /*
- ** verify if the cowfile has been properly closed
- */
- if (cowdev->cowhead->flags & COWDIRTY) {
- /*
- ** cowfile was not properly closed;
- ** check if automatic recovery is required
- ** (actual recovery will be done later on)
- */
- if (!autorecover) {
- printk(KERN_ERR
- "cowloop - cowfile %s is dirty "
- "(not properly closed by rmmod?)\n",
- cowf);
- printk(KERN_ERR
- "cowloop - run cowrepair or specify "
- "'option=r' to recover\n");
- return -EINVAL;
- }
- }
-
- /*
- ** verify if the cowfile is really related to this rdofile
- */
- if (cowdev->cowhead->rdoblocks != cowdev->numblocks) {
- printk(KERN_ERR
- "cowloop - cowfile %s (size %lld) not related "
- "to rdofile (size %lld)\n",
- cowf,
- (long long)cowdev->cowhead->rdoblocks <<MUSHIFT,
- (long long)cowdev->numblocks <<MUSHIFT);
- return -EINVAL;
- }
-
- if (cowdev->cowhead->rdofingerprint != cowdev->fingerprint) {
- printk(KERN_ERR
- "cowloop - cowfile %s not related to rdofile "
- " (fingerprint err - rdofile modified?)\n", cowf);
- return -EINVAL;
- }
- } else {
- /*
- ** new cowfile: determine the minimal size (cowhead+bitmap)
- */
- offset = (loff_t) MAPUNIT + cowdev->mapsize - 1;
-
- if ( cowlo_writecowraw(cowdev, "", 1, offset) < 1) {
- printk(KERN_ERR
- "cowloop - cannot set cowfile to size %lld\n",
- offset+1);
- return -EINVAL;
- }
-
- /*
- ** prepare new cowhead
- */
- cowdev->cowhead->magic = COWMAGIC;
- cowdev->cowhead->version = COWVERSION;
- cowdev->cowhead->mapunit = MAPUNIT;
- cowdev->cowhead->mapsize = cowdev->mapsize;
- cowdev->cowhead->rdoblocks = cowdev->numblocks;
- cowdev->cowhead->rdofingerprint = cowdev->fingerprint;
- cowdev->cowhead->cowused = 0;
-
- /*
- ** calculate start offset of data in cowfile,
- ** rounded up to multiple of 4K to avoid
- ** unnecessary disk-usage for written datablocks in
- ** the sparsed cowfile on e.g. 4K filesystems
- */
- cowdev->cowhead->doffset =
- ((MAPUNIT+cowdev->mapsize+4095)>>12)<<12;
- }
-
- cowdev->cowhead->flags = 0;
-
- DEBUGP(DCOW"cowloop - reserve space bitmap....\n");
-
- /*
- ** reserve space in memory for the entire bitmap and
- ** fill it with the bitmap-data from disk; the entire
- ** bitmap is allocated in several chunks because kmalloc
- ** has restrictions regarding the allowed size per kmalloc
- */
- cowdev->mapcount = (cowdev->mapsize+MAPCHUNKSZ-1)/MAPCHUNKSZ;
-
- /*
- ** the size of every bitmap chunk will be MAPCHUNKSZ bytes, except for
- ** the last bitmap chunk: calculate remaining size for this chunk
- */
- if (cowdev->mapsize % MAPCHUNKSZ == 0)
- cowdev->mapremain = MAPCHUNKSZ;
- else
- cowdev->mapremain = cowdev->mapsize % MAPCHUNKSZ;
-
- /*
- ** allocate space to store all pointers for the bitmap-chunks
- ** (initialize area with zeroes to allow proper undo)
- */
- cowdev->mapcache = kmalloc(cowdev->mapcount * sizeof(char *),
- GFP_KERNEL);
- if (!cowdev->mapcache) {
- printk(KERN_ERR
- "cowloop - can not allocate space for bitmap ptrs\n");
- return -ENOMEM;
- }
-
- memset(cowdev->mapcache, 0, cowdev->mapcount * sizeof(char *));
-
- /*
- ** allocate space to store the bitmap-chunks themselves
- */
- for (i=0; i < cowdev->mapcount; i++) {
- if (i < (cowdev->mapcount-1))
- *(cowdev->mapcache+i) = kmalloc(MAPCHUNKSZ, GFP_KERNEL);
- else
- *(cowdev->mapcache+i) = kmalloc(cowdev->mapremain,
- GFP_KERNEL);
-
- if (*(cowdev->mapcache+i) == NULL) {
- printk(KERN_ERR "cowloop - no space for bitmapchunk %ld"
- " totmapsz=%ld, mapcnt=%d mapunit=%d\n",
- i, cowdev->mapsize, cowdev->mapcount,
- MAPUNIT);
- return -ENOMEM;
- }
- }
-
- DEBUGP(DCOW"cowloop - read bitmap from cow....\n");
-
- /*
- ** read the entire bitmap from the cowfile into the in-memory cache;
- ** count the number of blocks that are in use already
- ** (statistical purposes)
- */
- for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
- i++, offset+=MAPCHUNKSZ) {
- unsigned long numbytes;
-
- if (i < (cowdev->mapcount-1))
- /*
- ** full bitmap chunk
- */
- numbytes = MAPCHUNKSZ;
- else
- /*
- ** last bitmap chunk: might be partly filled
- */
- numbytes = cowdev->mapremain;
-
- cowlo_readcowraw(cowdev, *(cowdev->mapcache+i),
- numbytes, offset);
- }
-
- /*
- ** if the cowfile was dirty and automatic recovery is required,
- ** reconstruct a proper bitmap in memory now
- */
- if (cowdev->cowhead->flags & COWDIRTY) {
- unsigned long long blocknum;
- char databuf[MAPUNIT];
- unsigned long mapnum, mapbyte, mapbit;
-
- printk(KERN_NOTICE "cowloop - recover dirty cowfile %s....\n",
- cowf);
-
- /*
- ** read all data blocks
- */
- for (blocknum=0, rv=1, offset=0;
- cowlo_readcow(cowdev, databuf, MAPUNIT, offset) > 0;
- blocknum++, offset += MAPUNIT) {
-
- /*
- ** if this datablock contains real data (not binary
- ** zeroes), set the corresponding bit in the bitmap
- */
- if ( memcmp(databuf, allzeroes, MAPUNIT) == 0)
- continue;
-
- mapnum = CALCMAP (blocknum);
- mapbyte = CALCBYTE(blocknum);
- mapbit = CALCBIT (blocknum);
-
- *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
- }
-
- printk(KERN_NOTICE "cowloop - cowfile recovery completed\n");
- }
-
- /*
- ** count all bits set in the bitmaps for statistical purposes
- */
- for (i=0, cowdev->nrcowblocks = 0; i < cowdev->mapcount; i++) {
- long numbytes;
- char *p;
-
- if (i < (cowdev->mapcount-1))
- numbytes = MAPCHUNKSZ;
- else
- numbytes = cowdev->mapremain;
-
- p = *(cowdev->mapcache+i);
-
- for (numbytes--; numbytes >= 0; numbytes--, p++) {
- /*
- ** for only eight checks the following construction
- ** is faster than a loop-construction
- */
- if ((*p) & 0x01) cowdev->nrcowblocks++;
- if ((*p) & 0x02) cowdev->nrcowblocks++;
- if ((*p) & 0x04) cowdev->nrcowblocks++;
- if ((*p) & 0x08) cowdev->nrcowblocks++;
- if ((*p) & 0x10) cowdev->nrcowblocks++;
- if ((*p) & 0x20) cowdev->nrcowblocks++;
- if ((*p) & 0x40) cowdev->nrcowblocks++;
- if ((*p) & 0x80) cowdev->nrcowblocks++;
- }
- }
-
- /*
- ** consistency-check for number of bits set in bitmap
- */
- if ( !(cowdev->cowhead->flags & COWDIRTY) &&
- (cowdev->cowhead->cowused != cowdev->nrcowblocks) ) {
- printk(KERN_ERR "cowloop - inconsistent cowfile admi\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
-** undo memory allocs and file opens issued so far
-** related to the cowfile
-*/
-static void
-cowlo_undo_opencow(struct cowloop_device *cowdev)
-{
- int i;
-
- if (cowdev->mapcache) {
- for (i=0; i < cowdev->mapcount; i++) {
- if (*(cowdev->mapcache+i) != NULL)
- kfree( *(cowdev->mapcache+i) );
- }
-
- kfree(cowdev->mapcache);
- }
-
- if (cowdev->cowhead)
- kfree(cowdev->cowhead);
-
- if ( (cowdev->state & COWCOWOPEN) && (cowdev->cowfp) )
- filp_close(cowdev->cowfp, 0);
-
- /*
- ** mark cowfile closed
- */
- cowdev->state &= ~COWCOWOPEN;
-}
-
-/*
-** flush the entire bitmap and the cowhead (clean) to the cowfile
-**
-** must be called with the cowdevices-lock set
-*/
-static void
-cowlo_sync(void)
-{
- int i, minor;
- loff_t offset;
- struct cowloop_device *cowdev;
-
- for (minor=0; minor < maxcows; minor++) {
- cowdev = cowdevall[minor];
- if ( ! (cowdev->state & COWRWCOWOPEN) )
- continue;
-
- for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
- i++, offset += MAPCHUNKSZ) {
- unsigned long numbytes;
-
- if (i < (cowdev->mapcount-1))
- /*
- ** full bitmap chunk
- */
- numbytes = MAPCHUNKSZ;
- else
- /*
- ** last bitmap chunk: might be partly filled
- */
- numbytes = cowdev->mapremain;
-
- DEBUGP(DCOW
- "cowloop - flushing bitmap %2d (%3ld Kb)\n",
- i, numbytes/1024);
-
- if (cowlo_writecowraw(cowdev, *(cowdev->mapcache+i),
- numbytes, offset) < numbytes) {
- break;
- }
- }
-
- /*
- ** flush clean up-to-date cowhead to cowfile
- */
- cowdev->cowhead->cowused = cowdev->nrcowblocks;
- cowdev->cowhead->flags &= ~COWDIRTY;
-
- DEBUGP(DCOW "cowloop - flushing cowhead (%3d Kb)\n",
- MAPUNIT/1024);
-
- cowlo_writecowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
- }
-}
-
-/*****************************************************************************/
-/* Module loading/unloading */
-/*****************************************************************************/
-
-/*
-** called during insmod/modprobe
-*/
-static int __init
-cowlo_init_module(void)
-{
- int rv;
- int minor, uptocows;
-
- revision[sizeof revision - 3] = '\0';
-
- printk(KERN_NOTICE "cowloop - (C) 2009 ATComputing.nl - version: %s\n", &revision[11]);
- printk(KERN_NOTICE "cowloop - info: www.ATComputing.nl/cowloop\n");
-
- memset(allzeroes, 0, MAPUNIT);
-
- /*
- ** Setup administration for all possible cowdevices.
- ** Note that their minor numbers go from 0 to MAXCOWS-1 inclusive
- ** and minor == MAXCOWS-1 is reserved for the control device.
- */
- if ((maxcows < 1) || (maxcows > MAXCOWS)) {
- printk(KERN_WARNING
- "cowloop - maxcows exceeds maximum of %d\n", MAXCOWS);
-
- maxcows = DFLCOWS;
- }
-
- /* allocate room for a table with a pointer to each cowloop_device: */
- if ( (cowdevall = kmalloc(maxcows * sizeof(struct cowloop_device *),
- GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING
- "cowloop - can not alloc table for %d devs\n", maxcows);
- uptocows = 0;
- rv = -ENOMEM;
- goto error_out;
- }
- memset(cowdevall, 0, maxcows * sizeof(struct cowloop_device *));
- /* then hook an actual cowloop_device struct to each pointer: */
- for (minor=0; minor < maxcows; minor++) {
- if ((cowdevall[minor] = kmalloc(sizeof(struct cowloop_device),
- GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING
- "cowloop - can not alloc admin-struct for dev no %d\n", minor);
-
- uptocows = minor; /* this is how far we got.... */
- rv = -ENOMEM;
- goto error_out;
- }
- memset(cowdevall[minor], 0, sizeof(struct cowloop_device));
- }
- uptocows = maxcows; /* we got all devices */
-
- sema_init(&cowdevlock, 1);
-
- /*
- ** register cowloop module
- */
- if ( register_blkdev(COWMAJOR, DEVICE_NAME) < 0) {
- printk(KERN_WARNING
- "cowloop - unable to get major %d for cowloop\n", COWMAJOR);
- rv = -EIO;
- goto error_out;
- }
-
- /*
- ** create a directory below /proc to allocate a file
- ** for each cowdevice that is allocated later on
- */
- cowlo_procdir = proc_mkdir("cow", NULL);
-
- /*
- ** check if a cowdevice has to be opened during insmod/modprobe;
- ** two parameters should be specified then: rdofile= and cowfile=
- */
- if( (rdofile[0] != '\0') && (cowfile[0] != '\0') ) {
- char *po = option;
- int wantrecover = 0;
-
- /*
- ** check if automatic recovery is wanted
- */
- while (*po) {
- if (*po == 'r') {
- wantrecover = 1;
- break;
- }
- po++;
- }
-
- /*
- ** open new cowdevice with minor number 0
- */
- if ( (rv = cowlo_openpair(rdofile, cowfile, wantrecover, 0))) {
- remove_proc_entry("cow", NULL);
- unregister_blkdev(COWMAJOR, DEVICE_NAME);
- goto error_out;
- }
- } else {
- /*
- ** check if only one parameter has been specified
- */
- if( (rdofile[0] != '\0') || (cowfile[0] != '\0') ) {
- printk(KERN_ERR
- "cowloop - only one filename specified\n");
- remove_proc_entry("cow", NULL);
- unregister_blkdev(COWMAJOR, DEVICE_NAME);
- rv = -EINVAL;
- goto error_out;
- }
- }
-
- /*
- ** allocate fake disk as control channel to handle the requests
- ** to activate and deactivate cowdevices dynamically
- */
- if (!(cowctlgd = alloc_disk(1))) {
- printk(KERN_WARNING
- "cowloop - unable to alloc_disk for cowctl\n");
-
- remove_proc_entry("cow", NULL);
- (void) cowlo_closepair(cowdevall[0]);
- unregister_blkdev(COWMAJOR, DEVICE_NAME);
- rv = -ENOMEM;
- goto error_out;
- }
-
- spin_lock_init(&cowctlrqlock);
- cowctlgd->major = COWMAJOR;
- cowctlgd->first_minor = COWCTL;
- cowctlgd->minors = 1;
- cowctlgd->fops = &cowlo_fops;
- cowctlgd->private_data = NULL;
- /* the device has capacity 0, so there will be no q-requests */
- cowctlgd->queue = blk_init_queue(NULL, &cowctlrqlock);
- sprintf(cowctlgd->disk_name, "cowctl");
- set_capacity(cowctlgd, 0);
-
- add_disk(cowctlgd);
-
- printk(KERN_NOTICE "cowloop - number of configured cowdevices: %d\n",
- maxcows);
- if (rdofile[0] != '\0') {
- printk(KERN_NOTICE "cowloop - initialized on rdofile=%s\n",
- rdofile);
- } else {
- printk(KERN_NOTICE "cowloop - initialized without rdofile yet\n");
- }
- return 0;
-
-error_out:
- for (minor=0; minor < uptocows ; minor++) {
- kfree(cowdevall[minor]);
- }
- kfree(cowdevall);
- return rv;
-}
-
-/*
-** called during rmmod
-*/
-static void __exit
-cowlo_cleanup_module(void)
-{
- int minor;
-
- /*
- ** flush bitmaps and cowheads to the cowfiles
- */
- down(&cowdevlock);
- cowlo_sync();
- up(&cowdevlock);
-
- /*
- ** close all cowdevices
- */
- for (minor=0; minor < maxcows; minor++)
- (void) cowlo_closepair(cowdevall[minor]);
-
- unregister_blkdev(COWMAJOR, DEVICE_NAME);
-
- /*
- ** get rid of /proc/cow and unregister the driver
- */
- remove_proc_entry("cow", NULL);
-
- for (minor = 0; minor < maxcows; minor++) {
- kfree(cowdevall[minor]);
- }
- kfree(cowdevall);
-
- del_gendisk(cowctlgd); /* revert the alloc_disk() */
- put_disk (cowctlgd); /* revert the add_disk() */
- blk_cleanup_queue(cowctlgd->queue); /* cleanup the empty queue */
-
- printk(KERN_NOTICE "cowloop - unloaded\n");
-}
-
-module_init(cowlo_init_module);
-module_exit(cowlo_cleanup_module);
diff --git a/drivers/staging/cowloop/cowloop.h b/drivers/staging/cowloop/cowloop.h
deleted file mode 100644
index bbd4a35ac667..000000000000
--- a/drivers/staging/cowloop/cowloop.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-** DO NOT MODIFY THESE VALUES (would make old cowfiles unusable)
-*/
-#define MAPUNIT 1024 /* blocksize for bit in bitmap */
-#define MUSHIFT 10 /* bitshift for bit in bitmap */
-#define MUMASK 0x3ff /* bitmask for bit in bitmap */
-
-#define COWMAGIC 0x574f437f /* byte-swapped '7f C O W' */
-#define COWDIRTY 0x01
-#define COWPACKED 0x02
-#define COWVERSION 1
-
-struct cowhead
-{
- int magic; /* identifies a cowfile */
- short version; /* version of cowhead */
- short flags; /* flags indicating status */
- unsigned long mapunit; /* blocksize per bit in bitmap */
- unsigned long mapsize; /* total size of bitmap (bytes) */
- unsigned long doffset; /* start-offset datablocks in cow */
- unsigned long rdoblocks; /* size of related read-only file */
- unsigned long rdofingerprint; /* fingerprint of read-only file */
- unsigned long cowused; /* number of datablocks used in cow */
-};
-
-#define COWDEVDIR "/dev/cow/"
-#define COWDEVICE COWDEVDIR "%ld"
-#define COWCONTROL COWDEVDIR "ctl"
-
-#define MAXCOWS 1024
-#define COWCTL (MAXCOWS-1) /* minor number of /dev/cow/ctl */
-
-#define COWPROCDIR "/proc/cow/"
-#define COWPROCFILE COWPROCDIR "%d"
-
-/*
-** ioctl related stuff
-*/
-#define ANYDEV ((unsigned long)-1)
-
-struct cowpair
-{
- unsigned char *rdofile; /* pathname of the rdofile */
- unsigned char *cowfile; /* pathname of the cowfile */
- unsigned short rdoflen; /* length of rdofile pathname */
- unsigned short cowflen; /* length of cowfile pathname */
- unsigned long device; /* requested/returned device number */
-};
-
-struct cowwatch
-{
- int flags; /* request flags */
- unsigned long device; /* requested device number */
- unsigned long threshold; /* continue if free Kb < threshold */
- unsigned long totalkb; /* ret: total filesystem size (Kb) */
- unsigned long availkb; /* ret: free filesystem size (Kb) */
-};
-
-#define WATCHWAIT 0x01 /* block until threshold reached */
-
-#define COWSYNC _IO ('C', 1)
-#define COWMKPAIR _IOW ('C', 2, struct cowpair)
-#define COWRMPAIR _IOW ('C', 3, unsigned long)
-#define COWWATCH _IOW ('C', 4, struct cowwatch)
-#define COWCLOSE _IOW ('C', 5, unsigned long)
-#define COWRDOPEN _IOW ('C', 6, unsigned long)
diff --git a/drivers/staging/cpc-usb/Kconfig b/drivers/staging/cpc-usb/Kconfig
deleted file mode 100644
index 2be0bc9c39d0..000000000000
--- a/drivers/staging/cpc-usb/Kconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-config USB_CPC
- tristate "CPC CAN USB driver"
- depends on USB && PROC_FS
- default n
diff --git a/drivers/staging/cpc-usb/Makefile b/drivers/staging/cpc-usb/Makefile
deleted file mode 100644
index 3f83170a8fab..000000000000
--- a/drivers/staging/cpc-usb/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_USB_CPC) += cpc-usb.o
-
-cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o
diff --git a/drivers/staging/cpc-usb/TODO b/drivers/staging/cpc-usb/TODO
deleted file mode 100644
index 9b1752fb9cd7..000000000000
--- a/drivers/staging/cpc-usb/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-Things to do for this driver to get merged into the main portion of the
-kernel:
- - checkpatch cleanups
- - sparse clean
- - remove proc code
- - tie into CAN socket interfaces if possible
- - figure out sane userspace api
- - use linux's error codes
-
-Send patches to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/cpc-usb/cpc-usb_drv.c b/drivers/staging/cpc-usb/cpc-usb_drv.c
deleted file mode 100644
index c5eca46996fb..000000000000
--- a/drivers/staging/cpc-usb/cpc-usb_drv.c
+++ /dev/null
@@ -1,1184 +0,0 @@
-/*
- * CPC-USB CAN Interface Kernel Driver
- *
- * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
- *
- * 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; version 2 of the License.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-
-#include <linux/proc_fs.h>
-
-#include "cpc.h"
-
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/* Version Information */
-#define DRIVER_AUTHOR "Sebastian Haas <haas@ems-wuensche.com>"
-#define DRIVER_DESC "CPC-USB Driver for Linux Kernel 2.6"
-#define DRIVER_VERSION CPC_DRIVER_VERSION
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-
-/* Define these values to match your devices */
-#define USB_CPCUSB_VENDOR_ID 0x12D6
-
-#define USB_CPCUSB_M16C_PRODUCT_ID 0x0888
-#define USB_CPCUSB_LPC2119_PRODUCT_ID 0x0444
-
-#define CPC_USB_PROC_DIR CPC_PROC_DIR "cpc-usb"
-
-static struct proc_dir_entry *procDir;
-static struct proc_dir_entry *procEntry;
-
-/* Module parameters */
-static int debug;
-module_param(debug, int, S_IRUGO);
-
-/* table of devices that work with this driver */
-static struct usb_device_id cpcusb_table[] = {
- {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_M16C_PRODUCT_ID)},
- {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_LPC2119_PRODUCT_ID)},
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, cpcusb_table);
-
-/* use to prevent kernel panic if driver is unloaded
- * while a programm has still open the device
- */
-DECLARE_WAIT_QUEUE_HEAD(rmmodWq);
-atomic_t useCount;
-
-static CPC_USB_T *CPCUSB_Table[CPC_USB_CARD_CNT] = { 0 };
-static unsigned int CPCUsbCnt;
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
-
-/* local function prototypes */
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
- loff_t *ppos);
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
- size_t count, loff_t *ppos);
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait);
-static int cpcusb_open(struct inode *inode, struct file *file);
-static int cpcusb_release(struct inode *inode, struct file *file);
-
-static int cpcusb_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-static void cpcusb_disconnect(struct usb_interface *interface);
-
-static void cpcusb_read_bulk_callback(struct urb *urb);
-static void cpcusb_write_bulk_callback(struct urb *urb);
-static void cpcusb_read_interrupt_callback(struct urb *urb);
-
-static int cpcusb_setup_intrep(CPC_USB_T *card);
-
-static struct file_operations cpcusb_fops = {
- /*
- * The owner field is part of the module-locking
- * mechanism. The idea is that the kernel knows
- * which module to increment the use-counter of
- * BEFORE it calls the device's open() function.
- * This also means that the kernel can decrement
- * the use-counter again before calling release()
- * or should the open() function fail.
- */
- .owner = THIS_MODULE,
-
- .read = cpcusb_read,
- .write = cpcusb_write,
- .poll = cpcusb_poll,
- .open = cpcusb_open,
- .release = cpcusb_release,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver cpcusb_class = {
- .name = "usb/cpc_usb%d",
- .fops = &cpcusb_fops,
- .minor_base = CPC_USB_BASE_MNR,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver cpcusb_driver = {
- .name = "cpc-usb",
- .probe = cpcusb_probe,
- .disconnect = cpcusb_disconnect,
- .id_table = cpcusb_table,
-};
-
-static int cpcusb_create_info_output(char *buf)
-{
- int i = 0, j;
-
- for (j = 0; j < CPC_USB_CARD_CNT; j++) {
- if (CPCUSB_Table[j]) {
- CPC_USB_T *card = CPCUSB_Table[j];
- CPC_CHAN_T *chan = card->chan;
-
- /* MINOR CHANNELNO BUSNO SLOTNO */
- i += sprintf(&buf[i], "%d %s\n", chan->minor,
- card->serialNumber);
- }
- }
-
- return i;
-}
-
-static int cpcusb_proc_read_info(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = cpcusb_create_info_output(page);
-
- if (len <= off + count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
-
- return len;
-}
-
-/*
- * Remove CPC-USB and cleanup
- */
-static inline void cpcusb_delete(CPC_USB_T *card)
-{
- if (card) {
- if (card->chan) {
- if (card->chan->buf)
- vfree(card->chan->buf);
-
- if (card->chan->CPCWait_q)
- kfree(card->chan->CPCWait_q);
-
- kfree(card->chan);
- }
-
- CPCUSB_Table[card->idx] = NULL;
- kfree(card);
- }
-}
-
-/*
- * setup the interrupt IN endpoint of a specific CPC-USB device
- */
-static int cpcusb_setup_intrep(CPC_USB_T *card)
-{
- int retval = 0;
- struct usb_endpoint_descriptor *ep;
-
- ep = &card->interface->altsetting[0].endpoint[card->num_intr_in].desc;
-
- card->intr_in_buffer[0] = 0;
- card->free_slots = 15; /* initial size */
-
- /* setup the urb */
- usb_fill_int_urb(card->intr_in_urb, card->udev,
- usb_rcvintpipe(card->udev, card->num_intr_in),
- card->intr_in_buffer,
- sizeof(card->intr_in_buffer),
- cpcusb_read_interrupt_callback,
- card,
- ep->bInterval);
-
- card->intr_in_urb->status = 0; /* needed! */
-
- /* submit the urb */
- retval = usb_submit_urb(card->intr_in_urb, GFP_KERNEL);
-
- if (retval)
- err("%s - failed submitting intr urb, error %d", __func__,
- retval);
-
- return retval;
-}
-
-static int cpcusb_open(struct inode *inode, struct file *file)
-{
- CPC_USB_T *card = NULL;
- struct usb_interface *interface;
- int subminor;
- int j, retval = 0;
-
- subminor = iminor(inode);
-
- /* prevent disconnects */
- down(&disconnect_sem);
-
- interface = usb_find_interface(&cpcusb_driver, subminor);
- if (!interface) {
- err("%s - error, can't find device for minor %d",
- __func__, subminor);
- retval = CPC_ERR_NO_INTERFACE_PRESENT;
- goto exit_no_device;
- }
-
- card = usb_get_intfdata(interface);
- if (!card) {
- retval = CPC_ERR_NO_INTERFACE_PRESENT;
- goto exit_no_device;
- }
-
- /* lock this device */
- down(&card->sem);
-
- /* increment our usage count for the driver */
- if (card->open) {
- dbg("device already opened");
- retval = CPC_ERR_CHANNEL_ALREADY_OPEN;
- goto exit_on_error;
- }
-
- /* save our object in the file's private structure */
- file->private_data = card;
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- usb_fill_bulk_urb(card->urbs[j].urb, card->udev,
- usb_rcvbulkpipe(card->udev, card->num_bulk_in),
- card->urbs[j].buffer, card->urbs[j].size,
- cpcusb_read_bulk_callback, card);
-
- retval = usb_submit_urb(card->urbs[j].urb, GFP_KERNEL);
-
- if (retval) {
- err("%s - failed submitting read urb, error %d",
- __func__, retval);
- retval = CPC_ERR_TRANSMISSION_FAILED;
- goto exit_on_error;
- }
- }
-
- info("%s - %d URB's submitted", __func__, j);
-
- ResetBuffer(card->chan);
-
- cpcusb_setup_intrep(card);
- card->open = 1;
-
- atomic_inc(&useCount);
-
-exit_on_error:
- /* unlock this device */
- up(&card->sem);
-
-exit_no_device:
- up(&disconnect_sem);
-
- return retval;
-}
-
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait)
-{
- CPC_USB_T *card = (CPC_USB_T *) file->private_data;
- unsigned int retval = 0;
-
- if (!card) {
- err("%s - device object lost", __func__);
- return -EIO;
- }
-
- poll_wait(file, card->chan->CPCWait_q, wait);
-
- if (IsBufferNotEmpty(card->chan) || !(card->present))
- retval |= (POLLIN | POLLRDNORM);
-
- if (card->free_slots)
- retval |= (POLLOUT | POLLWRNORM);
-
- return retval;
-}
-
-static int cpcusb_release(struct inode *inode, struct file *file)
-{
- CPC_USB_T *card = (CPC_USB_T *) file->private_data;
- int j, retval = 0;
-
- if (card == NULL) {
- dbg("%s - object is NULL", __func__);
- return CPC_ERR_NO_INTERFACE_PRESENT;
- }
-
- /* lock our device */
- down(&card->sem);
-
- if (!card->open) {
- dbg("%s - device not opened", __func__);
- retval = CPC_ERR_NO_INTERFACE_PRESENT;
- goto exit_not_opened;
- }
-
- /* if device wasn't unplugged kill all urbs */
- if (card->present) {
- /* kill read urbs */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- usb_kill_urb(card->urbs[j].urb);
- }
-
- /* kill irq urb */
- usb_kill_urb(card->intr_in_urb);
-
- /* kill write urbs */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- if (atomic_read(&card->wrUrbs[j].busy)) {
- usb_kill_urb(card->wrUrbs[j].urb);
- wait_for_completion(&card->wrUrbs[j].finished);
- }
- }
- }
-
- atomic_dec(&useCount);
-
- /* last process detached */
- if (atomic_read(&useCount) == 0) {
- wake_up(&rmmodWq);
- }
-
- if (!card->present && card->open) {
- /* the device was unplugged before the file was released */
- up(&card->sem);
- cpcusb_delete(card);
- return 0;
- }
-
- card->open = 0;
-
-exit_not_opened:
- up(&card->sem);
-
- return 0;
-}
-
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
- loff_t *ppos)
-{
- CPC_USB_T *card = (CPC_USB_T *) file->private_data;
- CPC_CHAN_T *chan;
- int retval = 0;
-
- if (count < sizeof(CPC_MSG_T))
- return CPC_ERR_UNKNOWN;
-
- /* check if can read from the given address */
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return CPC_ERR_UNKNOWN;
-
- /* lock this object */
- down(&card->sem);
-
- /* verify that the device wasn't unplugged */
- if (!card->present) {
- up(&card->sem);
- return CPC_ERR_NO_INTERFACE_PRESENT;
- }
-
- if (IsBufferEmpty(card->chan)) {
- retval = 0;
- } else {
- chan = card->chan;
-
-#if 0
- /* convert LPC2119 params back to SJA1000 params */
- if (card->deviceRevision >= 0x0200
- && chan->buf[chan->oidx].type == CPC_MSG_T_CAN_PRMS) {
- LPC2119_TO_SJA1000_Params(&chan->buf[chan->oidx]);
- }
-#endif
-
- if (copy_to_user(buffer, &chan->buf[chan->oidx], count) != 0) {
- retval = CPC_ERR_IO_TRANSFER;
- } else {
- chan->oidx = (chan->oidx + 1) % CPC_MSG_BUF_CNT;
- chan->WnR = 1;
- retval = sizeof(CPC_MSG_T);
- }
- }
-/* spin_unlock_irqrestore(&card->slock, flags); */
-
- /* unlock the device */
- up(&card->sem);
-
- return retval;
-}
-
-#define SHIFT 1
-static inline void cpcusb_align_buffer_alignment(unsigned char *buf)
-{
- /* CPC-USB uploads packed bytes. */
- CPC_MSG_T *cpc = (CPC_MSG_T *) buf;
- unsigned int i;
-
- for (i = 0; i < cpc->length + (2 * sizeof(unsigned long)); i++) {
- ((unsigned char *) &cpc->msgid)[1 + i] =
- ((unsigned char *) &cpc->msgid)[1 + SHIFT + i];
- }
-}
-
-static int cpc_get_buffer_count(CPC_CHAN_T *chan)
-{
- /* check the buffer parameters */
- if (chan->iidx == chan->oidx)
- return !chan->WnR ? CPC_MSG_BUF_CNT : 0;
- else if (chan->iidx >= chan->oidx)
- return (chan->iidx - chan->oidx) % CPC_MSG_BUF_CNT;
-
- return (chan->iidx + CPC_MSG_BUF_CNT - chan->oidx) % CPC_MSG_BUF_CNT;
-}
-
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
- size_t count, loff_t *ppos)
-{
- CPC_USB_T *card = (CPC_USB_T *) file->private_data;
- CPC_USB_WRITE_URB_T *wrUrb = NULL;
-
- ssize_t bytes_written = 0;
- int retval = 0;
- int j;
-
- unsigned char *obuf = NULL;
- unsigned char type = 0;
- CPC_MSG_T *info = NULL;
-
- dbg("%s - entered minor %d, count = %zu, present = %d",
- __func__, card->minor, count, card->present);
-
- if (count > sizeof(CPC_MSG_T))
- return CPC_ERR_UNKNOWN;
-
- /* check if can read from the given address */
- if (!access_ok(VERIFY_READ, buffer, count))
- return CPC_ERR_UNKNOWN;
-
- /* lock this object */
- down(&card->sem);
-
- /* verify that the device wasn't unplugged */
- if (!card->present) {
- retval = CPC_ERR_NO_INTERFACE_PRESENT;
- goto exit;
- }
-
- /* verify that we actually have some data to write */
- if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
- goto exit;
- }
-
- if (card->free_slots <= 5) {
- info = (CPC_MSG_T *) buffer;
-
- if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE
- || card->free_slots <= 0) {
- dbg("%s - send buffer full please try again %d",
- __func__, card->free_slots);
- retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
- goto exit;
- }
- }
-
- /* Find a free write urb */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- if (!atomic_read(&card->wrUrbs[j].busy)) {
- wrUrb = &card->wrUrbs[j]; /* remember found URB */
- atomic_set(&wrUrb->busy, 1); /* lock this URB */
- init_completion(&wrUrb->finished); /* init completion */
- dbg("WR URB no. %d started", j);
- break;
- }
- }
-
- /* don't found write urb say error */
- if (!wrUrb) {
- dbg("%s - no free send urb available", __func__);
- retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
- goto exit;
- }
- dbg("URB write req");
-
- obuf = (unsigned char *) wrUrb->urb->transfer_buffer;
-
- /* copy the data from userspace into our transfer buffer;
- * this is the only copy required.
- */
- if (copy_from_user(&obuf[4], buffer, count) != 0) {
- atomic_set(&wrUrb->busy, 0); /* release urb */
- retval = CPC_ERR_IO_TRANSFER;
- goto exit;
- }
-
- /* check if it is a DRIVER information message, so we can
- * response to that message and not the USB
- */
- info = (CPC_MSG_T *) &obuf[4];
-
- bytes_written = 11 + info->length;
- if (bytes_written >= wrUrb->size) {
- retval = CPC_ERR_IO_TRANSFER;
- goto exit;
- }
-
- switch (info->type) {
- case CPC_CMD_T_CLEAR_MSG_QUEUE:
- ResetBuffer(card->chan);
- break;
-
- case CPC_CMD_T_INQ_MSG_QUEUE_CNT:
- retval = cpc_get_buffer_count(card->chan);
- atomic_set(&wrUrb->busy, 0);
-
- goto exit;
-
- case CPC_CMD_T_INQ_INFO:
- if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) {
- /* release urb cause we'll use it for driver
- * information
- */
- atomic_set(&wrUrb->busy, 0);
- if (IsBufferFull(card->chan)) {
- retval = CPC_ERR_IO_TRANSFER;
- goto exit;
- }
-
- /* it is a driver information request message and we have
- * free rx slots to store the response
- */
- type = info->msg.info.type;
- info = &card->chan->buf[card->chan->iidx];
-
- info->type = CPC_MSG_T_INFO;
- info->msg.info.source = CPC_INFOMSG_T_DRIVER;
- info->msg.info.type = type;
-
- switch (type) {
- case CPC_INFOMSG_T_VERSION:
- info->length = strlen(CPC_DRIVER_VERSION) + 2;
- sprintf(info->msg.info.msg, "%s\n",
- CPC_DRIVER_VERSION);
- break;
-
- case CPC_INFOMSG_T_SERIAL:
- info->length = strlen(CPC_DRIVER_SERIAL) + 2;
- sprintf(info->msg.info.msg, "%s\n",
- CPC_DRIVER_SERIAL);
- break;
-
- default:
- info->length = 2;
- info->msg.info.type =
- CPC_INFOMSG_T_UNKNOWN_TYPE;
- }
-
- card->chan->WnR = 0;
- card->chan->iidx =
- (card->chan->iidx + 1) % CPC_MSG_BUF_CNT;
-
- retval = info->length;
- goto exit;
- }
- break;
- case CPC_CMD_T_CAN_PRMS:
- /* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */
- if (info->msg.canparams.cc_type != SJA1000
- && info->msg.canparams.cc_type != M16C_BASIC
- && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID
- && info->msg.canparams.cc_type != SJA1000)) {
- /* don't forget to release the urb */
- atomic_set(&wrUrb->busy, 0);
- retval = CPC_ERR_WRONG_CONTROLLER_TYPE;
- goto exit;
- }
- break;
- }
-
- /* just convert the params if it is an old CPC-USB with M16C controller */
- if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) {
- /* if it is a parameter message convert it from SJA1000 controller
- * settings to M16C Basic controller settings
- */
- SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]);
- }
-
- /* don't forget the byte alignment */
- cpcusb_align_buffer_alignment(&obuf[4]);
-
- /* setup a the 4 byte header */
- obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0;
-
- /* this urb was already set up, except for this write size */
- wrUrb->urb->transfer_buffer_length = bytes_written + 4;
-
- /* send the data out the bulk port */
- /* a character device write uses GFP_KERNEL,
- unless a spinlock is held */
- retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL);
- if (retval) {
- atomic_set(&wrUrb->busy, 0); /* release urb */
- err("%s - failed submitting write urb, error %d",
- __func__, retval);
- } else {
- retval = bytes_written;
- }
-
-exit:
- /* unlock the device */
- up(&card->sem);
-
- dbg("%s - leaved", __func__);
-
- return retval;
-}
-
-/*
- * callback for interrupt IN urb
- */
-static void cpcusb_read_interrupt_callback(struct urb *urb)
-{
- CPC_USB_T *card = (CPC_USB_T *) urb->context;
- int retval;
- unsigned long flags;
-
- spin_lock_irqsave(&card->slock, flags);
-
- if (!card->present) {
- spin_unlock_irqrestore(&card->slock, flags);
- info("%s - no such device", __func__);
- return;
- }
-
- switch (urb->status) {
- case 0: /* success */
- card->free_slots = card->intr_in_buffer[1];
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* urb was killed */
- spin_unlock_irqrestore(&card->slock, flags);
- dbg("%s - intr urb killed", __func__);
- return;
- default:
- info("%s - nonzero urb status %d", __func__, urb->status);
- break;
- }
-
- retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (retval) {
- err("%s - failed resubmitting intr urb, error %d",
- __func__, retval);
- }
-
- spin_unlock_irqrestore(&card->slock, flags);
- wake_up_interruptible(card->chan->CPCWait_q);
-
- return;
-}
-
-#define UN_SHIFT 1
-#define CPCMSG_HEADER_LEN_FIRMWARE 11
-static inline int cpcusb_unalign_and_copy_buffy(unsigned char *out,
- unsigned char *in)
-{
- unsigned int i, j;
-
- for (i = 0; i < 3; i++)
- out[i] = in[i];
-
- for (j = 0; j < (in[1] + (CPCMSG_HEADER_LEN_FIRMWARE - 3)); j++)
- out[j + i + UN_SHIFT] = in[j + i];
-
- return i + j;
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_read_bulk_callback(struct urb *urb)
-{
- CPC_USB_T *card = (CPC_USB_T *) urb->context;
- CPC_CHAN_T *chan;
- unsigned char *ibuf = urb->transfer_buffer;
- int retval, msgCnt, start, again = 0;
- unsigned long flags;
-
- if (!card) {
- err("%s - device object lost", __func__);
- return;
- }
-
- spin_lock_irqsave(&card->slock, flags);
-
- if (!card->present) {
- spin_unlock_irqrestore(&card->slock, flags);
- info("%s - no such device", __func__);
- return;
- }
-
- switch (urb->status) {
- case 0: /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* urb was killed */
- spin_unlock_irqrestore(&card->slock, flags);
- dbg("%s - read urb killed", __func__);
- return;
- default:
- info("%s - nonzero urb status %d", __func__, urb->status);
- break;
- }
-
- if (urb->actual_length) {
- msgCnt = ibuf[0] & ~0x80;
- again = ibuf[0] & 0x80;
-
- /* we have a 4 byte header */
- start = 4;
- chan = card->chan;
- while (msgCnt) {
- if (!(IsBufferFull(card->chan))) {
- start +=
- cpcusb_unalign_and_copy_buffy((unsigned char *)
- &chan->buf[chan->iidx], &ibuf[start]);
-
- if (start > urb->transfer_buffer_length) {
- err("%d > %d", start, urb->transfer_buffer_length);
- break;
- }
-
- chan->WnR = 0;
- chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT;
- msgCnt--;
- } else {
- break;
- }
- }
- }
-
- usb_fill_bulk_urb(urb, card->udev,
- usb_rcvbulkpipe(card->udev, card->num_bulk_in),
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- cpcusb_read_bulk_callback, card);
-
- retval = usb_submit_urb(urb, GFP_ATOMIC);
-
- if (retval) {
- err("%s - failed resubmitting read urb, error %d", __func__, retval);
- }
-
- spin_unlock_irqrestore(&card->slock, flags);
-
- wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_write_bulk_callback(struct urb *urb)
-{
- CPC_USB_T *card = (CPC_USB_T *) urb->context;
- unsigned long flags;
- int j;
-
- spin_lock_irqsave(&card->slock, flags);
-
- /* find this urb */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- if (card->wrUrbs[j].urb == urb) {
- dbg("URB found no. %d", j);
- /* notify anyone waiting that the write has finished */
- complete(&card->wrUrbs[j].finished);
- atomic_set(&card->wrUrbs[j].busy, 0);
- break;
- }
- }
-
- switch (urb->status) {
- case 0: /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* urb was killed */
- spin_unlock_irqrestore(&card->slock, flags);
- dbg("%s - write urb no. %d killed", __func__, j);
- return;
- default:
- info("%s - nonzero urb status %d", __func__, urb->status);
- break;
- }
-
- spin_unlock_irqrestore(&card->slock, flags);
-
- wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-static inline int cpcusb_get_free_slot(void)
-{
- int i;
-
- for (i = 0; i < CPC_USB_CARD_CNT; i++) {
- if (!CPCUSB_Table[i])
- return i;
- }
-
- return -1;
-}
-
-/*
- * probe function for new CPC-USB devices
- */
-static int cpcusb_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- CPC_USB_T *card = NULL;
- CPC_CHAN_T *chan = NULL;
-
- struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
-
- int i, j, retval = -ENOMEM, slot;
-
- slot = cpcusb_get_free_slot();
- if (slot < 0) {
- info("No more devices supported");
- return -ENOMEM;
- }
-
- /* allocate memory for our device state and initialize it */
- card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL);
- if (!card) {
- err("Out of memory");
- return -ENOMEM;
- }
- CPCUSB_Table[slot] = card;
-
- /* allocate and initialize the channel struct */
- card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL);
- if (!card->chan) {
- kfree(card);
- err("Out of memory");
- return -ENOMEM;
- }
-
- chan = card->chan;
- memset(chan, 0, sizeof(CPC_CHAN_T));
- ResetBuffer(chan);
-
- init_MUTEX(&card->sem);
- spin_lock_init(&card->slock);
-
- card->udev = udev;
- card->interface = interface;
- if (udev->descriptor.iSerialNumber) {
- usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber,
- 128);
- info("Serial %s", card->serialNumber);
- }
-
- card->productId = udev->descriptor.idProduct;
- info("Product %s",
- card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ?
- "CPC-USB/ARM7" : "CPC-USB/M16C");
-
- /* set up the endpoint information */
- /* check out the endpoints */
- /* use only the first bulk-in and bulk-out endpoints */
- iface_desc = &interface->altsetting[0];
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
-
- if (!card->num_intr_in &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_INT)) {
- card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- card->num_intr_in = 1;
-
- if (!card->intr_in_urb) {
- err("No free urbs available");
- goto error;
- }
-
- dbg("intr_in urb %d", card->num_intr_in);
- }
-
- if (!card->num_bulk_in &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_BULK)) {
- card->num_bulk_in = 2;
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- card->urbs[j].size = endpoint->wMaxPacketSize;
- card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!card->urbs[j].urb) {
- err("No free urbs available");
- goto error;
- }
- card->urbs[j].buffer =
- usb_buffer_alloc(udev,
- card->urbs[j].size,
- GFP_KERNEL,
- &card->urbs[j].urb->transfer_dma);
- if (!card->urbs[j].buffer) {
- err("Couldn't allocate bulk_in_buffer");
- goto error;
- }
- }
- info("%s - %d reading URB's allocated",
- __func__, CPC_USB_URB_CNT);
- }
-
- if (!card->num_bulk_out &&
- !(endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_BULK)) {
-
- card->num_bulk_out = 2;
-
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- card->wrUrbs[j].size =
- endpoint->wMaxPacketSize;
- card->wrUrbs[j].urb =
- usb_alloc_urb(0, GFP_KERNEL);
- if (!card->wrUrbs[j].urb) {
- err("No free urbs available");
- goto error;
- }
- card->wrUrbs[j].buffer = usb_buffer_alloc(udev,
- card->wrUrbs[j].size, GFP_KERNEL,
- &card->wrUrbs[j].urb->transfer_dma);
-
- if (!card->wrUrbs[j].buffer) {
- err("Couldn't allocate bulk_out_buffer");
- goto error;
- }
-
- usb_fill_bulk_urb(card->wrUrbs[j].urb, udev,
- usb_sndbulkpipe(udev, endpoint->bEndpointAddress),
- card->wrUrbs[j].buffer,
- card->wrUrbs[j].size,
- cpcusb_write_bulk_callback,
- card);
- }
-
- info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT);
- }
- }
-
- if (!(card->num_bulk_in && card->num_bulk_out)) {
- err("Couldn't find both bulk-in and bulk-out endpoints");
- goto error;
- }
-
- /* allow device read, write and ioctl */
- card->present = 1;
-
- /* we can register the device now, as it is ready */
- usb_set_intfdata(interface, card);
- retval = usb_register_dev(interface, &cpcusb_class);
-
- if (retval) {
- /* something prevented us from registering this driver */
- err("Not able to get a minor for this device.");
- usb_set_intfdata(interface, NULL);
- goto error;
- }
-
- card->chan->minor = card->minor = interface->minor;
-
- chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
- if (chan->buf == NULL) {
- err("Out of memory");
- retval = -ENOMEM;
- goto error;
- }
- info("Allocated memory for %d messages (%lu kbytes)",
- CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000);
- memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-
- ResetBuffer(chan);
-
- card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
- if (!card->chan->CPCWait_q) {
- err("Out of memory");
- retval = -ENOMEM;
- goto error;
- }
- init_waitqueue_head(card->chan->CPCWait_q);
-
- CPCUSB_Table[slot] = card;
- card->idx = slot;
- CPCUsbCnt++;
-
- /* let the user know what node this device is now attached to */
- info("Device now attached to USB-%d", card->minor);
- return 0;
-
-error:
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- if (card->urbs[j].buffer) {
- usb_buffer_free(card->udev, card->urbs[j].size,
- card->urbs[j].buffer,
- card->urbs[j].urb->transfer_dma);
- card->urbs[j].buffer = NULL;
- }
- if (card->urbs[j].urb) {
- usb_free_urb(card->urbs[j].urb);
- card->urbs[j].urb = NULL;
- }
- }
-
- cpcusb_delete(card);
- return retval;
-}
-
-/*
- * called by the usb core when the device is removed from the system
- */
-static void cpcusb_disconnect(struct usb_interface *interface)
-{
- CPC_USB_T *card = NULL;
- int minor, j;
-
- /* prevent races with open() */
- down(&disconnect_sem);
-
- card = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
-
- down(&card->sem);
-
- /* prevent device read, write and ioctl */
- card->present = 0;
-
- minor = card->minor;
-
- /* free all urbs and their buffers */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- /* terminate an ongoing write */
- if (atomic_read(&card->wrUrbs[j].busy)) {
- usb_kill_urb(card->wrUrbs[j].urb);
- wait_for_completion(&card->wrUrbs[j].finished);
- }
- usb_buffer_free(card->udev, card->wrUrbs[j].size,
- card->wrUrbs[j].buffer,
- card->wrUrbs[j].urb->transfer_dma);
- usb_free_urb(card->wrUrbs[j].urb);
- }
- info("%d write URBs freed", CPC_USB_URB_CNT);
-
- /* free all urbs and their buffers */
- for (j = 0; j < CPC_USB_URB_CNT; j++) {
- usb_buffer_free(card->udev, card->urbs[j].size,
- card->urbs[j].buffer,
- card->urbs[j].urb->transfer_dma);
- usb_free_urb(card->urbs[j].urb);
- }
- info("%d read URBs freed", CPC_USB_URB_CNT);
- usb_free_urb(card->intr_in_urb);
-
- /* give back our minor */
- usb_deregister_dev(interface, &cpcusb_class);
-
- up(&card->sem);
-
- /* if the device is opened, cpcusb_release will clean this up */
- if (!card->open)
- cpcusb_delete(card);
- else
- wake_up_interruptible(card->chan->CPCWait_q);
-
- up(&disconnect_sem);
-
- CPCUsbCnt--;
- info("USB-%d now disconnected", minor);
-}
-
-static int __init CPCUsb_Init(void)
-{
- int result, i;
-
- info(DRIVER_DESC " v" DRIVER_VERSION);
- info("Build on " __DATE__ " at " __TIME__);
-
- for (i = 0; i < CPC_USB_CARD_CNT; i++)
- CPCUSB_Table[i] = 0;
-
- /* register this driver with the USB subsystem */
- result = usb_register(&cpcusb_driver);
- if (result) {
- err("usb_register failed. Error number %d", result);
- return result;
- }
-
- procDir = proc_mkdir(CPC_USB_PROC_DIR, NULL);
- if (!procDir) {
- err("Could not create proc entry");
- } else {
- procEntry = create_proc_read_entry("info", 0444, procDir,
- cpcusb_proc_read_info,
- NULL);
- if (!procEntry) {
- err("Could not create proc entry %s", CPC_USB_PROC_DIR "/info");
- remove_proc_entry(CPC_USB_PROC_DIR, NULL);
- procDir = NULL;
- }
- }
-
- return 0;
-}
-
-static void __exit CPCUsb_Exit(void)
-{
- wait_event(rmmodWq, !atomic_read(&useCount));
-
- /* deregister this driver with the USB subsystem */
- usb_deregister(&cpcusb_driver);
-
- if (procDir) {
- if (procEntry)
- remove_proc_entry("info", procDir);
- remove_proc_entry(CPC_USB_PROC_DIR, NULL);
- }
-}
-
-module_init(CPCUsb_Init);
-module_exit(CPCUsb_Exit);
diff --git a/drivers/staging/cpc-usb/cpc.h b/drivers/staging/cpc-usb/cpc.h
deleted file mode 100644
index b2fda5d14c1d..000000000000
--- a/drivers/staging/cpc-usb/cpc.h
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * CPC CAN Interface Definitions
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * 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.
- */
-#ifndef CPC_HEADER
-#define CPC_HEADER
-
-/*
- * the maximum length of the union members within a CPC_MSG
- * this value can be defined by the customer, but has to be
- * >= 64 bytes
- * however, if not defined before, we set a length of 64 byte
- */
-#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
-#undef CPC_MSG_LEN
-#define CPC_MSG_LEN 64
-#endif
-
-/*
- * Transmission of events from CPC interfaces to PC can be individually
- * controlled per event type. Default state is: don't transmit
- * Control values are constructed by bit-or of Subject and Action
- * and passed to CPC_Control()
- */
-
-/* Control-Values for CPC_Control() Command Subject Selection */
-#define CONTR_CAN_Message 0x04
-#define CONTR_Busload 0x08
-#define CONTR_CAN_State 0x0C
-#define CONTR_SendAck 0x10
-#define CONTR_Filter 0x14
-#define CONTR_CmdQueue 0x18 /* reserved, do not use */
-#define CONTR_BusError 0x1C
-
-/* Control Command Actions */
-#define CONTR_CONT_OFF 0
-#define CONTR_CONT_ON 1
-#define CONTR_SING_ON 2
-/*
- * CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
- * read as: transmit at least once
- */
-
-/* defines for confirmed request */
-#define DO_NOT_CONFIRM 0
-#define DO_CONFIRM 1
-
-/* event flags */
-#define EVENT_READ 0x01
-#define EVENT_WRITE 0x02
-
-/*
- * Messages from CPC to PC contain a message object type field.
- * The following message types are sent by CPC and can be used in
- * handlers, others should be ignored.
- */
-#define CPC_MSG_T_RESYNC 0 /* Normally to be ignored */
-#define CPC_MSG_T_CAN 1 /* CAN data frame */
-#define CPC_MSG_T_BUSLOAD 2 /* Busload message */
-#define CPC_MSG_T_STRING 3 /* Normally to be ignored */
-#define CPC_MSG_T_CONTI 4 /* Normally to be ignored */
-#define CPC_MSG_T_MEM 7 /* Normally not to be handled */
-#define CPC_MSG_T_RTR 8 /* CAN remote frame */
-#define CPC_MSG_T_TXACK 9 /* Send acknowledge */
-#define CPC_MSG_T_POWERUP 10 /* Power-up message */
-#define CPC_MSG_T_CMD_NO 11 /* Normally to be ignored */
-#define CPC_MSG_T_CAN_PRMS 12 /* Actual CAN parameters */
-#define CPC_MSG_T_ABORTED 13 /* Command aborted message */
-#define CPC_MSG_T_CANSTATE 14 /* CAN state message */
-#define CPC_MSG_T_RESET 15 /* used to reset CAN-Controller */
-#define CPC_MSG_T_XCAN 16 /* XCAN data frame */
-#define CPC_MSG_T_XRTR 17 /* XCAN remote frame */
-#define CPC_MSG_T_INFO 18 /* information strings */
-#define CPC_MSG_T_CONTROL 19 /* used for control of interface/driver behaviour */
-#define CPC_MSG_T_CONFIRM 20 /* response type for confirmed requests */
-#define CPC_MSG_T_OVERRUN 21 /* response type for overrun conditions */
-#define CPC_MSG_T_KEEPALIVE 22 /* response type for keep alive conditions */
-#define CPC_MSG_T_CANERROR 23 /* response type for bus error conditions */
-#define CPC_MSG_T_DISCONNECTED 24 /* response type for a disconnected interface */
-#define CPC_MSG_T_ERR_COUNTER 25 /* RX/TX error counter of CAN controller */
-
-#define CPC_MSG_T_FIRMWARE 100 /* response type for USB firmware download */
-
-/*
- * Messages from the PC to the CPC interface contain a command field
- * Most of the command types are wrapped by the library functions and have therefore
- * normally not to be used.
- * However, programmers who wish to circumvent the library and talk directly
- * to the drivers (mainly Linux programmers) can use the following
- * command types:
- */
-#define CPC_CMD_T_CAN 1 /* CAN data frame */
-#define CPC_CMD_T_CONTROL 3 /* used for control of interface/driver behaviour */
-#define CPC_CMD_T_CAN_PRMS 6 /* set CAN parameters */
-#define CPC_CMD_T_CLEARBUF 8 /* clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead */
-#define CPC_CMD_T_INQ_CAN_PARMS 11 /* inquire actual CAN parameters */
-#define CPC_CMD_T_FILTER_PRMS 12 /* set filter parameter */
-#define CPC_CMD_T_RTR 13 /* CAN remote frame */
-#define CPC_CMD_T_CANSTATE 14 /* CAN state message */
-#define CPC_CMD_T_XCAN 15 /* XCAN data frame */
-#define CPC_CMD_T_XRTR 16 /* XCAN remote frame */
-#define CPC_CMD_T_RESET 17 /* used to reset CAN-Controller */
-#define CPC_CMD_T_INQ_INFO 18 /* miscellanous information strings */
-#define CPC_CMD_T_OPEN_CHAN 19 /* open a channel */
-#define CPC_CMD_T_CLOSE_CHAN 20 /* close a channel */
-#define CPC_CMD_T_CNTBUF 21 /* this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead */
-#define CPC_CMD_T_CAN_EXIT 200 /* exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1) */
-
-#define CPC_CMD_T_INQ_MSG_QUEUE_CNT CPC_CMD_T_CNTBUF /* inquires the count of elements in the message queue */
-#define CPC_CMD_T_INQ_ERR_COUNTER 25 /* request the CAN controllers error counter */
-#define CPC_CMD_T_CLEAR_MSG_QUEUE CPC_CMD_T_CLEARBUF /* clear CPC_MSG queue */
-#define CPC_CMD_T_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
-#define CPC_CMD_T_FIRMWARE 100 /* reserved, must not be used */
-#define CPC_CMD_T_USB_RESET 101 /* reserved, must not be used */
-#define CPC_CMD_T_WAIT_NOTIFY 102 /* reserved, must not be used */
-#define CPC_CMD_T_WAIT_SETUP 103 /* reserved, must not be used */
-#define CPC_CMD_T_ABORT 255 /* Normally not to be used */
-
-/* definitions for CPC_MSG_T_INFO information sources */
-#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
-#define CPC_INFOMSG_T_INTERFACE 1
-#define CPC_INFOMSG_T_DRIVER 2
-#define CPC_INFOMSG_T_LIBRARY 3
-
-/* information types */
-#define CPC_INFOMSG_T_UNKNOWN_TYPE 0
-#define CPC_INFOMSG_T_VERSION 1
-#define CPC_INFOMSG_T_SERIAL 2
-
-/* definitions for controller types */
-#define PCA82C200 1 /* Philips basic CAN controller, replaced by SJA1000 */
-#define SJA1000 2 /* Philips basic CAN controller */
-#define AN82527 3 /* Intel full CAN controller */
-#define M16C_BASIC 4 /* M16C controller running in basic CAN (not full CAN) mode */
-
-/* channel open error codes */
-#define CPC_ERR_NO_FREE_CHANNEL -1 /* no more free space within the channel array */
-#define CPC_ERR_CHANNEL_ALREADY_OPEN -2 /* the channel is already open */
-#define CPC_ERR_CHANNEL_NOT_ACTIVE -3 /* access to a channel not active failed */
-#define CPC_ERR_NO_DRIVER_PRESENT -4 /* no driver at the location searched by the library */
-#define CPC_ERR_NO_INIFILE_PRESENT -5 /* the library could not find the inifile */
-#define CPC_ERR_WRONG_PARAMETERS -6 /* wrong parameters in the inifile */
-#define CPC_ERR_NO_INTERFACE_PRESENT -7 /* 1. The specified interface is not connected */
- /* 2. The interface (mostly CPC-USB) was disconnected upon operation */
-#define CPC_ERR_NO_MATCHING_CHANNEL -8 /* the driver couldn't find a matching channel */
-#define CPC_ERR_NO_BUFFER_AVAILABLE -9 /* the driver couldn't allocate buffer for messages */
-#define CPC_ERR_NO_INTERRUPT -10 /* the requested interrupt couldn't be claimed */
-#define CPC_ERR_NO_MATCHING_INTERFACE -11 /* no interface type related to this channel was found */
-#define CPC_ERR_NO_RESOURCES -12 /* the requested resources could not be claimed */
-#define CPC_ERR_SOCKET -13 /* error concerning TCP sockets */
-
-/* init error codes */
-#define CPC_ERR_WRONG_CONTROLLER_TYPE -14 /* wrong CAN controller type within initialization */
-#define CPC_ERR_NO_RESET_MODE -15 /* the controller could not be set into reset mode */
-#define CPC_ERR_NO_CAN_ACCESS -16 /* the CAN controller could not be accessed */
-
-/* transmit error codes */
-#define CPC_ERR_CAN_WRONG_ID -20 /* the provided CAN id is too big */
-#define CPC_ERR_CAN_WRONG_LENGTH -21 /* the provided CAN length is too long */
-#define CPC_ERR_CAN_NO_TRANSMIT_BUF -22 /* the transmit buffer was occupied */
-#define CPC_ERR_CAN_TRANSMIT_TIMEOUT -23 /* The message could not be sent within a */
- /* specified time */
-
-/* other error codes */
-#define CPC_ERR_SERVICE_NOT_SUPPORTED -30 /* the requested service is not supported by the interface */
-#define CPC_ERR_IO_TRANSFER -31 /* a transmission error down to the driver occurred */
-#define CPC_ERR_TRANSMISSION_FAILED -32 /* a transmission error down to the interface occurred */
-#define CPC_ERR_TRANSMISSION_TIMEOUT -33 /* a timeout occurred within transmission to the interface */
-#define CPC_ERR_OP_SYS_NOT_SUPPORTED -35 /* the operating system is not supported */
-#define CPC_ERR_UNKNOWN -40 /* an unknown error ocurred (mostly IOCTL errors) */
-
-#define CPC_ERR_LOADING_DLL -50 /* the library 'cpcwin.dll' could not be loaded */
-#define CPC_ERR_ASSIGNING_FUNCTION -51 /* the specified function could not be assigned */
-#define CPC_ERR_DLL_INITIALIZATION -52 /* the DLL was not initialized correctly */
-#define CPC_ERR_MISSING_LICFILE -55 /* the file containing the licenses does not exist */
-#define CPC_ERR_MISSING_LICENSE -56 /* a required license was not found */
-
-/* CAN state bit values. Ignore any bits not listed */
-#define CPC_CAN_STATE_BUSOFF 0x80
-#define CPC_CAN_STATE_ERROR 0x40
-
-/* Mask to help ignore undefined bits */
-#define CPC_CAN_STATE_MASK 0xc0
-
-/*
- * CAN-Message representation in a CPC_MS
- * Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
- * or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
- */
-typedef struct CPC_CAN_MSG {
- u32 id;
- u8 length;
- u8 msg[8];
-} CPC_CAN_MSG_T;
-
-/* representation of the CAN parameters for the PCA82C200 controller */
-typedef struct CPC_PCA82C200_PARAMS {
- u8 acc_code; /* Acceptance-code for receive, Standard: 0 */
- u8 acc_mask; /* Acceptance-mask for receive, Standard: 0xff (everything) */
- u8 btr0; /* Bus-timing register 0 */
- u8 btr1; /* Bus-timing register 1 */
- u8 outp_contr; /* Output-control register */
-} CPC_PCA82C200_PARAMS_T;
-
-/* representation of the CAN parameters for the SJA1000 controller */
-typedef struct CPC_SJA1000_PARAMS {
- u8 mode; /* enables single or dual acceptance filtering */
- u8 acc_code0; /* Acceptance-code for receive, Standard: 0 */
- u8 acc_code1;
- u8 acc_code2;
- u8 acc_code3;
- u8 acc_mask0; /* Acceptance-mask for receive, Standard: 0xff (everything) */
- u8 acc_mask1;
- u8 acc_mask2;
- u8 acc_mask3;
- u8 btr0; /* Bus-timing register 0 */
- u8 btr1; /* Bus-timing register 1 */
- u8 outp_contr; /* Output-control register */
-} CPC_SJA1000_PARAMS_T;
-
-/*
- * representation of the CAN parameters for the M16C controller
- * in basic CAN mode (means no full CAN)
- */
-typedef struct CPC_M16C_BASIC_PARAMS {
- u8 con0;
- u8 con1;
- u8 ctlr0;
- u8 ctlr1;
- u8 clk;
- u8 acc_std_code0;
- u8 acc_std_code1;
- u8 acc_ext_code0;
- u8 acc_ext_code1;
- u8 acc_ext_code2;
- u8 acc_ext_code3;
- u8 acc_std_mask0;
- u8 acc_std_mask1;
- u8 acc_ext_mask0;
- u8 acc_ext_mask1;
- u8 acc_ext_mask2;
- u8 acc_ext_mask3;
-} CPC_M16C_BASIC_PARAMS_T;
-
-/* CAN params message representation */
-typedef struct CPC_CAN_PARAMS {
- u8 cc_type; /* represents the controller type */
- union {
- CPC_M16C_BASIC_PARAMS_T m16c_basic;
- CPC_SJA1000_PARAMS_T sja1000;
- CPC_PCA82C200_PARAMS_T pca82c200;
- } cc_params;
-} CPC_CAN_PARAMS_T;
-
-/* CHAN init params representation */
-typedef struct CPC_CHAN_PARAMS {
- int fd;
-} CPC_CHAN_PARAMS_T;
-
-/* CAN init params message representation */
-typedef struct CPC_INIT_PARAMS {
- CPC_CHAN_PARAMS_T chanparams;
- CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-/* structure for confirmed message handling */
-typedef struct CPC_CONFIRM {
- u8 result; /* error code */
-} CPC_CONFIRM_T;
-
-/* structure for information requests */
-typedef struct CPC_INFO {
- u8 source; /* interface, driver or library */
- u8 type; /* version or serial number */
- char msg[CPC_MSG_LEN - 2]; /* string holding the requested information */
-} CPC_INFO_T;
-
-/*
- * OVERRUN
- * In general two types of overrun may occur.
- * A hardware overrun, where the CAN controller
- * lost a message, because the interrupt was
- * not handled before the next messgae comes in.
- * Or a software overrun, where i.e. a received
- * message could not be stored in the CPC_MSG
- * buffer.
- */
-
-/* After a software overrun has occurred
- * we wait until we have CPC_OVR_GAP slots
- * free in the CPC_MSG buffer.
- */
-#define CPC_OVR_GAP 10
-
-/*
- * Two types of software overrun may occur.
- * A received CAN message or a CAN state event
- * can cause an overrun.
- * Note: A CPC_CMD which would normally store
- * its result immediately in the CPC_MSG
- * queue may fail, because the message queue is full.
- * This will not generate an overrun message, but
- * will halt command execution, until this command
- * is able to store its message in the message queue.
- */
-#define CPC_OVR_EVENT_CAN 0x01
-#define CPC_OVR_EVENT_CANSTATE 0x02
-#define CPC_OVR_EVENT_BUSERROR 0x04
-
-/*
- * If the CAN controller lost a message
- * we indicate it with the highest bit
- * set in the count field.
- */
-#define CPC_OVR_HW 0x80
-
-/* structure for overrun conditions */
-typedef struct {
- u8 event;
- u8 count;
-} CPC_OVERRUN_T;
-
-/*
- * CAN errors
- * Each CAN controller type has different
- * registers to record errors.
- * Therefor a structure containing the specific
- * errors is set up for each controller here
- */
-
-/*
- * SJA1000 error structure
- * see the SJA1000 datasheet for detailed
- * explanation of the registers
- */
-typedef struct CPC_SJA1000_CAN_ERROR {
- u8 ecc; /* error capture code register */
- u8 rxerr; /* RX error counter register */
- u8 txerr; /* TX error counter register */
-} CPC_SJA1000_CAN_ERROR_T;
-
-/*
- * M16C error structure
- * see the M16C datasheet for detailed
- * explanation of the registers
- */
-typedef struct CPC_M16C_CAN_ERROR {
- u8 tbd; /* to be defined */
-} CPC_M16C_CAN_ERROR_T;
-
-/* structure for CAN error conditions */
-#define CPC_CAN_ECODE_ERRFRAME 0x01
-typedef struct CPC_CAN_ERROR {
- u8 ecode;
- struct {
- u8 cc_type; /* CAN controller type */
- union {
- CPC_SJA1000_CAN_ERROR_T sja1000;
- CPC_M16C_CAN_ERROR_T m16c;
- } regs;
- } cc;
-} CPC_CAN_ERROR_T;
-
-/*
- * Structure containing RX/TX error counter.
- * This structure is used to request the
- * values of the CAN controllers TX and RX
- * error counter.
- */
-typedef struct CPC_CAN_ERR_COUNTER {
- u8 rx;
- u8 tx;
-} CPC_CAN_ERR_COUNTER_T;
-
-/* If this flag is set, transmissions from PC to CPC are protected against loss */
-#define CPC_SECURE_TO_CPC 0x01
-
-/* If this flag is set, transmissions from CPC to PC are protected against loss */
-#define CPC_SECURE_TO_PC 0x02
-
-/* If this flag is set, the CAN-transmit buffer is checked to be free before sending a message */
-#define CPC_SECURE_SEND 0x04
-
-/*
- * If this flag is set, the transmission complete flag is checked
- * after sending a message
- * THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
- */
-#define CPC_SECURE_TRANSMIT 0x08
-
-/* main message type used between library and application */
-typedef struct CPC_MSG {
- u8 type; /* type of message */
- u8 length; /* length of data within union 'msg' */
- u8 msgid; /* confirmation handle */
- u32 ts_sec; /* timestamp in seconds */
- u32 ts_nsec; /* timestamp in nano seconds */
- union {
- u8 generic[CPC_MSG_LEN];
- CPC_CAN_MSG_T canmsg;
- CPC_CAN_PARAMS_T canparams;
- CPC_CONFIRM_T confirmation;
- CPC_INFO_T info;
- CPC_OVERRUN_T overrun;
- CPC_CAN_ERROR_T error;
- CPC_CAN_ERR_COUNTER_T err_counter;
- u8 busload;
- u8 canstate;
- } msg;
-} CPC_MSG_T;
-
-#endif /* CPC_HEADER */
diff --git a/drivers/staging/cpc-usb/cpc_int.h b/drivers/staging/cpc-usb/cpc_int.h
deleted file mode 100644
index 38674e9690a0..000000000000
--- a/drivers/staging/cpc-usb/cpc_int.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * CPCLIB
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * 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.
- *
- */
-#ifndef CPC_INT_H
-#define CPC_INT_H
-
-#include <linux/wait.h>
-
-#define CPC_MSG_BUF_CNT 1500
-
-#define CPC_PROC_DIR "driver/"
-
-#undef dbg
-#undef err
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
-
-/* Macros help using of our buffers */
-#define IsBufferFull(x) (!(x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferEmpty(x) ((x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
-#define ResetBuffer(x) do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
-
-#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
-
-typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
- unsigned char val);
-typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
-
-typedef struct CPC_CHAN {
- void __iomem * canBase; /* base address of SJA1000 */
- chan_read_byte_t read_byte; /* CAN controller read access routine */
- chan_write_byte_t write_byte; /* CAN controller write access routine */
- CPC_MSG_T *buf; /* buffer for CPC msg */
- unsigned int iidx;
- unsigned int oidx;
- unsigned int WnR;
- unsigned int minor;
- unsigned int locked;
- unsigned int irqDisabled;
-
- unsigned char cpcCtrlCANMessage;
- unsigned char cpcCtrlCANState;
- unsigned char cpcCtrlBUSState;
-
- unsigned char controllerType;
-
- unsigned long ovrTimeSec;
- unsigned long ovrTimeNSec;
- unsigned long ovrLockedBuffer;
- CPC_OVERRUN_T ovr;
-
- /* for debugging only */
- unsigned int handledIrqs;
- unsigned int lostMessages;
-
- unsigned int sentStdCan;
- unsigned int sentExtCan;
- unsigned int sentStdRtr;
- unsigned int sentExtRtr;
-
- unsigned int recvStdCan;
- unsigned int recvExtCan;
- unsigned int recvStdRtr;
- unsigned int recvExtRtr;
-
- wait_queue_head_t *CPCWait_q;
-
- void *private;
-} CPC_CHAN_T;
-
-#endif
diff --git a/drivers/staging/cpc-usb/cpcusb.h b/drivers/staging/cpc-usb/cpcusb.h
deleted file mode 100644
index 6bdf30be239f..000000000000
--- a/drivers/staging/cpc-usb/cpcusb.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Header for CPC-USB Driver ********************
- * Copyright 1999, 2000, 2001
- *
- * Company: EMS Dr. Thomas Wuensche
- * Sonnenhang 3
- * 85304 Ilmmuenster
- * Phone: +49-8441-490260
- * Fax: +49-8441-81860
- * email: support@ems-wuensche.com
- * WWW: www.ems-wuensche.com
- */
-
-#ifndef CPCUSB_H
-#define CPCUSB_H
-
-#undef err
-#undef dbg
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
-
-#define CPC_USB_CARD_CNT 4
-
-typedef struct CPC_USB_READ_URB {
- unsigned char *buffer; /* the buffer to send data */
- size_t size; /* the size of the send buffer */
- struct urb *urb; /* the urb used to send data */
-} CPC_USB_READ_URB_T;
-
-typedef struct CPC_USB_WRITE_URB {
- unsigned char *buffer; /* the buffer to send data */
- size_t size; /* the size of the send buffer */
- struct urb *urb; /* the urb used to send data */
- atomic_t busy; /* true if write urb is busy */
- struct completion finished; /* wait for the write to finish */
-} CPC_USB_WRITE_URB_T;
-
-#define CPC_USB_URB_CNT 10
-
-typedef struct CPC_USB {
- struct usb_device *udev; /* save off the usb device pointer */
- struct usb_interface *interface; /* the interface for this device */
- unsigned char minor; /* the starting minor number for this device */
- unsigned char num_ports; /* the number of ports this device has */
- int num_intr_in; /* number of interrupt in endpoints we have */
- int num_bulk_in; /* number of bulk in endpoints we have */
- int num_bulk_out; /* number of bulk out endpoints we have */
-
- CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
-
- unsigned char intr_in_buffer[4]; /* interrupt transfer buffer */
- struct urb *intr_in_urb; /* interrupt transfer urb */
-
- CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
-
- int open; /* if the port is open or not */
- int present; /* if the device is not disconnected */
- struct semaphore sem; /* locks this structure */
-
- int free_slots; /* free send slots of CPC-USB */
- int idx;
-
- spinlock_t slock;
-
- char serialNumber[128]; /* serial number */
- int productId; /* product id to differ between M16C and LPC2119 */
- CPC_CHAN_T *chan;
-} CPC_USB_T;
-
-#define CPCTable CPCUSB_Table
-
-#define CPC_DRIVER_VERSION "0.724"
-#define CPC_DRIVER_SERIAL "not applicable"
-
-#define OBUF_SIZE 255 /* 4096 */
-
-/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
-#define RD_EXPIRE 12 /* Number of attempts to wait X seconds */
-
-#define CPC_USB_BASE_MNR 0 /* CPC-USB start at minor 0 */
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c.h b/drivers/staging/cpc-usb/sja2m16c.h
deleted file mode 100644
index 654bd3fc91dc..000000000000
--- a/drivers/staging/cpc-usb/sja2m16c.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _SJA2M16C_H
-#define _SJA2M16C_H
-
-#include "cpc.h"
-
-#define BAUDRATE_TOLERANCE_PERCENT 1
-#define SAMPLEPOINT_TOLERANCE_PERCENT 5
-#define SAMPLEPOINT_UPPER_LIMIT 88
-
-/* M16C parameters */
-struct FIELD_C0CONR {
- unsigned int brp:4;
- unsigned int sam:1;
- unsigned int pr:3;
- unsigned int dummy:8;
-};
-struct FIELD_C1CONR {
- unsigned int ph1:3;
- unsigned int ph2:3;
- unsigned int sjw:2;
- unsigned int dummy:8;
-};
-typedef union C0CONR {
- unsigned char c0con;
- struct FIELD_C0CONR bc0con;
-} C0CONR_T;
-typedef union C1CONR {
- unsigned char c1con;
- struct FIELD_C1CONR bc1con;
-} C1CONR_T;
-
-#define SJA_TSEG1 ((pParams->btr1 & 0x0f)+1)
-#define SJA_TSEG2 (((pParams->btr1 & 0x70)>>4)+1)
-#define SJA_BRP ((pParams->btr0 & 0x3f)+1)
-#define SJA_SJW ((pParams->btr0 & 0xc0)>>6)
-#define SJA_SAM ((pParams->btr1 & 0x80)>>7)
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
-
-#endif
diff --git a/drivers/staging/cpc-usb/sja2m16c_2.c b/drivers/staging/cpc-usb/sja2m16c_2.c
deleted file mode 100644
index bf0230fb7780..000000000000
--- a/drivers/staging/cpc-usb/sja2m16c_2.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/****************************************************************************
-*
-* Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
-*
-* - All rights reserved -
-*
-* This code is provided "as is" without warranty of any kind, either
-* expressed or implied, including but not limited to the liability
-* concerning the freedom from material defects, the fitness for parti-
-* cular purposes or the freedom of proprietary rights of third parties.
-*
-*****************************************************************************
-* Module name.: cpcusb
-*****************************************************************************
-* Include file: cpc.h
-*****************************************************************************
-* Project.....: Windows Driver Development Kit
-* Filename....: sja2m16c.cpp
-* Authors.....: (GU) Gerhard Uttenthaler
-* (CS) Christian Schoett
-*****************************************************************************
-* Short descr.: converts baudrate between SJA1000 and M16C
-*****************************************************************************
-* Description.: handles the baudrate conversion from SJA1000 parameters to
-* M16C parameters
-*****************************************************************************
-* Address : EMS Dr. Thomas Wuensche
-* Sonnenhang 3
-* D-85304 Ilmmuenster
-* Tel. : +49-8441-490260
-* Fax. : +49-8441-81860
-* email: support@ems-wuensche.com
-*****************************************************************************
-* History
-*****************************************************************************
-* Version Date Auth Remark
-*
-* 01.00 ?? GU - initial release
-* 01.10 ?????????? CS - adapted to fit into the USB Windows driver
-* 02.00 18.08.2004 GU - improved the baudrate calculating algorithm
-* - implemented acceptance filtering
-* 02.10 10.09.2004 CS - adapted to fit into the USB Windows driver
-*****************************************************************************
-* ToDo's
-*****************************************************************************
-*/
-
-/****************************************************************************/
-/* I N C L U D E S
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include "cpc.h"
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/*********************************************************************/
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
-{
- return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
- ph1 + 1 + ph2 +
- 1);
-}
-
-
-/*********************************************************************/
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
-{
- return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
- ph2 + 1);
-}
-
-
-/****************************************************************************
-* Function.....: SJA1000_TO_M16C_BASIC_Params
-*
-* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
-* parameters based on the sample point and the error. In
-* addition it converts the acceptance filter parameters to
-* suit the M16C parameters
-*
-* Parameters...: None
-*
-* Return values: None
-*
-* Comments.....:
-*****************************************************************************
-* History
-*****************************************************************************
-* 19.01.2005 CS - modifed the conversion of SJA1000 filter params into
-* M16C params. Due to compatibility reasons with the
-* older 82C200 CAN controller the SJA1000
-****************************************************************************/
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
-{
- int sjaBaudrate;
- int sjaSamplepoint;
- int *baudrate_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
- int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
- int baudrate_error_merk;
- int clk, brp, pr, ph1, ph2;
- int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
- int index;
- unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
- unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
- CPC_MSG_T * out;
- C0CONR_T c0con;
- C1CONR_T c1con;
- int tmpAccCode;
- int tmpAccMask;
-
- // we have to convert the parameters into M16C parameters
- CPC_SJA1000_PARAMS_T * pParams;
-
- // check if the type is CAN parameters and if we have to convert the given params
- if (in->type != CPC_CMD_T_CAN_PRMS
- || in->msg.canparams.cc_type != SJA1000)
- return 0;
- pParams =
- (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
- acc_code0 = pParams->acc_code0;
- acc_code1 = pParams->acc_code1;
- acc_code2 = pParams->acc_code2;
- acc_code3 = pParams->acc_code3;
- acc_mask0 = pParams->acc_mask0;
- acc_mask1 = pParams->acc_mask1;
- acc_mask2 = pParams->acc_mask2;
- acc_mask3 = pParams->acc_mask3;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
- info("acc_code0: %2.2Xh\n", acc_code0);
- info("acc_code1: %2.2Xh\n", acc_code1);
- info("acc_code2: %2.2Xh\n", acc_code2);
- info("acc_code3: %2.2Xh\n", acc_code3);
- info("acc_mask0: %2.2Xh\n", acc_mask0);
- info("acc_mask1: %2.2Xh\n", acc_mask1);
- info("acc_mask2: %2.2Xh\n", acc_mask2);
- info("acc_mask3: %2.2Xh\n", acc_mask3);
-
-#endif /* */
- if (!
- (baudrate_error =
- (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
- err("Could not allocate memory\n");
- return -3;
- }
- if (!
- (samplepoint_error =
- (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
- err("Could not allocate memory\n");
- vfree(baudrate_error);
- return -3;
- }
- memset(baudrate_error, 0xff, sizeof(baudrate_error));
- memset(samplepoint_error, 0xff, sizeof(baudrate_error));
- sjaBaudrate =
- 16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
- sjaSamplepoint =
- 100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
- if (sjaBaudrate == 0) {
- vfree(baudrate_error);
- vfree(samplepoint_error);
- return -2;
- }
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
- info("\nStarting SJA CAN params\n");
- info("-------------------------\n");
- info("TS1 : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
- info("BTR0 : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
- pParams->btr1);
- info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
- sjaBaudrate % 1000);
- info("Sample P: 0.%d\n", sjaSamplepoint);
- info("\n");
-
-#endif /* */
- c0con.bc0con.sam = SJA_SAM;
- c1con.bc1con.sjw = SJA_SJW;
-
- // calculate errors for all baudrates
- index = 0;
- for (clk = 0; clk < 5; clk++) {
- for (brp = 0; brp < 16; brp++) {
- for (pr = 0; pr < 8; pr++) {
- for (ph1 = 0; ph1 < 8; ph1++) {
- for (ph2 = 0; ph2 < 8; ph2++) {
- baudrate_error[index] =
- 100 *
- abs(baudrate_m16c
- (clk, brp, pr, ph1,
- ph2) -
- sjaBaudrate) /
- sjaBaudrate;
- samplepoint_error[index] =
- abs(samplepoint_m16c
- (brp, pr, ph1,
- ph2) -
- sjaSamplepoint);
-
-#if 0
- info
- ("Baudrate : %d kBaud\n",
- baudrate_m16c(clk,
- brp, pr,
- ph1,
- ph2));
- info
- ("Baudrate Error: %d\n",
- baudrate_error
- [index]);
- info
- ("Sample P Error: %d\n",
- samplepoint_error
- [index]);
- info
- ("clk : %d\n",
- clk);
-
-#endif /* */
- index++;
- }
- }
- }
- }
- }
-
- // mark all baudrate_error entries which are outer limits
- index = 0;
- for (clk = 0; clk < 5; clk++) {
- for (brp = 0; brp < 16; brp++) {
- for (pr = 0; pr < 8; pr++) {
- for (ph1 = 0; ph1 < 8; ph1++) {
- for (ph2 = 0; ph2 < 8; ph2++) {
- if ((baudrate_error[index]
- >
- BAUDRATE_TOLERANCE_PERCENT)
- ||
- (samplepoint_error
- [index] >
- SAMPLEPOINT_TOLERANCE_PERCENT)
- ||
- (samplepoint_m16c
- (brp, pr, ph1,
- ph2) >
- SAMPLEPOINT_UPPER_LIMIT))
- {
- baudrate_error
- [index] = -1;
- } else
- if (((1 + pr + 1 +
- ph1 + 1 + ph2 +
- 1) < 8)
- ||
- ((1 + pr + 1 +
- ph1 + 1 + ph2 +
- 1) > 25)) {
- baudrate_error
- [index] = -1;
- }
-
-#if 0
- else {
- info
- ("Baudrate : %d kBaud\n",
- baudrate_m16c
- (clk, brp, pr,
- ph1, ph2));
- info
- ("Baudrate Error: %d\n",
- baudrate_error
- [index]);
- info
- ("Sample P Error: %d\n",
- samplepoint_error
- [index]);
- }
-
-#endif /* */
- index++;
- }
- }
- }
- }
- }
-
- // find list of minimum of baudrate_error within unmarked entries
- clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
- baudrate_error_merk = 100;
- index = 0;
- for (clk = 0; clk < 5; clk++) {
- for (brp = 0; brp < 16; brp++) {
- for (pr = 0; pr < 8; pr++) {
- for (ph1 = 0; ph1 < 8; ph1++) {
- for (ph2 = 0; ph2 < 8; ph2++) {
- if (baudrate_error[index]
- != -1) {
- if (baudrate_error
- [index] <
- baudrate_error_merk)
- {
- baudrate_error_merk
- =
- baudrate_error
- [index];
- brp_merk =
- brp;
- pr_merk =
- pr;
- ph1_merk =
- ph1;
- ph2_merk =
- ph2;
- clk_merk =
- clk;
-
-#if 0
- info
- ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
- brp,
- pr,
- ph1,
- ph2);
- info
- ("Baudrate : %d kBaud\n",
- baudrate_m16c
- (clk,
- brp,
- pr,
- ph1,
- ph2));
- info
- ("Baudrate Error: %d\n",
- baudrate_error
- [index]);
- info
- ("Sample P Error: %d\n",
- samplepoint_error
- [index]);
-
-#endif /* */
- }
- }
- index++;
- }
- }
- }
- }
- }
- if (baudrate_error_merk == 100) {
- info("ERROR: Could not convert CAN init parameter\n");
- vfree(baudrate_error);
- vfree(samplepoint_error);
- return -1;
- }
-
- // setting m16c CAN parameter
- c0con.bc0con.brp = brp_merk;
- c0con.bc0con.pr = pr_merk;
- c1con.bc1con.ph1 = ph1_merk;
- c1con.bc1con.ph2 = ph2_merk;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
- info("\nResulting M16C CAN params\n");
- info("-------------------------\n");
- info("clk : %2.2Xh\n", clk_merk);
- info("ph1 : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
- c1con.bc1con.ph2 + 1);
- info("pr : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
- c0con.bc0con.brp + 1);
- info("sjw : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
- c0con.bc0con.sam);
- info("co1 : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
- info("Baudrate: %d.%dBaud\n",
- baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
- c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
- baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
- c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
- info("Sample P: 0.%d\n",
- samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
- c1con.bc1con.ph1, c1con.bc1con.ph2));
- info("\n");
-
-#endif /* */
- out = in;
- out->type = 6;
- out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
- out->msg.canparams.cc_type = M16C_BASIC;
- out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
- out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
- out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
- out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
- out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
- out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
- acc_code0;
- out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
-
-// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
- tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
- out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
- (unsigned char) tmpAccCode;
- out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
- (unsigned char) (tmpAccCode >> 8);
-
-// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
- out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
- ~acc_mask0;
- out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
- ~acc_mask1;
-
-// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
- tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
-
-// info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
- out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
- (unsigned char) ~tmpAccMask;
- out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
- (unsigned char) ~(tmpAccMask >> 8);
-
-// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
- out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
- (unsigned char) tmpAccCode;
- out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
- (unsigned char) (tmpAccCode >> 8);
- out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
- out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
- out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
- (unsigned char) ~tmpAccMask;
- out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
- (unsigned char) ~(tmpAccMask >> 8);
- out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
- ~acc_mask2;
- out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
- ~acc_mask3;
- vfree(baudrate_error);
- vfree(samplepoint_error);
- return 0;
-}
-
-
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig
new file mode 100644
index 000000000000..df7756a95fad
--- /dev/null
+++ b/drivers/staging/cx25821/Kconfig
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+ tristate "Conexant cx25821 support"
+ depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+ select I2C_ALGOBIT
+ select VIDEO_BTCX
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
+ select VIDEOBUF_DVB
+ select VIDEOBUF_DMA_SG
+ select VIDEO_CX25840
+ select VIDEO_CX2341X
+ ---help---
+ This is a video4linux driver for Conexant 25821 based
+ TV cards.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx25821
+
+config VIDEO_CX25821_ALSA
+ tristate "Conexant 25821 DMA audio support"
+ depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+ select SND_PCM
+ ---help---
+ This is a video4linux driver for direct (DMA) audio on
+ Conexant 25821 based capture cards using ALSA.
+
+ It only works with boards with function 01 enabled.
+ To check if your board supports, use lspci -n.
+ If supported, you should see 14f1:8801 or 14f1:8811
+ PCI device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx25821-alsa.
+
diff --git a/drivers/staging/cx25821/Makefile b/drivers/staging/cx25821/Makefile
new file mode 100644
index 000000000000..10f87f05d8e8
--- /dev/null
+++ b/drivers/staging/cx25821/Makefile
@@ -0,0 +1,14 @@
+cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o \
+ cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o \
+ cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o \
+ cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o \
+ cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o \
+ cx25821-audio-upstream.o cx25821-videoioctl.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/drivers/staging/cx25821/README b/drivers/staging/cx25821/README
new file mode 100644
index 000000000000..a9ba50b9888b
--- /dev/null
+++ b/drivers/staging/cx25821/README
@@ -0,0 +1,6 @@
+Todo:
+ - checkpatch.pl cleanups
+ - sparse cleanups
+
+Please send patches to linux-media@vger.kernel.org
+
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c
new file mode 100644
index 000000000000..e0eef12759e4
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-alsa.c
@@ -0,0 +1,789 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on SAA713x ALSA driver and CX88 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, version 2
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL SRAM_CH08
+
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+ Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_dev {
+ struct cx25821_dev *dev;
+ struct cx25821_dmaqueue q;
+
+ /* pci i/o */
+ struct pci_dev *pci;
+
+ /* audio controls */
+ int irq;
+
+ struct snd_card *card;
+
+ unsigned long iobase;
+ spinlock_t reg_lock;
+ atomic_t count;
+
+ unsigned int dma_size;
+ unsigned int period_size;
+ unsigned int num_periods;
+
+ struct videobuf_dmabuf *dma_risc;
+
+ struct cx25821_buffer *buf;
+
+ struct snd_pcm_substream *substream;
+};
+typedef struct cx25821_audio_dev snd_cx25821_card_t;
+
+
+/****************************************************************************
+ Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = { 1,[1 ... (SNDRV_CARDS - 1)] = 1 };
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+/****************************************************************************
+ Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); //"{{Conexant,23881},"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+ Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1 (1 << 0)
+#define AUD_INT_UP_RISCI1 (1 << 1)
+#define AUD_INT_RDS_DN_RISCI1 (1 << 2)
+#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2 (1 << 5)
+#define AUD_INT_RDS_DN_RISCI2 (1 << 6)
+#define AUD_INT_DN_SYNC (1 << 12)
+#define AUD_INT_UP_SYNC (1 << 13)
+#define AUD_INT_RDS_DN_SYNC (1 << 14)
+#define AUD_INT_OPC_ERR (1 << 16)
+#define AUD_INT_BER_IRQ (1 << 20)
+#define AUD_INT_MCHG_IRQ (1 << 21)
+#define GP_COUNT_CONTROL_RESET 0x3
+
+#define PCI_MSK_AUD_EXT (1 << 4)
+#define PCI_MSK_AUD_INT (1 << 3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip)
+{
+ struct cx25821_buffer *buf = chip->buf;
+ struct cx25821_dev *dev = chip->dev;
+ struct sram_channel *audio_ch =
+ &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+ u32 tmp = 0;
+
+ // enable output on the GPIO 0 for the MCLK ADC (Audio)
+ cx25821_set_gpiopin_direction(chip->dev, 0, 0);
+
+ /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+ cx_clear(AUD_INT_DMA_CTL,
+ FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+ /* setup fifo + format - out channel */
+ cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
+ buf->risc.dma);
+
+ /* sets bpl size */
+ cx_write(AUD_A_LNGTH, buf->bpl);
+
+ /* reset counter */
+ cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3
+ atomic_set(&chip->count, 0);
+
+ //Set the input mode to 16-bit
+ tmp = cx_read(AUD_A_CFG);
+ cx_write(AUD_A_CFG,
+ tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+ FLD_AUD_CLK_ENABLE);
+
+ //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d "
+ // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1,
+ // chip->num_periods, buf->bpl * chip->num_periods);
+
+ /* Enables corresponding bits at AUD_INT_STAT */
+ cx_write(AUD_A_INT_MSK,
+ FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC |
+ FLD_AUD_DST_OPC_ERR);
+
+ /* Clean any pending interrupt bits already set */
+ cx_write(AUD_A_INT_STAT, ~0);
+
+ /* enable audio irqs */
+ cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+ // Turn on audio downstream fifo and risc enable 0x101
+ tmp = cx_read(AUD_INT_DMA_CTL);
+ cx_set(AUD_INT_DMA_CTL,
+ tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+
+ mdelay(100);
+ return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(snd_cx25821_card_t * chip)
+{
+ struct cx25821_dev *dev = chip->dev;
+
+ /* stop dma */
+ cx_clear(AUD_INT_DMA_CTL,
+ FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+ /* disable irqs */
+ cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+ cx_clear(AUD_A_INT_MSK,
+ AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 |
+ AUD_INT_DN_RISCI1);
+
+ return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+ "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+ NULL, /* reserved */
+ "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+ NULL, /* reserved */
+ "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
+ NULL, /* reserved */
+ "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
+ NULL, /* reserved */
+ "opc_err", "par_err", "rip_err", /* 16-18 */
+ "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(snd_cx25821_card_t * chip, u32 status, u32 mask)
+{
+ struct cx25821_dev *dev = chip->dev;
+
+ if (0 == (status & mask)) {
+ return;
+ }
+
+ cx_write(AUD_A_INT_STAT, status);
+ if (debug > 1 || (status & mask & ~0xff))
+ cx25821_print_irqbits(dev->name, "irq aud",
+ cx25821_aud_irqs,
+ ARRAY_SIZE(cx25821_aud_irqs), status,
+ mask);
+
+ /* risc op code error */
+ if (status & AUD_INT_OPC_ERR) {
+ printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",
+ dev->name);
+
+ cx_clear(AUD_INT_DMA_CTL,
+ FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+ cx25821_sram_channel_dump_audio(dev,
+ &cx25821_sram_channels
+ [AUDIO_SRAM_CHANNEL]);
+ }
+ if (status & AUD_INT_DN_SYNC) {
+ printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",
+ dev->name);
+ cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+ return;
+ }
+
+ /* risc1 downstream */
+ if (status & AUD_INT_DN_RISCI1) {
+ atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+ snd_pcm_period_elapsed(chip->substream);
+ }
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+ snd_cx25821_card_t *chip = dev_id;
+ struct cx25821_dev *dev = chip->dev;
+ u32 status, pci_status;
+ u32 audint_status, audint_mask;
+ int loop, handled = 0;
+ int audint_count = 0;
+
+ audint_status = cx_read(AUD_A_INT_STAT);
+ audint_mask = cx_read(AUD_A_INT_MSK);
+ audint_count = cx_read(AUD_A_GPCNT);
+ status = cx_read(PCI_INT_STAT);
+
+ for (loop = 0; loop < 1; loop++) {
+ status = cx_read(PCI_INT_STAT);
+ if (0 == status) {
+ status = cx_read(PCI_INT_STAT);
+ audint_status = cx_read(AUD_A_INT_STAT);
+ audint_mask = cx_read(AUD_A_INT_MSK);
+
+ if (status) {
+ handled = 1;
+ cx_write(PCI_INT_STAT, status);
+
+ cx25821_aud_irq(chip, audint_status,
+ audint_mask);
+ break;
+ } else
+ goto out;
+ }
+
+ handled = 1;
+ cx_write(PCI_INT_STAT, status);
+
+ cx25821_aud_irq(chip, audint_status, audint_mask);
+ }
+
+ pci_status = cx_read(PCI_INT_STAT);
+
+ if (handled)
+ cx_write(PCI_INT_STAT, pci_status);
+
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+static int dsp_buffer_free(snd_cx25821_card_t * chip)
+{
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2, "Freeing buffer\n");
+ videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
+ videobuf_dma_free(chip->dma_risc);
+ btcx_riscmem_free(chip->pci, &chip->buf->risc);
+ kfree(chip->buf);
+
+ chip->dma_risc = NULL;
+ chip->dma_size = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE 384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* Analog audio output will be full of clicks and pops if there
+ are not exactly four lines in the SRAM FIFO buffer. */
+ .period_bytes_min = DEFAULT_FIFO_SIZE / 3,
+ .period_bytes_max = DEFAULT_FIFO_SIZE / 3,
+ .periods_min = 1,
+ .periods_max = AUDIO_LINE_SIZE,
+ .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+ snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ unsigned int bpl = 0;
+
+ if (!chip) {
+ printk(KERN_ERR "DEBUG: cx25821 can't find device struct."
+ " Can't proceed with open\n");
+ return -ENODEV;
+ }
+
+ err =
+ snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
+ goto _error;
+
+ chip->substream = substream;
+
+ runtime->hw = snd_cx25821_digital_hw;
+
+ if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+ DEFAULT_FIFO_SIZE) {
+ bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters
+ bpl &= ~7; /* must be multiple of 8 */
+
+ if (bpl > AUDIO_LINE_SIZE) {
+ bpl = AUDIO_LINE_SIZE;
+ }
+ runtime->hw.period_bytes_min = bpl;
+ runtime->hw.period_bytes_max = bpl;
+ }
+
+ return 0;
+ _error:
+ dprintk(1, "Error opening PCM!\n");
+ return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+ struct videobuf_dmabuf *dma;
+
+ struct cx25821_buffer *buf;
+ int ret;
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ chip->period_size = params_period_bytes(hw_params);
+ chip->num_periods = params_periods(hw_params);
+ chip->dma_size = chip->period_size * params_periods(hw_params);
+
+ BUG_ON(!chip->dma_size);
+ BUG_ON(chip->num_periods & (chip->num_periods - 1));
+
+ buf = videobuf_sg_alloc(sizeof(*buf));
+ if (NULL == buf)
+ return -ENOMEM;
+
+ if (chip->period_size > AUDIO_LINE_SIZE) {
+ chip->period_size = AUDIO_LINE_SIZE;
+ }
+
+ buf->vb.memory = V4L2_MEMORY_MMAP;
+ buf->vb.field = V4L2_FIELD_NONE;
+ buf->vb.width = chip->period_size;
+ buf->bpl = chip->period_size;
+ buf->vb.height = chip->num_periods;
+ buf->vb.size = chip->dma_size;
+
+ dma = videobuf_to_dma(&buf->vb);
+ videobuf_dma_init(dma);
+
+ ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+ (PAGE_ALIGN(buf->vb.size) >>
+ PAGE_SHIFT));
+ if (ret < 0)
+ goto error;
+
+ ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
+ if (ret < 0)
+ goto error;
+
+ ret =
+ cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+ buf->vb.width, buf->vb.height, 1);
+ if (ret < 0) {
+ printk(KERN_INFO
+ "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n");
+ goto error;
+ }
+
+ /* Loop back to start of program */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ buf->vb.state = VIDEOBUF_PREPARED;
+
+ chip->buf = buf;
+ chip->dma_risc = dma;
+
+ substream->runtime->dma_area = chip->dma_risc->vmalloc;
+ substream->runtime->dma_bytes = chip->dma_size;
+ substream->runtime->dma_addr = 0;
+
+ return 0;
+
+ error:
+ kfree(buf);
+ return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+ snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+ int err = 0;
+
+ /* Local interrupts are already disabled by ALSA */
+ spin_lock(&chip->reg_lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err = _cx25821_start_audio_dma(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ err = _cx25821_stop_audio_dma(chip);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&chip->reg_lock);
+
+ return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
+ *substream)
+{
+ snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ u16 count;
+
+ count = atomic_read(&chip->count);
+
+ return runtime->period_size * (count & (runtime->periods - 1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+{
+ void *pageptr = substream->runtime->dma_area + offset;
+
+ return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+ .open = snd_cx25821_pcm_open,
+ .close = snd_cx25821_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cx25821_hw_params,
+ .hw_free = snd_cx25821_hw_free,
+ .prepare = snd_cx25821_prepare,
+ .trigger = snd_cx25821_card_trigger,
+ .pointer = snd_cx25821_pointer,
+ .page = snd_cx25821_page,
+};
+
+/*
+ * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up
+ * the callbacks
+ */
+static int snd_cx25821_pcm(snd_cx25821_card_t * chip, int device, char *name)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+ if (err < 0) {
+ printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n",
+ __func__);
+ return err;
+ }
+ pcm->private_data = chip;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, name);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+ return 0;
+}
+
+/****************************************************************************
+ Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = {
+ {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Not used in the function snd_cx25821_dev_free so removing
+ * from the file.
+ */
+/*
+static int snd_cx25821_free(snd_cx25821_card_t *chip)
+{
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
+ cx25821_dev_unregister(chip->dev);
+ pci_disable_device(chip->pci);
+
+ return 0;
+}
+*/
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card *card)
+{
+ snd_cx25821_card_t *chip = card->private_data;
+
+ //snd_cx25821_free(chip);
+ snd_card_free(chip->card);
+}
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+ struct snd_card *card;
+ snd_cx25821_card_t *chip;
+ int err;
+
+ if (devno >= SNDRV_CARDS) {
+ printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n",
+ __func__);
+ return (-ENODEV);
+ }
+
+ if (!enable[devno]) {
+ ++devno;
+ printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__);
+ return (-ENOENT);
+ }
+
+ err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+ sizeof(snd_cx25821_card_t), &card);
+ if (err < 0) {
+ printk(KERN_INFO
+ "DEBUG ERROR: cannot create snd_card_new in %s\n",
+ __func__);
+ return err;
+ }
+
+ strcpy(card->driver, "cx25821");
+
+ /* Card "creation" */
+ card->private_free = snd_cx25821_dev_free;
+ chip = (snd_cx25821_card_t *) card->private_data;
+ spin_lock_init(&chip->reg_lock);
+
+ chip->dev = dev;
+ chip->card = card;
+ chip->pci = dev->pci;
+ chip->iobase = pci_resource_start(dev->pci, 0);
+
+ chip->irq = dev->pci->irq;
+
+ err = request_irq(dev->pci->irq, cx25821_irq,
+ IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip);
+
+ if (err < 0) {
+ printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n",
+ chip->dev->name, dev->pci->irq);
+ goto error;
+ }
+
+ if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) {
+ printk(KERN_INFO
+ "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+ __func__);
+ goto error;
+ }
+
+ snd_card_set_dev(card, &chip->pci->dev);
+
+ strcpy(card->shortname, "cx25821");
+ sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+ chip->iobase, chip->irq);
+ strcpy(card->mixername, "CX25821");
+
+ printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n",
+ card->driver, devno);
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n",
+ __func__);
+ goto error;
+ }
+
+ snd_cx25821_cards[devno] = card;
+
+ devno++;
+ return 0;
+
+ error:
+ snd_card_free(card);
+ return err;
+}
+
+/****************************************************************************
+ LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+ snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+ struct cx25821_dev *dev = NULL;
+ struct list_head *list;
+
+ list_for_each(list, &cx25821_devlist) {
+ dev = list_entry(list, struct cx25821_dev, devlist);
+ cx25821_audio_initdev(dev);
+ }
+
+ if (dev == NULL)
+ printk(KERN_INFO
+ "cx25821 ERROR ALSA: no cx25821 cards found\n");
+
+ return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c
new file mode 100644
index 000000000000..ddddf651266b
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-audio-upstream.c
@@ -0,0 +1,804 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include "cx25821-video.h"
+#include "cx25821-audio-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk =
+ FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC |
+ FLD_AUD_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc)
+{
+ unsigned int i, lines;
+ u32 cdt;
+
+ if (ch->cmds_start == 0) {
+ cx_write(ch->ptr1_reg, 0);
+ cx_write(ch->ptr2_reg, 0);
+ cx_write(ch->cnt2_reg, 0);
+ cx_write(ch->cnt1_reg, 0);
+ return 0;
+ }
+
+ bpl = (bpl + 7) & ~7; /* alignment */
+ cdt = ch->cdt;
+ lines = ch->fifo_size / bpl;
+
+ if (lines > 3) {
+ lines = 3;
+ }
+
+ BUG_ON(lines < 2);
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+ cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+ cx_write(cdt + 16 * i + 4, 0);
+ cx_write(cdt + 16 * i + 8, 0);
+ cx_write(cdt + 16 * i + 12, 0);
+ }
+
+ /* write CMDS */
+ cx_write(ch->cmds_start + 0, risc);
+
+ cx_write(ch->cmds_start + 4, 0);
+ cx_write(ch->cmds_start + 8, cdt);
+ cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
+ cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+ //IQ size
+ cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
+
+ for (i = 24; i < 80; i += 4)
+ cx_write(ch->cmds_start + i, 0);
+
+ /* fill registers */
+ cx_write(ch->ptr1_reg, ch->fifo_start);
+ cx_write(ch->ptr2_reg, cdt);
+ cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
+ cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
+
+ return 0;
+}
+
+static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
+ __le32 * rp,
+ dma_addr_t databuf_phys_addr,
+ unsigned int bpl,
+ int fifo_enable)
+{
+ unsigned int line;
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[dev->_audio_upstream_channel_select];
+ int offset = 0;
+
+ /* scan lines */
+ for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
+ *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+
+ // Check if we need to enable the FIFO after the first 3 lines
+ // For the upstream audio channel, the risc engine will enable the FIFO.
+ if (fifo_enable && line == 2) {
+ *(rp++) = RISC_WRITECR;
+ *(rp++) = sram_ch->dma_ctl;
+ *(rp++) = sram_ch->fld_aud_fifo_en;
+ *(rp++) = 0x00000020;
+ }
+
+ offset += AUDIO_LINE_SIZE;
+ }
+
+ return rp;
+}
+
+int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+ struct pci_dev *pci,
+ unsigned int bpl, unsigned int lines)
+{
+ __le32 *rp;
+ int fifo_enable = 0;
+ int frame = 0, i = 0;
+ int frame_size = AUDIO_DATA_BUF_SZ;
+ int databuf_offset = 0;
+ int risc_flag = RISC_CNT_INC;
+ dma_addr_t risc_phys_jump_addr;
+
+ /* Virtual address of Risc buffer program */
+ rp = dev->_risc_virt_addr;
+
+ /* sync instruction */
+ *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
+
+ for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
+ databuf_offset = frame_size * frame;
+
+ if (frame == 0) {
+ fifo_enable = 1;
+ risc_flag = RISC_CNT_RESET;
+ } else {
+ fifo_enable = 0;
+ risc_flag = RISC_CNT_INC;
+ }
+
+ //Calculate physical jump address
+ if ((frame + 1) == NUM_AUDIO_FRAMES) {
+ risc_phys_jump_addr =
+ dev->_risc_phys_start_addr +
+ RISC_SYNC_INSTRUCTION_SIZE;
+ } else {
+ risc_phys_jump_addr =
+ dev->_risc_phys_start_addr +
+ RISC_SYNC_INSTRUCTION_SIZE +
+ AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
+ }
+
+ rp = cx25821_risc_field_upstream_audio(dev, rp,
+ dev->
+ _audiodata_buf_phys_addr
+ + databuf_offset, bpl,
+ fifo_enable);
+
+ if (USE_RISC_NOOP_AUDIO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) = cpu_to_le32(RISC_NOOP);
+ }
+ }
+
+ // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ
+ *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+
+ //Recalculate virtual address based on frame index
+ rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
+ (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+ }
+
+ return 0;
+}
+
+void cx25821_free_memory_audio(struct cx25821_dev *dev)
+{
+ if (dev->_risc_virt_addr) {
+ pci_free_consistent(dev->pci, dev->_audiorisc_size,
+ dev->_risc_virt_addr, dev->_risc_phys_addr);
+ dev->_risc_virt_addr = NULL;
+ }
+
+ if (dev->_audiodata_buf_virt_addr) {
+ pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
+ dev->_audiodata_buf_virt_addr,
+ dev->_audiodata_buf_phys_addr);
+ dev->_audiodata_buf_virt_addr = NULL;
+ }
+}
+
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+{
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B];
+ u32 tmp = 0;
+
+ if (!dev->_audio_is_running) {
+ printk
+ ("cx25821: No audio file is currently running so return!\n");
+ return;
+ }
+ //Disable RISC interrupts
+ cx_write(sram_ch->int_msk, 0);
+
+ //Turn OFF risc and fifo enable in AUD_DMA_CNTRL
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_write(sram_ch->dma_ctl,
+ tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
+
+ //Clear data buffer memory
+ if (dev->_audiodata_buf_virt_addr)
+ memset(dev->_audiodata_buf_virt_addr, 0,
+ dev->_audiodata_buf_size);
+
+ dev->_audio_is_running = 0;
+ dev->_is_first_audio_frame = 0;
+ dev->_audioframe_count = 0;
+ dev->_audiofile_status = END_OF_FILE;
+
+ if (dev->_irq_audio_queues) {
+ kfree(dev->_irq_audio_queues);
+ dev->_irq_audio_queues = NULL;
+ }
+
+ if (dev->_audiofilename != NULL)
+ kfree(dev->_audiofilename);
+}
+
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+{
+ if (dev->_audio_is_running) {
+ cx25821_stop_upstream_audio(dev);
+ }
+
+ cx25821_free_memory_audio(dev);
+}
+
+int cx25821_get_audio_data(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int frame_index_temp = dev->_audioframe_index;
+ int i = 0;
+ int line_size = AUDIO_LINE_SIZE;
+ int frame_size = AUDIO_DATA_BUF_SZ;
+ int frame_offset = frame_size * frame_index_temp;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t file_offset = dev->_audioframe_count * frame_size;
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ if (dev->_audiofile_status == END_OF_FILE)
+ return 0;
+
+ myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_audiofilename, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered!\n",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk("%s: File has no READ operations registered! \n",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (i = 0; i < dev->_audio_lines_count; i++) {
+ pos = file_offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0 && vfs_read_retval == line_size
+ && dev->_audiodata_buf_virt_addr != NULL) {
+ memcpy((void *)(dev->_audiodata_buf_virt_addr +
+ frame_offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ file_offset += vfs_read_retval;
+ frame_offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Audio file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0)
+ dev->_audioframe_count++;
+
+ dev->_audiofile_status =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+static void cx25821_audioups_handler(struct work_struct *work)
+{
+ struct cx25821_dev *dev =
+ container_of(work, struct cx25821_dev, _audio_work_entry);
+
+ if (!dev) {
+ printk("ERROR %s(): since container_of(work_struct) FAILED! \n",
+ __func__);
+ return;
+ }
+
+ cx25821_get_audio_data(dev,
+ &dev->sram_channels[dev->
+ _audio_upstream_channel_select]);
+}
+
+int cx25821_openfile_audio(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int i = 0, j = 0;
+ int line_size = AUDIO_LINE_SIZE;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t pos;
+ loff_t offset = (unsigned long)0;
+ mm_segment_t old_fs;
+
+ myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_audiofilename, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered! \n",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk("%s: File has no READ operations registered! \n",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
+ for (i = 0; i < dev->_audio_lines_count; i++) {
+ pos = offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0
+ && vfs_read_retval == line_size
+ && dev->_audiodata_buf_virt_addr != NULL) {
+ memcpy((void *)(dev->
+ _audiodata_buf_virt_addr
+ + offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Audio file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0) {
+ dev->_audioframe_count++;
+ }
+
+ if (vfs_read_retval < line_size) {
+ break;
+ }
+ }
+
+ dev->_audiofile_status =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ myfile->f_pos = 0;
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch,
+ int bpl)
+{
+ int ret = 0;
+ dma_addr_t dma_addr;
+ dma_addr_t data_dma_addr;
+
+ cx25821_free_memory_audio(dev);
+
+ dev->_risc_virt_addr =
+ pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size,
+ &dma_addr);
+ dev->_risc_virt_start_addr = dev->_risc_virt_addr;
+ dev->_risc_phys_start_addr = dma_addr;
+ dev->_risc_phys_addr = dma_addr;
+ dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
+
+ if (!dev->_risc_virt_addr) {
+ printk
+ ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n");
+ return -ENOMEM;
+ }
+ //Clear out memory at address
+ memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
+
+ //For Audio Data buffer allocation
+ dev->_audiodata_buf_virt_addr =
+ pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size,
+ &data_dma_addr);
+ dev->_audiodata_buf_phys_addr = data_dma_addr;
+ dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
+
+ if (!dev->_audiodata_buf_virt_addr) {
+ printk
+ ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n");
+ return -ENOMEM;
+ }
+ //Clear out memory at address
+ memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
+
+ ret = cx25821_openfile_audio(dev, sram_ch);
+ if (ret < 0)
+ return ret;
+
+ //Creating RISC programs
+ ret =
+ cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+ dev->_audio_lines_count);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "cx25821 ERROR creating audio upstream RISC programs! \n");
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ return ret;
+}
+
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+ u32 status)
+{
+ int i = 0;
+ u32 int_msk_tmp;
+ struct sram_channel *channel = &dev->sram_channels[chan_num];
+ dma_addr_t risc_phys_jump_addr;
+ __le32 *rp;
+
+ if (status & FLD_AUD_SRC_RISCI1) {
+ //Get interrupt_index of the program that interrupted
+ u32 prog_cnt = cx_read(channel->gpcnt);
+
+ //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers
+ cx_write(channel->int_msk, 0);
+ cx_write(channel->int_stat, cx_read(channel->int_stat));
+
+ spin_lock(&dev->slock);
+
+ while (prog_cnt != dev->_last_index_irq) {
+ //Update _last_index_irq
+ if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) {
+ dev->_last_index_irq++;
+ } else {
+ dev->_last_index_irq = 0;
+ }
+
+ dev->_audioframe_index = dev->_last_index_irq;
+
+ queue_work(dev->_irq_audio_queues,
+ &dev->_audio_work_entry);
+ }
+
+ if (dev->_is_first_audio_frame) {
+ dev->_is_first_audio_frame = 0;
+
+ if (dev->_risc_virt_start_addr != NULL) {
+ risc_phys_jump_addr =
+ dev->_risc_phys_start_addr +
+ RISC_SYNC_INSTRUCTION_SIZE +
+ AUDIO_RISC_DMA_BUF_SIZE;
+
+ rp = cx25821_risc_field_upstream_audio(dev,
+ dev->
+ _risc_virt_start_addr
+ + 1,
+ dev->
+ _audiodata_buf_phys_addr,
+ AUDIO_LINE_SIZE,
+ FIFO_DISABLE);
+
+ if (USE_RISC_NOOP_AUDIO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) =
+ cpu_to_le32(RISC_NOOP);
+ }
+ }
+ // Jump to 2nd Audio Frame
+ *(rp++) =
+ cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
+ RISC_CNT_RESET);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+ }
+ }
+
+ spin_unlock(&dev->slock);
+ } else {
+ if (status & FLD_AUD_SRC_OF)
+ printk("%s: Audio Received Overflow Error Interrupt!\n",
+ __func__);
+
+ if (status & FLD_AUD_SRC_SYNC)
+ printk("%s: Audio Received Sync Error Interrupt!\n",
+ __func__);
+
+ if (status & FLD_AUD_SRC_OPC_ERR)
+ printk("%s: Audio Received OpCode Error Interrupt!\n",
+ __func__);
+
+ // Read and write back the interrupt status register to clear our bits
+ cx_write(channel->int_stat, cx_read(channel->int_stat));
+ }
+
+ if (dev->_audiofile_status == END_OF_FILE) {
+ printk("cx25821: EOF Channel Audio Framecount = %d\n",
+ dev->_audioframe_count);
+ return -1;
+ }
+ //ElSE, set the interrupt mask register, re-enable irq.
+ int_msk_tmp = cx_read(channel->int_msk);
+ cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+ return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
+{
+ struct cx25821_dev *dev = dev_id;
+ u32 msk_stat, audio_status;
+ int handled = 0;
+ struct sram_channel *sram_ch;
+
+ if (!dev)
+ return -1;
+
+ sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select];
+
+ msk_stat = cx_read(sram_ch->int_mstat);
+ audio_status = cx_read(sram_ch->int_stat);
+
+ // Only deal with our interrupt
+ if (audio_status) {
+ handled =
+ cx25821_audio_upstream_irq(dev,
+ dev->
+ _audio_upstream_channel_select,
+ audio_status);
+ }
+
+ if (handled < 0) {
+ cx25821_stop_upstream_audio(dev);
+ } else {
+ handled += handled;
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ int count = 0;
+ u32 tmp;
+
+ do {
+ //Wait 10 microsecond before checking to see if the FIFO is turned ON.
+ udelay(10);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+
+ if (count++ > 1000) //10 millisecond timeout
+ {
+ printk
+ ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n",
+ __func__);
+ return;
+ }
+
+ } while (!(tmp & sram_ch->fld_aud_fifo_en));
+
+}
+
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ u32 tmp = 0;
+ int err = 0;
+
+ // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS.
+ cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
+ cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+ /* reset counter */
+ cx_write(sram_ch->gpcnt_ctl, 3);
+
+ //Set the line length (It looks like we do not need to set the line length)
+ cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
+
+ //Set the input mode to 16-bit
+ tmp = cx_read(sram_ch->aud_cfg);
+ tmp |=
+ FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+ FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;
+ cx_write(sram_ch->aud_cfg, tmp);
+
+ // Read and write back the interrupt status register to clear it
+ tmp = cx_read(sram_ch->int_stat);
+ cx_write(sram_ch->int_stat, tmp);
+
+ // Clear our bits from the interrupt status register.
+ cx_write(sram_ch->int_stat, _intr_msk);
+
+ //Set the interrupt mask register, enable irq.
+ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+ tmp = cx_read(sram_ch->int_msk);
+ cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+ err =
+ request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+ IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
+ dev->pci->irq);
+ goto fail_irq;
+ }
+
+ // Start the DMA engine
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
+
+ dev->_audio_is_running = 1;
+ dev->_is_first_audio_frame = 1;
+
+ // The fifo_en bit turns on by the first Risc program
+ cx25821_wait_fifo_enable(dev, sram_ch);
+
+ return 0;
+
+ fail_irq:
+ cx25821_dev_unregister(dev);
+ return err;
+}
+
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
+{
+ struct sram_channel *sram_ch;
+ int retval = 0;
+ int err = 0;
+ int str_length = 0;
+
+ if (dev->_audio_is_running) {
+ printk("Audio Channel is still running so return!\n");
+ return 0;
+ }
+
+ dev->_audio_upstream_channel_select = channel_select;
+ sram_ch = &dev->sram_channels[channel_select];
+
+ //Work queue
+ INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
+ dev->_irq_audio_queues =
+ create_singlethread_workqueue("cx25821_audioworkqueue");
+
+ if (!dev->_irq_audio_queues) {
+ printk
+ ("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n");
+ return -ENOMEM;
+ }
+
+ dev->_last_index_irq = 0;
+ dev->_audio_is_running = 0;
+ dev->_audioframe_count = 0;
+ dev->_audiofile_status = RESET_STATUS;
+ dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
+ _line_size = AUDIO_LINE_SIZE;
+
+ if (dev->input_audiofilename) {
+ str_length = strlen(dev->input_audiofilename);
+ dev->_audiofilename =
+ (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_audiofilename)
+ goto error;
+
+ memcpy(dev->_audiofilename, dev->input_audiofilename,
+ str_length + 1);
+
+ //Default if filename is empty string
+ if (strcmp(dev->input_audiofilename, "") == 0) {
+ dev->_audiofilename = "/root/audioGOOD.wav";
+ }
+ } else {
+ str_length = strlen(_defaultAudioName);
+ dev->_audiofilename =
+ (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_audiofilename)
+ goto error;
+
+ memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);
+ }
+
+ retval =
+ cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size,
+ 0);
+
+ dev->audio_upstream_riscbuf_size =
+ AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+ RISC_SYNC_INSTRUCTION_SIZE;
+ dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
+
+ //Allocating buffers and prepare RISC program
+ retval =
+ cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "%s: Failed to set up Audio upstream buffers!\n",
+ dev->name);
+ goto error;
+ }
+ //Start RISC engine
+ cx25821_start_audio_dma_upstream(dev, sram_ch);
+
+ return 0;
+
+ error:
+ cx25821_dev_unregister(dev);
+
+ return err;
+}
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.h b/drivers/staging/cx25821/cx25821-audio-upstream.h
new file mode 100644
index 000000000000..ca987addf815
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-audio-upstream.h
@@ -0,0 +1,57 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define NUM_AUDIO_PROGS 8
+#define NUM_AUDIO_FRAMES 8
+#define END_OF_FILE 0
+#define IN_PROGRESS 1
+#define RESET_STATUS -1
+#define FIFO_DISABLE 0
+#define FIFO_ENABLE 1
+#define NUM_NO_OPS 4
+
+#define RISC_READ_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE 12
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define DWORD_SIZE 4
+#define AUDIO_SYNC_LINE 4
+
+#define LINES_PER_AUDIO_BUFFER 15
+#define AUDIO_LINE_SIZE 128
+#define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
+
+#define USE_RISC_NOOP_AUDIO 1
+
+#ifdef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+static int _line_size;
+char *_defaultAudioName = "/root/audioGOOD.wav";
diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h
new file mode 100644
index 000000000000..503f42f036a8
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-audio.h
@@ -0,0 +1,57 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP 1
+#define LINES_PER_BUFFER 15
+#define AUDIO_LINE_SIZE 128
+
+//Number of buffer programs to use at once.
+#define NUMBER_OF_PROGRAMS 8
+
+//Max size of the RISC program for a buffer. - worst case is 2 writes per line
+// Space is also added for the 4 no-op instructions added on the end.
+
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4)
+#endif
+
+// MAE 12 July 2005 Try to use NOOP RISC instruction instead
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4)
+#endif
+
+//Sizes of various instructions in bytes. Used when adding instructions.
+#define RISC_WRITE_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE 12
+#define RISC_SKIP_INSTRUCTION_SIZE 4
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_NOOP_INSTRUCTION_SIZE 4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c
new file mode 100644
index 000000000000..f78b8912d905
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-audups11.c
@@ -0,0 +1,434 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH11]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH11]
+ && h->video_dev[SRAM_CH11]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = 10;
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO11))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO11)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ //cx_write(channel11->dma_ctl, 0);
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO11)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO11);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO11);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+ return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+ int command = 0;
+ struct upstream_user_struct *data_from_user;
+
+ data_from_user = (struct upstream_user_struct *)arg;
+
+ if (!data_from_user) {
+ printk
+ ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
+ __func__);
+ return 0;
+ }
+
+ command = data_from_user->command;
+
+ if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) {
+ return 0;
+ }
+
+ dev->input_filename = data_from_user->input_filename;
+ dev->input_audiofilename = data_from_user->input_filename;
+ dev->vid_stdname = data_from_user->vid_stdname;
+ dev->pixel_format = data_from_user->pixel_format;
+ dev->channel_select = data_from_user->channel_select;
+ dev->command = data_from_user->command;
+
+ switch (command) {
+ case UPSTREAM_START_AUDIO:
+ cx25821_start_upstream_audio(dev, data_from_user);
+ break;
+
+ case UPSTREAM_STOP_AUDIO:
+ cx25821_stop_upstream_audio(dev);
+ break;
+ }
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+ return 0;
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl_upstream11,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template11 = {
+ .name = "cx25821-audioupstream",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-biffuncs.h b/drivers/staging/cx25821/cx25821-biffuncs.h
new file mode 100644
index 000000000000..9326a7c729ec
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-biffuncs.h
@@ -0,0 +1,45 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit) (1 << Bit)
+
+inline u8 getBit(u32 sample, u8 index)
+{
+ return (u8) ((sample >> index) & 1);
+}
+
+inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+ return value & ~(1 << bit);
+}
+
+inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+ sample |= (1 << bit);
+ return sample;
+
+}
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c
new file mode 100644
index 000000000000..4d0b9eac3e49
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-cards.c
@@ -0,0 +1,70 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+// board config info
+
+struct cx25821_board cx25821_boards[] = {
+ [UNKNOWN_BOARD] = {
+ .name = "UNKNOWN/GENERIC",
+ // Ensure safe default for unknown boards
+ .clk_freq = 0,
+ },
+
+ [CX25821_BOARD] = {
+ .name = "CX25821",
+ .portb = CX25821_RAW,
+ .portc = CX25821_264,
+ .input[0].type = CX25821_VMUX_COMPOSITE,
+ },
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[] = {
+ {
+ .subvendor = 0x14f1,
+ .subdevice = 0x0920,
+ .card = CX25821_BOARD,
+ },
+};
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+ static u8 eeprom[256];
+
+ if (dev->i2c_bus[0].i2c_rc == 0) {
+ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+ sizeof(eeprom));
+ }
+}
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c
new file mode 100644
index 000000000000..8aceae5a072e
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-core.c
@@ -0,0 +1,1551 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include <linux/i2c.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+struct list_head cx25821_devlist;
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static unsigned int cx25821_devcount = 0;
+
+static DEFINE_MUTEX(devlist);
+LIST_HEAD(cx25821_devlist);
+
+struct sram_channel cx25821_sram_channels[] = {
+ [SRAM_CH00] = {
+ .i = SRAM_CH00,
+ .name = "VID A",
+ .cmds_start = VID_A_DOWN_CMDS,
+ .ctrl_start = VID_A_IQ,
+ .cdt = VID_A_CDT,
+ .fifo_start = VID_A_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA1_PTR1,
+ .ptr2_reg = DMA1_PTR2,
+ .cnt1_reg = DMA1_CNT1,
+ .cnt2_reg = DMA1_CNT2,
+ .int_msk = VID_A_INT_MSK,
+ .int_stat = VID_A_INT_STAT,
+ .int_mstat = VID_A_INT_MSTAT,
+ .dma_ctl = VID_DST_A_DMA_CTL,
+ .gpcnt_ctl = VID_DST_A_GPCNT_CTL,
+ .gpcnt = VID_DST_A_GPCNT,
+ .vip_ctl = VID_DST_A_VIP_CTL,
+ .pix_frmt = VID_DST_A_PIX_FRMT,
+ },
+
+ [SRAM_CH01] = {
+ .i = SRAM_CH01,
+ .name = "VID B",
+ .cmds_start = VID_B_DOWN_CMDS,
+ .ctrl_start = VID_B_IQ,
+ .cdt = VID_B_CDT,
+ .fifo_start = VID_B_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA2_PTR1,
+ .ptr2_reg = DMA2_PTR2,
+ .cnt1_reg = DMA2_CNT1,
+ .cnt2_reg = DMA2_CNT2,
+ .int_msk = VID_B_INT_MSK,
+ .int_stat = VID_B_INT_STAT,
+ .int_mstat = VID_B_INT_MSTAT,
+ .dma_ctl = VID_DST_B_DMA_CTL,
+ .gpcnt_ctl = VID_DST_B_GPCNT_CTL,
+ .gpcnt = VID_DST_B_GPCNT,
+ .vip_ctl = VID_DST_B_VIP_CTL,
+ .pix_frmt = VID_DST_B_PIX_FRMT,
+ },
+
+ [SRAM_CH02] = {
+ .i = SRAM_CH02,
+ .name = "VID C",
+ .cmds_start = VID_C_DOWN_CMDS,
+ .ctrl_start = VID_C_IQ,
+ .cdt = VID_C_CDT,
+ .fifo_start = VID_C_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA3_PTR1,
+ .ptr2_reg = DMA3_PTR2,
+ .cnt1_reg = DMA3_CNT1,
+ .cnt2_reg = DMA3_CNT2,
+ .int_msk = VID_C_INT_MSK,
+ .int_stat = VID_C_INT_STAT,
+ .int_mstat = VID_C_INT_MSTAT,
+ .dma_ctl = VID_DST_C_DMA_CTL,
+ .gpcnt_ctl = VID_DST_C_GPCNT_CTL,
+ .gpcnt = VID_DST_C_GPCNT,
+ .vip_ctl = VID_DST_C_VIP_CTL,
+ .pix_frmt = VID_DST_C_PIX_FRMT,
+ },
+
+ [SRAM_CH03] = {
+ .i = SRAM_CH03,
+ .name = "VID D",
+ .cmds_start = VID_D_DOWN_CMDS,
+ .ctrl_start = VID_D_IQ,
+ .cdt = VID_D_CDT,
+ .fifo_start = VID_D_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA4_PTR1,
+ .ptr2_reg = DMA4_PTR2,
+ .cnt1_reg = DMA4_CNT1,
+ .cnt2_reg = DMA4_CNT2,
+ .int_msk = VID_D_INT_MSK,
+ .int_stat = VID_D_INT_STAT,
+ .int_mstat = VID_D_INT_MSTAT,
+ .dma_ctl = VID_DST_D_DMA_CTL,
+ .gpcnt_ctl = VID_DST_D_GPCNT_CTL,
+ .gpcnt = VID_DST_D_GPCNT,
+ .vip_ctl = VID_DST_D_VIP_CTL,
+ .pix_frmt = VID_DST_D_PIX_FRMT,
+ },
+
+ [SRAM_CH04] = {
+ .i = SRAM_CH04,
+ .name = "VID E",
+ .cmds_start = VID_E_DOWN_CMDS,
+ .ctrl_start = VID_E_IQ,
+ .cdt = VID_E_CDT,
+ .fifo_start = VID_E_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA5_PTR1,
+ .ptr2_reg = DMA5_PTR2,
+ .cnt1_reg = DMA5_CNT1,
+ .cnt2_reg = DMA5_CNT2,
+ .int_msk = VID_E_INT_MSK,
+ .int_stat = VID_E_INT_STAT,
+ .int_mstat = VID_E_INT_MSTAT,
+ .dma_ctl = VID_DST_E_DMA_CTL,
+ .gpcnt_ctl = VID_DST_E_GPCNT_CTL,
+ .gpcnt = VID_DST_E_GPCNT,
+ .vip_ctl = VID_DST_E_VIP_CTL,
+ .pix_frmt = VID_DST_E_PIX_FRMT,
+ },
+
+ [SRAM_CH05] = {
+ .i = SRAM_CH05,
+ .name = "VID F",
+ .cmds_start = VID_F_DOWN_CMDS,
+ .ctrl_start = VID_F_IQ,
+ .cdt = VID_F_CDT,
+ .fifo_start = VID_F_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA6_PTR1,
+ .ptr2_reg = DMA6_PTR2,
+ .cnt1_reg = DMA6_CNT1,
+ .cnt2_reg = DMA6_CNT2,
+ .int_msk = VID_F_INT_MSK,
+ .int_stat = VID_F_INT_STAT,
+ .int_mstat = VID_F_INT_MSTAT,
+ .dma_ctl = VID_DST_F_DMA_CTL,
+ .gpcnt_ctl = VID_DST_F_GPCNT_CTL,
+ .gpcnt = VID_DST_F_GPCNT,
+ .vip_ctl = VID_DST_F_VIP_CTL,
+ .pix_frmt = VID_DST_F_PIX_FRMT,
+ },
+
+ [SRAM_CH06] = {
+ .i = SRAM_CH06,
+ .name = "VID G",
+ .cmds_start = VID_G_DOWN_CMDS,
+ .ctrl_start = VID_G_IQ,
+ .cdt = VID_G_CDT,
+ .fifo_start = VID_G_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA7_PTR1,
+ .ptr2_reg = DMA7_PTR2,
+ .cnt1_reg = DMA7_CNT1,
+ .cnt2_reg = DMA7_CNT2,
+ .int_msk = VID_G_INT_MSK,
+ .int_stat = VID_G_INT_STAT,
+ .int_mstat = VID_G_INT_MSTAT,
+ .dma_ctl = VID_DST_G_DMA_CTL,
+ .gpcnt_ctl = VID_DST_G_GPCNT_CTL,
+ .gpcnt = VID_DST_G_GPCNT,
+ .vip_ctl = VID_DST_G_VIP_CTL,
+ .pix_frmt = VID_DST_G_PIX_FRMT,
+ },
+
+ [SRAM_CH07] = {
+ .i = SRAM_CH07,
+ .name = "VID H",
+ .cmds_start = VID_H_DOWN_CMDS,
+ .ctrl_start = VID_H_IQ,
+ .cdt = VID_H_CDT,
+ .fifo_start = VID_H_DOWN_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA8_PTR1,
+ .ptr2_reg = DMA8_PTR2,
+ .cnt1_reg = DMA8_CNT1,
+ .cnt2_reg = DMA8_CNT2,
+ .int_msk = VID_H_INT_MSK,
+ .int_stat = VID_H_INT_STAT,
+ .int_mstat = VID_H_INT_MSTAT,
+ .dma_ctl = VID_DST_H_DMA_CTL,
+ .gpcnt_ctl = VID_DST_H_GPCNT_CTL,
+ .gpcnt = VID_DST_H_GPCNT,
+ .vip_ctl = VID_DST_H_VIP_CTL,
+ .pix_frmt = VID_DST_H_PIX_FRMT,
+ },
+
+ [SRAM_CH08] = {
+ .name = "audio from",
+ .cmds_start = AUD_A_DOWN_CMDS,
+ .ctrl_start = AUD_A_IQ,
+ .cdt = AUD_A_CDT,
+ .fifo_start = AUD_A_DOWN_CLUSTER_1,
+ .fifo_size = AUDIO_CLUSTER_SIZE * 3,
+ .ptr1_reg = DMA17_PTR1,
+ .ptr2_reg = DMA17_PTR2,
+ .cnt1_reg = DMA17_CNT1,
+ .cnt2_reg = DMA17_CNT2,
+ },
+
+ [SRAM_CH09] = {
+ .i = SRAM_CH09,
+ .name = "VID Upstream I",
+ .cmds_start = VID_I_UP_CMDS,
+ .ctrl_start = VID_I_IQ,
+ .cdt = VID_I_CDT,
+ .fifo_start = VID_I_UP_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA15_PTR1,
+ .ptr2_reg = DMA15_PTR2,
+ .cnt1_reg = DMA15_CNT1,
+ .cnt2_reg = DMA15_CNT2,
+ .int_msk = VID_I_INT_MSK,
+ .int_stat = VID_I_INT_STAT,
+ .int_mstat = VID_I_INT_MSTAT,
+ .dma_ctl = VID_SRC_I_DMA_CTL,
+ .gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
+ .gpcnt = VID_SRC_I_GPCNT,
+
+ .vid_fmt_ctl = VID_SRC_I_FMT_CTL,
+ .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
+ .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
+ .vid_cdt_size = VID_SRC_I_CDT_SZ,
+ .irq_bit = 8,
+ },
+
+ [SRAM_CH10] = {
+ .i = SRAM_CH10,
+ .name = "VID Upstream J",
+ .cmds_start = VID_J_UP_CMDS,
+ .ctrl_start = VID_J_IQ,
+ .cdt = VID_J_CDT,
+ .fifo_start = VID_J_UP_CLUSTER_1,
+ .fifo_size = (VID_CLUSTER_SIZE << 2),
+ .ptr1_reg = DMA16_PTR1,
+ .ptr2_reg = DMA16_PTR2,
+ .cnt1_reg = DMA16_CNT1,
+ .cnt2_reg = DMA16_CNT2,
+ .int_msk = VID_J_INT_MSK,
+ .int_stat = VID_J_INT_STAT,
+ .int_mstat = VID_J_INT_MSTAT,
+ .dma_ctl = VID_SRC_J_DMA_CTL,
+ .gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
+ .gpcnt = VID_SRC_J_GPCNT,
+
+ .vid_fmt_ctl = VID_SRC_J_FMT_CTL,
+ .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
+ .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
+ .vid_cdt_size = VID_SRC_J_CDT_SZ,
+ .irq_bit = 9,
+ },
+
+ [SRAM_CH11] = {
+ .i = SRAM_CH11,
+ .name = "Audio Upstream Channel B",
+ .cmds_start = AUD_B_UP_CMDS,
+ .ctrl_start = AUD_B_IQ,
+ .cdt = AUD_B_CDT,
+ .fifo_start = AUD_B_UP_CLUSTER_1,
+ .fifo_size = (AUDIO_CLUSTER_SIZE * 3),
+ .ptr1_reg = DMA22_PTR1,
+ .ptr2_reg = DMA22_PTR2,
+ .cnt1_reg = DMA22_CNT1,
+ .cnt2_reg = DMA22_CNT2,
+ .int_msk = AUD_B_INT_MSK,
+ .int_stat = AUD_B_INT_STAT,
+ .int_mstat = AUD_B_INT_MSTAT,
+ .dma_ctl = AUD_INT_DMA_CTL,
+ .gpcnt_ctl = AUD_B_GPCNT_CTL,
+ .gpcnt = AUD_B_GPCNT,
+ .aud_length = AUD_B_LNGTH,
+ .aud_cfg = AUD_B_CFG,
+ .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
+ .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
+ .irq_bit = 11,
+ },
+};
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+ static char *instr[16] = {
+ [RISC_SYNC >> 28] = "sync",
+ [RISC_WRITE >> 28] = "write",
+ [RISC_WRITEC >> 28] = "writec",
+ [RISC_READ >> 28] = "read",
+ [RISC_READC >> 28] = "readc",
+ [RISC_JUMP >> 28] = "jump",
+ [RISC_SKIP >> 28] = "skip",
+ [RISC_WRITERM >> 28] = "writerm",
+ [RISC_WRITECM >> 28] = "writecm",
+ [RISC_WRITECR >> 28] = "writecr",
+ };
+ static int incr[16] = {
+ [RISC_WRITE >> 28] = 3,
+ [RISC_JUMP >> 28] = 3,
+ [RISC_SKIP >> 28] = 1,
+ [RISC_SYNC >> 28] = 1,
+ [RISC_WRITERM >> 28] = 3,
+ [RISC_WRITECM >> 28] = 3,
+ [RISC_WRITECR >> 28] = 4,
+ };
+ static char *bits[] = {
+ "12", "13", "14", "resync",
+ "cnt0", "cnt1", "18", "19",
+ "20", "21", "22", "23",
+ "irq1", "irq2", "eol", "sol",
+ };
+ int i;
+
+ printk("0x%08x [ %s", risc,
+ instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+ for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
+ if (risc & (1 << (i + 12)))
+ printk(" %s", bits[i]);
+ }
+ printk(" count=%d ]\n", risc & 0xfff);
+ return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ return cx_read(bus->reg_stat) & 0x01;
+}
+
+void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string)
+{
+ int tmp = 0;
+ u32 value = 0;
+
+ value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp);
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+ u32 tmp;
+
+ // enable RUN_RISC in Pecos
+ cx_write(DEV_CNTRL2, 0x20);
+
+ // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts
+ // I2C interrupt masking is handled by the I2C objects themselves.
+ cx_write(PCI_INT_MSK, 0x2001FFFF);
+
+ tmp = cx_read(RDR_TLCTL0);
+ tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit
+ cx_write(RDR_TLCTL0, tmp);
+
+ // PLL-A setting for the Audio Master Clock
+ cx_write(PLL_A_INT_FRAC, 0x9807A58B);
+
+ // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1
+ cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
+
+ // clear reset bit [31]
+ tmp = cx_read(PLL_A_INT_FRAC);
+ cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+ // PLL-B setting for Mobilygen Host Bus Interface
+ cx_write(PLL_B_INT_FRAC, 0x9883A86F);
+
+ // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0
+ cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
+
+ // clear reset bit [31]
+ tmp = cx_read(PLL_B_INT_FRAC);
+ cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+ // PLL-C setting for video upstream channel
+ cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
+
+ // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0
+ cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
+
+ // clear reset bit [31]
+ tmp = cx_read(PLL_C_INT_FRAC);
+ cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+ // PLL-D setting for audio upstream channel
+ cx_write(PLL_D_INT_FRAC, 0x98757F5B);
+
+ // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0
+ cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
+
+ // clear reset bit [31]
+ tmp = cx_read(PLL_D_INT_FRAC);
+ cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+ // This selects the PLL C clock source for the video upstream channel I and J
+ tmp = cx_read(VID_CH_CLK_SEL);
+ cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+ // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+ //select 656/VIP DST for downstream Channel A - C
+ tmp = cx_read(VID_CH_MODE_SEL);
+ //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+ cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+ // enables 656 port I and J as output
+ tmp = cx_read(CLK_RST);
+ tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead
+ cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+ mdelay(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc)
+{
+ unsigned int i, lines;
+ u32 cdt;
+
+ if (ch->cmds_start == 0) {
+ cx_write(ch->ptr1_reg, 0);
+ cx_write(ch->ptr2_reg, 0);
+ cx_write(ch->cnt2_reg, 0);
+ cx_write(ch->cnt1_reg, 0);
+ return 0;
+ }
+
+ bpl = (bpl + 7) & ~7; /* alignment */
+ cdt = ch->cdt;
+ lines = ch->fifo_size / bpl;
+
+ if (lines > 4) {
+ lines = 4;
+ }
+
+ BUG_ON(lines < 2);
+
+ cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ cx_write(8 + 4, 8);
+ cx_write(8 + 8, 0);
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+ cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+ cx_write(cdt + 16 * i + 4, 0);
+ cx_write(cdt + 16 * i + 8, 0);
+ cx_write(cdt + 16 * i + 12, 0);
+ }
+
+ //init the first cdt buffer
+ for (i = 0; i < 128; i++)
+ cx_write(ch->fifo_start + 4 * i, i);
+
+ /* write CMDS */
+ if (ch->jumponly) {
+ cx_write(ch->cmds_start + 0, 8);
+ } else {
+ cx_write(ch->cmds_start + 0, risc);
+ }
+
+ cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
+ cx_write(ch->cmds_start + 8, cdt);
+ cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+ cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+ if (ch->jumponly)
+ cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+ else
+ cx_write(ch->cmds_start + 20, 64 >> 2);
+
+ for (i = 24; i < 80; i += 4)
+ cx_write(ch->cmds_start + i, 0);
+
+ /* fill registers */
+ cx_write(ch->ptr1_reg, ch->fifo_start);
+ cx_write(ch->ptr2_reg, cdt);
+ cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+ cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+ return 0;
+}
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc)
+{
+ unsigned int i, lines;
+ u32 cdt;
+
+ if (ch->cmds_start == 0) {
+ cx_write(ch->ptr1_reg, 0);
+ cx_write(ch->ptr2_reg, 0);
+ cx_write(ch->cnt2_reg, 0);
+ cx_write(ch->cnt1_reg, 0);
+ return 0;
+ }
+
+ bpl = (bpl + 7) & ~7; /* alignment */
+ cdt = ch->cdt;
+ lines = ch->fifo_size / bpl;
+
+ if (lines > 3) {
+ lines = 3; //for AUDIO
+ }
+
+ BUG_ON(lines < 2);
+
+ cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ cx_write(8 + 4, 8);
+ cx_write(8 + 8, 0);
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+ cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+ cx_write(cdt + 16 * i + 4, 0);
+ cx_write(cdt + 16 * i + 8, 0);
+ cx_write(cdt + 16 * i + 12, 0);
+ }
+
+ /* write CMDS */
+ if (ch->jumponly) {
+ cx_write(ch->cmds_start + 0, 8);
+ } else {
+ cx_write(ch->cmds_start + 0, risc);
+ }
+
+ cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
+ cx_write(ch->cmds_start + 8, cdt);
+ cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+ cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+ //IQ size
+ if (ch->jumponly) {
+ cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+ } else {
+ cx_write(ch->cmds_start + 20, 64 >> 2);
+ }
+
+ //zero out
+ for (i = 24; i < 80; i += 4)
+ cx_write(ch->cmds_start + i, 0);
+
+ /* fill registers */
+ cx_write(ch->ptr1_reg, ch->fifo_start);
+ cx_write(ch->ptr2_reg, cdt);
+ cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+ cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+ return 0;
+}
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+ static char *name[] = {
+ "init risc lo",
+ "init risc hi",
+ "cdt base",
+ "cdt size",
+ "iq base",
+ "iq size",
+ "risc pc lo",
+ "risc pc hi",
+ "iq wr ptr",
+ "iq rd ptr",
+ "cdt current",
+ "pci target lo",
+ "pci target hi",
+ "line / byte",
+ };
+ u32 risc;
+ unsigned int i, j, n;
+
+ printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name,
+ ch->name);
+ for (i = 0; i < ARRAY_SIZE(name); i++)
+ printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i * 4,
+ name[i], cx_read(ch->cmds_start + 4 * i));
+
+ j = i * 4;
+ for (i = 0; i < 4;) {
+ risc = cx_read(ch->cmds_start + 4 * (i + 14));
+ printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i);
+ i += cx25821_risc_decode(risc);
+ }
+
+ for (i = 0; i < (64 >> 2); i += n) {
+ risc = cx_read(ch->ctrl_start + 4 * i);
+ /* No consideration for bits 63-32 */
+
+ printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
+ ch->ctrl_start + 4 * i, i);
+ n = cx25821_risc_decode(risc);
+ for (j = 1; j < n; j++) {
+ risc = cx_read(ch->ctrl_start + 4 * (i + j));
+ printk(KERN_WARNING
+ "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
+ 4 * (i + j), i + j, risc, j);
+ }
+ }
+
+ printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n",
+ ch->fifo_start, ch->fifo_start + ch->fifo_size);
+ printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n",
+ ch->ctrl_start, ch->ctrl_start + 6 * 16);
+ printk(KERN_WARNING " : ptr1_reg: 0x%08x\n",
+ cx_read(ch->ptr1_reg));
+ printk(KERN_WARNING " : ptr2_reg: 0x%08x\n",
+ cx_read(ch->ptr2_reg));
+ printk(KERN_WARNING " : cnt1_reg: 0x%08x\n",
+ cx_read(ch->cnt1_reg));
+ printk(KERN_WARNING " : cnt2_reg: 0x%08x\n",
+ cx_read(ch->cnt2_reg));
+}
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+ struct sram_channel *ch)
+{
+ static char *name[] = {
+ "init risc lo",
+ "init risc hi",
+ "cdt base",
+ "cdt size",
+ "iq base",
+ "iq size",
+ "risc pc lo",
+ "risc pc hi",
+ "iq wr ptr",
+ "iq rd ptr",
+ "cdt current",
+ "pci target lo",
+ "pci target hi",
+ "line / byte",
+ };
+
+ u32 risc, value, tmp;
+ unsigned int i, j, n;
+
+ printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n",
+ dev->name, ch->name);
+
+ for (i = 0; i < ARRAY_SIZE(name); i++)
+ printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n",
+ dev->name, i * 4, name[i],
+ cx_read(ch->cmds_start + 4 * i));
+
+ j = i * 4;
+ for (i = 0; i < 4;) {
+ risc = cx_read(ch->cmds_start + 4 * (i + 14));
+ printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i);
+ i += cx25821_risc_decode(risc);
+ }
+
+ for (i = 0; i < (64 >> 2); i += n) {
+ risc = cx_read(ch->ctrl_start + 4 * i);
+ /* No consideration for bits 63-32 */
+
+ printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
+ ch->ctrl_start + 4 * i, i);
+ n = cx25821_risc_decode(risc);
+
+ for (j = 1; j < n; j++) {
+ risc = cx_read(ch->ctrl_start + 4 * (i + j));
+ printk(KERN_WARNING
+ "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
+ 4 * (i + j), i + j, risc, j);
+ }
+ }
+
+ printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n",
+ ch->fifo_start, ch->fifo_start + ch->fifo_size);
+ printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n",
+ ch->ctrl_start, ch->ctrl_start + 6 * 16);
+ printk(KERN_WARNING " : ptr1_reg: 0x%08x\n",
+ cx_read(ch->ptr1_reg));
+ printk(KERN_WARNING " : ptr2_reg: 0x%08x\n",
+ cx_read(ch->ptr2_reg));
+ printk(KERN_WARNING " : cnt1_reg: 0x%08x\n",
+ cx_read(ch->cnt1_reg));
+ printk(KERN_WARNING " : cnt2_reg: 0x%08x\n",
+ cx_read(ch->cnt2_reg));
+
+ for (i = 0; i < 4; i++) {
+ risc = cx_read(ch->cmds_start + 56 + (i * 4));
+ printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc);
+ }
+
+ //read data from the first cdt buffer
+ risc = cx_read(AUD_A_CDT);
+ printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc);
+ for (i = 0; i < 8; i++) {
+ n = cx_read(risc + i * 4);
+ printk(KERN_WARNING "0x%x ", n);
+ }
+ printk(KERN_WARNING "\n\n");
+
+ value = cx_read(CLK_RST);
+ CX25821_INFO(" CLK_RST = 0x%x \n\n", value);
+
+ value = cx_read(PLL_A_POST_STAT_BIST);
+ CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value);
+ value = cx_read(PLL_A_INT_FRAC);
+ CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value);
+
+ value = cx_read(PLL_B_POST_STAT_BIST);
+ CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value);
+ value = cx_read(PLL_B_INT_FRAC);
+ CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value);
+
+ value = cx_read(PLL_C_POST_STAT_BIST);
+ CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value);
+ value = cx_read(PLL_C_INT_FRAC);
+ CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value);
+
+ value = cx_read(PLL_D_POST_STAT_BIST);
+ CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value);
+ value = cx_read(PLL_D_INT_FRAC);
+ CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value);
+
+ value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+ CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value);
+}
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+ int i;
+
+ /* disable RISC controller */
+ cx_write(DEV_CNTRL2, 0);
+
+ /* Disable Video A/B activity */
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ cx_write(dev->sram_channels[i].dma_ctl, 0);
+ cx_write(dev->sram_channels[i].int_msk, 0);
+ }
+
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J;
+ i++) {
+ cx_write(dev->sram_channels[i].dma_ctl, 0);
+ cx_write(dev->sram_channels[i].int_msk, 0);
+ }
+
+ /* Disable Audio activity */
+ cx_write(AUD_INT_DMA_CTL, 0);
+
+ /* Disable Serial port */
+ cx_write(UART_CTL, 0);
+
+ /* Disable Interrupts */
+ cx_write(PCI_INT_MSK, 0);
+ cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
+ u32 format)
+{
+ struct sram_channel *ch;
+
+ if (channel_select <= 7 && channel_select >= 0) {
+ ch = &cx25821_sram_channels[channel_select];
+ cx_write(ch->pix_frmt, format);
+ dev->pixel_formats[channel_select] = format;
+ }
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+ struct sram_channel *ch)
+{
+ cx_write(ch->pix_frmt, PIXEL_FRMT_422);
+ cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+ int i;
+
+ dprintk(1, "%s()\n", __func__);
+
+ cx25821_shutdown(dev);
+ cx_write(PCI_INT_STAT, 0xffffffff);
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++)
+ cx_write(dev->sram_channels[i].int_stat, 0xffffffff);
+
+ cx_write(AUD_A_INT_STAT, 0xffffffff);
+ cx_write(AUD_B_INT_STAT, 0xffffffff);
+ cx_write(AUD_C_INT_STAT, 0xffffffff);
+ cx_write(AUD_D_INT_STAT, 0xffffffff);
+ cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+ cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+ cx_write(PAD_CTRL, 0x12); //for I2C
+ cx25821_registers_init(dev); //init Pecos registers
+ mdelay(100);
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
+ cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440,
+ 0);
+ dev->pixel_formats[i] = PIXEL_FRMT_422;
+ dev->use_cif_resolution[i] = FALSE;
+ }
+
+ //Probably only affect Downstream
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J;
+ i++) {
+ cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
+ }
+
+ cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08],
+ 128, 0);
+
+ cx25821_gpio_init(dev);
+}
+
+static int get_resources(struct cx25821_dev *dev)
+{
+ if (request_mem_region
+ (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
+ dev->name))
+ return 0;
+
+ printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+ dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+ return -EBUSY;
+}
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+ dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
+
+ printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__,
+ dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+ if (dev == NULL)
+ return;
+
+ /* Releasing IO memory */
+ if (dev->lmmio != NULL) {
+ CX25821_INFO("Releasing lmmio.\n");
+ iounmap(dev->lmmio);
+ dev->lmmio = NULL;
+ }
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+ int io_size = 0, i;
+
+ struct video_device *video_template[] = {
+ &cx25821_video_template0,
+ &cx25821_video_template1,
+ &cx25821_video_template2,
+ &cx25821_video_template3,
+ &cx25821_video_template4,
+ &cx25821_video_template5,
+ &cx25821_video_template6,
+ &cx25821_video_template7,
+ &cx25821_video_template9,
+ &cx25821_video_template10,
+ &cx25821_video_template11,
+ &cx25821_videoioctl_template,
+ };
+
+ printk(KERN_INFO "\n***********************************\n");
+ printk(KERN_INFO "cx25821 set up\n");
+ printk(KERN_INFO "***********************************\n\n");
+
+ mutex_init(&dev->lock);
+
+ atomic_inc(&dev->refcount);
+
+ dev->nr = ++cx25821_devcount;
+ sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+ mutex_lock(&devlist);
+ list_add_tail(&dev->devlist, &cx25821_devlist);
+ mutex_unlock(&devlist);
+
+ strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
+ strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
+
+ if (dev->pci->device != 0x8210) {
+ printk(KERN_INFO
+ "%s() Exiting. Incorrect Hardware device = 0x%02x\n",
+ __func__, dev->pci->device);
+ return -1;
+ } else {
+ printk(KERN_INFO "Athena Hardware device = 0x%02x\n",
+ dev->pci->device);
+ }
+
+ /* Apply a sensible clock frequency for the PCIe bridge */
+ dev->clk_freq = 28000000;
+ dev->sram_channels = cx25821_sram_channels;
+
+ if (dev->nr > 1) {
+ CX25821_INFO("dev->nr > 1!");
+ }
+
+ /* board config */
+ dev->board = 1; //card[dev->nr];
+ dev->_max_num_decoders = MAX_DECODERS;
+
+ dev->pci_bus = dev->pci->bus->number;
+ dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+ dev->pci_irqmask = 0x001f00;
+
+ /* External Master 1 Bus */
+ dev->i2c_bus[0].nr = 0;
+ dev->i2c_bus[0].dev = dev;
+ dev->i2c_bus[0].reg_stat = I2C1_STAT;
+ dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
+ dev->i2c_bus[0].reg_addr = I2C1_ADDR;
+ dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+ dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+ dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */
+
+
+ if (get_resources(dev) < 0) {
+ printk(KERN_ERR "%s No more PCIe resources for "
+ "subsystem: %04x:%04x\n",
+ dev->name, dev->pci->subsystem_vendor,
+ dev->pci->subsystem_device);
+
+ cx25821_devcount--;
+ return -ENODEV;
+ }
+
+ /* PCIe stuff */
+ dev->base_io_addr = pci_resource_start(dev->pci, 0);
+ io_size = pci_resource_len(dev->pci, 0);
+
+ if (!dev->base_io_addr) {
+ CX25821_ERR("No PCI Memory resources, exiting!\n");
+ return -ENODEV;
+ }
+
+ dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+ if (!dev->lmmio) {
+ CX25821_ERR
+ ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+ cx25821_iounmap(dev);
+ return -ENOMEM;
+ }
+
+ dev->bmmio = (u8 __iomem *) dev->lmmio;
+
+ printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ dev->name, dev->pci->subsystem_vendor,
+ dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+ dev->board, card[dev->nr] == dev->board ?
+ "insmod option" : "autodetected");
+
+ /* init hardware */
+ cx25821_initialize(dev);
+
+ cx25821_i2c_register(&dev->i2c_bus[0]);
+// cx25821_i2c_register(&dev->i2c_bus[1]);
+// cx25821_i2c_register(&dev->i2c_bus[2]);
+
+ CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
+ dev->i2c_bus[0].i2c_rc);
+
+ cx25821_card_setup(dev);
+ medusa_video_init(dev);
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ if (cx25821_video_register(dev, i, video_template[i]) < 0) {
+ printk(KERN_ERR
+ "%s() Failed to register analog video adapters on VID channel %d\n",
+ __func__, i);
+ }
+ }
+
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+ i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+ //Since we don't have template8 for Audio Downstream
+ if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) {
+ printk(KERN_ERR
+ "%s() Failed to register analog video adapters for Upstream channel %d.\n",
+ __func__, i);
+ }
+ }
+
+ // register IOCTL device
+ dev->ioctl_dev =
+ cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH],
+ "video");
+
+ if (video_register_device
+ (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
+ cx25821_videoioctl_unregister(dev);
+ printk(KERN_ERR
+ "%s() Failed to register video adapter for IOCTL so releasing.\n",
+ __func__);
+ }
+
+ cx25821_dev_checkrevision(dev);
+ CX25821_INFO("cx25821 setup done!\n");
+
+ return 0;
+}
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+ struct upstream_user_struct *up_data)
+{
+ dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
+
+ dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+ medusa_set_videostandard(dev);
+
+ cx25821_vidupstream_init_ch1(dev, dev->channel_select,
+ dev->pixel_format);
+}
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+ struct upstream_user_struct *up_data)
+{
+ dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
+
+ dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+ medusa_set_videostandard(dev);
+
+ cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
+ dev->pixel_format_ch2);
+}
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+ struct upstream_user_struct *up_data)
+{
+ cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+ int i;
+
+ if (!dev->base_io_addr)
+ return;
+
+ cx25821_free_mem_upstream_ch1(dev);
+ cx25821_free_mem_upstream_ch2(dev);
+ cx25821_free_mem_upstream_audio(dev);
+
+ release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+ if (!atomic_dec_and_test(&dev->refcount))
+ return;
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++)
+ cx25821_video_unregister(dev, i);
+
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+ i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+ cx25821_video_unregister(dev, i);
+ }
+
+ cx25821_videoioctl_unregister(dev);
+
+ cx25821_i2c_unregister(&dev->i2c_bus[0]);
+ cx25821_iounmap(dev);
+}
+
+static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
+ unsigned int offset, u32 sync_line,
+ unsigned int bpl, unsigned int padding,
+ unsigned int lines)
+{
+ struct scatterlist *sg;
+ unsigned int line, todo;
+
+ /* sync instruction */
+ if (sync_line != NO_SYNC_LINE) {
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+ }
+
+ /* scan lines */
+ sg = sglist;
+ for (line = 0; line < lines; line++) {
+ while (offset && offset >= sg_dma_len(sg)) {
+ offset -= sg_dma_len(sg);
+ sg++;
+ }
+ if (bpl <= sg_dma_len(sg) - offset) {
+ /* fits into current chunk */
+ *(rp++) =
+ cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += bpl;
+ } else {
+ /* scanline needs to be split */
+ todo = bpl;
+ *(rp++) =
+ cpu_to_le32(RISC_WRITE | RISC_SOL |
+ (sg_dma_len(sg) - offset));
+ *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ todo -= (sg_dma_len(sg) - offset);
+ offset = 0;
+ sg++;
+ while (todo > sg_dma_len(sg)) {
+ *(rp++) =
+ cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ todo -= sg_dma_len(sg);
+ sg++;
+ }
+ *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += todo;
+ }
+
+ offset += padding;
+ }
+
+ return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int top_offset,
+ unsigned int bottom_offset, unsigned int bpl,
+ unsigned int padding, unsigned int lines)
+{
+ u32 instructions;
+ u32 fields;
+ __le32 *rp;
+ int rc;
+
+ fields = 0;
+ if (UNSET != top_offset)
+ fields++;
+ if (UNSET != bottom_offset)
+ fields++;
+
+ /* estimate risc mem: worst case is one write per page border +
+ one write per scan line + syncs + jump (all 2 dwords). Padding
+ can cause next bpl to start close to a page border. First DMA
+ region may be smaller than PAGE_SIZE */
+ /* write and jump need and extra dword */
+ instructions =
+ fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+ instructions += 2;
+ rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+
+ if (rc < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+
+ if (UNSET != top_offset) {
+ rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
+ lines);
+ }
+
+ if (UNSET != bottom_offset) {
+ rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+ padding, lines);
+ }
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+ return 0;
+}
+
+static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
+ unsigned int offset, u32 sync_line,
+ unsigned int bpl, unsigned int padding,
+ unsigned int lines, unsigned int lpi)
+{
+ struct scatterlist *sg;
+ unsigned int line, todo, sol;
+
+ /* sync instruction */
+ if (sync_line != NO_SYNC_LINE)
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+ /* scan lines */
+ sg = sglist;
+ for (line = 0; line < lines; line++) {
+ while (offset && offset >= sg_dma_len(sg)) {
+ offset -= sg_dma_len(sg);
+ sg++;
+ }
+
+ if (lpi && line > 0 && !(line % lpi))
+ sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+ else
+ sol = RISC_SOL;
+
+ if (bpl <= sg_dma_len(sg) - offset) {
+ /* fits into current chunk */
+ *(rp++) =
+ cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += bpl;
+ } else {
+ /* scanline needs to be split */
+ todo = bpl;
+ *(rp++) = cpu_to_le32(RISC_WRITE | sol |
+ (sg_dma_len(sg) - offset));
+ *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ todo -= (sg_dma_len(sg) - offset);
+ offset = 0;
+ sg++;
+ while (todo > sg_dma_len(sg)) {
+ *(rp++) = cpu_to_le32(RISC_WRITE |
+ sg_dma_len(sg));
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ todo -= sg_dma_len(sg);
+ sg++;
+ }
+ *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += todo;
+ }
+ offset += padding;
+ }
+
+ return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int bpl,
+ unsigned int lines, unsigned int lpi)
+{
+ u32 instructions;
+ __le32 *rp;
+ int rc;
+
+ /* estimate risc mem: worst case is one write per page border +
+ one write per scan line + syncs + jump (all 2 dwords). Here
+ there is no padding and no sync. First DMA region may be smaller
+ than PAGE_SIZE */
+ /* Jump and write need an extra dword */
+ instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+ instructions += 1;
+
+ if ((rc = btcx_riscmem_alloc(pci, risc, instructions * 12)) < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+ rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+ lines, lpi);
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+ return 0;
+}
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+ u32 reg, u32 mask, u32 value)
+{
+ __le32 *rp;
+ int rc;
+
+ rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
+
+ if (rc < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+
+ *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
+ *(rp++) = cpu_to_le32(reg);
+ *(rp++) = cpu_to_le32(value);
+ *(rp++) = cpu_to_le32(mask);
+ *(rp++) = cpu_to_le32(RISC_JUMP);
+ *(rp++) = cpu_to_le32(risc->dma);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+ struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+ BUG_ON(in_interrupt());
+ videobuf_waiton(&buf->vb, 0, 0);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+ btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+ struct cx25821_dev *dev = dev_id;
+ u32 pci_status, pci_mask;
+ u32 vid_status;
+ int i, handled = 0;
+ u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+ pci_status = cx_read(PCI_INT_STAT);
+ pci_mask = cx_read(PCI_INT_MSK);
+
+ if (pci_status == 0)
+ goto out;
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ if (pci_status & mask[i]) {
+ vid_status = cx_read(dev->sram_channels[i].int_stat);
+
+ if (vid_status)
+ handled +=
+ cx25821_video_irq(dev, i, vid_status);
+
+ cx_write(PCI_INT_STAT, mask[i]);
+ }
+ }
+
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+ int len, u32 bits, u32 mask)
+{
+ unsigned int i;
+
+ printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+
+ for (i = 0; i < len; i++) {
+ if (!(bits & (1 << i)))
+ continue;
+ if (strings[i])
+ printk(" %s", strings[i]);
+ else
+ printk(" %d", i);
+ if (!(mask & (1 << i)))
+ continue;
+ printk("*");
+ }
+ printk("\n");
+}
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+ struct cx25821_dev *dev = pci_get_drvdata(pci);
+ return dev;
+}
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ struct cx25821_dev *dev;
+ int err = 0;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (NULL == dev)
+ return -ENOMEM;
+
+ err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+ if (err < 0)
+ goto fail_free;
+
+ /* pci init */
+ dev->pci = pci_dev;
+ if (pci_enable_device(pci_dev)) {
+ err = -EIO;
+
+ printk(KERN_INFO "pci enable failed! ");
+
+ goto fail_unregister_device;
+ }
+
+ printk(KERN_INFO "cx25821 Athena pci enable ! \n");
+
+ if (cx25821_dev_setup(dev) < 0) {
+ err = -EINVAL;
+ goto fail_unregister_device;
+ }
+
+ /* print pci info */
+ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+ pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+ printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+ "latency: %d, mmio: 0x%llx\n", dev->name,
+ pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+ dev->pci_lat, (unsigned long long)dev->base_io_addr);
+
+ pci_set_master(pci_dev);
+ if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+ err = -EIO;
+ goto fail_irq;
+ }
+
+ err =
+ request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED,
+ dev->name, dev);
+
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
+ pci_dev->irq);
+ goto fail_irq;
+ }
+
+ return 0;
+
+ fail_irq:
+ printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n");
+ cx25821_dev_unregister(dev);
+
+ fail_unregister_device:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
+ fail_free:
+ kfree(dev);
+ return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+ struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+ struct cx25821_dev *dev = get_cx25821(v4l2_dev);
+
+ cx25821_shutdown(dev);
+ pci_disable_device(pci_dev);
+
+ /* unregister stuff */
+ if (pci_dev->irq)
+ free_irq(pci_dev->irq, dev);
+
+ mutex_lock(&devlist);
+ list_del(&dev->devlist);
+ mutex_unlock(&devlist);
+
+ cx25821_dev_unregister(dev);
+ v4l2_device_unregister(v4l2_dev);
+ kfree(dev);
+}
+
+static struct pci_device_id cx25821_pci_tbl[] = {
+ {
+ /* CX25821 Athena */
+ .vendor = 0x14f1,
+ .device = 0x8210,
+ .subvendor = 0x14f1,
+ .subdevice = 0x0920,
+ },
+ {
+ /* --- end of list --- */
+ }
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = {
+ .name = "cx25821",
+ .id_table = cx25821_pci_tbl,
+ .probe = cx25821_initdev,
+ .remove = __devexit_p(cx25821_finidev),
+ /* TODO */
+ .suspend = NULL,
+ .resume = NULL,
+};
+
+static int cx25821_init(void)
+{
+ INIT_LIST_HEAD(&cx25821_devlist);
+ printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n",
+ (CX25821_VERSION_CODE >> 16) & 0xff,
+ (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff);
+ return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void cx25821_fini(void)
+{
+ pci_unregister_driver(&cx25821_pci_driver);
+}
+
+EXPORT_SYMBOL(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_sram_channels);
+EXPORT_SYMBOL(cx25821_print_irqbits);
+EXPORT_SYMBOL(cx25821_dev_get);
+EXPORT_SYMBOL(cx25821_dev_unregister);
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff --git a/drivers/staging/cx25821/cx25821-gpio.c b/drivers/staging/cx25821/cx25821-gpio.c
new file mode 100644
index 000000000000..e8a37b47e437
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-gpio.c
@@ -0,0 +1,98 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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.
+ */
+
+#include "cx25821.h"
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+ int pin_number, int pin_logic_value)
+{
+ int bit = pin_number;
+ u32 gpio_oe_reg = GPIO_LO_OE;
+ u32 gpio_register = 0;
+ u32 value = 0;
+
+ // Check for valid pinNumber
+ if (pin_number >= 47)
+ return;
+
+ if (pin_number > 31) {
+ bit = pin_number - 31;
+ gpio_oe_reg = GPIO_HI_OE;
+ }
+ // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is
+ gpio_register = cx_read(gpio_oe_reg);
+
+ if (pin_logic_value == 1) {
+ value = gpio_register | Set_GPIO_Bit(bit);
+ } else {
+ value = gpio_register & Clear_GPIO_Bit(bit);
+ }
+
+ cx_write(gpio_oe_reg, value);
+}
+
+static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
+ int pin_number, int pin_logic_value)
+{
+ int bit = pin_number;
+ u32 gpio_reg = GPIO_LO;
+ u32 value = 0;
+
+ // Check for valid pinNumber
+ if (pin_number >= 47)
+ return;
+
+ cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction
+
+ if (pin_number > 31) {
+ bit = pin_number - 31;
+ gpio_reg = GPIO_HI;
+ }
+
+ value = cx_read(gpio_reg);
+
+ if (pin_logic_value == 0) {
+ value &= Clear_GPIO_Bit(bit);
+ } else {
+ value |= Set_GPIO_Bit(bit);
+ }
+
+ cx_write(gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+ if (dev == NULL) {
+ return;
+ }
+
+ switch (dev->board) {
+ case CX25821_BOARD_CONEXANT_ATHENA10:
+ default:
+ //set GPIO 5 to select the path for Medusa/Athena
+ cx25821_set_gpiopin_logicvalue(dev, 5, 1);
+ mdelay(20);
+ break;
+ }
+
+}
diff --git a/drivers/staging/cx25821/cx25821-gpio.h b/drivers/staging/cx25821/cx25821-gpio.h
new file mode 100644
index 000000000000..ca07644154af
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-gpio.h
@@ -0,0 +1,2 @@
+
+void cx25821_gpio_init(struct athena_dev *dev);
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c
new file mode 100644
index 000000000000..f4f2681d8f1c
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-i2c.c
@@ -0,0 +1,419 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan = 0;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)\
+ do { if (i2c_debug >= level)\
+ printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ } while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND (1 << 3)
+#define I2C_NOSTOP (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+ int count;
+
+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
+ if (!i2c_is_busy(i2c_adap))
+ break;
+ udelay(I2C_WAIT_DELAY);
+ }
+
+ if (I2C_WAIT_RETRY == count)
+ return 0;
+
+ return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ const struct i2c_msg *msg, int joined_rlen)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ u32 wdata, addr, ctrl;
+ int retval, cnt;
+
+ if (joined_rlen)
+ dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+ msg->len, joined_rlen);
+ else
+ dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+ /* Deal with i2c probe functions with zero payload */
+ if (msg->len == 0) {
+ cx_write(bus->reg_addr, msg->addr << 25);
+ cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+ if (!i2c_wait_done(i2c_adap))
+ return -EIO;
+
+ if (!i2c_slave_did_ack(i2c_adap))
+ return -EIO;
+
+ dprintk(1, "%s() returns 0\n", __func__);
+ return 0;
+ }
+
+ /* dev, reg + first byte */
+ addr = (msg->addr << 25) | msg->buf[0];
+ wdata = msg->buf[0];
+
+ ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+ if (msg->len > 1)
+ ctrl |= I2C_NOSTOP | I2C_EXTEND;
+ else if (joined_rlen)
+ ctrl |= I2C_NOSTOP;
+
+ cx_write(bus->reg_addr, addr);
+ cx_write(bus->reg_wdata, wdata);
+ cx_write(bus->reg_ctrl, ctrl);
+
+ retval = i2c_wait_done(i2c_adap);
+ if (retval < 0)
+ goto err;
+
+ if (retval == 0)
+ goto eio;
+
+ if (i2c_debug) {
+ if (!(ctrl & I2C_NOSTOP))
+ printk(" >\n");
+ }
+
+ for (cnt = 1; cnt < msg->len; cnt++) {
+ /* following bytes */
+ wdata = msg->buf[cnt];
+ ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+ if (cnt < msg->len - 1)
+ ctrl |= I2C_NOSTOP | I2C_EXTEND;
+ else if (joined_rlen)
+ ctrl |= I2C_NOSTOP;
+
+ cx_write(bus->reg_addr, addr);
+ cx_write(bus->reg_wdata, wdata);
+ cx_write(bus->reg_ctrl, ctrl);
+
+ retval = i2c_wait_done(i2c_adap);
+ if (retval < 0)
+ goto err;
+
+ if (retval == 0)
+ goto eio;
+
+ if (i2c_debug) {
+ dprintk(1, " %02x", msg->buf[cnt]);
+ if (!(ctrl & I2C_NOSTOP))
+ dprintk(1, " >\n");
+ }
+ }
+
+ return msg->len;
+
+ eio:
+ retval = -EIO;
+ err:
+ if (i2c_debug)
+ printk(KERN_ERR " ERR: %d\n", retval);
+ return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ const struct i2c_msg *msg, int joined)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ u32 ctrl, cnt;
+ int retval;
+
+ if (i2c_debug && !joined)
+ dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+ /* Deal with i2c probe functions with zero payload */
+ if (msg->len == 0) {
+ cx_write(bus->reg_addr, msg->addr << 25);
+ cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+ if (!i2c_wait_done(i2c_adap))
+ return -EIO;
+ if (!i2c_slave_did_ack(i2c_adap))
+ return -EIO;
+
+ dprintk(1, "%s() returns 0\n", __func__);
+ return 0;
+ }
+
+ if (i2c_debug) {
+ if (joined)
+ dprintk(1, " R");
+ else
+ dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+ }
+
+ for (cnt = 0; cnt < msg->len; cnt++) {
+
+ ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+ if (cnt < msg->len - 1)
+ ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+ cx_write(bus->reg_addr, msg->addr << 25);
+ cx_write(bus->reg_ctrl, ctrl);
+
+ retval = i2c_wait_done(i2c_adap);
+ if (retval < 0)
+ goto err;
+ if (retval == 0)
+ goto eio;
+ msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+ if (i2c_debug) {
+ dprintk(1, " %02x", msg->buf[cnt]);
+ if (!(ctrl & I2C_NOSTOP))
+ dprintk(1, " >\n");
+ }
+ }
+
+ return msg->len;
+ eio:
+ retval = -EIO;
+ err:
+ if (i2c_debug)
+ printk(KERN_ERR " ERR: %d\n", retval);
+ return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+ struct cx25821_i2c *bus = i2c_adap->algo_data;
+ struct cx25821_dev *dev = bus->dev;
+ int i, retval = 0;
+
+ dprintk(1, "%s(num = %d)\n", __func__, num);
+
+ for (i = 0; i < num; i++) {
+ dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
+ __func__, num, msgs[i].addr, msgs[i].len);
+
+ if (msgs[i].flags & I2C_M_RD) {
+ /* read */
+ retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+ } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+ msgs[i].addr == msgs[i + 1].addr) {
+ /* write then read from same address */
+ retval =
+ i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
+
+ if (retval < 0)
+ goto err;
+ i++;
+ retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+ } else {
+ /* write */
+ retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+ }
+
+ if (retval < 0)
+ goto err;
+ }
+ return num;
+
+ err:
+ return retval;
+}
+
+
+static u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+ .master_xfer = i2c_xfer,
+ .functionality = cx25821_functionality,
+};
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+ .name = "cx25821",
+ .owner = THIS_MODULE,
+ .algo = &cx25821_i2c_algo_template,
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+ .name = "cx25821 internal",
+};
+
+/* init + register i2c algo-bit adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+ struct cx25821_dev *dev = bus->dev;
+
+ dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+ memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template,
+ sizeof(bus->i2c_adap));
+ memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template,
+ sizeof(bus->i2c_algo));
+ memcpy(&bus->i2c_client, &cx25821_i2c_client_template,
+ sizeof(bus->i2c_client));
+
+ bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+ strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+ bus->i2c_algo.data = bus;
+ bus->i2c_adap.algo_data = bus;
+ i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+ i2c_add_adapter(&bus->i2c_adap);
+
+ bus->i2c_client.adapter = &bus->i2c_adap;
+
+ //set up the I2c
+ bus->i2c_client.addr = (0x88 >> 1);
+
+ return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+ i2c_del_adapter(&bus->i2c_adap);
+ return 0;
+}
+
+void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+{
+ /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+ char buffer[3];
+ struct i2c_msg msg;
+ dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+ /* Register 0x144 */
+ buffer[0] = 0x01;
+ buffer[1] = 0x44;
+ if (enable == 1)
+ buffer[2] = 0x05;
+ else
+ buffer[2] = 0x00;
+
+ msg.addr = 0x44;
+ msg.flags = I2C_M_TEN;
+ msg.len = 3;
+ msg.buf = buffer;
+
+ i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
+}
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+ struct i2c_client *client = &bus->i2c_client;
+ int retval = 0;
+ int v = 0;
+ u8 addr[2] = { 0, 0 };
+ u8 buf[4] = { 0, 0, 0, 0 };
+
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 4,
+ .buf = buf,
+ }
+ };
+
+ addr[0] = (reg_addr >> 8);
+ addr[1] = (reg_addr & 0xff);
+ msgs[0].addr = 0x44;
+ msgs[1].addr = 0x44;
+
+ retval = i2c_xfer(client->adapter, msgs, 2);
+
+ v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ *value = v;
+
+ return v;
+}
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+ struct i2c_client *client = &bus->i2c_client;
+ int retval = 0;
+ u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+ struct i2c_msg msgs[1] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 6,
+ .buf = buf,
+ }
+ };
+
+ buf[0] = reg_addr >> 8;
+ buf[1] = reg_addr & 0xff;
+ buf[5] = (value >> 24) & 0xff;
+ buf[4] = (value >> 16) & 0xff;
+ buf[3] = (value >> 8) & 0xff;
+ buf[2] = value & 0xff;
+ client->flags = 0;
+ msgs[0].addr = 0x44;
+
+ retval = i2c_xfer(client->adapter, msgs, 1);
+
+ return retval;
+}
diff --git a/drivers/staging/cx25821/cx25821-medusa-defines.h b/drivers/staging/cx25821/cx25821-medusa-defines.h
new file mode 100644
index 000000000000..b0d216ba7f81
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-medusa-defines.h
@@ -0,0 +1,51 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+// Video deocder that we supported
+#define VDEC_A 0
+#define VDEC_B 1
+#define VDEC_C 2
+#define VDEC_D 3
+#define VDEC_E 4
+#define VDEC_F 5
+#define VDEC_G 6
+#define VDEC_H 7
+
+//#define AUTO_SWITCH_BIT[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+// The following bit position enables automatic source switching for decoder A-H.
+// Display index per camera.
+//#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
+
+// Select input bit to video decoder A-H.
+//#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31};
+
+// end of display sequence
+#define END_OF_SEQ 0xF;
+
+// registry string size
+#define MAX_REGISTRY_SZ 40;
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-medusa-reg.h b/drivers/staging/cx25821/cx25821-medusa-reg.h
new file mode 100644
index 000000000000..12c90f831b22
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-medusa-reg.h
@@ -0,0 +1,455 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+// Serial Slave Registers
+#define HOST_REGISTER1 0x0000
+#define HOST_REGISTER2 0x0001
+
+// Chip Configuration Registers
+#define CHIP_CTRL 0x0100
+#define AFE_AB_CTRL 0x0104
+#define AFE_CD_CTRL 0x0108
+#define AFE_EF_CTRL 0x010C
+#define AFE_GH_CTRL 0x0110
+#define DENC_AB_CTRL 0x0114
+#define BYP_AB_CTRL 0x0118
+#define MON_A_CTRL 0x011C
+#define DISP_SEQ_A 0x0120
+#define DISP_SEQ_B 0x0124
+#define DISP_AB_CNT 0x0128
+#define DISP_CD_CNT 0x012C
+#define DISP_EF_CNT 0x0130
+#define DISP_GH_CNT 0x0134
+#define DISP_IJ_CNT 0x0138
+#define PIN_OE_CTRL 0x013C
+#define PIN_SPD_CTRL 0x0140
+#define PIN_SPD_CTRL2 0x0144
+#define IRQ_STAT_CTRL 0x0148
+#define POWER_CTRL_AB 0x014C
+#define POWER_CTRL_CD 0x0150
+#define POWER_CTRL_EF 0x0154
+#define POWER_CTRL_GH 0x0158
+#define TUNE_CTRL 0x015C
+#define BIAS_CTRL 0x0160
+#define AFE_AB_DIAG_CTRL 0x0164
+#define AFE_CD_DIAG_CTRL 0x0168
+#define AFE_EF_DIAG_CTRL 0x016C
+#define AFE_GH_DIAG_CTRL 0x0170
+#define PLL_AB_DIAG_CTRL 0x0174
+#define PLL_CD_DIAG_CTRL 0x0178
+#define PLL_EF_DIAG_CTRL 0x017C
+#define PLL_GH_DIAG_CTRL 0x0180
+#define TEST_CTRL 0x0184
+#define BIST_STAT 0x0188
+#define BIST_STAT2 0x018C
+#define BIST_VID_PLL_AB_STAT 0x0190
+#define BIST_VID_PLL_CD_STAT 0x0194
+#define BIST_VID_PLL_EF_STAT 0x0198
+#define BIST_VID_PLL_GH_STAT 0x019C
+#define DLL_DIAG_CTRL 0x01A0
+#define DEV_CH_ID_CTRL 0x01A4
+#define ABIST_CTRL_STATUS 0x01A8
+#define ABIST_FREQ 0x01AC
+#define ABIST_GOERT_SHIFT 0x01B0
+#define ABIST_COEF12 0x01B4
+#define ABIST_COEF34 0x01B8
+#define ABIST_COEF56 0x01BC
+#define ABIST_COEF7_SNR 0x01C0
+#define ABIST_ADC_CAL 0x01C4
+#define ABIST_BIN1_VGA0 0x01C8
+#define ABIST_BIN2_VGA1 0x01CC
+#define ABIST_BIN3_VGA2 0x01D0
+#define ABIST_BIN4_VGA3 0x01D4
+#define ABIST_BIN5_VGA4 0x01D8
+#define ABIST_BIN6_VGA5 0x01DC
+#define ABIST_BIN7_VGA6 0x0x1E0
+#define ABIST_CLAMP_A 0x0x1E4
+#define ABIST_CLAMP_B 0x0x1E8
+#define ABIST_CLAMP_C 0x01EC
+#define ABIST_CLAMP_D 0x01F0
+#define ABIST_CLAMP_E 0x01F4
+#define ABIST_CLAMP_F 0x01F8
+
+// Digital Video Encoder A Registers
+#define DENC_A_REG_1 0x0200
+#define DENC_A_REG_2 0x0204
+#define DENC_A_REG_3 0x0208
+#define DENC_A_REG_4 0x020C
+#define DENC_A_REG_5 0x0210
+#define DENC_A_REG_6 0x0214
+#define DENC_A_REG_7 0x0218
+#define DENC_A_REG_8 0x021C
+
+// Digital Video Encoder B Registers
+#define DENC_B_REG_1 0x0300
+#define DENC_B_REG_2 0x0304
+#define DENC_B_REG_3 0x0308
+#define DENC_B_REG_4 0x030C
+#define DENC_B_REG_5 0x0310
+#define DENC_B_REG_6 0x0314
+#define DENC_B_REG_7 0x0318
+#define DENC_B_REG_8 0x031C
+
+// Video Decoder A Registers
+#define MODE_CTRL 0x1000
+#define OUT_CTRL1 0x1004
+#define OUT_CTRL_NS 0x1008
+#define GEN_STAT 0x100C
+#define INT_STAT_MASK 0x1010
+#define LUMA_CTRL 0x1014
+#define CHROMA_CTRL 0x1018
+#define CRUSH_CTRL 0x101C
+#define HORIZ_TIM_CTRL 0x1020
+#define VERT_TIM_CTRL 0x1024
+#define MISC_TIM_CTRL 0x1028
+#define FIELD_COUNT 0x102C
+#define HSCALE_CTRL 0x1030
+#define VSCALE_CTRL 0x1034
+#define MAN_VGA_CTRL 0x1038
+#define MAN_AGC_CTRL 0x103C
+#define DFE_CTRL1 0x1040
+#define DFE_CTRL2 0x1044
+#define DFE_CTRL3 0x1048
+#define PLL_CTRL 0x104C
+#define PLL_CTRL_FAST 0x1050
+#define HTL_CTRL 0x1054
+#define SRC_CFG 0x1058
+#define SC_STEP_SIZE 0x105C
+#define SC_CONVERGE_CTRL 0x1060
+#define SC_LOOP_CTRL 0x1064
+#define COMB_2D_HFS_CFG 0x1068
+#define COMB_2D_HFD_CFG 0x106C
+#define COMB_2D_LF_CFG 0x1070
+#define COMB_2D_BLEND 0x1074
+#define COMB_MISC_CTRL 0x1078
+#define COMB_FLAT_THRESH_CTRL 0x107C
+#define COMB_TEST 0x1080
+#define BP_MISC_CTRL 0x1084
+#define VCR_DET_CTRL 0x1088
+#define NOISE_DET_CTRL 0x108C
+#define COMB_FLAT_NOISE_CTRL 0x1090
+#define VERSION 0x11F8
+#define SOFT_RST_CTRL 0x11FC
+
+// Video Decoder B Registers
+#define VDEC_B_MODE_CTRL 0x1200
+#define VDEC_B_OUT_CTRL1 0x1204
+#define VDEC_B_OUT_CTRL_NS 0x1208
+#define VDEC_B_GEN_STAT 0x120C
+#define VDEC_B_INT_STAT_MASK 0x1210
+#define VDEC_B_LUMA_CTRL 0x1214
+#define VDEC_B_CHROMA_CTRL 0x1218
+#define VDEC_B_CRUSH_CTRL 0x121C
+#define VDEC_B_HORIZ_TIM_CTRL 0x1220
+#define VDEC_B_VERT_TIM_CTRL 0x1224
+#define VDEC_B_MISC_TIM_CTRL 0x1228
+#define VDEC_B_FIELD_COUNT 0x122C
+#define VDEC_B_HSCALE_CTRL 0x1230
+#define VDEC_B_VSCALE_CTRL 0x1234
+#define VDEC_B_MAN_VGA_CTRL 0x1238
+#define VDEC_B_MAN_AGC_CTRL 0x123C
+#define VDEC_B_DFE_CTRL1 0x1240
+#define VDEC_B_DFE_CTRL2 0x1244
+#define VDEC_B_DFE_CTRL3 0x1248
+#define VDEC_B_PLL_CTRL 0x124C
+#define VDEC_B_PLL_CTRL_FAST 0x1250
+#define VDEC_B_HTL_CTRL 0x1254
+#define VDEC_B_SRC_CFG 0x1258
+#define VDEC_B_SC_STEP_SIZE 0x125C
+#define VDEC_B_SC_CONVERGE_CTRL 0x1260
+#define VDEC_B_SC_LOOP_CTRL 0x1264
+#define VDEC_B_COMB_2D_HFS_CFG 0x1268
+#define VDEC_B_COMB_2D_HFD_CFG 0x126C
+#define VDEC_B_COMB_2D_LF_CFG 0x1270
+#define VDEC_B_COMB_2D_BLEND 0x1274
+#define VDEC_B_COMB_MISC_CTRL 0x1278
+#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C
+#define VDEC_B_COMB_TEST 0x1280
+#define VDEC_B_BP_MISC_CTRL 0x1284
+#define VDEC_B_VCR_DET_CTRL 0x1288
+#define VDEC_B_NOISE_DET_CTRL 0x128C
+#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290
+#define VDEC_B_VERSION 0x13F8
+#define VDEC_B_SOFT_RST_CTRL 0x13FC
+
+// Video Decoder C Registers
+#define VDEC_C_MODE_CTRL 0x1400
+#define VDEC_C_OUT_CTRL1 0x1404
+#define VDEC_C_OUT_CTRL_NS 0x1408
+#define VDEC_C_GEN_STAT 0x140C
+#define VDEC_C_INT_STAT_MASK 0x1410
+#define VDEC_C_LUMA_CTRL 0x1414
+#define VDEC_C_CHROMA_CTRL 0x1418
+#define VDEC_C_CRUSH_CTRL 0x141C
+#define VDEC_C_HORIZ_TIM_CTRL 0x1420
+#define VDEC_C_VERT_TIM_CTRL 0x1424
+#define VDEC_C_MISC_TIM_CTRL 0x1428
+#define VDEC_C_FIELD_COUNT 0x142C
+#define VDEC_C_HSCALE_CTRL 0x1430
+#define VDEC_C_VSCALE_CTRL 0x1434
+#define VDEC_C_MAN_VGA_CTRL 0x1438
+#define VDEC_C_MAN_AGC_CTRL 0x143C
+#define VDEC_C_DFE_CTRL1 0x1440
+#define VDEC_C_DFE_CTRL2 0x1444
+#define VDEC_C_DFE_CTRL3 0x1448
+#define VDEC_C_PLL_CTRL 0x144C
+#define VDEC_C_PLL_CTRL_FAST 0x1450
+#define VDEC_C_HTL_CTRL 0x1454
+#define VDEC_C_SRC_CFG 0x1458
+#define VDEC_C_SC_STEP_SIZE 0x145C
+#define VDEC_C_SC_CONVERGE_CTRL 0x1460
+#define VDEC_C_SC_LOOP_CTRL 0x1464
+#define VDEC_C_COMB_2D_HFS_CFG 0x1468
+#define VDEC_C_COMB_2D_HFD_CFG 0x146C
+#define VDEC_C_COMB_2D_LF_CFG 0x1470
+#define VDEC_C_COMB_2D_BLEND 0x1474
+#define VDEC_C_COMB_MISC_CTRL 0x1478
+#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C
+#define VDEC_C_COMB_TEST 0x1480
+#define VDEC_C_BP_MISC_CTRL 0x1484
+#define VDEC_C_VCR_DET_CTRL 0x1488
+#define VDEC_C_NOISE_DET_CTRL 0x148C
+#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490
+#define VDEC_C_VERSION 0x15F8
+#define VDEC_C_SOFT_RST_CTRL 0x15FC
+
+// Video Decoder D Registers
+#define VDEC_D_MODE_CTRL 0x1600
+#define VDEC_D_OUT_CTRL1 0x1604
+#define VDEC_D_OUT_CTRL_NS 0x1608
+#define VDEC_D_GEN_STAT 0x160C
+#define VDEC_D_INT_STAT_MASK 0x1610
+#define VDEC_D_LUMA_CTRL 0x1614
+#define VDEC_D_CHROMA_CTRL 0x1618
+#define VDEC_D_CRUSH_CTRL 0x161C
+#define VDEC_D_HORIZ_TIM_CTRL 0x1620
+#define VDEC_D_VERT_TIM_CTRL 0x1624
+#define VDEC_D_MISC_TIM_CTRL 0x1628
+#define VDEC_D_FIELD_COUNT 0x162C
+#define VDEC_D_HSCALE_CTRL 0x1630
+#define VDEC_D_VSCALE_CTRL 0x1634
+#define VDEC_D_MAN_VGA_CTRL 0x1638
+#define VDEC_D_MAN_AGC_CTRL 0x163C
+#define VDEC_D_DFE_CTRL1 0x1640
+#define VDEC_D_DFE_CTRL2 0x1644
+#define VDEC_D_DFE_CTRL3 0x1648
+#define VDEC_D_PLL_CTRL 0x164C
+#define VDEC_D_PLL_CTRL_FAST 0x1650
+#define VDEC_D_HTL_CTRL 0x1654
+#define VDEC_D_SRC_CFG 0x1658
+#define VDEC_D_SC_STEP_SIZE 0x165C
+#define VDEC_D_SC_CONVERGE_CTRL 0x1660
+#define VDEC_D_SC_LOOP_CTRL 0x1664
+#define VDEC_D_COMB_2D_HFS_CFG 0x1668
+#define VDEC_D_COMB_2D_HFD_CFG 0x166C
+#define VDEC_D_COMB_2D_LF_CFG 0x1670
+#define VDEC_D_COMB_2D_BLEND 0x1674
+#define VDEC_D_COMB_MISC_CTRL 0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C
+#define VDEC_D_COMB_TEST 0x1680
+#define VDEC_D_BP_MISC_CTRL 0x1684
+#define VDEC_D_VCR_DET_CTRL 0x1688
+#define VDEC_D_NOISE_DET_CTRL 0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690
+#define VDEC_D_VERSION 0x17F8
+#define VDEC_D_SOFT_RST_CTRL 0x17FC
+
+// Video Decoder E Registers
+#define VDEC_E_MODE_CTRL 0x1800
+#define VDEC_E_OUT_CTRL1 0x1804
+#define VDEC_E_OUT_CTRL_NS 0x1808
+#define VDEC_E_GEN_STAT 0x180C
+#define VDEC_E_INT_STAT_MASK 0x1810
+#define VDEC_E_LUMA_CTRL 0x1814
+#define VDEC_E_CHROMA_CTRL 0x1818
+#define VDEC_E_CRUSH_CTRL 0x181C
+#define VDEC_E_HORIZ_TIM_CTRL 0x1820
+#define VDEC_E_VERT_TIM_CTRL 0x1824
+#define VDEC_E_MISC_TIM_CTRL 0x1828
+#define VDEC_E_FIELD_COUNT 0x182C
+#define VDEC_E_HSCALE_CTRL 0x1830
+#define VDEC_E_VSCALE_CTRL 0x1834
+#define VDEC_E_MAN_VGA_CTRL 0x1838
+#define VDEC_E_MAN_AGC_CTRL 0x183C
+#define VDEC_E_DFE_CTRL1 0x1840
+#define VDEC_E_DFE_CTRL2 0x1844
+#define VDEC_E_DFE_CTRL3 0x1848
+#define VDEC_E_PLL_CTRL 0x184C
+#define VDEC_E_PLL_CTRL_FAST 0x1850
+#define VDEC_E_HTL_CTRL 0x1854
+#define VDEC_E_SRC_CFG 0x1858
+#define VDEC_E_SC_STEP_SIZE 0x185C
+#define VDEC_E_SC_CONVERGE_CTRL 0x1860
+#define VDEC_E_SC_LOOP_CTRL 0x1864
+#define VDEC_E_COMB_2D_HFS_CFG 0x1868
+#define VDEC_E_COMB_2D_HFD_CFG 0x186C
+#define VDEC_E_COMB_2D_LF_CFG 0x1870
+#define VDEC_E_COMB_2D_BLEND 0x1874
+#define VDEC_E_COMB_MISC_CTRL 0x1878
+#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C
+#define VDEC_E_COMB_TEST 0x1880
+#define VDEC_E_BP_MISC_CTRL 0x1884
+#define VDEC_E_VCR_DET_CTRL 0x1888
+#define VDEC_E_NOISE_DET_CTRL 0x188C
+#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890
+#define VDEC_E_VERSION 0x19F8
+#define VDEC_E_SOFT_RST_CTRL 0x19FC
+
+// Video Decoder F Registers
+#define VDEC_F_MODE_CTRL 0x1A00
+#define VDEC_F_OUT_CTRL1 0x1A04
+#define VDEC_F_OUT_CTRL_NS 0x1A08
+#define VDEC_F_GEN_STAT 0x1A0C
+#define VDEC_F_INT_STAT_MASK 0x1A10
+#define VDEC_F_LUMA_CTRL 0x1A14
+#define VDEC_F_CHROMA_CTRL 0x1A18
+#define VDEC_F_CRUSH_CTRL 0x1A1C
+#define VDEC_F_HORIZ_TIM_CTRL 0x1A20
+#define VDEC_F_VERT_TIM_CTRL 0x1A24
+#define VDEC_F_MISC_TIM_CTRL 0x1A28
+#define VDEC_F_FIELD_COUNT 0x1A2C
+#define VDEC_F_HSCALE_CTRL 0x1A30
+#define VDEC_F_VSCALE_CTRL 0x1A34
+#define VDEC_F_MAN_VGA_CTRL 0x1A38
+#define VDEC_F_MAN_AGC_CTRL 0x1A3C
+#define VDEC_F_DFE_CTRL1 0x1A40
+#define VDEC_F_DFE_CTRL2 0x1A44
+#define VDEC_F_DFE_CTRL3 0x1A48
+#define VDEC_F_PLL_CTRL 0x1A4C
+#define VDEC_F_PLL_CTRL_FAST 0x1A50
+#define VDEC_F_HTL_CTRL 0x1A54
+#define VDEC_F_SRC_CFG 0x1A58
+#define VDEC_F_SC_STEP_SIZE 0x1A5C
+#define VDEC_F_SC_CONVERGE_CTRL 0x1A60
+#define VDEC_F_SC_LOOP_CTRL 0x1A64
+#define VDEC_F_COMB_2D_HFS_CFG 0x1A68
+#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C
+#define VDEC_F_COMB_2D_LF_CFG 0x1A70
+#define VDEC_F_COMB_2D_BLEND 0x1A74
+#define VDEC_F_COMB_MISC_CTRL 0x1A78
+#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C
+#define VDEC_F_COMB_TEST 0x1A80
+#define VDEC_F_BP_MISC_CTRL 0x1A84
+#define VDEC_F_VCR_DET_CTRL 0x1A88
+#define VDEC_F_NOISE_DET_CTRL 0x1A8C
+#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90
+#define VDEC_F_VERSION 0x1BF8
+#define VDEC_F_SOFT_RST_CTRL 0x1BFC
+
+// Video Decoder G Registers
+#define VDEC_G_MODE_CTRL 0x1C00
+#define VDEC_G_OUT_CTRL1 0x1C04
+#define VDEC_G_OUT_CTRL_NS 0x1C08
+#define VDEC_G_GEN_STAT 0x1C0C
+#define VDEC_G_INT_STAT_MASK 0x1C10
+#define VDEC_G_LUMA_CTRL 0x1C14
+#define VDEC_G_CHROMA_CTRL 0x1C18
+#define VDEC_G_CRUSH_CTRL 0x1C1C
+#define VDEC_G_HORIZ_TIM_CTRL 0x1C20
+#define VDEC_G_VERT_TIM_CTRL 0x1C24
+#define VDEC_G_MISC_TIM_CTRL 0x1C28
+#define VDEC_G_FIELD_COUNT 0x1C2C
+#define VDEC_G_HSCALE_CTRL 0x1C30
+#define VDEC_G_VSCALE_CTRL 0x1C34
+#define VDEC_G_MAN_VGA_CTRL 0x1C38
+#define VDEC_G_MAN_AGC_CTRL 0x1C3C
+#define VDEC_G_DFE_CTRL1 0x1C40
+#define VDEC_G_DFE_CTRL2 0x1C44
+#define VDEC_G_DFE_CTRL3 0x1C48
+#define VDEC_G_PLL_CTRL 0x1C4C
+#define VDEC_G_PLL_CTRL_FAST 0x1C50
+#define VDEC_G_HTL_CTRL 0x1C54
+#define VDEC_G_SRC_CFG 0x1C58
+#define VDEC_G_SC_STEP_SIZE 0x1C5C
+#define VDEC_G_SC_CONVERGE_CTRL 0x1C60
+#define VDEC_G_SC_LOOP_CTRL 0x1C64
+#define VDEC_G_COMB_2D_HFS_CFG 0x1C68
+#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C
+#define VDEC_G_COMB_2D_LF_CFG 0x1C70
+#define VDEC_G_COMB_2D_BLEND 0x1C74
+#define VDEC_G_COMB_MISC_CTRL 0x1C78
+#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C
+#define VDEC_G_COMB_TEST 0x1C80
+#define VDEC_G_BP_MISC_CTRL 0x1C84
+#define VDEC_G_VCR_DET_CTRL 0x1C88
+#define VDEC_G_NOISE_DET_CTRL 0x1C8C
+#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90
+#define VDEC_G_VERSION 0x1DF8
+#define VDEC_G_SOFT_RST_CTRL 0x1DFC
+
+// Video Decoder H Registers
+#define VDEC_H_MODE_CTRL 0x1E00
+#define VDEC_H_OUT_CTRL1 0x1E04
+#define VDEC_H_OUT_CTRL_NS 0x1E08
+#define VDEC_H_GEN_STAT 0x1E0C
+#define VDEC_H_INT_STAT_MASK 0x1E1E
+#define VDEC_H_LUMA_CTRL 0x1E14
+#define VDEC_H_CHROMA_CTRL 0x1E18
+#define VDEC_H_CRUSH_CTRL 0x1E1C
+#define VDEC_H_HORIZ_TIM_CTRL 0x1E20
+#define VDEC_H_VERT_TIM_CTRL 0x1E24
+#define VDEC_H_MISC_TIM_CTRL 0x1E28
+#define VDEC_H_FIELD_COUNT 0x1E2C
+#define VDEC_H_HSCALE_CTRL 0x1E30
+#define VDEC_H_VSCALE_CTRL 0x1E34
+#define VDEC_H_MAN_VGA_CTRL 0x1E38
+#define VDEC_H_MAN_AGC_CTRL 0x1E3C
+#define VDEC_H_DFE_CTRL1 0x1E40
+#define VDEC_H_DFE_CTRL2 0x1E44
+#define VDEC_H_DFE_CTRL3 0x1E48
+#define VDEC_H_PLL_CTRL 0x1E4C
+#define VDEC_H_PLL_CTRL_FAST 0x1E50
+#define VDEC_H_HTL_CTRL 0x1E54
+#define VDEC_H_SRC_CFG 0x1E58
+#define VDEC_H_SC_STEP_SIZE 0x1E5C
+#define VDEC_H_SC_CONVERGE_CTRL 0x1E60
+#define VDEC_H_SC_LOOP_CTRL 0x1E64
+#define VDEC_H_COMB_2D_HFS_CFG 0x1E68
+#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C
+#define VDEC_H_COMB_2D_LF_CFG 0x1E70
+#define VDEC_H_COMB_2D_BLEND 0x1E74
+#define VDEC_H_COMB_MISC_CTRL 0x1E78
+#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C
+#define VDEC_H_COMB_TEST 0x1E80
+#define VDEC_H_BP_MISC_CTRL 0x1E84
+#define VDEC_H_VCR_DET_CTRL 0x1E88
+#define VDEC_H_NOISE_DET_CTRL 0x1E8C
+#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90
+#define VDEC_H_VERSION 0x1FF8
+#define VDEC_H_SOFT_RST_CTRL 0x1FFC
+
+//*****************************************************************************
+// LUMA_CTRL register fields
+#define VDEC_A_BRITE_CTRL 0x1014
+#define VDEC_A_CNTRST_CTRL 0x1015
+#define VDEC_A_PEAK_SEL 0x1016
+
+//*****************************************************************************
+// CHROMA_CTRL register fields
+#define VDEC_A_USAT_CTRL 0x1018
+#define VDEC_A_VSAT_CTRL 0x1019
+#define VDEC_A_HUE_CTRL 0x101A
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c
new file mode 100644
index 000000000000..e4df8134f059
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-medusa-video.c
@@ -0,0 +1,869 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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.
+ */
+
+#include "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//medusa_enable_bluefield_output()
+//
+// Enable the generation of blue filed output if no video
+//
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
+ int enable)
+{
+ int ret_val = 1;
+ u32 value = 0;
+ u32 tmp = 0;
+ int out_ctrl = OUT_CTRL1;
+ int out_ctrl_ns = OUT_CTRL_NS;
+
+ switch (channel) {
+ default:
+ case VDEC_A:
+ break;
+ case VDEC_B:
+ out_ctrl = VDEC_B_OUT_CTRL1;
+ out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+ break;
+ case VDEC_C:
+ out_ctrl = VDEC_C_OUT_CTRL1;
+ out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+ break;
+ case VDEC_D:
+ out_ctrl = VDEC_D_OUT_CTRL1;
+ out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+ break;
+ case VDEC_E:
+ out_ctrl = VDEC_E_OUT_CTRL1;
+ out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+ return;
+ case VDEC_F:
+ out_ctrl = VDEC_F_OUT_CTRL1;
+ out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+ return;
+ case VDEC_G:
+ out_ctrl = VDEC_G_OUT_CTRL1;
+ out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+ return;
+ case VDEC_H:
+ out_ctrl = VDEC_H_OUT_CTRL1;
+ out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+ return;
+ }
+
+ value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+ value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN
+ if (enable)
+ value |= 0x00000080; // set BLUE_FIELD_EN
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+ value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+ value &= 0xFFFFFF7F;
+ if (enable)
+ value |= 0x00000080; // set BLUE_FIELD_EN
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+ int ret_val = 0;
+ int i = 0;
+ u32 value = 0;
+ u32 tmp = 0;
+
+ mutex_lock(&dev->lock);
+
+ for (i = 0; i < MAX_DECODERS; i++) {
+ // set video format NTSC-M
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+ &tmp);
+ value &= 0xFFFFFFF0;
+ value |= 0x10001; // enable the fast locking mode bit[16]
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+ value);
+
+ // resolution NTSC 720x480
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+ value &= 0x00C00C00;
+ value |= 0x612D0074;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), value);
+
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), &tmp);
+ value &= 0x00C00C00;
+ value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), value);
+
+ // chroma subcarrier step size
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+
+ // enable VIP optional active
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), &tmp);
+ value &= 0xFFFBFFFF;
+ value |= 0x00040000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), value);
+
+ // enable VIP optional active (VIP_OPT_AL) for direct output.
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+ &tmp);
+ value &= 0xFFFBFFFF;
+ value |= 0x00040000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+ value);
+
+ // clear VPRES_VERT_EN bit, fixes the chroma run away problem
+ // when the input switching rate < 16 fields
+ //
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), &tmp);
+ value = setBitAtPos(value, 14); // disable special play detection
+ value = clearBitAtPos(value, 15);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), value);
+
+ // set vbi_gate_en to 0
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+ &tmp);
+ value = clearBitAtPos(value, 29);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+ value);
+
+ // Enable the generation of blue field output if no video
+ medusa_enable_bluefield_output(dev, i, 1);
+ }
+
+ for (i = 0; i < MAX_ENCODERS; i++) {
+ // NTSC hclock
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), &tmp);
+ value &= 0xF000FC00;
+ value |= 0x06B402D0;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), value);
+
+ // burst begin and burst end
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), &tmp);
+ value &= 0xFF000000;
+ value |= 0x007E9054;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), value);
+
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), &tmp);
+ value &= 0xFC00FE00;
+ value |= 0x00EC00F0;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), value);
+
+ // set NTSC vblank, no phase alternation, 7.5 IRE pedestal
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), &tmp);
+ value &= 0x00FCFFFF;
+ value |= 0x13020000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), value);
+
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), &tmp);
+ value &= 0xFFFF0000;
+ value |= 0x0000E575;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), value);
+
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+
+ // Subcarrier Increment
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+ }
+
+ //set picture resolutions
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480
+
+ // set Bypass input format to NTSC 525 lines
+ value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+ value |= 0x00080200;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+ mutex_unlock(&dev->lock);
+
+ return ret_val;
+}
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+ int ret_val = -1;
+ u32 value = 0, tmp = 0;
+
+ // Setup for 2D threshold
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
+ 0x20002861);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
+ 0x20002861);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
+ 0x200A1023);
+
+ // Setup flat chroma and luma thresholds
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+ value &= 0x06230000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+
+ // set comb 2D blend
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
+ 0x210F0F0F);
+
+ // COMB MISC CONTROL
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
+ 0x41120A7F);
+
+ return ret_val;
+}
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+ int ret_val = 0;
+ int i = 0;
+ u32 value = 0;
+ u32 tmp = 0;
+
+ mutex_lock(&dev->lock);
+
+ for (i = 0; i < MAX_DECODERS; i++) {
+ // set video format PAL-BDGHI
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+ &tmp);
+ value &= 0xFFFFFFF0;
+ value |= 0x10004; // enable the fast locking mode bit[16]
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+ value);
+
+ // resolution PAL 720x576
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+ value &= 0x00C00C00;
+ value |= 0x632D007D;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), value);
+
+ // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), &tmp);
+ value &= 0x00C00C00;
+ value |= 0x28240026; // vblank_cnt + 2 to get camera ID
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), value);
+
+ // chroma subcarrier step size
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+
+ // enable VIP optional active
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), &tmp);
+ value &= 0xFFFBFFFF;
+ value |= 0x00040000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), value);
+
+ // enable VIP optional active (VIP_OPT_AL) for direct output.
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+ &tmp);
+ value &= 0xFFFBFFFF;
+ value |= 0x00040000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+ value);
+
+ // clear VPRES_VERT_EN bit, fixes the chroma run away problem
+ // when the input switching rate < 16 fields
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), &tmp);
+ value = setBitAtPos(value, 14); // disable special play detection
+ value = clearBitAtPos(value, 15);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), value);
+
+ // set vbi_gate_en to 0
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+ &tmp);
+ value = clearBitAtPos(value, 29);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+ value);
+
+ medusa_PALCombInit(dev, i);
+
+ // Enable the generation of blue field output if no video
+ medusa_enable_bluefield_output(dev, i, 1);
+ }
+
+ for (i = 0; i < MAX_ENCODERS; i++) {
+ // PAL hclock
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), &tmp);
+ value &= 0xF000FC00;
+ value |= 0x06C002D0;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), value);
+
+ // burst begin and burst end
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), &tmp);
+ value &= 0xFF000000;
+ value |= 0x007E9754;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), value);
+
+ // hblank and vactive
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), &tmp);
+ value &= 0xFC00FE00;
+ value |= 0x00FC0120;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), value);
+
+ // set PAL vblank, phase alternation, 0 IRE pedestal
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), &tmp);
+ value &= 0x00FCFFFF;
+ value |= 0x14010000;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), value);
+
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), &tmp);
+ value &= 0xFFFF0000;
+ value |= 0x0000F078;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), value);
+
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+
+ // Subcarrier Increment
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+ }
+
+ //set picture resolutions
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576
+
+ // set Bypass input format to PAL 625 lines
+ value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+ value &= 0xFFF7FDFF;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+ mutex_unlock(&dev->lock);
+
+ return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+ int status = STATUS_SUCCESS;
+ u32 value = 0, tmp = 0;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) {
+ status = medusa_initialize_pal(dev);
+ } else {
+ status = medusa_initialize_ntsc(dev);
+ }
+
+ // Enable DENC_A output
+ value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+ value = setBitAtPos(value, 4);
+ status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+
+ // Enable DENC_B output
+ value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+ value = setBitAtPos(value, 4);
+ status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+
+ return status;
+}
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width,
+ int decoder_select)
+{
+ int decoder = 0;
+ int decoder_count = 0;
+ int ret_val = 0;
+ u32 hscale = 0x0;
+ u32 vscale = 0x0;
+ const int MAX_WIDTH = 720;
+
+ mutex_lock(&dev->lock);
+
+ // validate the width - cannot be negative
+ if (width > MAX_WIDTH) {
+ printk
+ ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n",
+ __func__, width, MAX_WIDTH);
+ width = MAX_WIDTH;
+ }
+
+ if (decoder_select <= 7 && decoder_select >= 0) {
+ decoder = decoder_select;
+ decoder_count = decoder_select + 1;
+ } else {
+ decoder = 0;
+ decoder_count = _num_decoders;
+ }
+
+ switch (width) {
+ case 320:
+ hscale = 0x13E34B;
+ vscale = 0x0;
+ break;
+
+ case 352:
+ hscale = 0x10A273;
+ vscale = 0x0;
+ break;
+
+ case 176:
+ hscale = 0x3115B2;
+ vscale = 0x1E00;
+ break;
+
+ case 160:
+ hscale = 0x378D84;
+ vscale = 0x1E00;
+ break;
+
+ default: //720
+ hscale = 0x0;
+ vscale = 0x0;
+ break;
+ }
+
+ for (; decoder < decoder_count; decoder++) {
+ // write scaling values for each decoder
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ HSCALE_CTRL + (0x200 * decoder), hscale);
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VSCALE_CTRL + (0x200 * decoder), vscale);
+ }
+
+ mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+ int duration)
+{
+ int ret_val = 0;
+ u32 fld_cnt = 0;
+ u32 tmp = 0;
+ u32 disp_cnt_reg = DISP_AB_CNT;
+
+ mutex_lock(&dev->lock);
+
+ // no support
+ if (decoder < VDEC_A && decoder > VDEC_H) {
+ mutex_unlock(&dev->lock);
+ return;
+ }
+
+ switch (decoder) {
+ default:
+ break;
+ case VDEC_C:
+ case VDEC_D:
+ disp_cnt_reg = DISP_CD_CNT;
+ break;
+ case VDEC_E:
+ case VDEC_F:
+ disp_cnt_reg = DISP_EF_CNT;
+ break;
+ case VDEC_G:
+ case VDEC_H:
+ disp_cnt_reg = DISP_GH_CNT;
+ break;
+ }
+
+ _display_field_cnt[decoder] = duration;
+
+ // update hardware
+ fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+
+ if (!(decoder % 2)) // EVEN decoder
+ {
+ fld_cnt &= 0xFFFF0000;
+ fld_cnt |= duration;
+ } else {
+ fld_cnt &= 0x0000FFFF;
+ fld_cnt |= ((u32) duration) << 16;
+ }
+
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+
+ mutex_unlock(&dev->lock);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Map to Medusa register setting
+static int mapM(int srcMin,
+ int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
+{
+ int numerator;
+ int denominator;
+ int quotient;
+
+ if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) {
+ return -1;
+ }
+ // This is the overall expression used:
+ // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+ // but we need to account for rounding so below we use the modulus
+ // operator to find the remainder and increment if necessary.
+ numerator = (srcVal - srcMin) * (dstMax - dstMin);
+ denominator = srcMax - srcMin;
+ quotient = numerator / denominator;
+
+ if (2 * (numerator % denominator) >= denominator) {
+ quotient++;
+ }
+
+ *dstVal = quotient + dstMin;
+
+ return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+ unsigned char temp;
+
+ if (numeric >= 0)
+ return numeric;
+ else {
+ temp = ~(abs(numeric) & 0xFF);
+ temp += 1;
+ return temp;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+ int ret_val = 0;
+ int value = 0;
+ u32 val = 0, tmp = 0;
+
+ mutex_lock(&dev->lock);
+ if ((brightness > VIDEO_PROCAMP_MAX)
+ || (brightness < VIDEO_PROCAMP_MIN)) {
+ mutex_unlock(&dev->lock);
+ return -1;
+ }
+ ret_val =
+ mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+ SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+ value = convert_to_twos(value, 8);
+ val =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+ val &= 0xFFFFFF00;
+ ret_val |=
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_BRITE_CTRL + (0x200 * decoder),
+ val | value);
+ mutex_unlock(&dev->lock);
+ return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+ int ret_val = 0;
+ int value = 0;
+ u32 val = 0, tmp = 0;
+
+ mutex_lock(&dev->lock);
+
+ if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+ mutex_unlock(&dev->lock);
+ return -1;
+ }
+
+ ret_val =
+ mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+ UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+ val =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+ val &= 0xFFFFFF00;
+ ret_val |=
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_CNTRST_CTRL + (0x200 * decoder),
+ val | value);
+
+ mutex_unlock(&dev->lock);
+ return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+ int ret_val = 0;
+ int value = 0;
+ u32 val = 0, tmp = 0;
+
+ mutex_lock(&dev->lock);
+
+ if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+ mutex_unlock(&dev->lock);
+ return -1;
+ }
+
+ ret_val =
+ mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
+ SIGNED_BYTE_MAX, &value);
+
+ value = convert_to_twos(value, 8);
+ val =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+ val &= 0xFFFFFF00;
+
+ ret_val |=
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+
+ mutex_unlock(&dev->lock);
+ return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+ int ret_val = 0;
+ int value = 0;
+ u32 val = 0, tmp = 0;
+
+ mutex_lock(&dev->lock);
+
+ if ((saturation > VIDEO_PROCAMP_MAX)
+ || (saturation < VIDEO_PROCAMP_MIN)) {
+ mutex_unlock(&dev->lock);
+ return -1;
+ }
+
+ ret_val =
+ mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+ UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+
+ val =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+ val &= 0xFFFFFF00;
+ ret_val |=
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_USAT_CTRL + (0x200 * decoder),
+ val | value);
+
+ val =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+ val &= 0xFFFFFF00;
+ ret_val |=
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_VSAT_CTRL + (0x200 * decoder),
+ val | value);
+
+ mutex_unlock(&dev->lock);
+ return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Program the display sequence and monitor output.
+//
+int medusa_video_init(struct cx25821_dev *dev)
+{
+ u32 value = 0, tmp = 0;
+ int ret_val = 0;
+ int i = 0;
+
+ mutex_lock(&dev->lock);
+
+ _num_decoders = dev->_max_num_decoders;
+
+ // disable Auto source selection on all video decoders
+ value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+ value &= 0xFFFFF0FF;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ // Turn off Master source switch enable
+ value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+ value &= 0xFFFFFFDF;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dev->lock);
+
+ for (i = 0; i < _num_decoders; i++) {
+ medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+ }
+
+ mutex_lock(&dev->lock);
+
+ // Select monitor as DENC A input, power up the DAC
+ value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+ value &= 0xFF70FF70;
+ value |= 0x00090008; // set en_active
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ // enable input is VIP/656
+ value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+ value |= 0x00040100; // enable VIP
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ // select AFE clock to output mode
+ value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+ value &= 0x83FFFFFF;
+ ret_val =
+ cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+ value | 0x10000000);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ // Turn on all of the data out and control output pins.
+ value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+ value &= 0xFEF0FE00;
+ if (_num_decoders == MAX_DECODERS) {
+ // Note: The octal board does not support control pins(bit16-19).
+ // These bits are ignored in the octal board.
+ value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface
+ } else {
+ value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface
+ }
+
+ value |= 7;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dev->lock);
+
+ ret_val = medusa_set_videostandard(dev);
+
+ if (ret_val < 0) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+
+ return 1;
+}
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.h b/drivers/staging/cx25821/cx25821-medusa-video.h
new file mode 100644
index 000000000000..2fab4b2f251c
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-medusa-video.h
@@ -0,0 +1,49 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#include "cx25821-medusa-defines.h"
+
+// Color control constants
+#define VIDEO_PROCAMP_MIN 0
+#define VIDEO_PROCAMP_MAX 10000
+#define UNSIGNED_BYTE_MIN 0
+#define UNSIGNED_BYTE_MAX 0xFF
+#define SIGNED_BYTE_MIN -128
+#define SIGNED_BYTE_MAX 127
+
+// Default video color settings
+#define SHARPNESS_DEFAULT 50
+#define SATURATION_DEFAULT 5000
+#define BRIGHTNESS_DEFAULT 6200
+#define CONTRAST_DEFAULT 5000
+#define HUE_DEFAULT 5000
+
+unsigned short _num_decoders;
+unsigned short _num_cameras;
+
+unsigned int _video_standard;
+int _display_field_cnt[MAX_DECODERS];
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h
new file mode 100644
index 000000000000..7241e7ee3fd3
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-reg.h
@@ -0,0 +1,1592 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC 0x00010000
+#define RISC_CNT_RESET 0x00030000
+#define RISC_IRQ1 0x01000000
+#define RISC_IRQ2 0x02000000
+#define RISC_EOL 0x04000000
+#define RISC_SOL 0x08000000
+#define RISC_WRITE 0x10000000
+#define RISC_SKIP 0x20000000
+#define RISC_JUMP 0x70000000
+#define RISC_SYNC 0x80000000
+#define RISC_RESYNC 0x80008000
+#define RISC_READ 0x90000000
+#define RISC_WRITERM 0xB0000000
+#define RISC_WRITECM 0xC0000000
+#define RISC_WRITECR 0xD0000000
+#define RISC_WRITEC 0x50000000
+#define RISC_READC 0xA0000000
+
+#define RISC_SYNC_ODD 0x00000000
+#define RISC_SYNC_EVEN 0x00000200
+#define RISC_SYNC_ODD_VBI 0x00000006
+#define RISC_SYNC_EVEN_VBI 0x00000207
+#define RISC_NOOP 0xF0000000
+
+//*****************************************************************************
+// ASB SRAM
+//*****************************************************************************
+#define TX_SRAM 0x000000 // Transmit SRAM
+
+//*****************************************************************************
+#define RX_RAM 0x010000 // Receive SRAM
+
+//*****************************************************************************
+// Application Layer (AL)
+//*****************************************************************************
+#define DEV_CNTRL2 0x040000 // Device control
+#define FLD_RUN_RISC 0x00000020
+
+//*****************************************************************************
+#define PCI_INT_MSK 0x040010 // PCI interrupt mask
+#define PCI_INT_STAT 0x040014 // PCI interrupt status
+#define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status
+#define FLD_HAMMERHEAD_INT (1 << 27)
+#define FLD_UART_INT (1 << 26)
+#define FLD_IRQN_INT (1 << 25)
+#define FLD_TM_INT (1 << 28)
+#define FLD_I2C_3_RACK (1 << 27)
+#define FLD_I2C_3_INT (1 << 26)
+#define FLD_I2C_2_RACK (1 << 25)
+#define FLD_I2C_2_INT (1 << 24)
+#define FLD_I2C_1_RACK (1 << 23)
+#define FLD_I2C_1_INT (1 << 22)
+
+#define FLD_APB_DMA_BERR_INT (1 << 21)
+#define FLD_AL_WR_BERR_INT (1 << 20)
+#define FLD_AL_RD_BERR_INT (1 << 19)
+#define FLD_RISC_WR_BERR_INT (1 << 18)
+#define FLD_RISC_RD_BERR_INT (1 << 17)
+
+#define FLD_VID_I_INT (1 << 8)
+#define FLD_VID_H_INT (1 << 7)
+#define FLD_VID_G_INT (1 << 6)
+#define FLD_VID_F_INT (1 << 5)
+#define FLD_VID_E_INT (1 << 4)
+#define FLD_VID_D_INT (1 << 3)
+#define FLD_VID_C_INT (1 << 2)
+#define FLD_VID_B_INT (1 << 1)
+#define FLD_VID_A_INT (1 << 0)
+
+//*****************************************************************************
+#define VID_A_INT_MSK 0x040020 // Video A interrupt mask
+#define VID_A_INT_STAT 0x040024 // Video A interrupt status
+#define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status
+#define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status
+
+//*****************************************************************************
+#define VID_B_INT_MSK 0x040030 // Video B interrupt mask
+#define VID_B_INT_STAT 0x040034 // Video B interrupt status
+#define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status
+#define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status
+
+//*****************************************************************************
+#define VID_C_INT_MSK 0x040040 // Video C interrupt mask
+#define VID_C_INT_STAT 0x040044 // Video C interrupt status
+#define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status
+#define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status
+
+//*****************************************************************************
+#define VID_D_INT_MSK 0x040050 // Video D interrupt mask
+#define VID_D_INT_STAT 0x040054 // Video D interrupt status
+#define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status
+#define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status
+
+//*****************************************************************************
+#define VID_E_INT_MSK 0x040060 // Video E interrupt mask
+#define VID_E_INT_STAT 0x040064 // Video E interrupt status
+#define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status
+#define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status
+
+//*****************************************************************************
+#define VID_F_INT_MSK 0x040070 // Video F interrupt mask
+#define VID_F_INT_STAT 0x040074 // Video F interrupt status
+#define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status
+#define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status
+
+//*****************************************************************************
+#define VID_G_INT_MSK 0x040080 // Video G interrupt mask
+#define VID_G_INT_STAT 0x040084 // Video G interrupt status
+#define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status
+#define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status
+
+//*****************************************************************************
+#define VID_H_INT_MSK 0x040090 // Video H interrupt mask
+#define VID_H_INT_STAT 0x040094 // Video H interrupt status
+#define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status
+#define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status
+
+//*****************************************************************************
+#define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask
+#define VID_I_INT_STAT 0x0400A4 // Video I interrupt status
+#define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status
+#define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status
+
+//*****************************************************************************
+#define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask
+#define VID_J_INT_STAT 0x0400B4 // Video J interrupt status
+#define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status
+#define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status
+
+#define FLD_VID_SRC_OPC_ERR 0x00020000
+#define FLD_VID_DST_OPC_ERR 0x00010000
+#define FLD_VID_SRC_SYNC 0x00002000
+#define FLD_VID_DST_SYNC 0x00001000
+#define FLD_VID_SRC_UF 0x00000200
+#define FLD_VID_DST_OF 0x00000100
+#define FLD_VID_SRC_RISC2 0x00000020
+#define FLD_VID_DST_RISC2 0x00000010
+#define FLD_VID_SRC_RISC1 0x00000002
+#define FLD_VID_DST_RISC1 0x00000001
+#define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF
+#define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF
+
+//*****************************************************************************
+#define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask
+#define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status
+#define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status
+#define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status
+
+//*****************************************************************************
+#define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask
+#define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status
+#define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status
+#define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status
+
+//*****************************************************************************
+#define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask
+#define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status
+#define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status
+#define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status
+
+//*****************************************************************************
+#define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask
+#define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status
+#define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status
+#define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status
+
+//*****************************************************************************
+#define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask
+#define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status
+#define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status
+#define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status
+
+#define FLD_AUD_SRC_OPC_ERR 0x00020000
+#define FLD_AUD_DST_OPC_ERR 0x00010000
+#define FLD_AUD_SRC_SYNC 0x00002000
+#define FLD_AUD_DST_SYNC 0x00001000
+#define FLD_AUD_SRC_OF 0x00000200
+#define FLD_AUD_DST_OF 0x00000100
+#define FLD_AUD_SRC_RISCI2 0x00000020
+#define FLD_AUD_DST_RISCI2 0x00000010
+#define FLD_AUD_SRC_RISCI1 0x00000002
+#define FLD_AUD_DST_RISCI1 0x00000001
+
+//*****************************************************************************
+#define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask
+#define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status
+#define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status
+#define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status
+
+//*****************************************************************************
+#define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask
+#define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status
+#define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status
+#define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status
+
+#define FLD_MBIF_DST_OPC_ERR 0x00010000
+#define FLD_MBIF_DST_SYNC 0x00001000
+#define FLD_MBIF_DST_OF 0x00000100
+#define FLD_MBIF_DST_RISCI2 0x00000010
+#define FLD_MBIF_DST_RISCI1 0x00000001
+
+//*****************************************************************************
+#define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask
+#define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status
+#define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status
+#define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status
+#define FLD_AUD_EXT_OPC_ERR 0x00010000
+#define FLD_AUD_EXT_SYNC 0x00001000
+#define FLD_AUD_EXT_OF 0x00000100
+#define FLD_AUD_EXT_RISCI2 0x00000010
+#define FLD_AUD_EXT_RISCI1 0x00000001
+
+//*****************************************************************************
+#define GPIO_LO 0x110010 // Lower of GPIO pins [31:0]
+#define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31]
+
+#define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0]
+#define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32]
+
+#define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask
+#define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status
+#define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status
+#define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity
+#define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity
+
+#define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask
+#define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status
+#define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status
+#define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity
+#define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity
+
+#define FLD_GPIO43_INT (1 << 11)
+#define FLD_GPIO42_INT (1 << 10)
+#define FLD_GPIO41_INT (1 << 9)
+#define FLD_GPIO40_INT (1 << 8)
+
+#define FLD_GPIO9_INT (1 << 9)
+#define FLD_GPIO8_INT (1 << 8)
+#define FLD_GPIO7_INT (1 << 7)
+#define FLD_GPIO6_INT (1 << 6)
+#define FLD_GPIO5_INT (1 << 5)
+#define FLD_GPIO4_INT (1 << 4)
+#define FLD_GPIO3_INT (1 << 3)
+#define FLD_GPIO2_INT (1 << 2)
+#define FLD_GPIO1_INT (1 << 1)
+#define FLD_GPIO0_INT (1 << 0)
+
+//*****************************************************************************
+#define TC_REQ 0x040090 // Rider PCI Express traFFic class request
+
+//*****************************************************************************
+#define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set
+
+//*****************************************************************************
+// Rider
+//*****************************************************************************
+
+// PCI Compatible Header
+//*****************************************************************************
+#define RDR_CFG0 0x050000
+#define RDR_VENDOR_DEVICE_ID_CFG 0x050000
+
+//*****************************************************************************
+#define RDR_CFG1 0x050004
+
+//*****************************************************************************
+#define RDR_CFG2 0x050008
+
+//*****************************************************************************
+#define RDR_CFG3 0x05000C
+
+//*****************************************************************************
+#define RDR_CFG4 0x050010
+
+//*****************************************************************************
+#define RDR_CFG5 0x050014
+
+//*****************************************************************************
+#define RDR_CFG6 0x050018
+
+//*****************************************************************************
+#define RDR_CFG7 0x05001C
+
+//*****************************************************************************
+#define RDR_CFG8 0x050020
+
+//*****************************************************************************
+#define RDR_CFG9 0x050024
+
+//*****************************************************************************
+#define RDR_CFGA 0x050028
+
+//*****************************************************************************
+#define RDR_CFGB 0x05002C
+#define RDR_SUSSYSTEM_ID_CFG 0x05002C
+
+//*****************************************************************************
+#define RDR_CFGC 0x050030
+
+//*****************************************************************************
+#define RDR_CFGD 0x050034
+
+//*****************************************************************************
+#define RDR_CFGE 0x050038
+
+//*****************************************************************************
+#define RDR_CFGF 0x05003C
+
+//*****************************************************************************
+// PCI-Express Capabilities
+//*****************************************************************************
+#define RDR_PECAP 0x050040
+
+//*****************************************************************************
+#define RDR_PEDEVCAP 0x050044
+
+//*****************************************************************************
+#define RDR_PEDEVSC 0x050048
+
+//*****************************************************************************
+#define RDR_PELINKCAP 0x05004C
+
+//*****************************************************************************
+#define RDR_PELINKSC 0x050050
+
+//*****************************************************************************
+#define RDR_PMICAP 0x050080
+
+//*****************************************************************************
+#define RDR_PMCSR 0x050084
+
+//*****************************************************************************
+#define RDR_VPDCAP 0x050090
+
+//*****************************************************************************
+#define RDR_VPDDATA 0x050094
+
+//*****************************************************************************
+#define RDR_MSICAP 0x0500A0
+
+//*****************************************************************************
+#define RDR_MSIARL 0x0500A4
+
+//*****************************************************************************
+#define RDR_MSIARU 0x0500A8
+
+//*****************************************************************************
+#define RDR_MSIDATA 0x0500AC
+
+//*****************************************************************************
+// PCI Express Extended Capabilities
+//*****************************************************************************
+#define RDR_AERXCAP 0x050100
+
+//*****************************************************************************
+#define RDR_AERUESTA 0x050104
+
+//*****************************************************************************
+#define RDR_AERUEMSK 0x050108
+
+//*****************************************************************************
+#define RDR_AERUESEV 0x05010C
+
+//*****************************************************************************
+#define RDR_AERCESTA 0x050110
+
+//*****************************************************************************
+#define RDR_AERCEMSK 0x050114
+
+//*****************************************************************************
+#define RDR_AERCC 0x050118
+
+//*****************************************************************************
+#define RDR_AERHL0 0x05011C
+
+//*****************************************************************************
+#define RDR_AERHL1 0x050120
+
+//*****************************************************************************
+#define RDR_AERHL2 0x050124
+
+//*****************************************************************************
+#define RDR_AERHL3 0x050128
+
+//*****************************************************************************
+#define RDR_VCXCAP 0x050200
+
+//*****************************************************************************
+#define RDR_VCCAP1 0x050204
+
+//*****************************************************************************
+#define RDR_VCCAP2 0x050208
+
+//*****************************************************************************
+#define RDR_VCSC 0x05020C
+
+//*****************************************************************************
+#define RDR_VCR0_CAP 0x050210
+
+//*****************************************************************************
+#define RDR_VCR0_CTRL 0x050214
+
+//*****************************************************************************
+#define RDR_VCR0_STAT 0x050218
+
+//*****************************************************************************
+#define RDR_VCR1_CAP 0x05021C
+
+//*****************************************************************************
+#define RDR_VCR1_CTRL 0x050220
+
+//*****************************************************************************
+#define RDR_VCR1_STAT 0x050224
+
+//*****************************************************************************
+#define RDR_VCR2_CAP 0x050228
+
+//*****************************************************************************
+#define RDR_VCR2_CTRL 0x05022C
+
+//*****************************************************************************
+#define RDR_VCR2_STAT 0x050230
+
+//*****************************************************************************
+#define RDR_VCR3_CAP 0x050234
+
+//*****************************************************************************
+#define RDR_VCR3_CTRL 0x050238
+
+//*****************************************************************************
+#define RDR_VCR3_STAT 0x05023C
+
+//*****************************************************************************
+#define RDR_VCARB0 0x050240
+
+//*****************************************************************************
+#define RDR_VCARB1 0x050244
+
+//*****************************************************************************
+#define RDR_VCARB2 0x050248
+
+//*****************************************************************************
+#define RDR_VCARB3 0x05024C
+
+//*****************************************************************************
+#define RDR_VCARB4 0x050250
+
+//*****************************************************************************
+#define RDR_VCARB5 0x050254
+
+//*****************************************************************************
+#define RDR_VCARB6 0x050258
+
+//*****************************************************************************
+#define RDR_VCARB7 0x05025C
+
+//*****************************************************************************
+#define RDR_RDRSTAT0 0x050300
+
+//*****************************************************************************
+#define RDR_RDRSTAT1 0x050304
+
+//*****************************************************************************
+#define RDR_RDRCTL0 0x050308
+
+//*****************************************************************************
+#define RDR_RDRCTL1 0x05030C
+
+//*****************************************************************************
+// Transaction Layer Registers
+//*****************************************************************************
+#define RDR_TLSTAT0 0x050310
+
+//*****************************************************************************
+#define RDR_TLSTAT1 0x050314
+
+//*****************************************************************************
+#define RDR_TLCTL0 0x050318
+#define FLD_CFG_UR_CPL_MODE 0x00000040
+#define FLD_CFG_CORR_ERR_QUITE 0x00000020
+#define FLD_CFG_RCB_CK_EN 0x00000010
+#define FLD_CFG_BNDRY_CK_EN 0x00000008
+#define FLD_CFG_BYTE_EN_CK_EN 0x00000004
+#define FLD_CFG_RELAX_ORDER_MSK 0x00000002
+#define FLD_CFG_TAG_ORDER_EN 0x00000001
+
+//*****************************************************************************
+#define RDR_TLCTL1 0x05031C
+
+//*****************************************************************************
+#define RDR_REQRCAL 0x050320
+
+//*****************************************************************************
+#define RDR_REQRCAU 0x050324
+
+//*****************************************************************************
+#define RDR_REQEPA 0x050328
+
+//*****************************************************************************
+#define RDR_REQCTRL 0x05032C
+
+//*****************************************************************************
+#define RDR_REQSTAT 0x050330
+
+//*****************************************************************************
+#define RDR_TL_TEST 0x050334
+
+//*****************************************************************************
+#define RDR_VCR01_CTL 0x050348
+
+//*****************************************************************************
+#define RDR_VCR23_CTL 0x05034C
+
+//*****************************************************************************
+#define RDR_RX_VCR0_FC 0x050350
+
+//*****************************************************************************
+#define RDR_RX_VCR1_FC 0x050354
+
+//*****************************************************************************
+#define RDR_RX_VCR2_FC 0x050358
+
+//*****************************************************************************
+#define RDR_RX_VCR3_FC 0x05035C
+
+//*****************************************************************************
+// Data Link Layer Registers
+//*****************************************************************************
+#define RDR_DLLSTAT 0x050360
+
+//*****************************************************************************
+#define RDR_DLLCTRL 0x050364
+
+//*****************************************************************************
+#define RDR_REPLAYTO 0x050368
+
+//*****************************************************************************
+#define RDR_ACKLATTO 0x05036C
+
+//*****************************************************************************
+// MAC Layer Registers
+//*****************************************************************************
+#define RDR_MACSTAT0 0x050380
+
+//*****************************************************************************
+#define RDR_MACSTAT1 0x050384
+
+//*****************************************************************************
+#define RDR_MACCTRL0 0x050388
+
+//*****************************************************************************
+#define RDR_MACCTRL1 0x05038C
+
+//*****************************************************************************
+#define RDR_MACCTRL2 0x050390
+
+//*****************************************************************************
+#define RDR_MAC_LB_DATA 0x050394
+
+//*****************************************************************************
+#define RDR_L0S_EXIT_LAT 0x050398
+
+//*****************************************************************************
+// DMAC
+//*****************************************************************************
+#define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1
+
+//*****************************************************************************
+#define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2
+
+//*****************************************************************************
+#define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3
+
+//*****************************************************************************
+#define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4
+
+//*****************************************************************************
+#define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5
+
+//*****************************************************************************
+#define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6
+
+//*****************************************************************************
+#define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7
+
+//*****************************************************************************
+#define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8
+
+//*****************************************************************************
+#define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9
+
+//*****************************************************************************
+#define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10
+
+//*****************************************************************************
+#define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11
+
+//*****************************************************************************
+#define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12
+
+//*****************************************************************************
+#define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13
+
+//*****************************************************************************
+#define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14
+
+//*****************************************************************************
+#define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15
+
+//*****************************************************************************
+#define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16
+
+//*****************************************************************************
+#define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17
+
+//*****************************************************************************
+#define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18
+
+//*****************************************************************************
+#define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19
+
+//*****************************************************************************
+#define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20
+
+//*****************************************************************************
+#define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21
+
+//*****************************************************************************
+#define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22
+
+//*****************************************************************************
+#define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23
+
+//*****************************************************************************
+#define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24
+
+//*****************************************************************************
+#define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25
+
+//*****************************************************************************
+#define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26
+
+//*****************************************************************************
+#define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1
+
+//*****************************************************************************
+#define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2
+
+//*****************************************************************************
+#define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3
+
+//*****************************************************************************
+#define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4
+
+//*****************************************************************************
+#define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5
+
+//*****************************************************************************
+#define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6
+
+//*****************************************************************************
+#define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7
+
+//*****************************************************************************
+#define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8
+
+//*****************************************************************************
+#define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9
+
+//*****************************************************************************
+#define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10
+
+//*****************************************************************************
+#define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11
+
+//*****************************************************************************
+#define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12
+
+//*****************************************************************************
+#define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13
+
+//*****************************************************************************
+#define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14
+
+//*****************************************************************************
+#define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15
+
+//*****************************************************************************
+#define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16
+
+//*****************************************************************************
+#define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17
+
+//*****************************************************************************
+#define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18
+
+//*****************************************************************************
+#define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19
+
+//*****************************************************************************
+#define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20
+
+//*****************************************************************************
+#define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21
+
+//*****************************************************************************
+#define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22
+
+//*****************************************************************************
+#define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23
+
+//*****************************************************************************
+#define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24
+
+//*****************************************************************************
+#define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25
+
+//*****************************************************************************
+#define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26
+
+//*****************************************************************************
+#define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1
+
+//*****************************************************************************
+#define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2
+
+//*****************************************************************************
+#define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3
+
+//*****************************************************************************
+#define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4
+
+//*****************************************************************************
+#define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5
+
+//*****************************************************************************
+#define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6
+
+//*****************************************************************************
+#define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7
+
+//*****************************************************************************
+#define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8
+
+//*****************************************************************************
+#define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9
+
+//*****************************************************************************
+#define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10
+
+//*****************************************************************************
+#define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11
+
+//*****************************************************************************
+#define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12
+
+//*****************************************************************************
+#define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13
+
+//*****************************************************************************
+#define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14
+
+//*****************************************************************************
+#define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15
+
+//*****************************************************************************
+#define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16
+
+//*****************************************************************************
+#define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17
+
+//*****************************************************************************
+#define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18
+
+//*****************************************************************************
+#define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19
+
+//*****************************************************************************
+#define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20
+
+//*****************************************************************************
+#define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21
+
+//*****************************************************************************
+#define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22
+
+//*****************************************************************************
+#define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23
+
+//*****************************************************************************
+#define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24
+
+//*****************************************************************************
+#define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25
+
+//*****************************************************************************
+#define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26
+
+//*****************************************************************************
+#define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1
+
+//*****************************************************************************
+#define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2
+
+//*****************************************************************************
+#define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3
+
+//*****************************************************************************
+#define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4
+
+//*****************************************************************************
+#define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5
+
+//*****************************************************************************
+#define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6
+
+//*****************************************************************************
+#define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7
+
+//*****************************************************************************
+#define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8
+
+//*****************************************************************************
+#define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9
+
+//*****************************************************************************
+#define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10
+
+//*****************************************************************************
+#define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11
+
+//*****************************************************************************
+#define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12
+
+//*****************************************************************************
+#define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13
+
+//*****************************************************************************
+#define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14
+
+//*****************************************************************************
+#define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15
+
+//*****************************************************************************
+#define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16
+
+//*****************************************************************************
+#define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17
+
+//*****************************************************************************
+#define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18
+
+//*****************************************************************************
+#define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19
+
+//*****************************************************************************
+#define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20
+
+//*****************************************************************************
+#define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21
+
+//*****************************************************************************
+#define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22
+
+//*****************************************************************************
+#define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23
+
+//*****************************************************************************
+#define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24
+
+//*****************************************************************************
+#define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25
+
+//*****************************************************************************
+#define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26
+
+//*****************************************************************************
+ // ITG
+//*****************************************************************************
+#define TM_CNT_LDW 0x110000 // Timer : Counter low
+
+//*****************************************************************************
+#define TM_CNT_UW 0x110004 // Timer : Counter high word
+
+//*****************************************************************************
+#define TM_LMT_LDW 0x110008 // Timer : Limit low
+
+//*****************************************************************************
+#define TM_LMT_UW 0x11000C // Timer : Limit high word
+
+//*****************************************************************************
+#define GP0_IO 0x110010 // GPIO output enables data I/O
+#define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable
+#define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status
+#define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control
+
+//*****************************************************************************
+#define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode
+#define FLD_GP_ISM_SNS 0x00000070
+#define FLD_GP_ISM_POL 0x00000007
+
+//*****************************************************************************
+#define SOFT_RESET 0x11001C // Output system reset reg
+#define FLD_PECOS_SOFT_RESET 0x00000001
+
+//*****************************************************************************
+#define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin
+#define MC416_OEN 0x110024 // Output enable of GPIO[18:3]
+#define MC416_CTL 0x110028
+
+//*****************************************************************************
+#define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select
+
+#define FLD_ALT_GPIO_OUT_SEL 0xF0000000
+// 0 Disabled <-- default
+// 1 GPIO[0]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+// 8 ATT_IF
+
+#define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000
+// 0 AUX_PLL_CLK<-- default
+// 1 GPIO[2]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_IR_TX_ALT_SEL 0x00F00000
+// 0 IR_TX <-- default
+// 1 GPIO[1]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_IR_RX_ALT_SEL 0x000F0000
+// 0 IR_RX <-- default
+// 1 GPIO[0]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_GPIO10_ALT_SEL 0x0000F000
+// 0 GPIO[10] <-- default
+// 1 GPIO[0]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_GPIO2_ALT_SEL 0x00000F00
+// 0 GPIO[2] <-- default
+// 1 GPIO[1]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_GPIO1_ALT_SEL 0x000000F0
+// 0 GPIO[1] <-- default
+// 1 GPIO[0]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define FLD_GPIO0_ALT_SEL 0x0000000F
+// 0 GPIO[0] <-- default
+// 1 GPIO[1]
+// 2 GPIO[10]
+// 3 VIP_656_DATA_VAL
+// 4 VIP_656_DATA[0]
+// 5 VIP_656_CLK
+// 6 VIP_656_DATA_EXT[1]
+// 7 VIP_656_DATA_EXT[0]
+
+#define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select
+
+#define FLD_GPIO10_ALT_IN_SEL 0x0000F000
+// 0 GPIO[10] <-- default
+// 1 IR_RX
+// 2 IR_TX
+// 3 AUX_PLL_CLK
+// 4 IF_ATT_SEL
+// 5 GPIO[0]
+// 6 GPIO[1]
+// 7 GPIO[2]
+
+#define FLD_GPIO2_ALT_IN_SEL 0x00000F00
+// 0 GPIO[2] <-- default
+// 1 IR_RX
+// 2 IR_TX
+// 3 AUX_PLL_CLK
+// 4 IF_ATT_SEL
+
+#define FLD_GPIO1_ALT_IN_SEL 0x000000F0
+// 0 GPIO[1] <-- default
+// 1 IR_RX
+// 2 IR_TX
+// 3 AUX_PLL_CLK
+// 4 IF_ATT_SEL
+
+#define FLD_GPIO0_ALT_IN_SEL 0x0000000F
+// 0 GPIO[0] <-- default
+// 1 IR_RX
+// 2 IR_TX
+// 3 AUX_PLL_CLK
+// 4 IF_ATT_SEL
+
+//*****************************************************************************
+#define TEST_BUS_CTL1 0x110040 // Test bus control register #1
+
+//*****************************************************************************
+#define TEST_BUS_CTL2 0x110044 // Test bus control register #2
+
+//*****************************************************************************
+#define CLK_DELAY 0x110048 // Clock delay
+#define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock
+
+//*****************************************************************************
+#define PAD_CTRL 0x110068 // Pad drive strength control
+
+//*****************************************************************************
+#define MBIST_CTRL 0x110050 // SRAM memory built-in self test control
+
+//*****************************************************************************
+#define MBIST_STAT 0x110054 // SRAM memory built-in self test status
+
+//*****************************************************************************
+// PLL registers
+//*****************************************************************************
+#define PLL_A_INT_FRAC 0x110088
+#define PLL_A_POST_STAT_BIST 0x11008C
+#define PLL_B_INT_FRAC 0x110090
+#define PLL_B_POST_STAT_BIST 0x110094
+#define PLL_C_INT_FRAC 0x110098
+#define PLL_C_POST_STAT_BIST 0x11009C
+#define PLL_D_INT_FRAC 0x1100A0
+#define PLL_D_POST_STAT_BIST 0x1100A4
+
+#define CLK_RST 0x11002C
+#define FLD_VID_I_CLK_NOE 0x00001000
+#define FLD_VID_J_CLK_NOE 0x00002000
+#define FLD_USE_ALT_PLL_REF 0x00004000
+
+#define VID_CH_MODE_SEL 0x110078
+#define VID_CH_CLK_SEL 0x11007C
+
+//*****************************************************************************
+#define VBI_A_DMA 0x130008 // VBI A DMA data port
+
+//*****************************************************************************
+#define VID_A_VIP_CTL 0x130080 // Video A VIP format control
+#define FLD_VIP_MODE 0x00000001
+
+//*****************************************************************************
+#define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format
+#define FLD_VID_A_GAMMA_DIS 0x00000008
+#define FLD_VID_A_FORMAT 0x00000007
+#define FLD_VID_A_GAMMA_FACTOR 0x00000010
+
+//*****************************************************************************
+#define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control
+#define FLD_VID_A_VIP_EXT 0x00000003
+
+//*****************************************************************************
+#define VID_B_DMA 0x130100 // Video B DMA data port
+
+//*****************************************************************************
+#define VBI_B_DMA 0x130108 // VBI B DMA data port
+
+//*****************************************************************************
+#define VID_B_SRC_SEL 0x130144 // Video B source select
+#define FLD_VID_B_SRC_SEL 0x00000000
+
+//*****************************************************************************
+#define VID_B_LNGTH 0x130150 // Video B line length
+#define FLD_VID_B_LN_LNGTH 0x00000FFF
+
+//*****************************************************************************
+#define VID_B_VIP_CTL 0x130180 // Video B VIP format control
+
+//*****************************************************************************
+#define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format
+#define FLD_VID_B_GAMMA_DIS 0x00000008
+#define FLD_VID_B_FORMAT 0x00000007
+#define FLD_VID_B_GAMMA_FACTOR 0x00000010
+
+//*****************************************************************************
+#define VID_C_DMA 0x130200 // Video C DMA data port
+
+//*****************************************************************************
+#define VID_C_LNGTH 0x130250 // Video C line length
+#define FLD_VID_C_LN_LNGTH 0x00000FFF
+
+//*****************************************************************************
+// Video Destination Channels
+//*****************************************************************************
+
+#define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter
+#define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter
+#define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter
+#define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter
+#define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter
+#define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter
+#define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter
+#define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter
+
+//*****************************************************************************
+
+#define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control
+#define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control
+#define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control
+#define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control
+#define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control
+#define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control
+#define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control
+#define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control
+
+//*****************************************************************************
+
+#define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control
+#define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control
+#define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control
+#define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control
+#define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control
+#define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control
+#define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control
+#define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control
+
+#define FLD_VID_RISC_EN 0x00000010
+#define FLD_VID_FIFO_EN 0x00000001
+
+//*****************************************************************************
+
+#define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control
+#define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control
+#define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control
+#define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control
+#define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control
+#define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control
+#define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control
+#define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control
+
+//*****************************************************************************
+
+#define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format
+#define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format
+#define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format
+#define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format
+#define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format
+#define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format
+#define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format
+#define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format
+
+//*****************************************************************************
+// Video Source Channels
+//*****************************************************************************
+
+#define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control
+#define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control
+#define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control
+#define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control
+#define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control
+#define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control
+#define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control
+#define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control
+
+//*****************************************************************************
+
+#define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter
+#define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter
+#define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter
+#define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter
+#define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter
+#define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter
+#define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter
+#define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter
+
+//*****************************************************************************
+
+#define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control
+#define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control
+#define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control
+#define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control
+#define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control
+#define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control
+#define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control
+#define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control
+
+#define FLD_APB_RISC_EN 0x00000010
+#define FLD_APB_FIFO_EN 0x00000001
+
+//*****************************************************************************
+
+#define VID_SRC_A_FMT_CTL 0x130810 // Video A format control
+#define VID_SRC_B_FMT_CTL 0x130910 // Video B format control
+#define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control
+#define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control
+#define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control
+#define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control
+#define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control
+#define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control
+
+//*****************************************************************************
+
+#define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1
+#define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1
+#define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1
+#define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1
+#define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1
+#define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1
+#define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1
+#define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1
+
+//*****************************************************************************
+
+#define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2
+#define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2
+#define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2
+#define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2
+#define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2
+#define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2
+#define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2
+#define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2
+
+//*****************************************************************************
+
+#define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size
+#define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size
+#define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size
+#define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size
+#define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size
+#define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size
+#define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size
+#define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size
+
+//*****************************************************************************
+// Audio I/F
+//*****************************************************************************
+#define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port
+#define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port
+
+#define AUD_A_GPCNT 0x140010 // Audio Int A gp counter
+#define FLD_AUD_A_GP_CNT 0x0000FFFF
+
+#define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control
+
+#define AUD_A_LNGTH 0x140018 // Audio Int A line length
+
+#define AUD_A_CFG 0x14001C // Audio Int A configuration
+
+//*****************************************************************************
+#define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port
+#define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port
+
+#define AUD_B_GPCNT 0x140110 // Audio Int B gp counter
+#define FLD_AUD_B_GP_CNT 0x0000FFFF
+
+#define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control
+
+#define AUD_B_LNGTH 0x140118 // Audio Int B line length
+
+#define AUD_B_CFG 0x14011C // Audio Int B configuration
+
+//*****************************************************************************
+#define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port
+#define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port
+
+#define AUD_C_GPCNT 0x140210 // Audio Int C gp counter
+#define FLD_AUD_C_GP_CNT 0x0000FFFF
+
+#define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control
+
+#define AUD_C_LNGTH 0x140218 // Audio Int C line length
+
+#define AUD_C_CFG 0x14021C // Audio Int C configuration
+
+//*****************************************************************************
+#define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port
+#define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port
+
+#define AUD_D_GPCNT 0x140310 // Audio Int D gp counter
+#define FLD_AUD_D_GP_CNT 0x0000FFFF
+
+#define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control
+
+#define AUD_D_LNGTH 0x140318 // Audio Int D line length
+
+#define AUD_D_CFG 0x14031C // Audio Int D configuration
+
+//*****************************************************************************
+#define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port
+
+#define AUD_E_GPCNT 0x140410 // Audio Int E gp counter
+#define FLD_AUD_E_GP_CNT 0x0000FFFF
+
+#define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control
+
+#define AUD_E_CFG 0x14041C // Audio Int E configuration
+
+//*****************************************************************************
+
+#define FLD_AUD_DST_LN_LNGTH 0x00000FFF
+
+#define FLD_AUD_DST_PK_MODE 0x00004000
+
+#define FLD_AUD_CLK_ENABLE 0x00000200
+
+#define FLD_AUD_MASTER_MODE 0x00000002
+
+#define FLD_AUD_SONY_MODE 0x00000001
+
+#define FLD_AUD_CLK_SELECT_PLL_D 0x00001800
+
+#define FLD_AUD_DST_ENABLE 0x00020000
+
+#define FLD_AUD_SRC_ENABLE 0x00010000
+
+//*****************************************************************************
+#define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control
+
+#define FLD_AUD_SRC_E_RISC_EN 0x00008000
+#define FLD_AUD_SRC_C_RISC_EN 0x00004000
+#define FLD_AUD_SRC_B_RISC_EN 0x00002000
+#define FLD_AUD_SRC_A_RISC_EN 0x00001000
+
+#define FLD_AUD_DST_D_RISC_EN 0x00000800
+#define FLD_AUD_DST_C_RISC_EN 0x00000400
+#define FLD_AUD_DST_B_RISC_EN 0x00000200
+#define FLD_AUD_DST_A_RISC_EN 0x00000100
+
+#define FLD_AUD_SRC_E_FIFO_EN 0x00000080
+#define FLD_AUD_SRC_C_FIFO_EN 0x00000040
+#define FLD_AUD_SRC_B_FIFO_EN 0x00000020
+#define FLD_AUD_SRC_A_FIFO_EN 0x00000010
+
+#define FLD_AUD_DST_D_FIFO_EN 0x00000008
+#define FLD_AUD_DST_C_FIFO_EN 0x00000004
+#define FLD_AUD_DST_B_FIFO_EN 0x00000002
+#define FLD_AUD_DST_A_FIFO_EN 0x00000001
+
+//*****************************************************************************
+//
+// Mobilygen Interface Registers
+//
+//*****************************************************************************
+// Mobilygen Interface A
+//*****************************************************************************
+#define MB_IF_A_DMA 0x150000 // MBIF A DMA data port
+#define MB_IF_A_GPCN 0x150008 // MBIF A GP counter
+#define MB_IF_A_GPCN_CTRL 0x15000C
+#define MB_IF_A_DMA_CTRL 0x150010
+#define MB_IF_A_LENGTH 0x150014
+#define MB_IF_A_HDMA_XFER_SZ 0x150018
+#define MB_IF_A_HCMD 0x15001C
+#define MB_IF_A_HCONFIG 0x150020
+#define MB_IF_A_DATA_STRUCT_0 0x150024
+#define MB_IF_A_DATA_STRUCT_1 0x150028
+#define MB_IF_A_DATA_STRUCT_2 0x15002C
+#define MB_IF_A_DATA_STRUCT_3 0x150030
+#define MB_IF_A_DATA_STRUCT_4 0x150034
+#define MB_IF_A_DATA_STRUCT_5 0x150038
+#define MB_IF_A_DATA_STRUCT_6 0x15003C
+#define MB_IF_A_DATA_STRUCT_7 0x150040
+#define MB_IF_A_DATA_STRUCT_8 0x150044
+#define MB_IF_A_DATA_STRUCT_9 0x150048
+#define MB_IF_A_DATA_STRUCT_A 0x15004C
+#define MB_IF_A_DATA_STRUCT_B 0x150050
+#define MB_IF_A_DATA_STRUCT_C 0x150054
+#define MB_IF_A_DATA_STRUCT_D 0x150058
+#define MB_IF_A_DATA_STRUCT_E 0x15005C
+#define MB_IF_A_DATA_STRUCT_F 0x150060
+//*****************************************************************************
+// Mobilygen Interface B
+//*****************************************************************************
+#define MB_IF_B_DMA 0x160000 // MBIF A DMA data port
+#define MB_IF_B_GPCN 0x160008 // MBIF A GP counter
+#define MB_IF_B_GPCN_CTRL 0x16000C
+#define MB_IF_B_DMA_CTRL 0x160010
+#define MB_IF_B_LENGTH 0x160014
+#define MB_IF_B_HDMA_XFER_SZ 0x160018
+#define MB_IF_B_HCMD 0x16001C
+#define MB_IF_B_HCONFIG 0x160020
+#define MB_IF_B_DATA_STRUCT_0 0x160024
+#define MB_IF_B_DATA_STRUCT_1 0x160028
+#define MB_IF_B_DATA_STRUCT_2 0x16002C
+#define MB_IF_B_DATA_STRUCT_3 0x160030
+#define MB_IF_B_DATA_STRUCT_4 0x160034
+#define MB_IF_B_DATA_STRUCT_5 0x160038
+#define MB_IF_B_DATA_STRUCT_6 0x16003C
+#define MB_IF_B_DATA_STRUCT_7 0x160040
+#define MB_IF_B_DATA_STRUCT_8 0x160044
+#define MB_IF_B_DATA_STRUCT_9 0x160048
+#define MB_IF_B_DATA_STRUCT_A 0x16004C
+#define MB_IF_B_DATA_STRUCT_B 0x160050
+#define MB_IF_B_DATA_STRUCT_C 0x160054
+#define MB_IF_B_DATA_STRUCT_D 0x160058
+#define MB_IF_B_DATA_STRUCT_E 0x16005C
+#define MB_IF_B_DATA_STRUCT_F 0x160060
+
+// MB_DMA_CTRL
+#define FLD_MB_IF_RISC_EN 0x00000010
+#define FLD_MB_IF_FIFO_EN 0x00000001
+
+// MB_LENGTH
+#define FLD_MB_IF_LN_LNGTH 0x00000FFF
+
+// MB_HCMD register
+#define FLD_MB_HCMD_H_GO 0x80000000
+#define FLD_MB_HCMD_H_BUSY 0x40000000
+#define FLD_MB_HCMD_H_DMA_HOLD 0x10000000
+#define FLD_MB_HCMD_H_DMA_BUSY 0x08000000
+#define FLD_MB_HCMD_H_DMA_TYPE 0x04000000
+#define FLD_MB_HCMD_H_DMA_XACT 0x02000000
+#define FLD_MB_HCMD_H_RW_N 0x01000000
+#define FLD_MB_HCMD_H_ADDR 0x00FF0000
+#define FLD_MB_HCMD_H_DATA 0x0000FFFF
+
+//*****************************************************************************
+// I2C #1
+//*****************************************************************************
+#define I2C1_ADDR 0x180000 // I2C #1 address
+#define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address
+ // RO [24] reserved
+//*****************************************************************************
+#define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address
+
+//*****************************************************************************
+#define I2C1_WDATA 0x180004 // I2C #1 write data
+#define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0]
+
+//*****************************************************************************
+#define I2C1_CTRL 0x180008 // I2C #1 control
+#define FLD_I2C_PERIOD 0xFF000000 // RW [31:24]
+#define FLD_I2C_SCL_IN 0x00200000 // RW [21]
+#define FLD_I2C_SDA_IN 0x00100000 // RW [20]
+ // RO [19:18] reserved
+#define FLD_I2C_SCL_OUT 0x00020000 // RW [17]
+#define FLD_I2C_SDA_OUT 0x00010000 // RW [16]
+ // RO [15] reserved
+#define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12]
+#define FLD_I2C_SADDR_INC 0x00000800 // RW [11]
+ // RO [10:9] reserved
+#define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8]
+ // RO [7:6] reserved
+#define FLD_I2C_SOFT 0x00000020 // RW [5]
+#define FLD_I2C_NOSTOP 0x00000010 // RW [4]
+#define FLD_I2C_EXTEND 0x00000008 // RW [3]
+#define FLD_I2C_SYNC 0x00000004 // RW [2]
+#define FLD_I2C_READ_SA 0x00000002 // RW [1]
+#define FLD_I2C_READ_WRN 0x00000001 // RW [0]
+
+//*****************************************************************************
+#define I2C1_RDATA 0x18000C // I2C #1 read data
+#define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0]
+
+//*****************************************************************************
+#define I2C1_STAT 0x180010 // I2C #1 status
+#define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1]
+#define FLD_I2C_RACK 0x00000001 // RO [0]
+
+//*****************************************************************************
+// I2C #2
+//*****************************************************************************
+#define I2C2_ADDR 0x190000 // I2C #2 address
+
+//*****************************************************************************
+#define I2C2_WDATA 0x190004 // I2C #2 write data
+
+//*****************************************************************************
+#define I2C2_CTRL 0x190008 // I2C #2 control
+
+//*****************************************************************************
+#define I2C2_RDATA 0x19000C // I2C #2 read data
+
+//*****************************************************************************
+#define I2C2_STAT 0x190010 // I2C #2 status
+
+//*****************************************************************************
+// I2C #3
+//*****************************************************************************
+#define I2C3_ADDR 0x1A0000 // I2C #3 address
+
+//*****************************************************************************
+#define I2C3_WDATA 0x1A0004 // I2C #3 write data
+
+//*****************************************************************************
+#define I2C3_CTRL 0x1A0008 // I2C #3 control
+
+//*****************************************************************************
+#define I2C3_RDATA 0x1A000C // I2C #3 read data
+
+//*****************************************************************************
+#define I2C3_STAT 0x1A0010 // I2C #3 status
+
+//*****************************************************************************
+// UART
+//*****************************************************************************
+#define UART_CTL 0x1B0000 // UART Control Register
+#define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0
+#define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0
+#define FLD_RX_EN (1 << 1) // RW field - default 0
+#define FLD_TX_EN (1 << 0) // RW field - default 0
+
+//*****************************************************************************
+#define UART_BRD 0x1B0004 // UART Baud Rate Divisor
+#define FLD_BRD 0x0000FFFF // RW field - default 0x197
+
+//*****************************************************************************
+#define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer
+#define FLD_DB 0xFFFFFFFF // RW field - default 0
+
+//*****************************************************************************
+#define UART_ISR 0x1B000C // UART Interrupt Status
+#define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0
+#define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0
+#define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0
+#define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0
+#define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0
+#define FLD_FRM_ERR (1 << 2) // RW field - default 0
+#define FLD_RXD_RDY (1 << 1) // RW field - default 0
+#define FLD_TXD_EMPTY (1 << 0) // RW field - default 0
+
+//*****************************************************************************
+#define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count
+#define FLD_TXD_CNT (0x1F << 8) // RW field - default 0
+#define FLD_RXD_CNT (0x1F << 0) // RW field - default 0
+
+//*****************************************************************************
+// Motion Detection
+#define MD_CH0_GRID_BLOCK_YCNT 0x170014
+#define MD_CH1_GRID_BLOCK_YCNT 0x170094
+#define MD_CH2_GRID_BLOCK_YCNT 0x170114
+#define MD_CH3_GRID_BLOCK_YCNT 0x170194
+#define MD_CH4_GRID_BLOCK_YCNT 0x170214
+#define MD_CH5_GRID_BLOCK_YCNT 0x170294
+#define MD_CH6_GRID_BLOCK_YCNT 0x170314
+#define MD_CH7_GRID_BLOCK_YCNT 0x170394
+
+#define PIXEL_FRMT_422 4
+#define PIXEL_FRMT_411 5
+#define PIXEL_FRMT_Y8 6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif //Athena_REGISTERS
diff --git a/drivers/staging/cx25821/cx25821-sram.h b/drivers/staging/cx25821/cx25821-sram.h
new file mode 100644
index 000000000000..bd677ee22996
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-sram.h
@@ -0,0 +1,261 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ * 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 __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+//#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM
+#define VID_CMDS_SIZE 80 // Video CMDS size in bytes
+#define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes
+#define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes
+
+//#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers
+#define VID_IQ_SIZE 64 // VID instruction queue size in bytes
+#define MBIF_IQ_SIZE 64
+#define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes
+
+#define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes
+#define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes
+#define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes
+
+//#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM
+//#define RX_SRAM_END_SIZE = 0; // End of RX SRAM
+
+//#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM
+//#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora
+
+#define VID_CLUSTER_SIZE 1440 // VID cluster data line
+#define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line
+#define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line
+
+//#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM
+//#define TX_SRAM_END_SIZE = 0; // End of TX SRAM
+
+// Receive SRAM
+#define RX_SRAM_START 0x10000
+#define VID_A_DOWN_CMDS 0x10000
+#define VID_B_DOWN_CMDS 0x10050
+#define VID_C_DOWN_CMDS 0x100A0
+#define VID_D_DOWN_CMDS 0x100F0
+#define VID_E_DOWN_CMDS 0x10140
+#define VID_F_DOWN_CMDS 0x10190
+#define VID_G_DOWN_CMDS 0x101E0
+#define VID_H_DOWN_CMDS 0x10230
+#define VID_A_UP_CMDS 0x10280
+#define VID_B_UP_CMDS 0x102D0
+#define VID_C_UP_CMDS 0x10320
+#define VID_D_UP_CMDS 0x10370
+#define VID_E_UP_CMDS 0x103C0
+#define VID_F_UP_CMDS 0x10410
+#define VID_I_UP_CMDS 0x10460
+#define VID_J_UP_CMDS 0x104B0
+#define AUD_A_DOWN_CMDS 0x10500
+#define AUD_B_DOWN_CMDS 0x10550
+#define AUD_C_DOWN_CMDS 0x105A0
+#define AUD_D_DOWN_CMDS 0x105F0
+#define AUD_A_UP_CMDS 0x10640
+#define AUD_B_UP_CMDS 0x10690
+#define AUD_C_UP_CMDS 0x106E0
+#define AUD_E_UP_CMDS 0x10730
+#define MBIF_A_DOWN_CMDS 0x10780
+#define MBIF_B_DOWN_CMDS 0x107D0
+#define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40
+
+//#define RX_SRAM_POOL_START = 0x105B0;
+
+#define VID_A_IQ 0x11000
+#define VID_B_IQ 0x11040
+#define VID_C_IQ 0x11080
+#define VID_D_IQ 0x110C0
+#define VID_E_IQ 0x11100
+#define VID_F_IQ 0x11140
+#define VID_G_IQ 0x11180
+#define VID_H_IQ 0x111C0
+#define VID_I_IQ 0x11200
+#define VID_J_IQ 0x11240
+#define AUD_A_IQ 0x11280
+#define AUD_B_IQ 0x112C0
+#define AUD_C_IQ 0x11300
+#define AUD_D_IQ 0x11340
+#define AUD_E_IQ 0x11380
+#define MBIF_A_IQ 0x11000
+#define MBIF_B_IQ 0x110C0
+
+#define VID_A_CDT 0x10C00
+#define VID_B_CDT 0x10C40
+#define VID_C_CDT 0x10C80
+#define VID_D_CDT 0x10CC0
+#define VID_E_CDT 0x10D00
+#define VID_F_CDT 0x10D40
+#define VID_G_CDT 0x10D80
+#define VID_H_CDT 0x10DC0
+#define VID_I_CDT 0x10E00
+#define VID_J_CDT 0x10E40
+#define AUD_A_CDT 0x10E80
+#define AUD_B_CDT 0x10EB0
+#define AUD_C_CDT 0x10EE0
+#define AUD_D_CDT 0x10F10
+#define AUD_E_CDT 0x10F40
+#define MBIF_A_CDT 0x10C00
+#define MBIF_B_CDT 0x10CC0
+
+// Cluster Buffer for RX
+#define VID_A_UP_CLUSTER_1 0x11400
+#define VID_A_UP_CLUSTER_2 0x119A0
+#define VID_A_UP_CLUSTER_3 0x11F40
+#define VID_A_UP_CLUSTER_4 0x124E0
+
+#define VID_B_UP_CLUSTER_1 0x12A80
+#define VID_B_UP_CLUSTER_2 0x13020
+#define VID_B_UP_CLUSTER_3 0x135C0
+#define VID_B_UP_CLUSTER_4 0x13B60
+
+#define VID_C_UP_CLUSTER_1 0x14100
+#define VID_C_UP_CLUSTER_2 0x146A0
+#define VID_C_UP_CLUSTER_3 0x14C40
+#define VID_C_UP_CLUSTER_4 0x151E0
+
+#define VID_D_UP_CLUSTER_1 0x15780
+#define VID_D_UP_CLUSTER_2 0x15D20
+#define VID_D_UP_CLUSTER_3 0x162C0
+#define VID_D_UP_CLUSTER_4 0x16860
+
+#define VID_E_UP_CLUSTER_1 0x16E00
+#define VID_E_UP_CLUSTER_2 0x173A0
+#define VID_E_UP_CLUSTER_3 0x17940
+#define VID_E_UP_CLUSTER_4 0x17EE0
+
+#define VID_F_UP_CLUSTER_1 0x18480
+#define VID_F_UP_CLUSTER_2 0x18A20
+#define VID_F_UP_CLUSTER_3 0x18FC0
+#define VID_F_UP_CLUSTER_4 0x19560
+
+#define VID_I_UP_CLUSTER_1 0x19B00
+#define VID_I_UP_CLUSTER_2 0x1A0A0
+#define VID_I_UP_CLUSTER_3 0x1A640
+#define VID_I_UP_CLUSTER_4 0x1ABE0
+
+#define VID_J_UP_CLUSTER_1 0x1B180
+#define VID_J_UP_CLUSTER_2 0x1B720
+#define VID_J_UP_CLUSTER_3 0x1BCC0
+#define VID_J_UP_CLUSTER_4 0x1C260
+
+#define AUD_A_UP_CLUSTER_1 0x1C800
+#define AUD_A_UP_CLUSTER_2 0x1C880
+#define AUD_A_UP_CLUSTER_3 0x1C900
+
+#define AUD_B_UP_CLUSTER_1 0x1C980
+#define AUD_B_UP_CLUSTER_2 0x1CA00
+#define AUD_B_UP_CLUSTER_3 0x1CA80
+
+#define AUD_C_UP_CLUSTER_1 0x1CB00
+#define AUD_C_UP_CLUSTER_2 0x1CB80
+#define AUD_C_UP_CLUSTER_3 0x1CC00
+
+#define AUD_E_UP_CLUSTER_1 0x1CC80
+#define AUD_E_UP_CLUSTER_2 0x1CD00
+#define AUD_E_UP_CLUSTER_3 0x1CD80
+
+#define RX_SRAM_POOL_FREE 0x1CE00
+#define RX_SRAM_END 0x1D000
+
+// Free Receive SRAM 144 Bytes
+
+// Transmit SRAM
+#define TX_SRAM_POOL_START 0x00000
+
+#define VID_A_DOWN_CLUSTER_1 0x00040
+#define VID_A_DOWN_CLUSTER_2 0x005E0
+#define VID_A_DOWN_CLUSTER_3 0x00B80
+#define VID_A_DOWN_CLUSTER_4 0x01120
+
+#define VID_B_DOWN_CLUSTER_1 0x016C0
+#define VID_B_DOWN_CLUSTER_2 0x01C60
+#define VID_B_DOWN_CLUSTER_3 0x02200
+#define VID_B_DOWN_CLUSTER_4 0x027A0
+
+#define VID_C_DOWN_CLUSTER_1 0x02D40
+#define VID_C_DOWN_CLUSTER_2 0x032E0
+#define VID_C_DOWN_CLUSTER_3 0x03880
+#define VID_C_DOWN_CLUSTER_4 0x03E20
+
+#define VID_D_DOWN_CLUSTER_1 0x043C0
+#define VID_D_DOWN_CLUSTER_2 0x04960
+#define VID_D_DOWN_CLUSTER_3 0x04F00
+#define VID_D_DOWN_CLUSTER_4 0x054A0
+
+#define VID_E_DOWN_CLUSTER_1 0x05a40
+#define VID_E_DOWN_CLUSTER_2 0x05FE0
+#define VID_E_DOWN_CLUSTER_3 0x06580
+#define VID_E_DOWN_CLUSTER_4 0x06B20
+
+#define VID_F_DOWN_CLUSTER_1 0x070C0
+#define VID_F_DOWN_CLUSTER_2 0x07660
+#define VID_F_DOWN_CLUSTER_3 0x07C00
+#define VID_F_DOWN_CLUSTER_4 0x081A0
+
+#define VID_G_DOWN_CLUSTER_1 0x08740
+#define VID_G_DOWN_CLUSTER_2 0x08CE0
+#define VID_G_DOWN_CLUSTER_3 0x09280
+#define VID_G_DOWN_CLUSTER_4 0x09820
+
+#define VID_H_DOWN_CLUSTER_1 0x09DC0
+#define VID_H_DOWN_CLUSTER_2 0x0A360
+#define VID_H_DOWN_CLUSTER_3 0x0A900
+#define VID_H_DOWN_CLUSTER_4 0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1 0x0B500
+#define AUD_A_DOWN_CLUSTER_2 0x0B580
+#define AUD_A_DOWN_CLUSTER_3 0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1 0x0B680
+#define AUD_B_DOWN_CLUSTER_2 0x0B700
+#define AUD_B_DOWN_CLUSTER_3 0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1 0x0B800
+#define AUD_C_DOWN_CLUSTER_2 0x0B880
+#define AUD_C_DOWN_CLUSTER_3 0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1 0x0B980
+#define AUD_D_DOWN_CLUSTER_2 0x0BA00
+#define AUD_D_DOWN_CLUSTER_3 0x0BA80
+
+#define TX_SRAM_POOL_FREE 0x0BB00
+#define TX_SRAM_END 0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
new file mode 100644
index 000000000000..c8905e0ac509
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
@@ -0,0 +1,835 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream-ch2.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk =
+ FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR;
+
+static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
+ __le32 * rp, unsigned int offset,
+ unsigned int bpl, u32 sync_line,
+ unsigned int lines,
+ int fifo_enable, int field_type)
+{
+ unsigned int line, i;
+ int dist_betwn_starts = bpl * 2;
+
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+ if (USE_RISC_NOOP_VIDEO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) = cpu_to_le32(RISC_NOOP);
+ }
+ }
+
+ /* scan lines */
+ for (line = 0; line < lines; line++) {
+ *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+
+ if ((lines <= NTSC_FIELD_HEIGHT)
+ || (line < (NTSC_FIELD_HEIGHT - 1))
+ || !(dev->_isNTSC_ch2)) {
+ offset += dist_betwn_starts;
+ }
+ }
+
+ return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
+ __le32 * rp,
+ dma_addr_t databuf_phys_addr,
+ unsigned int offset,
+ u32 sync_line, unsigned int bpl,
+ unsigned int lines,
+ int fifo_enable, int field_type)
+{
+ unsigned int line, i;
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[dev->_channel2_upstream_select];
+ int dist_betwn_starts = bpl * 2;
+
+ /* sync instruction */
+ if (sync_line != NO_SYNC_LINE) {
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+ }
+
+ if (USE_RISC_NOOP_VIDEO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) = cpu_to_le32(RISC_NOOP);
+ }
+ }
+
+ /* scan lines */
+ for (line = 0; line < lines; line++) {
+ *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+
+ if ((lines <= NTSC_FIELD_HEIGHT)
+ || (line < (NTSC_FIELD_HEIGHT - 1))
+ || !(dev->_isNTSC_ch2)) {
+ offset += dist_betwn_starts;
+ }
+
+ // check if we need to enable the FIFO after the first 4 lines
+ // For the upstream video channel, the risc engine will enable the FIFO.
+ if (fifo_enable && line == 3) {
+ *(rp++) = RISC_WRITECR;
+ *(rp++) = sram_ch->dma_ctl;
+ *(rp++) = FLD_VID_FIFO_EN;
+ *(rp++) = 0x00000001;
+ }
+ }
+
+ return rp;
+}
+
+int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+ struct pci_dev *pci,
+ unsigned int top_offset, unsigned int bpl,
+ unsigned int lines)
+{
+ __le32 *rp;
+ int fifo_enable = 0;
+ int singlefield_lines = lines >> 1; //get line count for single field
+ int odd_num_lines = singlefield_lines;
+ int frame = 0;
+ int frame_size = 0;
+ int databuf_offset = 0;
+ int risc_program_size = 0;
+ int risc_flag = RISC_CNT_RESET;
+ unsigned int bottom_offset = bpl;
+ dma_addr_t risc_phys_jump_addr;
+
+ if (dev->_isNTSC_ch2) {
+ odd_num_lines = singlefield_lines + 1;
+ risc_program_size = FRAME1_VID_PROG_SIZE;
+ frame_size =
+ (bpl ==
+ Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+ FRAME_SIZE_NTSC_Y422;
+ } else {
+ risc_program_size = PAL_VID_PROG_SIZE;
+ frame_size =
+ (bpl ==
+ Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ }
+
+ /* Virtual address of Risc buffer program */
+ rp = dev->_dma_virt_addr_ch2;
+
+ for (frame = 0; frame < NUM_FRAMES; frame++) {
+ databuf_offset = frame_size * frame;
+
+ if (UNSET != top_offset) {
+ fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+ rp = cx25821_risc_field_upstream_ch2(dev, rp,
+ dev->
+ _data_buf_phys_addr_ch2
+ + databuf_offset,
+ top_offset, 0, bpl,
+ odd_num_lines,
+ fifo_enable,
+ ODD_FIELD);
+ }
+
+ fifo_enable = FIFO_DISABLE;
+
+ //Even field
+ rp = cx25821_risc_field_upstream_ch2(dev, rp,
+ dev->
+ _data_buf_phys_addr_ch2 +
+ databuf_offset,
+ bottom_offset, 0x200, bpl,
+ singlefield_lines,
+ fifo_enable, EVEN_FIELD);
+
+ if (frame == 0) {
+ risc_flag = RISC_CNT_RESET;
+ risc_phys_jump_addr =
+ dev->_dma_phys_start_addr_ch2 + risc_program_size;
+ } else {
+ risc_flag = RISC_CNT_INC;
+ risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
+ }
+
+ // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ
+ *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+ }
+
+ return 0;
+}
+
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+{
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J];
+ u32 tmp = 0;
+
+ if (!dev->_is_running_ch2) {
+ printk
+ ("cx25821: No video file is currently running so return!\n");
+ return;
+ }
+ //Disable RISC interrupts
+ tmp = cx_read(sram_ch->int_msk);
+ cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+ //Turn OFF risc and fifo
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+ //Clear data buffer memory
+ if (dev->_data_buf_virt_addr_ch2)
+ memset(dev->_data_buf_virt_addr_ch2, 0,
+ dev->_data_buf_size_ch2);
+
+ dev->_is_running_ch2 = 0;
+ dev->_is_first_frame_ch2 = 0;
+ dev->_frame_count_ch2 = 0;
+ dev->_file_status_ch2 = END_OF_FILE;
+
+ if (dev->_irq_queues_ch2) {
+ kfree(dev->_irq_queues_ch2);
+ dev->_irq_queues_ch2 = NULL;
+ }
+
+ if (dev->_filename_ch2 != NULL)
+ kfree(dev->_filename_ch2);
+
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
+{
+ if (dev->_is_running_ch2) {
+ cx25821_stop_upstream_video_ch2(dev);
+ }
+
+ if (dev->_dma_virt_addr_ch2) {
+ pci_free_consistent(dev->pci, dev->_risc_size_ch2,
+ dev->_dma_virt_addr_ch2,
+ dev->_dma_phys_addr_ch2);
+ dev->_dma_virt_addr_ch2 = NULL;
+ }
+
+ if (dev->_data_buf_virt_addr_ch2) {
+ pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
+ dev->_data_buf_virt_addr_ch2,
+ dev->_data_buf_phys_addr_ch2);
+ dev->_data_buf_virt_addr_ch2 = NULL;
+ }
+}
+
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int frame_index_temp = dev->_frame_index_ch2;
+ int i = 0;
+ int line_size =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int frame_size = 0;
+ int frame_offset = 0;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t file_offset;
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ if (dev->_file_status_ch2 == END_OF_FILE)
+ return 0;
+
+ if (dev->_isNTSC_ch2) {
+ frame_size =
+ (line_size ==
+ Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+ FRAME_SIZE_NTSC_Y422;
+ } else {
+ frame_size =
+ (line_size ==
+ Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ }
+
+ frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+ file_offset = dev->_frame_count_ch2 * frame_size;
+
+ myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_filename_ch2, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk("%s: File has no READ operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (i = 0; i < dev->_lines_count_ch2; i++) {
+ pos = file_offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0 && vfs_read_retval == line_size
+ && dev->_data_buf_virt_addr_ch2 != NULL) {
+ memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
+ frame_offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ file_offset += vfs_read_retval;
+ frame_offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Video file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0)
+ dev->_frame_count_ch2++;
+
+ dev->_file_status_ch2 =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+static void cx25821_vidups_handler_ch2(struct work_struct *work)
+{
+ struct cx25821_dev *dev =
+ container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
+
+ if (!dev) {
+ printk("ERROR %s(): since container_of(work_struct) FAILED! \n",
+ __func__);
+ return;
+ }
+
+ cx25821_get_frame_ch2(dev,
+ &dev->sram_channels[dev->
+ _channel2_upstream_select]);
+}
+
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int i = 0, j = 0;
+ int line_size =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t pos;
+ loff_t offset = (unsigned long)0;
+ mm_segment_t old_fs;
+
+ myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_filename_ch2, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk
+ ("%s: File has no READ operations registered! Returning.",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (j = 0; j < NUM_FRAMES; j++) {
+ for (i = 0; i < dev->_lines_count_ch2; i++) {
+ pos = offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0
+ && vfs_read_retval == line_size
+ && dev->_data_buf_virt_addr_ch2 != NULL) {
+ memcpy((void *)(dev->
+ _data_buf_virt_addr_ch2
+ + offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Video file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0)
+ dev->_frame_count_ch2++;
+
+ if (vfs_read_retval < line_size) {
+ break;
+ }
+ }
+
+ dev->_file_status_ch2 =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ myfile->f_pos = 0;
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch,
+ int bpl)
+{
+ int ret = 0;
+ dma_addr_t dma_addr;
+ dma_addr_t data_dma_addr;
+
+ if (dev->_dma_virt_addr_ch2 != NULL) {
+ pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+ dev->_dma_virt_addr_ch2,
+ dev->_dma_phys_addr_ch2);
+ }
+
+ dev->_dma_virt_addr_ch2 =
+ pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+ &dma_addr);
+ dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
+ dev->_dma_phys_start_addr_ch2 = dma_addr;
+ dev->_dma_phys_addr_ch2 = dma_addr;
+ dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
+
+ if (!dev->_dma_virt_addr_ch2) {
+ printk
+ ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n");
+ return -ENOMEM;
+ }
+
+ //Iniitize at this address until n bytes to 0
+ memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
+
+ if (dev->_data_buf_virt_addr_ch2 != NULL) {
+ pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+ dev->_data_buf_virt_addr_ch2,
+ dev->_data_buf_phys_addr_ch2);
+ }
+ //For Video Data buffer allocation
+ dev->_data_buf_virt_addr_ch2 =
+ pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+ &data_dma_addr);
+ dev->_data_buf_phys_addr_ch2 = data_dma_addr;
+ dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
+
+ if (!dev->_data_buf_virt_addr_ch2) {
+ printk
+ ("cx25821: FAILED to allocate memory for data buffer! Returning.\n");
+ return -ENOMEM;
+ }
+
+ //Initialize at this address until n bytes to 0
+ memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
+
+ ret = cx25821_openfile_ch2(dev, sram_ch);
+ if (ret < 0)
+ return ret;
+
+ //Creating RISC programs
+ ret =
+ cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
+ dev->_lines_count_ch2);
+ if (ret < 0) {
+ printk(KERN_INFO
+ "cx25821: Failed creating Video Upstream Risc programs! \n");
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ return ret;
+}
+
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
+ u32 status)
+{
+ u32 int_msk_tmp;
+ struct sram_channel *channel = &dev->sram_channels[chan_num];
+ int singlefield_lines = NTSC_FIELD_HEIGHT;
+ int line_size_in_bytes = Y422_LINE_SZ;
+ int odd_risc_prog_size = 0;
+ dma_addr_t risc_phys_jump_addr;
+ __le32 *rp;
+
+ if (status & FLD_VID_SRC_RISC1) {
+ // We should only process one program per call
+ u32 prog_cnt = cx_read(channel->gpcnt);
+
+ //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers
+ int_msk_tmp = cx_read(channel->int_msk);
+ cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+ cx_write(channel->int_stat, _intr_msk);
+
+ spin_lock(&dev->slock);
+
+ dev->_frame_index_ch2 = prog_cnt;
+
+ queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
+
+ if (dev->_is_first_frame_ch2) {
+ dev->_is_first_frame_ch2 = 0;
+
+ if (dev->_isNTSC_ch2) {
+ singlefield_lines += 1;
+ odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+ } else {
+ singlefield_lines = PAL_FIELD_HEIGHT;
+ odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+ }
+
+ if (dev->_dma_virt_start_addr_ch2 != NULL) {
+ line_size_in_bytes =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ :
+ Y422_LINE_SZ;
+ risc_phys_jump_addr =
+ dev->_dma_phys_start_addr_ch2 +
+ odd_risc_prog_size;
+
+ rp = cx25821_update_riscprogram_ch2(dev,
+ dev->
+ _dma_virt_start_addr_ch2,
+ TOP_OFFSET,
+ line_size_in_bytes,
+ 0x0,
+ singlefield_lines,
+ FIFO_DISABLE,
+ ODD_FIELD);
+
+ // Jump to Even Risc program of 1st Frame
+ *(rp++) = cpu_to_le32(RISC_JUMP);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+ }
+ }
+
+ spin_unlock(&dev->slock);
+ }
+
+ if (dev->_file_status_ch2 == END_OF_FILE) {
+ printk("cx25821: EOF Channel 2 Framecount = %d\n",
+ dev->_frame_count_ch2);
+ return -1;
+ }
+ //ElSE, set the interrupt mask register, re-enable irq.
+ int_msk_tmp = cx_read(channel->int_msk);
+ cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+ return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
+{
+ struct cx25821_dev *dev = dev_id;
+ u32 msk_stat, vid_status;
+ int handled = 0;
+ int channel_num = 0;
+ struct sram_channel *sram_ch;
+
+ if (!dev)
+ return -1;
+
+ channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
+
+ sram_ch = &dev->sram_channels[channel_num];
+
+ msk_stat = cx_read(sram_ch->int_mstat);
+ vid_status = cx_read(sram_ch->int_stat);
+
+ // Only deal with our interrupt
+ if (vid_status) {
+ handled =
+ cx25821_video_upstream_irq_ch2(dev, channel_num,
+ vid_status);
+ }
+
+ if (handled < 0) {
+ cx25821_stop_upstream_video_ch2(dev);
+ } else {
+ handled += handled;
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
+ struct sram_channel *ch, int pix_format)
+{
+ int width = WIDTH_D1;
+ int height = dev->_lines_count_ch2;
+ int num_lines, odd_num_lines;
+ u32 value;
+ int vip_mode = PIXEL_ENGINE_VIP1;
+
+ value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+ value &= 0xFFFFFFEF;
+ value |= dev->_isNTSC_ch2 ? 0 : 0x10;
+ cx_write(ch->vid_fmt_ctl, value);
+
+ // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format
+ cx_write(ch->vid_active_ctl1, width);
+
+ num_lines = (height / 2) & 0x3FF;
+ odd_num_lines = num_lines;
+
+ if (dev->_isNTSC_ch2) {
+ odd_num_lines += 1;
+ }
+
+ value = (num_lines << 16) | odd_num_lines;
+
+ // set number of active lines in field 0 (top) and field 1 (bottom)
+ cx_write(ch->vid_active_ctl2, value);
+
+ cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ u32 tmp = 0;
+ int err = 0;
+
+ // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+ // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds.
+ cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
+ cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+ /* reset counter */
+ cx_write(sram_ch->gpcnt_ctl, 3);
+
+ // Clear our bits from the interrupt status register.
+ cx_write(sram_ch->int_stat, _intr_msk);
+
+ //Set the interrupt mask register, enable irq.
+ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+ tmp = cx_read(sram_ch->int_msk);
+ cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+ err =
+ request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+ IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
+ dev->pci->irq);
+ goto fail_irq;
+ }
+ // Start the DMA engine
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+ dev->_is_running_ch2 = 1;
+ dev->_is_first_frame_ch2 = 1;
+
+ return 0;
+
+ fail_irq:
+ cx25821_dev_unregister(dev);
+ return err;
+}
+
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
+ int pixel_format)
+{
+ struct sram_channel *sram_ch;
+ u32 tmp;
+ int retval = 0;
+ int err = 0;
+ int data_frame_size = 0;
+ int risc_buffer_size = 0;
+ int str_length = 0;
+
+ if (dev->_is_running_ch2) {
+ printk("Video Channel is still running so return!\n");
+ return 0;
+ }
+
+ dev->_channel2_upstream_select = channel_select;
+ sram_ch = &dev->sram_channels[channel_select];
+
+ INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
+ dev->_irq_queues_ch2 =
+ create_singlethread_workqueue("cx25821_workqueue2");
+
+ if (!dev->_irq_queues_ch2) {
+ printk
+ ("cx25821: create_singlethread_workqueue() for Video FAILED!\n");
+ return -ENOMEM;
+ }
+ // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+ dev->_is_running_ch2 = 0;
+ dev->_frame_count_ch2 = 0;
+ dev->_file_status_ch2 = RESET_STATUS;
+ dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
+ dev->_pixel_format_ch2 = pixel_format;
+ dev->_line_size_ch2 =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+ data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+ risc_buffer_size =
+ dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+ if (dev->input_filename_ch2) {
+ str_length = strlen(dev->input_filename_ch2);
+ dev->_filename_ch2 =
+ (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_filename_ch2)
+ goto error;
+
+ memcpy(dev->_filename_ch2, dev->input_filename_ch2,
+ str_length + 1);
+ } else {
+ str_length = strlen(dev->_defaultname_ch2);
+ dev->_filename_ch2 =
+ (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_filename_ch2)
+ goto error;
+
+ memcpy(dev->_filename_ch2, dev->_defaultname_ch2,
+ str_length + 1);
+ }
+
+ //Default if filename is empty string
+ if (strcmp(dev->input_filename_ch2, "") == 0) {
+ if (dev->_isNTSC_ch2) {
+ dev->_filename_ch2 =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+ "/root/vidtest.yuv";
+ } else {
+ dev->_filename_ch2 =
+ (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+ "/root/pal422.yuv";
+ }
+ }
+
+ retval =
+ cx25821_sram_channel_setup_upstream(dev, sram_ch,
+ dev->_line_size_ch2, 0);
+
+ /* setup fifo + format */
+ cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
+
+ dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
+ dev->upstream_databuf_size_ch2 = data_frame_size * 2;
+
+ //Allocating buffers and prepare RISC program
+ retval =
+ cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+ dev->_line_size_ch2);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "%s: Failed to set up Video upstream buffers!\n",
+ dev->name);
+ goto error;
+ }
+
+ cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
+
+ return 0;
+
+ error:
+ cx25821_dev_unregister(dev);
+
+ return err;
+}
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h
new file mode 100644
index 000000000000..73feea114c1c
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h
@@ -0,0 +1,101 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OPEN_FILE_1 0
+#define NUM_PROGS 8
+#define NUM_FRAMES 2
+#define ODD_FIELD 0
+#define EVEN_FIELD 1
+#define TOP_OFFSET 0
+#define FIFO_DISABLE 0
+#define FIFO_ENABLE 1
+#define TEST_FRAMES 5
+#define END_OF_FILE 0
+#define IN_PROGRESS 1
+#define RESET_STATUS -1
+#define NUM_NO_OPS 5
+
+// PAL and NTSC line sizes and number of lines.
+#define WIDTH_D1 720
+#define NTSC_LINES_PER_FRAME 480
+#define PAL_LINES_PER_FRAME 576
+#define PAL_LINE_SZ 1440
+#define Y422_LINE_SZ 1440
+#define Y411_LINE_SZ 1080
+#define NTSC_FIELD_HEIGHT 240
+#define NTSC_ODD_FLD_LINES 241
+#define PAL_FIELD_HEIGHT 288
+
+#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define JUMP_INSTRUCTION_SIZE 12
+#define MAXSIZE_NO_OPS 36
+#define DWORD_SIZE 4
+
+#define USE_RISC_NOOP_VIDEO 1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+ RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+ JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE)
+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )
+#define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) )
+#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )
+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )
+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )
+#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) )
+#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )
+#endif
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c
new file mode 100644
index 000000000000..3d7dd3f66541
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video-upstream.c
@@ -0,0 +1,894 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk =
+ FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc)
+{
+ unsigned int i, lines;
+ u32 cdt;
+
+ if (ch->cmds_start == 0) {
+ cx_write(ch->ptr1_reg, 0);
+ cx_write(ch->ptr2_reg, 0);
+ cx_write(ch->cnt2_reg, 0);
+ cx_write(ch->cnt1_reg, 0);
+ return 0;
+ }
+
+ bpl = (bpl + 7) & ~7; /* alignment */
+ cdt = ch->cdt;
+ lines = ch->fifo_size / bpl;
+
+ if (lines > 4) {
+ lines = 4;
+ }
+
+ BUG_ON(lines < 2);
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+ cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+ cx_write(cdt + 16 * i + 4, 0);
+ cx_write(cdt + 16 * i + 8, 0);
+ cx_write(cdt + 16 * i + 12, 0);
+ }
+
+ /* write CMDS */
+ cx_write(ch->cmds_start + 0, risc);
+
+ cx_write(ch->cmds_start + 4, 0);
+ cx_write(ch->cmds_start + 8, cdt);
+ cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+ cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+ cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
+
+ for (i = 24; i < 80; i += 4)
+ cx_write(ch->cmds_start + i, 0);
+
+ /* fill registers */
+ cx_write(ch->ptr1_reg, ch->fifo_start);
+ cx_write(ch->ptr2_reg, cdt);
+ cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+ cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+ return 0;
+}
+
+static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
+ __le32 * rp, unsigned int offset,
+ unsigned int bpl, u32 sync_line,
+ unsigned int lines, int fifo_enable,
+ int field_type)
+{
+ unsigned int line, i;
+ int dist_betwn_starts = bpl * 2;
+
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+ if (USE_RISC_NOOP_VIDEO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) = cpu_to_le32(RISC_NOOP);
+ }
+ }
+
+ /* scan lines */
+ for (line = 0; line < lines; line++) {
+ *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+
+ if ((lines <= NTSC_FIELD_HEIGHT)
+ || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+ offset += dist_betwn_starts;
+ }
+ }
+
+ return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
+ dma_addr_t databuf_phys_addr,
+ unsigned int offset, u32 sync_line,
+ unsigned int bpl, unsigned int lines,
+ int fifo_enable, int field_type)
+{
+ unsigned int line, i;
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[dev->_channel_upstream_select];
+ int dist_betwn_starts = bpl * 2;
+
+ /* sync instruction */
+ if (sync_line != NO_SYNC_LINE) {
+ *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+ }
+
+ if (USE_RISC_NOOP_VIDEO) {
+ for (i = 0; i < NUM_NO_OPS; i++) {
+ *(rp++) = cpu_to_le32(RISC_NOOP);
+ }
+ }
+
+ /* scan lines */
+ for (line = 0; line < lines; line++) {
+ *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+
+ if ((lines <= NTSC_FIELD_HEIGHT)
+ || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+ offset += dist_betwn_starts; //to skip the other field line
+ }
+
+ // check if we need to enable the FIFO after the first 4 lines
+ // For the upstream video channel, the risc engine will enable the FIFO.
+ if (fifo_enable && line == 3) {
+ *(rp++) = RISC_WRITECR;
+ *(rp++) = sram_ch->dma_ctl;
+ *(rp++) = FLD_VID_FIFO_EN;
+ *(rp++) = 0x00000001;
+ }
+ }
+
+ return rp;
+}
+
+int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+ struct pci_dev *pci,
+ unsigned int top_offset,
+ unsigned int bpl, unsigned int lines)
+{
+ __le32 *rp;
+ int fifo_enable = 0;
+ int singlefield_lines = lines >> 1; //get line count for single field
+ int odd_num_lines = singlefield_lines;
+ int frame = 0;
+ int frame_size = 0;
+ int databuf_offset = 0;
+ int risc_program_size = 0;
+ int risc_flag = RISC_CNT_RESET;
+ unsigned int bottom_offset = bpl;
+ dma_addr_t risc_phys_jump_addr;
+
+ if (dev->_isNTSC) {
+ odd_num_lines = singlefield_lines + 1;
+ risc_program_size = FRAME1_VID_PROG_SIZE;
+ frame_size =
+ (bpl ==
+ Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+ FRAME_SIZE_NTSC_Y422;
+ } else {
+ risc_program_size = PAL_VID_PROG_SIZE;
+ frame_size =
+ (bpl ==
+ Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ }
+
+ /* Virtual address of Risc buffer program */
+ rp = dev->_dma_virt_addr;
+
+ for (frame = 0; frame < NUM_FRAMES; frame++) {
+ databuf_offset = frame_size * frame;
+
+ if (UNSET != top_offset) {
+ fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+ rp = cx25821_risc_field_upstream(dev, rp,
+ dev->
+ _data_buf_phys_addr +
+ databuf_offset,
+ top_offset, 0, bpl,
+ odd_num_lines,
+ fifo_enable,
+ ODD_FIELD);
+ }
+
+ fifo_enable = FIFO_DISABLE;
+
+ //Even Field
+ rp = cx25821_risc_field_upstream(dev, rp,
+ dev->_data_buf_phys_addr +
+ databuf_offset, bottom_offset,
+ 0x200, bpl, singlefield_lines,
+ fifo_enable, EVEN_FIELD);
+
+ if (frame == 0) {
+ risc_flag = RISC_CNT_RESET;
+ risc_phys_jump_addr =
+ dev->_dma_phys_start_addr + risc_program_size;
+ } else {
+ risc_phys_jump_addr = dev->_dma_phys_start_addr;
+ risc_flag = RISC_CNT_INC;
+ }
+
+ // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ
+ *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+ }
+
+ return 0;
+}
+
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+{
+ struct sram_channel *sram_ch =
+ &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I];
+ u32 tmp = 0;
+
+ if (!dev->_is_running) {
+ printk
+ ("cx25821: No video file is currently running so return!\n");
+ return;
+ }
+ //Disable RISC interrupts
+ tmp = cx_read(sram_ch->int_msk);
+ cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+ //Turn OFF risc and fifo enable
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+ //Clear data buffer memory
+ if (dev->_data_buf_virt_addr)
+ memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+ dev->_is_running = 0;
+ dev->_is_first_frame = 0;
+ dev->_frame_count = 0;
+ dev->_file_status = END_OF_FILE;
+
+ if (dev->_irq_queues) {
+ kfree(dev->_irq_queues);
+ dev->_irq_queues = NULL;
+ }
+
+ if (dev->_filename != NULL)
+ kfree(dev->_filename);
+
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
+{
+ if (dev->_is_running) {
+ cx25821_stop_upstream_video_ch1(dev);
+ }
+
+ if (dev->_dma_virt_addr) {
+ pci_free_consistent(dev->pci, dev->_risc_size,
+ dev->_dma_virt_addr, dev->_dma_phys_addr);
+ dev->_dma_virt_addr = NULL;
+ }
+
+ if (dev->_data_buf_virt_addr) {
+ pci_free_consistent(dev->pci, dev->_data_buf_size,
+ dev->_data_buf_virt_addr,
+ dev->_data_buf_phys_addr);
+ dev->_data_buf_virt_addr = NULL;
+ }
+}
+
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int frame_index_temp = dev->_frame_index;
+ int i = 0;
+ int line_size =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int frame_size = 0;
+ int frame_offset = 0;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t file_offset;
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ if (dev->_file_status == END_OF_FILE)
+ return 0;
+
+ if (dev->_isNTSC) {
+ frame_size =
+ (line_size ==
+ Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+ FRAME_SIZE_NTSC_Y422;
+ } else {
+ frame_size =
+ (line_size ==
+ Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ }
+
+ frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+ file_offset = dev->_frame_count * frame_size;
+
+ myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_filename, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk("%s: File has no READ operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (i = 0; i < dev->_lines_count; i++) {
+ pos = file_offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0 && vfs_read_retval == line_size
+ && dev->_data_buf_virt_addr != NULL) {
+ memcpy((void *)(dev->_data_buf_virt_addr +
+ frame_offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ file_offset += vfs_read_retval;
+ frame_offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Video file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0)
+ dev->_frame_count++;
+
+ dev->_file_status =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+static void cx25821_vidups_handler(struct work_struct *work)
+{
+ struct cx25821_dev *dev =
+ container_of(work, struct cx25821_dev, _irq_work_entry);
+
+ if (!dev) {
+ printk("ERROR %s(): since container_of(work_struct) FAILED! \n",
+ __func__);
+ return;
+ }
+
+ cx25821_get_frame(dev,
+ &dev->sram_channels[dev->_channel_upstream_select]);
+}
+
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+ struct file *myfile;
+ int i = 0, j = 0;
+ int line_size =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ ssize_t vfs_read_retval = 0;
+ char mybuf[line_size];
+ loff_t pos;
+ loff_t offset = (unsigned long)0;
+ mm_segment_t old_fs;
+
+ myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+ if (IS_ERR(myfile)) {
+ const int open_errno = -PTR_ERR(myfile);
+ printk("%s(): ERROR opening file(%s) with errno = %d! \n",
+ __func__, dev->_filename, open_errno);
+ return PTR_ERR(myfile);
+ } else {
+ if (!(myfile->f_op)) {
+ printk("%s: File has no file operations registered!",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ if (!myfile->f_op->read) {
+ printk
+ ("%s: File has no READ operations registered! Returning.",
+ __func__);
+ filp_close(myfile, NULL);
+ return -EIO;
+ }
+
+ pos = myfile->f_pos;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ for (j = 0; j < NUM_FRAMES; j++) {
+ for (i = 0; i < dev->_lines_count; i++) {
+ pos = offset;
+
+ vfs_read_retval =
+ vfs_read(myfile, mybuf, line_size, &pos);
+
+ if (vfs_read_retval > 0
+ && vfs_read_retval == line_size
+ && dev->_data_buf_virt_addr != NULL) {
+ memcpy((void *)(dev->
+ _data_buf_virt_addr +
+ offset / 4), mybuf,
+ vfs_read_retval);
+ }
+
+ offset += vfs_read_retval;
+
+ if (vfs_read_retval < line_size) {
+ printk(KERN_INFO
+ "Done: exit %s() since no more bytes to read from Video file.\n",
+ __func__);
+ break;
+ }
+ }
+
+ if (i > 0)
+ dev->_frame_count++;
+
+ if (vfs_read_retval < line_size) {
+ break;
+ }
+ }
+
+ dev->_file_status =
+ (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+ set_fs(old_fs);
+ myfile->f_pos = 0;
+ filp_close(myfile, NULL);
+ }
+
+ return 0;
+}
+
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch, int bpl)
+{
+ int ret = 0;
+ dma_addr_t dma_addr;
+ dma_addr_t data_dma_addr;
+
+ if (dev->_dma_virt_addr != NULL) {
+ pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
+ dev->_dma_virt_addr, dev->_dma_phys_addr);
+ }
+
+ dev->_dma_virt_addr =
+ pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size,
+ &dma_addr);
+ dev->_dma_virt_start_addr = dev->_dma_virt_addr;
+ dev->_dma_phys_start_addr = dma_addr;
+ dev->_dma_phys_addr = dma_addr;
+ dev->_risc_size = dev->upstream_riscbuf_size;
+
+ if (!dev->_dma_virt_addr) {
+ printk
+ ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n");
+ return -ENOMEM;
+ }
+
+ //Clear memory at address
+ memset(dev->_dma_virt_addr, 0, dev->_risc_size);
+
+ if (dev->_data_buf_virt_addr != NULL) {
+ pci_free_consistent(dev->pci, dev->upstream_databuf_size,
+ dev->_data_buf_virt_addr,
+ dev->_data_buf_phys_addr);
+ }
+ //For Video Data buffer allocation
+ dev->_data_buf_virt_addr =
+ pci_alloc_consistent(dev->pci, dev->upstream_databuf_size,
+ &data_dma_addr);
+ dev->_data_buf_phys_addr = data_dma_addr;
+ dev->_data_buf_size = dev->upstream_databuf_size;
+
+ if (!dev->_data_buf_virt_addr) {
+ printk
+ ("cx25821: FAILED to allocate memory for data buffer! Returning.\n");
+ return -ENOMEM;
+ }
+
+ //Clear memory at address
+ memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+ ret = cx25821_openfile(dev, sram_ch);
+ if (ret < 0)
+ return ret;
+
+ //Create RISC programs
+ ret =
+ cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+ dev->_lines_count);
+ if (ret < 0) {
+ printk(KERN_INFO
+ "cx25821: Failed creating Video Upstream Risc programs! \n");
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ return ret;
+}
+
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+ u32 status)
+{
+ u32 int_msk_tmp;
+ struct sram_channel *channel = &dev->sram_channels[chan_num];
+ int singlefield_lines = NTSC_FIELD_HEIGHT;
+ int line_size_in_bytes = Y422_LINE_SZ;
+ int odd_risc_prog_size = 0;
+ dma_addr_t risc_phys_jump_addr;
+ __le32 *rp;
+
+ if (status & FLD_VID_SRC_RISC1) {
+ // We should only process one program per call
+ u32 prog_cnt = cx_read(channel->gpcnt);
+
+ //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers
+ int_msk_tmp = cx_read(channel->int_msk);
+ cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+ cx_write(channel->int_stat, _intr_msk);
+
+ spin_lock(&dev->slock);
+
+ dev->_frame_index = prog_cnt;
+
+ queue_work(dev->_irq_queues, &dev->_irq_work_entry);
+
+ if (dev->_is_first_frame) {
+ dev->_is_first_frame = 0;
+
+ if (dev->_isNTSC) {
+ singlefield_lines += 1;
+ odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+ } else {
+ singlefield_lines = PAL_FIELD_HEIGHT;
+ odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+ }
+
+ if (dev->_dma_virt_start_addr != NULL) {
+ line_size_in_bytes =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_411) ? Y411_LINE_SZ :
+ Y422_LINE_SZ;
+ risc_phys_jump_addr =
+ dev->_dma_phys_start_addr +
+ odd_risc_prog_size;
+
+ rp = cx25821_update_riscprogram(dev,
+ dev->
+ _dma_virt_start_addr,
+ TOP_OFFSET,
+ line_size_in_bytes,
+ 0x0,
+ singlefield_lines,
+ FIFO_DISABLE,
+ ODD_FIELD);
+
+ // Jump to Even Risc program of 1st Frame
+ *(rp++) = cpu_to_le32(RISC_JUMP);
+ *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+ *(rp++) = cpu_to_le32(0);
+ }
+ }
+
+ spin_unlock(&dev->slock);
+ } else {
+ if (status & FLD_VID_SRC_UF)
+ printk
+ ("%s: Video Received Underflow Error Interrupt!\n",
+ __func__);
+
+ if (status & FLD_VID_SRC_SYNC)
+ printk("%s: Video Received Sync Error Interrupt!\n",
+ __func__);
+
+ if (status & FLD_VID_SRC_OPC_ERR)
+ printk("%s: Video Received OpCode Error Interrupt!\n",
+ __func__);
+ }
+
+ if (dev->_file_status == END_OF_FILE) {
+ printk("cx25821: EOF Channel 1 Framecount = %d\n",
+ dev->_frame_count);
+ return -1;
+ }
+ //ElSE, set the interrupt mask register, re-enable irq.
+ int_msk_tmp = cx_read(channel->int_msk);
+ cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+ return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
+{
+ struct cx25821_dev *dev = dev_id;
+ u32 msk_stat, vid_status;
+ int handled = 0;
+ int channel_num = 0;
+ struct sram_channel *sram_ch;
+
+ if (!dev)
+ return -1;
+
+ channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
+
+ sram_ch = &dev->sram_channels[channel_num];
+
+ msk_stat = cx_read(sram_ch->int_mstat);
+ vid_status = cx_read(sram_ch->int_stat);
+
+ // Only deal with our interrupt
+ if (vid_status) {
+ handled =
+ cx25821_video_upstream_irq(dev, channel_num, vid_status);
+ }
+
+ if (handled < 0) {
+ cx25821_stop_upstream_video_ch1(dev);
+ } else {
+ handled += handled;
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
+ int pix_format)
+{
+ int width = WIDTH_D1;
+ int height = dev->_lines_count;
+ int num_lines, odd_num_lines;
+ u32 value;
+ int vip_mode = OUTPUT_FRMT_656;
+
+ value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+ value &= 0xFFFFFFEF;
+ value |= dev->_isNTSC ? 0 : 0x10;
+ cx_write(ch->vid_fmt_ctl, value);
+
+ // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format
+ cx_write(ch->vid_active_ctl1, width);
+
+ num_lines = (height / 2) & 0x3FF;
+ odd_num_lines = num_lines;
+
+ if (dev->_isNTSC) {
+ odd_num_lines += 1;
+ }
+
+ value = (num_lines << 16) | odd_num_lines;
+
+ // set number of active lines in field 0 (top) and field 1 (bottom)
+ cx_write(ch->vid_active_ctl2, value);
+
+ cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+ struct sram_channel *sram_ch)
+{
+ u32 tmp = 0;
+ int err = 0;
+
+ // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+ // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds.
+ cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
+ cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+ /* reset counter */
+ cx_write(sram_ch->gpcnt_ctl, 3);
+
+ // Clear our bits from the interrupt status register.
+ cx_write(sram_ch->int_stat, _intr_msk);
+
+ //Set the interrupt mask register, enable irq.
+ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+ tmp = cx_read(sram_ch->int_msk);
+ cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+ err =
+ request_irq(dev->pci->irq, cx25821_upstream_irq,
+ IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
+ dev->pci->irq);
+ goto fail_irq;
+ }
+
+ // Start the DMA engine
+ tmp = cx_read(sram_ch->dma_ctl);
+ cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+ dev->_is_running = 1;
+ dev->_is_first_frame = 1;
+
+ return 0;
+
+ fail_irq:
+ cx25821_dev_unregister(dev);
+ return err;
+}
+
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
+ int pixel_format)
+{
+ struct sram_channel *sram_ch;
+ u32 tmp;
+ int retval = 0;
+ int err = 0;
+ int data_frame_size = 0;
+ int risc_buffer_size = 0;
+ int str_length = 0;
+
+ if (dev->_is_running) {
+ printk("Video Channel is still running so return!\n");
+ return 0;
+ }
+
+ dev->_channel_upstream_select = channel_select;
+ sram_ch = &dev->sram_channels[channel_select];
+
+ INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
+ dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
+
+ if (!dev->_irq_queues) {
+ printk
+ ("cx25821: create_singlethread_workqueue() for Video FAILED!\n");
+ return -ENOMEM;
+ }
+ // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+ dev->_is_running = 0;
+ dev->_frame_count = 0;
+ dev->_file_status = RESET_STATUS;
+ dev->_lines_count = dev->_isNTSC ? 480 : 576;
+ dev->_pixel_format = pixel_format;
+ dev->_line_size =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+ data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+ risc_buffer_size =
+ dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+ if (dev->input_filename) {
+ str_length = strlen(dev->input_filename);
+ dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_filename)
+ goto error;
+
+ memcpy(dev->_filename, dev->input_filename, str_length + 1);
+ } else {
+ str_length = strlen(dev->_defaultname);
+ dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL);
+
+ if (!dev->_filename)
+ goto error;
+
+ memcpy(dev->_filename, dev->_defaultname, str_length + 1);
+ }
+
+ //Default if filename is empty string
+ if (strcmp(dev->input_filename, "") == 0) {
+ if (dev->_isNTSC) {
+ dev->_filename =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+ "/root/vidtest.yuv";
+ } else {
+ dev->_filename =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+ "/root/pal422.yuv";
+ }
+ }
+
+ dev->_is_running = 0;
+ dev->_frame_count = 0;
+ dev->_file_status = RESET_STATUS;
+ dev->_lines_count = dev->_isNTSC ? 480 : 576;
+ dev->_pixel_format = pixel_format;
+ dev->_line_size =
+ (dev->_pixel_format ==
+ PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+
+ retval =
+ cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size,
+ 0);
+
+ /* setup fifo + format */
+ cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
+
+ dev->upstream_riscbuf_size = risc_buffer_size * 2;
+ dev->upstream_databuf_size = data_frame_size * 2;
+
+ //Allocating buffers and prepare RISC program
+ retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "%s: Failed to set up Video upstream buffers!\n",
+ dev->name);
+ goto error;
+ }
+
+ cx25821_start_video_dma_upstream(dev, sram_ch);
+
+ return 0;
+
+ error:
+ cx25821_dev_unregister(dev);
+
+ return err;
+}
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h
new file mode 100644
index 000000000000..cc9f93842514
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video-upstream.h
@@ -0,0 +1,109 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ * 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.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OUTPUT_FRMT_656 0
+#define OPEN_FILE_1 0
+#define NUM_PROGS 8
+#define NUM_FRAMES 2
+#define ODD_FIELD 0
+#define EVEN_FIELD 1
+#define TOP_OFFSET 0
+#define FIFO_DISABLE 0
+#define FIFO_ENABLE 1
+#define TEST_FRAMES 5
+#define END_OF_FILE 0
+#define IN_PROGRESS 1
+#define RESET_STATUS -1
+#define NUM_NO_OPS 5
+
+// PAL and NTSC line sizes and number of lines.
+#define WIDTH_D1 720
+#define NTSC_LINES_PER_FRAME 480
+#define PAL_LINES_PER_FRAME 576
+#define PAL_LINE_SZ 1440
+#define Y422_LINE_SZ 1440
+#define Y411_LINE_SZ 1080
+#define NTSC_FIELD_HEIGHT 240
+#define NTSC_ODD_FLD_LINES 241
+#define PAL_FIELD_HEIGHT 288
+
+#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define JUMP_INSTRUCTION_SIZE 12
+#define MAXSIZE_NO_OPS 36
+#define DWORD_SIZE 4
+
+#define USE_RISC_NOOP_VIDEO 1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+ RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+ JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE)
+
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+ RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )
+
+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )
+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )
+
+#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+#define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) )
+#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )
+#endif
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
new file mode 100644
index 000000000000..8834bc80a5ab
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video.c
@@ -0,0 +1,1299 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug = VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void init_controls(struct cx25821_dev *dev, int chan_num);
+
+#define FORMAT_FLAGS_PACKED 0x01
+
+struct cx25821_fmt formats[] = {
+ {
+ .name = "8 bpp, gray",
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .depth = 8,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .name = "4:1:1, packed, Y41P",
+ .fourcc = V4L2_PIX_FMT_Y41P,
+ .depth = 12,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .name = "4:2:0, YUV",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .flags = FORMAT_FLAGS_PACKED,
+ },
+};
+
+int get_format_size(void)
+{
+ return ARRAY_SIZE(formats);
+}
+
+struct cx25821_fmt *format_by_fourcc(unsigned int fourcc)
+{
+ unsigned int i;
+
+ if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) {
+ return formats + 1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++)
+ if (formats[i].fourcc == fourcc)
+ return formats + i;
+
+ printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+ return NULL;
+}
+
+void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q)
+{
+ struct cx25821_buffer *buf;
+ struct list_head *item;
+ dprintk(1, "%s()\n", __func__);
+
+ if (!list_empty(&q->active)) {
+ list_for_each(item, &q->active)
+ buf = list_entry(item, struct cx25821_buffer, vb.queue);
+ }
+
+ if (!list_empty(&q->queued)) {
+ list_for_each(item, &q->queued)
+ buf = list_entry(item, struct cx25821_buffer, vb.queue);
+ }
+
+}
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
+ u32 count)
+{
+ struct cx25821_buffer *buf;
+ int bc;
+
+ for (bc = 0;; bc++) {
+ if (list_empty(&q->active)) {
+ dprintk(1, "bc=%d (=0: active empty)\n", bc);
+ break;
+ }
+
+ buf =
+ list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+ /* count comes from the hw and it is 16bit wide --
+ * this trick handles wrap-arounds correctly for
+ * up to 32767 buffers in flight... */
+ if ((s16) (count - buf->count) < 0) {
+ break;
+ }
+
+ do_gettimeofday(&buf->vb.ts);
+ buf->vb.state = VIDEOBUF_DONE;
+ list_del(&buf->vb.queue);
+ wake_up(&buf->vb.done);
+ }
+
+ if (list_empty(&q->active))
+ del_timer(&q->timeout);
+ else
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ if (bc != 1)
+ printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+ __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+ dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__,
+ (unsigned int)norm, v4l2_norm_to_name(norm));
+
+ dev->tvnorm = norm;
+
+ /* Tell the internal A/V decoder */
+ cx25821_call_all(dev, core, s_std, norm);
+
+ return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+ struct pci_dev *pci,
+ struct video_device *template,
+ char *type)
+{
+ struct video_device *vfd;
+ dprintk(1, "%s()\n", __func__);
+
+ vfd = video_device_alloc();
+ if (NULL == vfd)
+ return NULL;
+ *vfd = *template;
+ vfd->minor = -1;
+ vfd->v4l2_dev = &dev->v4l2_dev;
+ vfd->release = video_device_release;
+ snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
+ cx25821_boards[dev->board].name);
+ return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+ int i;
+
+ if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+ return -EINVAL;
+ for (i = 0; i < CX25821_CTLS; i++)
+ if (cx25821_ctls[i].v.id == qctrl->id)
+ break;
+ if (i == CX25821_CTLS) {
+ *qctrl = no_ctl;
+ return 0;
+ }
+ *qctrl = cx25821_ctls[i].v;
+ return 0;
+}
+*/
+
+// resource management
+int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit)
+{
+ dprintk(1, "%s()\n", __func__);
+ if (fh->resources & bit)
+ /* have it already allocated */
+ return 1;
+
+ /* is it free? */
+ mutex_lock(&dev->lock);
+ if (dev->resources & bit) {
+ /* no, someone else uses it */
+ mutex_unlock(&dev->lock);
+ return 0;
+ }
+ /* it's free, grab it */
+ fh->resources |= bit;
+ dev->resources |= bit;
+ dprintk(1, "res: get %d\n", bit);
+ mutex_unlock(&dev->lock);
+ return 1;
+}
+
+int res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+ return fh->resources & bit;
+}
+
+int res_locked(struct cx25821_dev *dev, unsigned int bit)
+{
+ return dev->resources & bit;
+}
+
+void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits)
+{
+ BUG_ON((fh->resources & bits) != bits);
+ dprintk(1, "%s()\n", __func__);
+
+ mutex_lock(&dev->lock);
+ fh->resources &= ~bits;
+ dev->resources &= ~bits;
+ dprintk(1, "res: put %d\n", bits);
+ mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+ struct v4l2_routing route;
+ memset(&route, 0, sizeof(route));
+
+ dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+ __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
+ INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
+ dev->input = input;
+
+ route.input = INPUT(input)->vmux;
+
+ /* Tell the internal A/V decoder */
+ cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
+
+ return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q,
+ struct cx25821_buffer *buf,
+ struct sram_channel *channel)
+{
+ int tmp = 0;
+
+ /* setup fifo + format */
+ cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+ /* reset counter */
+ cx_write(channel->gpcnt_ctl, 3);
+ q->count = 1;
+
+ /* enable irq */
+ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
+ cx_set(channel->int_msk, 0x11);
+
+ /* start dma */
+ cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */
+
+ /* make sure upstream setting if any is reversed */
+ tmp = cx_read(VID_CH_MODE_SEL);
+ cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+ return 0;
+}
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q,
+ struct sram_channel *channel)
+{
+ struct cx25821_buffer *buf, *prev;
+ struct list_head *item;
+
+ if (!list_empty(&q->active)) {
+ buf =
+ list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+ cx25821_start_video_dma(dev, q, buf, channel);
+
+ list_for_each(item, &q->active) {
+ buf = list_entry(item, struct cx25821_buffer, vb.queue);
+ buf->count = q->count++;
+ }
+
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ return 0;
+ }
+
+ prev = NULL;
+ for (;;) {
+ if (list_empty(&q->queued))
+ return 0;
+
+ buf =
+ list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+
+ if (NULL == prev) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf, channel);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ } else if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+ } else {
+ return 0;
+ }
+ prev = buf;
+ }
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+ struct cx25821_data *timeout_data = (struct cx25821_data *)data;
+ struct cx25821_dev *dev = timeout_data->dev;
+ struct sram_channel *channel = timeout_data->channel;
+ struct cx25821_dmaqueue *q = &dev->vidq[channel->i];
+ struct cx25821_buffer *buf;
+ unsigned long flags;
+
+ //cx25821_sram_channel_dump(dev, channel);
+ cx_clear(channel->dma_ctl, 0x11);
+
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&q->active)) {
+ buf =
+ list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+ list_del(&buf->vb.queue);
+
+ buf->vb.state = VIDEOBUF_ERROR;
+ wake_up(&buf->vb.done);
+ }
+
+ cx25821_restart_video_queue(dev, q, channel);
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+ u32 count = 0;
+ int handled = 0;
+ u32 mask;
+ struct sram_channel *channel = &dev->sram_channels[chan_num];
+
+ mask = cx_read(channel->int_msk);
+ if (0 == (status & mask))
+ return handled;
+
+ cx_write(channel->int_stat, status);
+
+ /* risc op code error */
+ if (status & (1 << 16)) {
+ printk(KERN_WARNING "%s, %s: video risc op code error\n",
+ dev->name, channel->name);
+ cx_clear(channel->dma_ctl, 0x11);
+ cx25821_sram_channel_dump(dev, channel);
+ }
+
+ /* risc1 y */
+ if (status & FLD_VID_DST_RISC1) {
+ spin_lock(&dev->slock);
+ count = cx_read(channel->gpcnt);
+ cx25821_video_wakeup(dev, &dev->vidq[channel->i], count);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+
+ /* risc2 y */
+ if (status & 0x10) {
+ dprintk(2, "stopper video\n");
+ spin_lock(&dev->slock);
+ cx25821_restart_video_queue(dev, &dev->vidq[channel->i],
+ channel);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+ return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+ if (dev->ioctl_dev) {
+ if (dev->ioctl_dev->minor != -1)
+ video_unregister_device(dev->ioctl_dev);
+ else
+ video_device_release(dev->ioctl_dev);
+
+ dev->ioctl_dev = NULL;
+ }
+}
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+ cx_clear(PCI_INT_MSK, 1);
+
+ if (dev->video_dev[chan_num]) {
+ if (-1 != dev->video_dev[chan_num]->minor)
+ video_unregister_device(dev->video_dev[chan_num]);
+ else
+ video_device_release(dev->video_dev[chan_num]);
+
+ dev->video_dev[chan_num] = NULL;
+
+ btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper);
+
+ printk(KERN_WARNING "device %d released!\n", chan_num);
+ }
+
+}
+
+int cx25821_video_register(struct cx25821_dev *dev, int chan_num,
+ struct video_device *video_template)
+{
+ int err;
+
+ spin_lock_init(&dev->slock);
+
+ //printk(KERN_WARNING "Channel %d\n", chan_num);
+
+#ifdef TUNER_FLAG
+ dev->tvnorm = video_template->current_norm;
+#endif
+
+ /* init video dma queues */
+ dev->timeout_data[chan_num].dev = dev;
+ dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num];
+ INIT_LIST_HEAD(&dev->vidq[chan_num].active);
+ INIT_LIST_HEAD(&dev->vidq[chan_num].queued);
+ dev->vidq[chan_num].timeout.function = cx25821_vid_timeout;
+ dev->vidq[chan_num].timeout.data =
+ (unsigned long)&dev->timeout_data[chan_num];
+ init_timer(&dev->vidq[chan_num].timeout);
+ cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper,
+ dev->sram_channels[chan_num].dma_ctl, 0x11, 0);
+
+ /* register v4l devices */
+ dev->video_dev[chan_num] =
+ cx25821_vdev_init(dev, dev->pci, video_template, "video");
+ err =
+ video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER,
+ video_nr[dev->nr]);
+
+ if (err < 0) {
+ goto fail_unreg;
+ }
+ //set PCI interrupt
+ cx_set(PCI_INT_MSK, 0xff);
+
+ /* initial device configuration */
+ mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+ cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+ mutex_unlock(&dev->lock);
+
+ init_controls(dev, chan_num);
+
+ return 0;
+
+ fail_unreg:
+ cx25821_video_unregister(dev, chan_num);
+ return err;
+}
+
+int buffer_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size)
+{
+ struct cx25821_fh *fh = q->priv_data;
+
+ *size = fh->fmt->depth * fh->width * fh->height >> 3;
+
+ if (0 == *count)
+ *count = 32;
+
+ while (*size * *count > vid_limit * 1024 * 1024)
+ (*count)--;
+
+ return 0;
+}
+
+int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct cx25821_fh *fh = q->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ int rc, init_buffer = 0;
+ u32 line0_offset, line1_offset;
+ struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+ int bpl_local = LINE_SIZE_D1;
+ int channel_opened = 0;
+
+ BUG_ON(NULL == fh->fmt);
+ if (fh->width < 48 || fh->width > 720 ||
+ fh->height < 32 || fh->height > 576)
+ return -EINVAL;
+
+ buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ return -EINVAL;
+
+ if (buf->fmt != fh->fmt ||
+ buf->vb.width != fh->width ||
+ buf->vb.height != fh->height || buf->vb.field != field) {
+ buf->fmt = fh->fmt;
+ buf->vb.width = fh->width;
+ buf->vb.height = fh->height;
+ buf->vb.field = field;
+ init_buffer = 1;
+ }
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ init_buffer = 1;
+ rc = videobuf_iolock(q, &buf->vb, NULL);
+ if (0 != rc) {
+ printk(KERN_DEBUG "videobuf_iolock failed!\n");
+ goto fail;
+ }
+ }
+
+ dprintk(1, "init_buffer=%d\n", init_buffer);
+
+ if (init_buffer) {
+
+ channel_opened = dev->channel_opened;
+ channel_opened = (channel_opened < 0
+ || channel_opened > 7) ? 7 : channel_opened;
+
+ if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411)
+ buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+ else
+ buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+ if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) {
+ bpl_local = buf->bpl;
+ } else {
+ bpl_local = buf->bpl; //Default
+
+ if (channel_opened >= 0 && channel_opened <= 7) {
+ if (dev->use_cif_resolution[channel_opened]) {
+ if (dev->tvnorm & V4L2_STD_PAL_BG
+ || dev->tvnorm & V4L2_STD_PAL_DK)
+ bpl_local = 352 << 1;
+ else
+ bpl_local =
+ dev->
+ cif_width[channel_opened] <<
+ 1;
+ }
+ }
+ }
+
+ switch (buf->vb.field) {
+ case V4L2_FIELD_TOP:
+ cx25821_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, 0, UNSET,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_BOTTOM:
+ cx25821_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, UNSET, 0,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_INTERLACED:
+ /* All other formats are top field first */
+ line0_offset = 0;
+ line1_offset = buf->bpl;
+ dprintk(1, "top field first\n");
+
+ cx25821_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, line0_offset,
+ bpl_local, bpl_local, bpl_local,
+ buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_TB:
+ cx25821_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ 0, buf->bpl * (buf->vb.height >> 1),
+ buf->bpl, 0, buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_BT:
+ cx25821_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ buf->bpl * (buf->vb.height >> 1), 0,
+ buf->bpl, 0, buf->vb.height >> 1);
+ break;
+ default:
+ BUG();
+ }
+ }
+
+ dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+ buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
+ fh->fmt->name, (unsigned long)buf->risc.dma);
+
+ buf->vb.state = VIDEOBUF_PREPARED;
+
+ return 0;
+
+ fail:
+ cx25821_free_buffer(q, buf);
+ return rc;
+}
+
+void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+
+ cx25821_free_buffer(q, buf);
+}
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return &fh->vidq;
+ default:
+ BUG();
+ return NULL;
+ }
+}
+
+int get_resource(struct cx25821_fh *fh, int resource)
+{
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return resource;
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+/* VIDEO IOCTLS */
+int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+
+ f->fmt.pix.width = fh->width;
+ f->fmt.pix.height = fh->height;
+ f->fmt.pix.field = fh->vidq.field;
+ f->fmt.pix.pixelformat = fh->fmt->fourcc;
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+ return 0;
+}
+
+int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct cx25821_fmt *fmt;
+ enum v4l2_field field;
+ unsigned int maxw, maxh;
+
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ if (NULL == fmt)
+ return -EINVAL;
+
+ field = f->fmt.pix.field;
+ maxw = 720;
+ maxh = 576;
+
+ if (V4L2_FIELD_ANY == field) {
+ field = (f->fmt.pix.height > maxh / 2)
+ ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+ }
+
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ maxh = maxh / 2;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ f->fmt.pix.field = field;
+ if (f->fmt.pix.height < 32)
+ f->fmt.pix.height = 32;
+ if (f->fmt.pix.height > maxh)
+ f->fmt.pix.height = maxh;
+ if (f->fmt.pix.width < 48)
+ f->fmt.pix.width = 48;
+ if (f->fmt.pix.width > maxw)
+ f->fmt.pix.width = maxw;
+ f->fmt.pix.width &= ~0x03;
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+ return 0;
+}
+
+int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ strcpy(cap->driver, "cx25821");
+ strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+ sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+ cap->version = CX25821_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+ if (UNSET != dev->tuner_type)
+ cap->capabilities |= V4L2_CAP_TUNER;
+ return 0;
+}
+
+int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ if (unlikely(f->index >= ARRAY_SIZE(formats)))
+ return -EINVAL;
+
+ strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+ f->pixelformat = formats[f->index].fourcc;
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+ struct cx25821_fh *fh = priv;
+ struct videobuf_queue *q;
+ struct v4l2_requestbuffers req;
+ unsigned int i;
+ int err;
+
+ q = get_queue(fh);
+ memset(&req, 0, sizeof(req));
+ req.type = q->type;
+ req.count = 8;
+ req.memory = V4L2_MEMORY_MMAP;
+ err = videobuf_reqbufs(q, &req);
+ if (err < 0)
+ return err;
+
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
+ }
+ return 0;
+}
+#endif
+
+int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_querybuf(get_queue(fh), p);
+}
+
+int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_qbuf(get_queue(fh), p);
+}
+
+int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+ *p = v4l2_prio_max(&dev->prio);
+
+ return 0;
+}
+
+int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio)
+{
+ struct cx25821_fh *fh = f;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+ return v4l2_prio_change(&dev->prio, &fh->prio, prio);
+}
+
+#ifdef TUNER_FLAG
+int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ if (dev->tvnorm == *tvnorms) {
+ return 0;
+ }
+
+ mutex_lock(&dev->lock);
+ cx25821_set_tvnorm(dev, *tvnorms);
+ mutex_unlock(&dev->lock);
+
+ medusa_set_videostandard(dev);
+
+ return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+ static const char *iname[] = {
+ [CX25821_VMUX_COMPOSITE] = "Composite",
+ [CX25821_VMUX_SVIDEO] = "S-Video",
+ [CX25821_VMUX_DEBUG] = "for debug only",
+ };
+ unsigned int n;
+ dprintk(1, "%s()\n", __func__);
+
+ n = i->index;
+ if (n > 2)
+ return -EINVAL;
+
+ if (0 == INPUT(n)->type)
+ return -EINVAL;
+
+ memset(i, 0, sizeof(*i));
+ i->index = n;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ strcpy(i->name, iname[INPUT(n)->type]);
+
+ i->std = CX25821_NORMS;
+ return 0;
+}
+
+int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ dprintk(1, "%s()\n", __func__);
+ return cx25821_enum_input(dev, i);
+}
+
+int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ *i = dev->input;
+ dprintk(1, "%s() returns %d\n", __func__, *i);
+ return 0;
+}
+
+int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ dprintk(1, "%s(%d)\n", __func__, i);
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ if (i > 2) {
+ dprintk(1, "%s() -EINVAL\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+ cx25821_video_mux(dev, i);
+ mutex_unlock(&dev->lock);
+ return 0;
+}
+
+#ifdef TUNER_FLAG
+int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ f->frequency = dev->freq;
+
+ cx25821_call_all(dev, tuner, g_frequency, f);
+
+ return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+ mutex_lock(&dev->lock);
+ dev->freq = f->frequency;
+
+ cx25821_call_all(dev, tuner, s_frequency, f);
+
+ /* When changing channels it is required to reset TVAUDIO */
+ msleep(10);
+
+ mutex_unlock(&dev->lock);
+
+ return 0;
+}
+
+int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int vidioc_g_register(struct file *file, void *fh,
+ struct v4l2_dbg_register *reg)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+ if (!v4l2_chip_match_host(&reg->match))
+ return -EINVAL;
+
+ cx25821_call_all(dev, core, g_register, reg);
+
+ return 0;
+}
+
+int vidioc_s_register(struct file *file, void *fh,
+ struct v4l2_dbg_register *reg)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+ if (!v4l2_chip_match_host(&reg->match))
+ return -EINVAL;
+
+ cx25821_call_all(dev, core, s_register, reg);
+
+ return 0;
+}
+
+#endif
+
+#ifdef TUNER_FLAG
+int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ if (unlikely(UNSET == dev->tuner_type))
+ return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
+
+ strcpy(t->name, "Television");
+ t->type = V4L2_TUNER_ANALOG_TV;
+ t->capability = V4L2_TUNER_CAP_NORM;
+ t->rangehigh = 0xffffffffUL;
+
+ t->signal = 0xffff; /* LOCKED */
+ return 0;
+}
+
+int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ struct cx25821_fh *fh = priv;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(1, "%s()\n", __func__);
+ if (UNSET == dev->tuner_type)
+ return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
+
+ return 0;
+}
+
+#endif
+// ******************************************************************************************
+static const struct v4l2_queryctrl no_ctl = {
+ .name = "42",
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+ /* --- video --- */
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 6200,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_HUE,
+ .name = "Hue",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+ int i;
+
+ if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+ return -EINVAL;
+ for (i = 0; i < CX25821_CTLS; i++)
+ if (cx25821_ctls[i].id == qctrl->id)
+ break;
+ if (i == CX25821_CTLS) {
+ *qctrl = no_ctl;
+ return 0;
+ }
+ *qctrl = cx25821_ctls[i];
+ return 0;
+}
+
+int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qctrl)
+{
+ return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS */
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+ unsigned int i;
+
+ for (i = 0; i < CX25821_CTLS; i++)
+ if (cx25821_ctls[i].id == id)
+ return cx25821_ctls + i;
+ return NULL;
+}
+
+int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ const struct v4l2_queryctrl *ctrl;
+
+ ctrl = ctrl_by_id(ctl->id);
+
+ if (NULL == ctrl)
+ return -EINVAL;
+ switch (ctl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctl->value = dev->ctl_bright;
+ break;
+ case V4L2_CID_HUE:
+ ctl->value = dev->ctl_hue;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctl->value = dev->ctl_contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ ctl->value = dev->ctl_saturation;
+ break;
+ }
+ return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+ struct v4l2_control *ctl, int chan_num)
+{
+ int err;
+ const struct v4l2_queryctrl *ctrl;
+
+ err = -EINVAL;
+
+ ctrl = ctrl_by_id(ctl->id);
+
+ if (NULL == ctrl)
+ return err;
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER:
+ if (ctl->value < ctrl->minimum)
+ ctl->value = ctrl->minimum;
+ if (ctl->value > ctrl->maximum)
+ ctl->value = ctrl->maximum;
+ break;
+ default:
+ /* nothing */ ;
+ };
+
+ switch (ctl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev->ctl_bright = ctl->value;
+ medusa_set_brightness(dev, ctl->value, chan_num);
+ break;
+ case V4L2_CID_HUE:
+ dev->ctl_hue = ctl->value;
+ medusa_set_hue(dev, ctl->value, chan_num);
+ break;
+ case V4L2_CID_CONTRAST:
+ dev->ctl_contrast = ctl->value;
+ medusa_set_contrast(dev, ctl->value, chan_num);
+ break;
+ case V4L2_CID_SATURATION:
+ dev->ctl_saturation = ctl->value;
+ medusa_set_saturation(dev, ctl->value, chan_num);
+ break;
+ }
+
+ err = 0;
+
+ return err;
+}
+
+static void init_controls(struct cx25821_dev *dev, int chan_num)
+{
+ struct v4l2_control ctrl;
+ int i;
+ for (i = 0; i < CX25821_CTLS; i++) {
+ ctrl.id = cx25821_ctls[i].id;
+ ctrl.value = cx25821_ctls[i].default_value;
+
+ cx25821_set_control(dev, &ctrl, chan_num);
+ }
+}
+
+int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+ cropcap->pixelaspect.numerator =
+ dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+ cropcap->pixelaspect.denominator =
+ dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+ cropcap->defrect = cropcap->bounds;
+ return 0;
+}
+
+int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ struct cx25821_fh *fh = priv;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+ // vidioc_s_crop not supported
+ return -EINVAL;
+}
+
+int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+ // vidioc_g_crop not supported
+ return -EINVAL;
+}
+
+int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
+{
+ // medusa does not support video standard sensing of current input
+ *norm = CX25821_NORMS;
+
+ return 0;
+}
+
+int is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+ if (tvnorm == V4L2_STD_PAL_BG) {
+ if (width == 352 || width == 720)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (tvnorm == V4L2_STD_NTSC_M) {
+ if (width == 320 || width == 352 || width == 720)
+ return 1;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+int is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+ if (tvnorm == V4L2_STD_PAL_BG) {
+ if (height == 576 || height == 288)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (tvnorm == V4L2_STD_NTSC_M) {
+ if (height == 480 || height == 240)
+ return 1;
+ else
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h
new file mode 100644
index 000000000000..4417ff5d90d4
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video.h
@@ -0,0 +1,194 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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 CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+/* Include V4L1 specific functions. Should be removed soon */
+#include <linux/videodev.h>
+#endif
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)\
+ do { if (VIDEO_DEBUG >= level)\
+ printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ } while (0)
+
+//For IOCTL to identify running upstream
+#define UPSTREAM_START_VIDEO 700
+#define UPSTREAM_STOP_VIDEO 701
+#define UPSTREAM_START_AUDIO 702
+#define UPSTREAM_STOP_AUDIO 703
+#define UPSTREAM_DUMP_REGISTERS 702
+#define SET_VIDEO_STD 800
+#define SET_PIXEL_FORMAT 1000
+#define ENABLE_CIF_RESOLUTION 1001
+
+#define REG_READ 900
+#define REG_WRITE 901
+#define MEDUSA_READ 910
+#define MEDUSA_WRITE 911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_video_template0;
+extern struct video_device cx25821_video_template1;
+extern struct video_device cx25821_video_template2;
+extern struct video_device cx25821_video_template3;
+extern struct video_device cx25821_video_template4;
+extern struct video_device cx25821_video_template5;
+extern struct video_device cx25821_video_template6;
+extern struct video_device cx25821_video_template7;
+extern struct video_device cx25821_video_template9;
+extern struct video_device cx25821_video_template10;
+extern struct video_device cx25821_video_template11;
+extern struct video_device cx25821_videoioctl_template;
+//extern const u32 *ctrl_classes[];
+
+extern unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED 0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void dump_video_queue(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q);
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+ unsigned int bit);
+extern int res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int res_locked(struct cx25821_dev *dev, unsigned int bit);
+extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+ unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q,
+ struct cx25821_buffer *buf,
+ struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
+ unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num,
+ struct video_device *video_template);
+extern int get_format_size(void);
+
+extern int buffer_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size);
+extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field);
+extern void buffer_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int get_resource(struct cx25821_fh *fh, int resource);
+extern int video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f);
+extern int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap);
+extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f);
+extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf);
+extern int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p);
+extern int vidioc_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *p);
+extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *i);
+extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i);
+extern int vidioc_s_input(struct file *file, void *priv, unsigned int i);
+extern int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl);
+extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f);
+extern int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f);
+extern int vidioc_g_register(struct file *file, void *fh,
+ struct v4l2_dbg_register *reg);
+extern int vidioc_s_register(struct file *file, void *fh,
+ struct v4l2_dbg_register *reg);
+extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+
+extern int is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p);
+extern int vidioc_s_priority(struct file *file, void *f,
+ enum v4l2_priority prio);
+
+extern int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev,
+ struct v4l2_control *ctrl, int chan_num);
+
+extern int vidioc_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *cropcap);
+extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop);
+extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop);
+
+extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm);
+#endif
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c
new file mode 100644
index 000000000000..950fac1d7003
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video0.c
@@ -0,0 +1,451 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH00]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH00]
+ && h->video_dev[SRAM_CH00]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH00;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO0))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO0)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH00]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO0)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO0);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO0);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = PIXEL_FRMT_422;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH00] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH00] = 0;
+ }
+ dev->cif_width[SRAM_CH00] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH00);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH00].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 0 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH00);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template0 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c
new file mode 100644
index 000000000000..a4dddc684adf
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video1.c
@@ -0,0 +1,451 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH01]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH01]
+ && h->video_dev[SRAM_CH01]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH01;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO1))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO1)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH01]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO1)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO1);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO1);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH01, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH01] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH01] = 0;
+ }
+ dev->cif_width[SRAM_CH01] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH01);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH01].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 1 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH01);
+}
+
+//exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template1 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c
new file mode 100644
index 000000000000..8e04e253f5d9
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video2.c
@@ -0,0 +1,452 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH02]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH02]
+ && h->video_dev[SRAM_CH02]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH02;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO2))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO2)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH02]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO2)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO2);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO2);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH02, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH02] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH02] = 0;
+ }
+ dev->cif_width[SRAM_CH02] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH02);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH02].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 2 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH02);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template2 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c
new file mode 100644
index 000000000000..8801a8ead904
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video3.c
@@ -0,0 +1,451 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH03]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH03]
+ && h->video_dev[SRAM_CH03]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH03;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO3))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO3)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH03]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO3)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO3);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO3);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH03, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH03] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH03] = 0;
+ }
+ dev->cif_width[SRAM_CH03] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH03);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH03].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 3 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH03);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template3 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c
new file mode 100644
index 000000000000..ab0d747138ad
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video4.c
@@ -0,0 +1,450 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH04]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH04]
+ && h->video_dev[SRAM_CH04]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH04;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO4))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO4)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH04]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO4)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO4);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO4);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ // check priority
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH04, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH04] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH04] = 0;
+ }
+ dev->cif_width[SRAM_CH04] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH04);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH04].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 4 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH04);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template4 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c
new file mode 100644
index 000000000000..7ef0b971f5cf
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video5.c
@@ -0,0 +1,450 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH05]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH05]
+ && h->video_dev[SRAM_CH05]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH05;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO5))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO5)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH05]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO5)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO5);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO5);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH05, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH05] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH05] = 0;
+ }
+ dev->cif_width[SRAM_CH05] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH05);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH05].count;
+
+ return ret_val;
+}
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 5 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH05);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template5 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c
new file mode 100644
index 000000000000..3c41b49e2ea9
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video6.c
@@ -0,0 +1,450 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH06]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH06]
+ && h->video_dev[SRAM_CH06]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH06;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO6))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO6)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH06]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO6)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO6);
+ }
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO6);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH06, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH06] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH06] = 0;
+ }
+ dev->cif_width[SRAM_CH06] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH06);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH06].count;
+
+ return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 6 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH06);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template6 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c
new file mode 100644
index 000000000000..625c9b78a9cf
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-video7.c
@@ -0,0 +1,449 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH07]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH07]
+ && h->video_dev[SRAM_CH07]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = SRAM_CH07;
+ pix_format =
+ (dev->pixel_formats[dev->channel_opened] ==
+ PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO7))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO7)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+ if (buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = fh->dev;
+
+ if (dev && dev->use_cif_resolution[SRAM_CH07]) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (fh->width * 2),
+ (fh->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
+ }
+
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO7)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO7);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO7);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+ int pix_format = 0;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->vidq.field = f->fmt.pix.field;
+
+ // check if width and height is valid based on set standard
+ if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) {
+ fh->width = f->fmt.pix.width;
+ }
+
+ if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) {
+ fh->height = f->fmt.pix.height;
+ }
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pix_format = PIXEL_FRMT_422;
+ else
+ return -EINVAL;
+
+ cx25821_set_pixel_format(dev, SRAM_CH07, pix_format);
+
+ // check if cif resolution
+ if (fh->width == 320 || fh->width == 352) {
+ dev->use_cif_resolution[SRAM_CH07] = 1;
+ } else {
+ dev->use_cif_resolution[SRAM_CH07] = 0;
+ }
+ dev->cif_width[SRAM_CH07] = fh->width;
+ medusa_set_resolution(dev, fh->width, SRAM_CH07);
+
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ int ret_val = 0;
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+ ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+ p->sequence = dev->vidq[SRAM_CH07].count;
+
+ return ret_val;
+}
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07];
+ u32 tmp = 0;
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ printk(KERN_INFO "Video input 7 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return cx25821_set_control(dev, ctl, SRAM_CH07);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template7 = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c
new file mode 100644
index 000000000000..2a312ce78c63
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-videoioctl.c
@@ -0,0 +1,496 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[VIDEO_IOCTL_CH]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ u32 pix_format;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->ioctl_dev && h->ioctl_dev->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = VIDEO_IOCTL_CH;
+ pix_format = V4L2_PIX_FMT_YUYV;
+ fh->fmt = format_by_fourcc(pix_format);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO_IOCTL)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO_IOCTL)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO_IOCTL);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO_IOCTL);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct downstream_user_struct *data_from_user;
+ int command;
+ int width = 720;
+ int selected_channel = 0, pix_format = 0, i = 0;
+ int cif_enable = 0, cif_width = 0;
+ u32 value = 0;
+
+ data_from_user = (struct downstream_user_struct *)arg;
+
+ if (!data_from_user) {
+ printk("cx25821 in %s(): User data is INVALID. Returning.\n",
+ __func__);
+ return 0;
+ }
+
+ command = data_from_user->command;
+
+ if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
+ && command != ENABLE_CIF_RESOLUTION && command != REG_READ
+ && command != REG_WRITE && command != MEDUSA_READ
+ && command != MEDUSA_WRITE) {
+ return 0;
+ }
+
+ switch (command) {
+ case SET_VIDEO_STD:
+ dev->tvnorm =
+ !strcmp(data_from_user->vid_stdname,
+ "PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+ medusa_set_videostandard(dev);
+ break;
+
+ case SET_PIXEL_FORMAT:
+ selected_channel = data_from_user->decoder_select;
+ pix_format = data_from_user->pixel_format;
+
+ if (!(selected_channel <= 7 && selected_channel >= 0)) {
+ selected_channel -= 4;
+ selected_channel = selected_channel % 8;
+ }
+
+ if (selected_channel >= 0)
+ cx25821_set_pixel_format(dev, selected_channel,
+ pix_format);
+
+ break;
+
+ case ENABLE_CIF_RESOLUTION:
+ selected_channel = data_from_user->decoder_select;
+ cif_enable = data_from_user->cif_resolution_enable;
+ cif_width = data_from_user->cif_width;
+
+ if (cif_enable) {
+ if (dev->tvnorm & V4L2_STD_PAL_BG
+ || dev->tvnorm & V4L2_STD_PAL_DK)
+ width = 352;
+ else
+ width = (cif_width == 320
+ || cif_width == 352) ? cif_width : 320;
+ }
+
+ if (!(selected_channel <= 7 && selected_channel >= 0)) {
+ selected_channel -= 4;
+ selected_channel = selected_channel % 8;
+ }
+
+ if (selected_channel <= 7 && selected_channel >= 0) {
+ dev->use_cif_resolution[selected_channel] = cif_enable;
+ dev->cif_width[selected_channel] = width;
+ } else {
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ dev->use_cif_resolution[i] = cif_enable;
+ dev->cif_width[i] = width;
+ }
+ }
+
+ medusa_set_resolution(dev, width, selected_channel);
+ break;
+ case REG_READ:
+ data_from_user->reg_data = cx_read(data_from_user->reg_address);
+ break;
+ case REG_WRITE:
+ cx_write(data_from_user->reg_address, data_from_user->reg_data);
+ break;
+ case MEDUSA_READ:
+ value =
+ cx25821_i2c_read(&dev->i2c_bus[0],
+ (u16) data_from_user->reg_address,
+ &data_from_user->reg_data);
+ break;
+ case MEDUSA_WRITE:
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ (u16) data_from_user->reg_address,
+ data_from_user->reg_data);
+ break;
+ }
+
+ return 0;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return 0;
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl_set,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+ .name = "cx25821-videoioctl",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c
new file mode 100644
index 000000000000..77b63b060405
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-vidups10.c
@@ -0,0 +1,435 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH10]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH10]
+ && h->video_dev[SRAM_CH10]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = 9;
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO10))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO10)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ //cx_write(channel10->dma_ctl, 0);
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO10)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO10);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO10);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+ int command = 0;
+ struct upstream_user_struct *data_from_user;
+
+ data_from_user = (struct upstream_user_struct *)arg;
+
+ if (!data_from_user) {
+ printk
+ ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
+ __func__);
+ return 0;
+ }
+
+ command = data_from_user->command;
+
+ if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) {
+ return 0;
+ }
+
+ dev->input_filename_ch2 = data_from_user->input_filename;
+ dev->input_audiofilename = data_from_user->input_filename;
+ dev->vid_stdname_ch2 = data_from_user->vid_stdname;
+ dev->pixel_format_ch2 = data_from_user->pixel_format;
+ dev->channel_select_ch2 = data_from_user->channel_select;
+ dev->command_ch2 = data_from_user->command;
+
+ switch (command) {
+ case UPSTREAM_START_VIDEO:
+ cx25821_start_upstream_video_ch2(dev, data_from_user);
+ break;
+
+ case UPSTREAM_STOP_VIDEO:
+ cx25821_stop_upstream_video_ch2(dev);
+ break;
+ }
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return 0;
+}
+
+//exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl_upstream10,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template10 = {
+ .name = "cx25821-upstream10",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c
new file mode 100644
index 000000000000..75c8c1eed2da
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821-vidups9.c
@@ -0,0 +1,433 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#include "cx25821-video.h"
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct cx25821_buffer *buf =
+ container_of(vb, struct cx25821_buffer, vb);
+ struct cx25821_buffer *prev;
+ struct cx25821_fh *fh = vq->priv_data;
+ struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09];
+
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+ buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ cx25821_start_video_dma(dev, q, buf,
+ &dev->sram_channels[SRAM_CH09]);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(2,
+ "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+ buf, buf->vb.i, buf->count, q->count);
+ } else {
+ prev =
+ list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width
+ && prev->vb.height == buf->vb.height
+ && prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(2,
+ "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+ buf, buf->vb.i, buf->count);
+
+ } else {
+ list_add_tail(&buf->vb.queue, &q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+ buf->vb.i);
+ }
+ }
+
+ if (list_empty(&q->active)) {
+ dprintk(2, "active queue empty!\n");
+ }
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+ int minor = video_devdata(file)->minor;
+ struct cx25821_dev *h, *dev = NULL;
+ struct cx25821_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+
+ lock_kernel();
+ list_for_each(list, &cx25821_devlist) {
+ h = list_entry(list, struct cx25821_dev, devlist);
+
+ if (h->video_dev[SRAM_CH09]
+ && h->video_dev[SRAM_CH09]->minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+
+ if (NULL == dev) {
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+ fh->width = 720;
+
+ if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+ fh->height = 576;
+ else
+ fh->height = 480;
+
+ dev->channel_opened = 8;
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+ v4l2_prio_open(&dev->prio, &fh->prio);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx25821_buffer), fh);
+
+ dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
+
+ return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+ loff_t * ppos)
+{
+ struct cx25821_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (res_locked(fh->dev, RESOURCE_VIDEO9))
+ return -EBUSY;
+
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static unsigned int video_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_buffer *buf;
+
+ if (res_check(fh, RESOURCE_VIDEO9)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vidq.stream.next,
+ struct cx25821_buffer, vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+
+ //stop the risc engine and fifo
+ //cx_write(channel9->dma_ctl, 0);
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO9)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev, fh, RESOURCE_VIDEO9);
+ }
+
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq, fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+
+ v4l2_prio_close(&dev->prio, &fh->prio);
+
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(i != fh->type)) {
+ return -EINVAL;
+ }
+
+ if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) {
+ return -EBUSY;
+ }
+
+ return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = fh->dev;
+ int err, res;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (i != fh->type)
+ return -EINVAL;
+
+ res = get_resource(fh, RESOURCE_VIDEO9);
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev, fh, res);
+ return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cx25821_fh *fh = file->private_data;
+ struct cx25821_dev *dev = fh->dev;
+ int command = 0;
+ struct upstream_user_struct *data_from_user;
+
+ data_from_user = (struct upstream_user_struct *)arg;
+
+ if (!data_from_user) {
+ printk
+ ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
+ __func__);
+ return 0;
+ }
+
+ command = data_from_user->command;
+
+ if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) {
+ return 0;
+ }
+
+ dev->input_filename = data_from_user->input_filename;
+ dev->input_audiofilename = data_from_user->input_filename;
+ dev->vid_stdname = data_from_user->vid_stdname;
+ dev->pixel_format = data_from_user->pixel_format;
+ dev->channel_select = data_from_user->channel_select;
+ dev->command = data_from_user->command;
+
+ switch (command) {
+ case UPSTREAM_START_VIDEO:
+ cx25821_start_upstream_video_ch1(dev, data_from_user);
+ break;
+
+ case UPSTREAM_STOP_VIDEO:
+ cx25821_stop_upstream_video_ch1(dev);
+ break;
+ }
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_fh *fh = priv;
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ int err;
+
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+ fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
+ fh->height, fh->vidq.field);
+ cx25821_call_all(dev, video, s_fmt, f);
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx25821_fh *fh = priv;
+ return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ char name[32 + 2];
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx25821_call_all(dev, core, log_status);
+ printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+ struct cx25821_fh *fh = priv;
+ int err;
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ }
+
+ return 0;
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
+ .ioctl = video_ioctl_upstream9,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
+#endif
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_g_priority = vidioc_g_priority,
+ .vidioc_s_priority = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template9 = {
+ .name = "cx25821-upstream9",
+ .fops = &video_fops,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h
new file mode 100644
index 000000000000..cf2286d83b6a
--- /dev/null
+++ b/drivers/staging/cx25821/cx25821.h
@@ -0,0 +1,602 @@
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on Steven Toth <stoth@linuxtv.org> cx23885 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 CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kdev_t.h>
+#include <linux/smp_lock.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE 1
+#define FALSE 0
+#define LINE_SIZE_D1 1440
+
+// Number of decoders and encoders
+#define MAX_DECODERS 8
+#define MAX_ENCODERS 2
+#define QUAD_DECODERS 4
+#define MAX_CAMERAS 16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT 8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0 1
+#define RESOURCE_VIDEO1 2
+#define RESOURCE_VIDEO2 4
+#define RESOURCE_VIDEO3 8
+#define RESOURCE_VIDEO4 16
+#define RESOURCE_VIDEO5 32
+#define RESOURCE_VIDEO6 64
+#define RESOURCE_VIDEO7 128
+#define RESOURCE_VIDEO8 256
+#define RESOURCE_VIDEO9 512
+#define RESOURCE_VIDEO10 1024
+#define RESOURCE_VIDEO11 2048
+#define RESOURCE_VIDEO_IOCTL 4096
+
+#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */
+
+#define UNKNOWN_BOARD 0
+#define CX25821_BOARD 1
+
+/* Currently supported by the driver */
+#define CX25821_NORMS (\
+ V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+ V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
+ V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \
+ V4L2_STD_PAL_Nc )
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM 12
+#define VID_CHANNEL_NUM 8
+
+struct cx25821_fmt {
+ char *name;
+ u32 fourcc; /* v4l2 format id */
+ int depth;
+ int flags;
+ u32 cxformat;
+};
+
+struct cx25821_ctrl {
+ struct v4l2_queryctrl v;
+ u32 off;
+ u32 reg;
+ u32 mask;
+ u32 shift;
+};
+
+struct cx25821_tvnorm {
+ char *name;
+ v4l2_std_id id;
+ u32 cxiformat;
+ u32 cxoformat;
+};
+
+struct cx25821_fh {
+ struct cx25821_dev *dev;
+ enum v4l2_buf_type type;
+ int radio;
+ u32 resources;
+
+ enum v4l2_priority prio;
+
+ /* video overlay */
+ struct v4l2_window win;
+ struct v4l2_clip *clips;
+ unsigned int nclips;
+
+ /* video capture */
+ struct cx25821_fmt *fmt;
+ unsigned int width, height;
+
+ /* vbi capture */
+ struct videobuf_queue vidq;
+ struct videobuf_queue vbiq;
+
+ /* H264 Encoder specifics ONLY */
+ struct videobuf_queue mpegq;
+ atomic_t v4l_reading;
+};
+
+enum cx25821_itype {
+ CX25821_VMUX_COMPOSITE = 1,
+ CX25821_VMUX_SVIDEO,
+ CX25821_VMUX_DEBUG,
+ CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+ CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+ CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct videobuf_buffer vb;
+
+ /* cx25821 specific */
+ unsigned int bpl;
+ struct btcx_riscmem risc;
+ struct cx25821_fmt *fmt;
+ u32 count;
+};
+
+struct cx25821_input {
+ enum cx25821_itype type;
+ unsigned int vmux;
+ u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+typedef enum {
+ CX25821_UNDEFINED = 0,
+ CX25821_RAW,
+ CX25821_264
+} port_t;
+
+struct cx25821_board {
+ char *name;
+ port_t porta, portb, portc;
+ unsigned int tuner_type;
+ unsigned int radio_type;
+ unsigned char tuner_addr;
+ unsigned char radio_addr;
+
+ u32 clk_freq;
+ struct cx25821_input input[2];
+};
+
+struct cx25821_subid {
+ u16 subvendor;
+ u16 subdevice;
+ u32 card;
+};
+
+struct cx25821_i2c {
+ struct cx25821_dev *dev;
+
+ int nr;
+
+ /* i2c i/o */
+ struct i2c_adapter i2c_adap;
+ struct i2c_algo_bit_data i2c_algo;
+ struct i2c_client i2c_client;
+ u32 i2c_rc;
+
+ /* cx25821 registers used for raw addess */
+ u32 i2c_period;
+ u32 reg_ctrl;
+ u32 reg_stat;
+ u32 reg_addr;
+ u32 reg_rdata;
+ u32 reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+ struct list_head active;
+ struct list_head queued;
+ struct timer_list timeout;
+ struct btcx_riscmem stopper;
+ u32 count;
+};
+
+struct cx25821_data {
+ struct cx25821_dev *dev;
+ struct sram_channel *channel;
+};
+
+struct cx25821_dev {
+ struct list_head devlist;
+ atomic_t refcount;
+ struct v4l2_device v4l2_dev;
+
+ struct v4l2_prio_state prio;
+
+ /* pci stuff */
+ struct pci_dev *pci;
+ unsigned char pci_rev, pci_lat;
+ int pci_bus, pci_slot;
+ u32 base_io_addr;
+ u32 __iomem *lmmio;
+ u8 __iomem *bmmio;
+ int pci_irqmask;
+ int hwrevision;
+
+ u32 clk_freq;
+
+ /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+ struct cx25821_i2c i2c_bus[3];
+
+ int nr;
+ struct mutex lock;
+
+ /* board details */
+ unsigned int board;
+ char name[32];
+
+ /* sram configuration */
+ struct sram_channel *sram_channels;
+
+ /* Analog video */
+ u32 resources;
+ unsigned int input;
+ u32 tvaudio;
+ v4l2_std_id tvnorm;
+ unsigned int tuner_type;
+ unsigned char tuner_addr;
+ unsigned int radio_type;
+ unsigned char radio_addr;
+ unsigned int has_radio;
+ unsigned int videc_type;
+ unsigned char videc_addr;
+ unsigned short _max_num_decoders;
+
+ int ctl_bright;
+ int ctl_contrast;
+ int ctl_hue;
+ int ctl_saturation;
+
+ struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+ /* Analog Audio Upstream */
+ int _audio_is_running;
+ int _audiopixel_format;
+ int _is_first_audio_frame;
+ int _audiofile_status;
+ int _audio_lines_count;
+ int _audioframe_count;
+ int _audio_upstream_channel_select;
+ int _last_index_irq; //The last interrupt index processed.
+
+ __le32 *_risc_audio_jmp_addr;
+ __le32 *_risc_virt_start_addr;
+ __le32 *_risc_virt_addr;
+ dma_addr_t _risc_phys_addr;
+ dma_addr_t _risc_phys_start_addr;
+
+ unsigned int _audiorisc_size;
+ unsigned int _audiodata_buf_size;
+ __le32 *_audiodata_buf_virt_addr;
+ dma_addr_t _audiodata_buf_phys_addr;
+ char *_audiofilename;
+
+ /* V4l */
+ u32 freq;
+ struct video_device *video_dev[MAX_VID_CHANNEL_NUM];
+ struct video_device *vbi_dev;
+ struct video_device *radio_dev;
+ struct video_device *ioctl_dev;
+
+ struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM];
+ spinlock_t slock;
+
+ /* Video Upstream */
+ int _line_size;
+ int _prog_cnt;
+ int _pixel_format;
+ int _is_first_frame;
+ int _is_running;
+ int _file_status;
+ int _lines_count;
+ int _frame_count;
+ int _channel_upstream_select;
+ unsigned int _risc_size;
+
+ __le32 *_dma_virt_start_addr;
+ __le32 *_dma_virt_addr;
+ dma_addr_t _dma_phys_addr;
+ dma_addr_t _dma_phys_start_addr;
+
+ unsigned int _data_buf_size;
+ __le32 *_data_buf_virt_addr;
+ dma_addr_t _data_buf_phys_addr;
+ char *_filename;
+ char *_defaultname;
+
+ int _line_size_ch2;
+ int _prog_cnt_ch2;
+ int _pixel_format_ch2;
+ int _is_first_frame_ch2;
+ int _is_running_ch2;
+ int _file_status_ch2;
+ int _lines_count_ch2;
+ int _frame_count_ch2;
+ int _channel2_upstream_select;
+ unsigned int _risc_size_ch2;
+
+ __le32 *_dma_virt_start_addr_ch2;
+ __le32 *_dma_virt_addr_ch2;
+ dma_addr_t _dma_phys_addr_ch2;
+ dma_addr_t _dma_phys_start_addr_ch2;
+
+ unsigned int _data_buf_size_ch2;
+ __le32 *_data_buf_virt_addr_ch2;
+ dma_addr_t _data_buf_phys_addr_ch2;
+ char *_filename_ch2;
+ char *_defaultname_ch2;
+
+ /* MPEG Encoder ONLY settings */
+ u32 cx23417_mailbox;
+ struct cx2341x_mpeg_params mpeg_params;
+ struct video_device *v4l_device;
+ atomic_t v4l_reader_count;
+ struct cx25821_tvnorm encodernorm;
+
+ u32 upstream_riscbuf_size;
+ u32 upstream_databuf_size;
+ u32 upstream_riscbuf_size_ch2;
+ u32 upstream_databuf_size_ch2;
+ u32 audio_upstream_riscbuf_size;
+ u32 audio_upstream_databuf_size;
+ int _isNTSC;
+ int _frame_index;
+ int _audioframe_index;
+ struct workqueue_struct *_irq_queues;
+ struct work_struct _irq_work_entry;
+ struct workqueue_struct *_irq_queues_ch2;
+ struct work_struct _irq_work_entry_ch2;
+ struct workqueue_struct *_irq_audio_queues;
+ struct work_struct _audio_work_entry;
+ char *input_filename;
+ char *input_filename_ch2;
+ int _frame_index_ch2;
+ int _isNTSC_ch2;
+ char *vid_stdname_ch2;
+ int pixel_format_ch2;
+ int channel_select_ch2;
+ int command_ch2;
+ char *input_audiofilename;
+ char *vid_stdname;
+ int pixel_format;
+ int channel_select;
+ int command;
+ int pixel_formats[VID_CHANNEL_NUM];
+ int use_cif_resolution[VID_CHANNEL_NUM];
+ int cif_width[VID_CHANNEL_NUM];
+ int channel_opened;
+};
+
+struct upstream_user_struct {
+ char *input_filename;
+ char *vid_stdname;
+ int pixel_format;
+ int channel_select;
+ int command;
+};
+
+struct downstream_user_struct {
+ char *vid_stdname;
+ int pixel_format;
+ int cif_resolution_enable;
+ int cif_width;
+ int decoder_select;
+ int command;
+ int reg_address;
+ int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+ return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+extern struct list_head cx25821_devlist;
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00 0 /* Video A */
+#define SRAM_CH01 1 /* Video B */
+#define SRAM_CH02 2 /* Video C */
+#define SRAM_CH03 3 /* Video D */
+#define SRAM_CH04 4 /* Video E */
+#define SRAM_CH05 5 /* Video F */
+#define SRAM_CH06 6 /* Video G */
+#define SRAM_CH07 7 /* Video H */
+
+#define SRAM_CH08 8 /* Audio A */
+#define SRAM_CH09 9 /* Video Upstream I */
+#define SRAM_CH10 10 /* Video Upstream J */
+#define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11
+#define VIDEO_IOCTL_CH 11
+
+struct sram_channel {
+ char *name;
+ u32 i;
+ u32 cmds_start;
+ u32 ctrl_start;
+ u32 cdt;
+ u32 fifo_start;
+ u32 fifo_size;
+ u32 ptr1_reg;
+ u32 ptr2_reg;
+ u32 cnt1_reg;
+ u32 cnt2_reg;
+ u32 int_msk;
+ u32 int_stat;
+ u32 int_mstat;
+ u32 dma_ctl;
+ u32 gpcnt_ctl;
+ u32 gpcnt;
+ u32 aud_length;
+ u32 aud_cfg;
+ u32 fld_aud_fifo_en;
+ u32 fld_aud_risc_en;
+
+ //For Upstream Video
+ u32 vid_fmt_ctl;
+ u32 vid_active_ctl1;
+ u32 vid_active_ctl2;
+ u32 vid_cdt_size;
+
+ u32 vip_ctl;
+ u32 pix_frmt;
+ u32 jumponly;
+ u32 irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS 0
+#define STATUS_UNSUCCESSFUL -1
+
+#define cx_read(reg) readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+ writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+ ((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit) cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit) cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit) (1 << Bit)
+#define Clear_GPIO_Bit(Bit) (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...) printk(KERN_ERR "cx25821(%d): " fmt, dev->board, ## args)
+#define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args)
+#define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int cx25821_ir_init(struct cx25821_dev *dev);
+extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+ int pin_number, int pin_logic_value);
+
+extern int medusa_video_init(struct cx25821_dev *dev);
+extern int medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
+ int decoder_select);
+extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
+ int decoder);
+extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
+ int decoder);
+extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
+ int decoder);
+
+extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+ struct sram_channel *ch, unsigned int bpl,
+ u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int top_offset,
+ unsigned int bottom_offset,
+ unsigned int bpl,
+ unsigned int padding, unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int bpl,
+ unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct videobuf_queue *q,
+ struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+ u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+ struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+ struct sram_channel *ch);
+
+extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
+ int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc);
+
+extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
+ int channel_select, int pixel_format);
+extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
+ int channel_select, int pixel_format);
+extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
+ int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+ struct upstream_user_struct
+ *up_data);
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+ struct upstream_user_struct
+ *up_data);
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+ struct upstream_user_struct *up_data);
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+ u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+ struct pci_dev *pci,
+ struct video_device *template,
+ char *type);
+#endif
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
index ac8577358ba0..c24e4e0367a2 100644
--- a/drivers/staging/dst/dcore.c
+++ b/drivers/staging/dst/dcore.c
@@ -102,7 +102,7 @@ static int dst_request(struct request_queue *q, struct bio *bio)
struct dst_node *n = q->queuedata;
int err = -EIO;
- if (bio_empty_barrier(bio) && !q->prepare_discard_fn) {
+ if (bio_empty_barrier(bio) && !blk_queue_discard(q)) {
/*
* This is a dirty^Wnice hack, but if we complete this
* operation with -EOPNOTSUPP like intended, XFS
@@ -847,7 +847,7 @@ static dst_command_func dst_commands[] = {
/*
* Configuration parser.
*/
-static void cn_dst_callback(struct cn_msg *msg)
+static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct dst_ctl *ctl;
int err;
@@ -855,6 +855,11 @@ static void cn_dst_callback(struct cn_msg *msg)
struct dst_node *n = NULL, *tmp;
unsigned int hash;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
if (msg->len < sizeof(struct dst_ctl)) {
err = -EBADMSG;
goto out;
diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h
index 6294d3814e72..2c3d65a622a7 100644
--- a/drivers/staging/et131x/et1310_address_map.h
+++ b/drivers/staging/et131x/et1310_address_map.h
@@ -223,7 +223,7 @@ typedef union _TXDMA_PR_NUM_DES_t {
extern inline void add_10bit(u32 *v, int n)
{
- *v = INDEX10(*v + n);
+ *v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP);
}
/*
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
index 8f2e91fa0a86..10e21db57ac3 100644
--- a/drivers/staging/et131x/et1310_rx.c
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -1177,12 +1177,20 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
static inline u32 bump_fbr(u32 *fbr, u32 limit)
{
- u32 v = *fbr;
- add_10bit(&v, 1);
- if (v > limit)
- v = (*fbr & ~ET_DMA10_MASK) ^ ET_DMA10_WRAP;
- *fbr = v;
- return v;
+ u32 v = *fbr;
+ v++;
+ /* This works for all cases where limit < 1024. The 1023 case
+ works because 1023++ is 1024 which means the if condition is not
+ taken but the carry of the bit into the wrap bit toggles the wrap
+ value correctly */
+ if ((v & ET_DMA10_MASK) > limit) {
+ v &= ~ET_DMA10_MASK;
+ v ^= ET_DMA10_WRAP;
+ }
+ /* For the 1023 case */
+ v &= (ET_DMA10_MASK|ET_DMA10_WRAP);
+ *fbr = v;
+ return v;
}
/**
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index ca6ade6c4b47..e47f683a323e 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,5 +1,5 @@
config VIDEO_GO7007
- tristate "Go 7007 support"
+ tristate "WIS GO7007 MPEG encoder support"
depends on VIDEO_DEV && PCI && I2C && INPUT
depends on SND
select VIDEOBUF_DMA_SG
@@ -10,17 +10,19 @@ config VIDEO_GO7007
select CRC32
default N
---help---
- This is a video4linux driver for some weird device...
+ This is a video4linux driver for the WIS GO7007 MPEG
+ encoder chip.
To compile this driver as a module, choose M here: the
module will be called go7007
config VIDEO_GO7007_USB
- tristate "Go 7007 USB support"
+ tristate "WIS GO7007 USB support"
depends on VIDEO_GO7007 && USB
default N
---help---
- This is a video4linux driver for some weird device...
+ This is a video4linux driver for the WIS GO7007 MPEG
+ encoder chip over USB.
To compile this driver as a module, choose M here: the
module will be called go7007-usb
@@ -30,8 +32,78 @@ config VIDEO_GO7007_USB_S2250_BOARD
depends on VIDEO_GO7007_USB && DVB_USB
default N
---help---
- This is a video4linux driver for the Sensoray 2250/2251 device
+ This is a video4linux driver for the Sensoray 2250/2251 device.
To compile this driver as a module, choose M here: the
- module will be called s2250-board
+ module will be called s2250
+
+config VIDEO_GO7007_OV7640
+ tristate "OV7640 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the OV7640 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-ov7640
+
+config VIDEO_GO7007_SAA7113
+ tristate "SAA7113 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the SAA7113 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-saa7113
+
+config VIDEO_GO7007_SAA7115
+ tristate "SAA7115 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the SAA7115 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-saa7115
+
+config VIDEO_GO7007_TW9903
+ tristate "TW9903 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the TW9903 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-tw9903
+
+config VIDEO_GO7007_UDA1342
+ tristate "UDA1342 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the UDA1342 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-uda1342
+
+config VIDEO_GO7007_SONY_TUNER
+ tristate "Sony tuner subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the Sony Tuner sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-sony-tuner
+
+config VIDEO_GO7007_TW2804
+ tristate "TW2804 subdev support"
+ depends on VIDEO_GO7007
+ default N
+ ---help---
+ This is a video4linux driver for the TW2804 sub-device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wis-tw2804
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile
index e514b4af6d06..1301caa7495d 100644
--- a/drivers/staging/go7007/Makefile
+++ b/drivers/staging/go7007/Makefile
@@ -6,22 +6,29 @@
obj-$(CONFIG_VIDEO_GO7007) += go7007.o
obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
+obj-$(CONFIG_VIDEO_GO7007_SAA7113) += wis-saa7113.o
+obj-$(CONFIG_VIDEO_GO7007_OV7640) += wis-ov7640.o
+obj-$(CONFIG_VIDEO_GO7007_SAA7115) += wis-saa7115.o
+obj-$(CONFIG_VIDEO_GO7007_TW9903) += wis-tw9903.o
+obj-$(CONFIG_VIDEO_GO7007_UDA1342) += wis-uda1342.o
+obj-$(CONFIG_VIDEO_GO7007_SONY_TUNER) += wis-sony-tuner.o
+obj-$(CONFIG_VIDEO_GO7007_TW2804) += wis-tw2804.o
go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
- snd-go7007.o wis-saa7113.o
+ snd-go7007.o
s2250-objs += s2250-board.o s2250-loader.o
-# Uncompile when the saa7134 patches get into upstream
+# Uncomment when the saa7134 patches get into upstream
#ifneq ($(CONFIG_VIDEO_SAA7134),)
#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
-#EXTRA_CFLAGS += -Idrivers/media/video/saa7134
+#EXTRA_CFLAGS += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3
#endif
+# S2250 needs cypress ezusb loader from dvb-usb
ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),)
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
endif
-EXTRA_CFLAGS += -Idrivers/staging/saa7134
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index 77b1e769ac92..472f4bb08fdc 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -27,7 +27,7 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/firmware.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/system.h>
#include <linux/videodev2.h>
@@ -49,7 +49,7 @@ int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
go->hpi_ops->read_interrupt(go);
if (wait_event_timeout(go->interrupt_waitq,
go->interrupt_available, 5*HZ) < 0) {
- printk(KERN_ERR "go7007: timeout waiting for read interrupt\n");
+ v4l2_err(go->video_dev, "timeout waiting for read interrupt\n");
return -1;
}
if (!go->interrupt_available)
@@ -97,13 +97,12 @@ static int go7007_load_encoder(struct go7007 *go)
u16 intr_val, intr_data;
if (request_firmware(&fw_entry, fw_name, go->dev)) {
- printk(KERN_ERR
- "go7007: unable to load firmware from file \"%s\"\n",
- fw_name);
+ v4l2_err(go, "unable to load firmware from file "
+ "\"%s\"\n", fw_name);
return -1;
}
if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
- printk(KERN_ERR "go7007: file \"%s\" does not appear to be "
+ v4l2_err(go, "file \"%s\" does not appear to be "
"go7007 firmware\n", fw_name);
release_firmware(fw_entry);
return -1;
@@ -111,7 +110,7 @@ static int go7007_load_encoder(struct go7007 *go)
fw_len = fw_entry->size - 16;
bounce = kmalloc(fw_len, GFP_KERNEL);
if (bounce == NULL) {
- printk(KERN_ERR "go7007: unable to allocate %d bytes for "
+ v4l2_err(go, "unable to allocate %d bytes for "
"firmware transfer\n", fw_len);
release_firmware(fw_entry);
return -1;
@@ -122,7 +121,7 @@ static int go7007_load_encoder(struct go7007 *go)
go7007_send_firmware(go, bounce, fw_len) < 0 ||
go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
(intr_val & ~0x1) != 0x5a5a) {
- printk(KERN_ERR "go7007: error transferring firmware\n");
+ v4l2_err(go, "error transferring firmware\n");
rv = -1;
}
kfree(bounce);
@@ -140,9 +139,9 @@ int go7007_boot_encoder(struct go7007 *go, int init_i2c)
{
int ret;
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
ret = go7007_load_encoder(go);
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
if (ret < 0)
return -1;
if (!init_i2c)
@@ -257,9 +256,9 @@ int go7007_register_encoder(struct go7007 *go)
printk(KERN_INFO "go7007: registering new %s\n", go->name);
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
ret = go7007_init_encoder(go);
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
if (ret < 0)
return -1;
@@ -316,7 +315,7 @@ int go7007_start_encoder(struct go7007 *go)
if (go7007_send_firmware(go, fw, fw_len) < 0 ||
go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
- printk(KERN_ERR "go7007: error transferring firmware\n");
+ v4l2_err(go->video_dev, "error transferring firmware\n");
rv = -1;
goto start_error;
}
@@ -325,7 +324,7 @@ int go7007_start_encoder(struct go7007 *go)
go->parse_length = 0;
go->seen_frame = 0;
if (go7007_stream_start(go) < 0) {
- printk(KERN_ERR "go7007: error starting stream transfer\n");
+ v4l2_err(go->video_dev, "error starting stream transfer\n");
rv = -1;
goto start_error;
}
@@ -421,7 +420,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
for (i = 0; i < length; ++i) {
if (go->active_buf != NULL &&
go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) {
- printk(KERN_DEBUG "go7007: dropping oversized frame\n");
+ v4l2_info(go->video_dev, "dropping oversized frame\n");
go->active_buf->offset -= go->active_buf->bytesused;
go->active_buf->bytesused = 0;
go->active_buf->modet_active = 0;
@@ -604,7 +603,7 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
go->tuner_type = -1;
go->channel_number = 0;
go->name[0] = 0;
- init_MUTEX(&go->hw_lock);
+ mutex_init(&go->hw_lock);
init_waitqueue_head(&go->frame_waitq);
spin_lock_init(&go->spinlock);
go->video_dev = NULL;
@@ -669,8 +668,8 @@ void go7007_remove(struct go7007 *go)
if (i2c_del_adapter(&go->i2c_adapter) == 0)
go->i2c_adapter_online = 0;
else
- printk(KERN_ERR
- "go7007: error removing I2C adapter!\n");
+ v4l2_err(go->video_dev,
+ "error removing I2C adapter!\n");
}
if (go->audio_enabled)
diff --git a/drivers/staging/go7007/go7007-fw.c b/drivers/staging/go7007/go7007-fw.c
index 871ed43e4e05..a8bb264e0074 100644
--- a/drivers/staging/go7007/go7007-fw.c
+++ b/drivers/staging/go7007/go7007-fw.c
@@ -1034,7 +1034,8 @@ static int brctrl_to_package(struct go7007 *go,
0xBF1B, framelen[7],
0, 0,
-#if 0 /* Remove once we don't care about matching */
+#if 0
+ /* Remove once we don't care about matching */
0x200e, 0x0000,
0xBF56, 4,
0xBF57, 0,
diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c
index c82867fdd28d..b8cfa1a6eaeb 100644
--- a/drivers/staging/go7007/go7007-i2c.c
+++ b/drivers/staging/go7007/go7007-i2c.c
@@ -24,7 +24,7 @@
#include <linux/time.h>
#include <linux/device.h>
#include <linux/i2c.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/system.h>
@@ -48,7 +48,7 @@
/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs
* on the Adlink PCI-MPG24, so access is shared between all of them. */
-static DECLARE_MUTEX(adlink_mpg24_i2c_lock);
+static DEFINE_MUTEX(adlink_mpg24_i2c_lock);
static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
u16 command, int flags, u8 *data)
@@ -69,11 +69,11 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
*data, command, addr);
#endif
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
/* Bridge the I2C port on this GO7007 to the shared bus */
- down(&adlink_mpg24_i2c_lock);
+ mutex_lock(&adlink_mpg24_i2c_lock);
go7007_write_addr(go, 0x3c82, 0x0020);
}
@@ -134,9 +134,9 @@ i2c_done:
if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
/* Isolate the I2C port on this GO7007 from the shared bus */
go7007_write_addr(go, 0x3c82, 0x0000);
- up(&adlink_mpg24_i2c_lock);
+ mutex_unlock(&adlink_mpg24_i2c_lock);
}
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
return ret;
}
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h
index 178d18119faa..ce9307e3e186 100644
--- a/drivers/staging/go7007/go7007-priv.h
+++ b/drivers/staging/go7007/go7007-priv.h
@@ -132,7 +132,7 @@ struct go7007_buffer {
struct go7007_file {
struct go7007 *go;
- struct semaphore lock;
+ struct mutex lock;
int buf_count;
struct go7007_buffer *bufs;
};
@@ -170,7 +170,7 @@ struct go7007 {
int ref_count;
enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
spinlock_t spinlock;
- struct semaphore hw_lock;
+ struct mutex hw_lock;
int streaming;
int in_use;
int audio_enabled;
@@ -240,7 +240,7 @@ struct go7007 {
unsigned short interrupt_data;
};
-/* All of these must be called with the hpi_lock semaphore held! */
+/* All of these must be called with the hpi_lock mutex held! */
#define go7007_interface_reset(go) \
((go)->hpi_ops->interface_reset(go))
#define go7007_write_interrupt(go, x, y) \
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index aa4a9e0b9954..ecaa3c989cf4 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -33,7 +33,8 @@
static unsigned int assume_endura;
module_param(assume_endura, int, 0644);
-MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura");
+MODULE_PARM_DESC(assume_endura, "when probing fails, "
+ "hardware is a Pelco Endura");
/* #define GO7007_USB_DEBUG */
/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
@@ -44,12 +45,12 @@ MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura"
/*
* Pipes on EZ-USB interface:
- * 0 snd - Control
- * 0 rcv - Control
- * 2 snd - Download firmware (control)
- * 4 rcv - Read Interrupt (interrupt)
- * 6 rcv - Read Video (bulk)
- * 8 rcv - Read Audio (bulk)
+ * 0 snd - Control
+ * 0 rcv - Control
+ * 2 snd - Download firmware (control)
+ * 4 rcv - Read Interrupt (interrupt)
+ * 6 rcv - Read Video (bulk)
+ * 8 rcv - Read Audio (bulk)
*/
#define GO7007_USB_EZUSB (1<<0)
@@ -62,7 +63,7 @@ struct go7007_usb_board {
struct go7007_usb {
struct go7007_usb_board *board;
- struct semaphore i2c_lock;
+ struct mutex i2c_lock;
struct usb_device *usbdev;
struct urb *video_urbs[8];
struct urb *audio_urbs[8];
@@ -97,7 +98,7 @@ static struct go7007_usb_board board_matrix_ii = {
},
},
.num_inputs = 2,
- .inputs = {
+ .inputs = {
{
.video_input = 0,
.name = "Composite",
@@ -134,7 +135,7 @@ static struct go7007_usb_board board_matrix_reload = {
},
},
.num_inputs = 2,
- .inputs = {
+ .inputs = {
{
.video_input = 0,
.name = "Composite",
@@ -172,7 +173,7 @@ static struct go7007_usb_board board_star_trek = {
},
},
.num_inputs = 2,
- .inputs = {
+ .inputs = {
{
.video_input = 1,
/* .audio_input = AUDIO_EXTERN, */
@@ -228,7 +229,7 @@ static struct go7007_usb_board board_px_tv402u = {
},
},
.num_inputs = 3,
- .inputs = {
+ .inputs = {
{
.video_input = 1,
.audio_input = TVAUDIO_INPUT_EXTERN,
@@ -276,7 +277,7 @@ static struct go7007_usb_board board_xmen = {
},
},
.num_inputs = 1,
- .inputs = {
+ .inputs = {
{
.name = "Camera",
},
@@ -309,7 +310,7 @@ static struct go7007_usb_board board_matrix_revolution = {
},
},
.num_inputs = 2,
- .inputs = {
+ .inputs = {
{
.video_input = 2,
.name = "Composite",
@@ -341,7 +342,7 @@ static struct go7007_usb_board board_lifeview_lr192 = {
GO7007_SENSOR_SCALING,
.num_i2c_devs = 0,
.num_inputs = 1,
- .inputs = {
+ .inputs = {
{
.video_input = 0,
.name = "Composite",
@@ -367,7 +368,7 @@ static struct go7007_usb_board board_endura = {
.sensor_h_offset = 8,
.num_i2c_devs = 0,
.num_inputs = 1,
- .inputs = {
+ .inputs = {
{
.name = "Camera",
},
@@ -399,7 +400,7 @@ static struct go7007_usb_board board_adlink_mpg24 = {
},
},
.num_inputs = 1,
- .inputs = {
+ .inputs = {
{
.name = "Composite",
},
@@ -430,7 +431,7 @@ static struct go7007_usb_board board_sensoray_2250 = {
},
},
.num_inputs = 2,
- .inputs = {
+ .inputs = {
{
.video_input = 0,
.name = "Composite",
@@ -734,14 +735,15 @@ static int go7007_usb_read_interrupt(struct go7007 *go)
static void go7007_usb_read_video_pipe_complete(struct urb *urb)
{
struct go7007 *go = (struct go7007 *)urb->context;
- int r, status = urb-> status;
+ int r, status = urb->status;
if (!go->streaming) {
wake_up_interruptible(&go->frame_waitq);
return;
}
if (status) {
- printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", status);
+ printk(KERN_ERR "go7007-usb: error in video pipe: %d\n",
+ status);
return;
}
if (urb->actual_length != urb->transfer_buffer_length) {
@@ -762,7 +764,8 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
if (!go->streaming)
return;
if (status) {
- printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", status);
+ printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
+ status);
return;
}
if (urb->actual_length != urb->transfer_buffer_length) {
@@ -877,7 +880,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
if (go->status == STATUS_SHUTDOWN)
return -1;
- down(&usb->i2c_lock);
+ mutex_lock(&usb->i2c_lock);
for (i = 0; i < num; ++i) {
/* The hardware command is "write some bytes then read some
@@ -935,7 +938,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
ret = 0;
i2c_done:
- up(&usb->i2c_lock);
+ mutex_unlock(&usb->i2c_lock);
return ret;
}
@@ -1017,7 +1020,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
break;
case GO7007_BOARDID_SENSORAY_2250:
printk(KERN_INFO "Sensoray 2250 found\n");
- name = "Sensoray 2250/2251\n";
+ name = "Sensoray 2250/2251";
board = &board_sensoray_2250;
break;
default:
@@ -1065,7 +1068,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
if (board->flags & GO7007_USB_EZUSB_I2C) {
memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
sizeof(go7007_usb_adap_templ));
- init_MUTEX(&usb->i2c_lock);
+ mutex_init(&usb->i2c_lock);
go->i2c_adapter.dev.parent = go->dev;
i2c_set_adapdata(&go->i2c_adapter, go);
if (i2c_add_adapter(&go->i2c_adapter) < 0) {
@@ -1096,7 +1099,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
usb->board = board = &board_endura;
go->board_info = &board->main_info;
strncpy(go->name, "Pelco Endura",
- sizeof(go->name));
+ sizeof(go->name));
} else {
u16 channel;
@@ -1154,8 +1157,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
* to the EZ-USB GPIO output pins */
if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
NULL, 0, 0) < 0) {
- printk(KERN_ERR
- "go7007-usb: GPIO write failed!\n");
+ printk(KERN_ERR "go7007-usb: GPIO write failed!\n");
goto initfail;
}
}
diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c
index 06cacd37bbd8..4bd353afa596 100644
--- a/drivers/staging/go7007/go7007-v4l2.c
+++ b/drivers/staging/go7007/go7007-v4l2.c
@@ -30,7 +30,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/i2c.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/system.h>
@@ -75,7 +75,7 @@ static int go7007_streamoff(struct go7007 *go)
int retval = -EINVAL;
unsigned long flags;
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
if (go->streaming) {
go->streaming = 0;
go7007_stream_stop(go);
@@ -85,7 +85,7 @@ static int go7007_streamoff(struct go7007 *go)
go7007_reset_encoder(go);
retval = 0;
}
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
return 0;
}
@@ -101,7 +101,7 @@ static int go7007_open(struct file *file)
return -ENOMEM;
++go->ref_count;
gofh->go = go;
- init_MUTEX(&gofh->lock);
+ mutex_init(&gofh->lock);
gofh->buf_count = 0;
file->private_data = gofh;
return 0;
@@ -383,13 +383,10 @@ static int clip_to_modet_map(struct go7007 *go, int region,
}
return 0;
}
+#endif
-static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
+static int mpeg_queryctrl(struct v4l2_queryctrl *ctrl)
{
- static const u32 user_ctrls[] = {
- V4L2_CID_USER_CLASS,
- 0
- };
static const u32 mpeg_ctrls[] = {
V4L2_CID_MPEG_CLASS,
V4L2_CID_MPEG_STREAM_TYPE,
@@ -401,26 +398,15 @@ static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
0
};
static const u32 *ctrl_classes[] = {
- user_ctrls,
mpeg_ctrls,
NULL
};
- /* The ctrl may already contain the queried i2c controls,
- * query the mpeg controls if the existing ctrl id is
- * greater than the next mpeg ctrl id.
- */
- id = v4l2_ctrl_next(ctrl_classes, id);
- if (id >= ctrl->id && ctrl->name[0])
- return 0;
-
- memset(ctrl, 0, sizeof(*ctrl));
- ctrl->id = id;
+ ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
switch (ctrl->id) {
- case V4L2_CID_USER_CLASS:
case V4L2_CID_MPEG_CLASS:
- return v4l2_ctrl_query_fill_std(ctrl);
+ return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
case V4L2_CID_MPEG_STREAM_TYPE:
return v4l2_ctrl_query_fill(ctrl,
V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
@@ -437,20 +423,21 @@ static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
V4L2_MPEG_VIDEO_ASPECT_1x1);
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15);
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- return v4l2_ctrl_query_fill_std(ctrl);
+ return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
case V4L2_CID_MPEG_VIDEO_BITRATE:
return v4l2_ctrl_query_fill(ctrl,
64000,
10000000, 1,
- 9800000);
+ 1500000);
default:
- break;
+ return -EINVAL;
}
- return -EINVAL;
+ return 0;
}
-static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
+static int mpeg_s_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
{
/* pretty sure we can't change any of these while streaming */
if (go->streaming)
@@ -528,6 +515,8 @@ static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
}
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ if (ctrl->value < 0 || ctrl->value > 34)
+ return -EINVAL;
go->gop_size = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
@@ -547,7 +536,7 @@ static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
return 0;
}
-static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go)
+static int mpeg_g_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
{
switch (ctrl->id) {
case V4L2_CID_MPEG_STREAM_TYPE:
@@ -600,13 +589,11 @@ static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go)
}
return 0;
}
-#endif
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
strlcpy(cap->driver, "go7007", sizeof(cap->driver));
strlcpy(cap->card, go->name, sizeof(cap->card));
@@ -653,8 +640,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt->fmt.pix.width = go->width;
@@ -672,8 +658,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
return set_capture_size(go, fmt, 1);
}
@@ -681,8 +666,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (go->streaming)
return -EBUSY;
@@ -705,14 +689,14 @@ static int vidioc_reqbufs(struct file *file, void *priv,
req->memory != V4L2_MEMORY_MMAP)
return -EINVAL;
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
for (i = 0; i < gofh->buf_count; ++i)
if (gofh->bufs[i].mapped > 0)
goto unlock_and_return;
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
if (go->in_use > 0 && gofh->buf_count == 0) {
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
goto unlock_and_return;
}
@@ -731,7 +715,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
GFP_KERNEL);
if (!gofh->bufs) {
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
goto unlock_and_return;
}
@@ -750,8 +734,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
}
gofh->buf_count = count;
- up(&go->hw_lock);
- up(&gofh->lock);
+ mutex_unlock(&go->hw_lock);
+ mutex_unlock(&gofh->lock);
memset(req, 0, sizeof(*req));
@@ -762,7 +746,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return 0;
unlock_and_return:
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return retval;
}
@@ -778,7 +762,7 @@ static int vidioc_querybuf(struct file *file, void *priv,
index = buf->index;
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
if (index >= gofh->buf_count)
goto unlock_and_return;
@@ -802,12 +786,12 @@ static int vidioc_querybuf(struct file *file, void *priv,
buf->memory = V4L2_MEMORY_MMAP;
buf->m.offset = index * GO7007_BUF_SIZE;
buf->length = GO7007_BUF_SIZE;
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return 0;
unlock_and_return:
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return retval;
}
@@ -824,7 +808,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
buf->memory != V4L2_MEMORY_MMAP)
return retval;
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
if (buf->index < 0 || buf->index >= gofh->buf_count)
goto unlock_and_return;
@@ -865,12 +849,12 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
spin_lock_irqsave(&go->spinlock, flags);
list_add_tail(&gobuf->stream, &go->stream);
spin_unlock_irqrestore(&go->spinlock, flags);
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return 0;
unlock_and_return:
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return retval;
}
@@ -890,7 +874,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
if (buf->memory != V4L2_MEMORY_MMAP)
return retval;
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
if (list_empty(&go->stream))
goto unlock_and_return;
gobuf = list_entry(go->stream.next,
@@ -934,11 +918,11 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
buf->length = GO7007_BUF_SIZE;
buf->reserved = gobuf->modet_active;
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return 0;
unlock_and_return:
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return retval;
}
@@ -952,8 +936,8 @@ static int vidioc_streamon(struct file *file, void *priv,
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- down(&gofh->lock);
- down(&go->hw_lock);
+ mutex_lock(&gofh->lock);
+ mutex_lock(&go->hw_lock);
if (!go->streaming) {
go->streaming = 1;
@@ -964,8 +948,8 @@ static int vidioc_streamon(struct file *file, void *priv,
else
retval = 0;
}
- up(&go->hw_lock);
- up(&gofh->lock);
+ mutex_unlock(&go->hw_lock);
+ mutex_unlock(&gofh->lock);
return retval;
}
@@ -978,9 +962,9 @@ static int vidioc_streamoff(struct file *file, void *priv,
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
go7007_streamoff(go);
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return 0;
}
@@ -988,22 +972,20 @@ static int vidioc_streamoff(struct file *file, void *priv,
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *query)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (!go->i2c_adapter_online)
return -EIO;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query);
- return (!query->name[0]) ? -EINVAL : 0;
+ return (!query->name[0]) ? mpeg_queryctrl(query) : 0;
}
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
struct v4l2_queryctrl query;
if (!go->i2c_adapter_online)
@@ -1013,7 +995,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
query.id = ctrl->id;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
if (query.name[0] == 0)
- return -EINVAL;
+ return mpeg_g_ctrl(ctrl, go);
i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl);
return 0;
@@ -1022,8 +1004,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
struct v4l2_queryctrl query;
if (!go->i2c_adapter_online)
@@ -1033,7 +1014,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
query.id = ctrl->id;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
if (query.name[0] == 0)
- return -EINVAL;
+ return mpeg_s_ctrl(ctrl, go);
i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl);
return 0;
@@ -1042,8 +1023,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
static int vidioc_g_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parm)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
struct v4l2_fract timeperframe = {
.numerator = 1001 * go->fps_scale,
.denominator = go->sensor_framerate,
@@ -1061,8 +1041,7 @@ static int vidioc_g_parm(struct file *filp, void *priv,
static int vidioc_s_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parm)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
unsigned int n, d;
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1094,8 +1073,7 @@ static int vidioc_s_parm(struct file *filp, void *priv,
static int vidioc_enum_framesizes(struct file *filp, void *priv,
struct v4l2_frmsizeenum *fsize)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
/* Return -EINVAL, if it is a TV board */
if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
@@ -1115,8 +1093,7 @@ static int vidioc_enum_framesizes(struct file *filp, void *priv,
static int vidioc_enum_frameintervals(struct file *filp, void *priv,
struct v4l2_frmivalenum *fival)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
/* Return -EINVAL, if it is a TV board */
if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
@@ -1133,10 +1110,27 @@ static int vidioc_enum_frameintervals(struct file *filp, void *priv,
return 0;
}
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
+
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ *std = V4L2_STD_NTSC;
+ break;
+ case GO7007_STD_PAL:
+ *std = V4L2_STD_PAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (go->streaming)
return -EBUSY;
@@ -1178,30 +1172,27 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
return 0;
}
-#if 0
- case VIDIOC_QUERYSTD:
- {
- v4l2_std_id *std = arg;
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
+{
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
- if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
- go->input == go->board_info->num_inputs - 1) {
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter,
- VIDIOC_QUERYSTD, arg);
- } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
- *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
- else
- *std = 0;
- return 0;
- }
-#endif
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYSTD, std);
+ } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+ *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+ else
+ *std = 0;
+
+ return 0;
+}
static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *inp)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (inp->index >= go->board_info->num_inputs)
return -EINVAL;
@@ -1230,8 +1221,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
*input = go->input;
@@ -1240,8 +1230,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (input >= go->board_info->num_inputs)
return -EINVAL;
@@ -1262,8 +1251,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
return -EINVAL;
@@ -1281,8 +1269,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
return -EINVAL;
@@ -1308,8 +1295,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
return -EINVAL;
@@ -1324,8 +1310,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
return -EINVAL;
@@ -1340,8 +1325,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cropcap)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1385,8 +1369,7 @@ static int vidioc_cropcap(struct file *file, void *priv,
static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
{
- struct go7007_file *gofh = priv;
- struct go7007 *go = gofh->go;
+ struct go7007 *go = ((struct go7007_file *) priv)->go;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1734,18 +1717,18 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
return -EINVAL; /* only support VM_SHARED mapping */
if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
return -EINVAL; /* must map exactly one full buffer */
- down(&gofh->lock);
+ mutex_lock(&gofh->lock);
index = vma->vm_pgoff / GO7007_BUF_PAGES;
if (index >= gofh->buf_count) {
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return -EINVAL; /* trying to map beyond requested buffers */
}
if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return -EINVAL; /* offset is not aligned on buffer boundary */
}
if (gofh->bufs[index].mapped > 0) {
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return -EBUSY;
}
gofh->bufs[index].mapped = 1;
@@ -1754,7 +1737,7 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_DONTEXPAND;
vma->vm_flags &= ~VM_IO;
vma->vm_private_data = &gofh->bufs[index];
- up(&gofh->lock);
+ mutex_unlock(&gofh->lock);
return 0;
}
@@ -1801,7 +1784,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
@@ -1862,7 +1847,7 @@ void go7007_v4l2_remove(struct go7007 *go)
{
unsigned long flags;
- down(&go->hw_lock);
+ mutex_lock(&go->hw_lock);
if (go->streaming) {
go->streaming = 0;
go7007_stream_stop(go);
@@ -1870,7 +1855,7 @@ void go7007_v4l2_remove(struct go7007 *go)
abort_queued(go);
spin_unlock_irqrestore(&go->spinlock, flags);
}
- up(&go->hw_lock);
+ mutex_unlock(&go->hw_lock);
if (go->video_dev)
video_unregister_device(go->video_dev);
}
diff --git a/drivers/staging/go7007/go7007.txt b/drivers/staging/go7007/go7007.txt
index 1c2907c1dc81..06a76da32128 100644
--- a/drivers/staging/go7007/go7007.txt
+++ b/drivers/staging/go7007/go7007.txt
@@ -2,7 +2,7 @@ This is a driver for the WIS GO7007SB multi-format video encoder.
Pete Eberlein <pete@sensoray.com>
-The driver was originally released under the GPL and is currently hosted at:
+The driver was orignally released under the GPL and is currently hosted at:
http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver
The go7007 firmware can be acquired from the package on the site above.
@@ -24,10 +24,10 @@ These should be used instead of the non-standard GO7007 ioctls described
below.
-The README files from the original package appears below:
+The README files from the orignal package appear below:
---------------------------------------------------------------------------
- WIS GO7007SB Public Linux Driver
+ WIS GO7007SB Public Linux Driver
---------------------------------------------------------------------------
@@ -78,23 +78,23 @@ All vendor-built kernels should already be configured properly. However,
for custom-built kernels, the following options need to be enabled in the
kernel as built-in or modules:
- CONFIG_HOTPLUG - Support for hot-pluggable devices
- CONFIG_MODULES - Enable loadable module support
- CONFIG_KMOD - Automatic kernel module loading
- CONFIG_FW_LOADER - Hotplug firmware loading support
- CONFIG_I2C - I2C support
- CONFIG_VIDEO_DEV - Video For Linux
- CONFIG_SOUND - Sound card support
- CONFIG_SND - Advanced Linux Sound Architecture
- CONFIG_USB - Support for Host-side USB
- CONFIG_USB_DEVICEFS - USB device filesystem
- CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support
+ CONFIG_HOTPLUG - Support for hot-pluggable devices
+ CONFIG_MODULES - Enable loadable module support
+ CONFIG_KMOD - Automatic kernel module loading
+ CONFIG_FW_LOADER - Hotplug firmware loading support
+ CONFIG_I2C - I2C support
+ CONFIG_VIDEO_DEV - Video For Linux
+ CONFIG_SOUND - Sound card support
+ CONFIG_SND - Advanced Linux Sound Architecture
+ CONFIG_USB - Support for Host-side USB
+ CONFIG_USB_DEVICEFS - USB device filesystem
+ CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support
Additionally, to use the example application, the following options need to
be enabled in the ALSA section:
- CONFIG_SND_MIXER_OSS - OSS Mixer API
- CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API
+ CONFIG_SND_MIXER_OSS - OSS Mixer API
+ CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API
The hotplug scripts, along with the fxload utility, must also be installed.
These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>.
@@ -107,7 +107,7 @@ fxload and for loading firmware into the driver using the firmware agent.
Most users should be able to compile the driver by simply running:
- $ make
+ $ make
in the top-level directory of the driver kit. First the kernel modules
will be built, followed by the example applications.
@@ -117,12 +117,12 @@ currently-running kernel, or if the module should be built for a kernel
other than the currently-running kernel, an additional parameter will need
to be passed to make to specify the appropriate kernel source directory:
- $ make KERNELSRC=/usr/src/linux-2.6.10-custom3
+ $ make KERNELSRC=/usr/src/linux-2.6.10-custom3
Once the compile completes, the driver and firmware files should be
installed by running:
- $ make install
+ $ make install
The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra"
and the firmware files will be placed in the appropriate hotplug firmware
@@ -200,7 +200,7 @@ stereo audio broadcasts on the A2 carrier.
To verify that the configuration has been placed in the correct location,
execute:
- $ modprobe -c | grep wis-sony-tuner
+ $ modprobe -c | grep wis-sony-tuner
If the configuration line appears, then modprobe will pass the parameters
correctly the next time the wis-sony-tuner module is loaded into the
@@ -223,7 +223,7 @@ This application will auto-detect the V4L2 and ALSA/OSS device names of the
hardware and will record video and audio to an AVI file for a specified
number of seconds. For example:
- $ apps/gorecord -duration 60 capture.avi
+ $ apps/gorecord -duration 60 capture.avi
If this application does not successfully record an AVI file, the error
messages produced by gorecord and recorded in the system log (usually in
@@ -286,35 +286,35 @@ features of the GO7007SB encoder, which are described below:
Fields in struct go7007_comp_params:
- __u32 The maximum number of frames in each
- gop_size Group Of Pictures; i.e. the maximum
- number of frames minus one between
- each key frame.
+ __u32 The maximum number of frames in each
+ gop_size Group Of Pictures; i.e. the maximum
+ number of frames minus one between
+ each key frame.
- __u32 The maximum number of sequential
- max_b_frames bidirectionally-predicted frames.
- (B-frames are not yet supported.)
+ __u32 The maximum number of sequential
+ max_b_frames bidirectionally-predicted frames.
+ (B-frames are not yet supported.)
- enum go7007_aspect_ratio The aspect ratio to be encoded in the
- aspect_ratio meta-data of the compressed format.
+ enum go7007_aspect_ratio The aspect ratio to be encoded in the
+ aspect_ratio meta-data of the compressed format.
- Choices are:
- GO7007_ASPECT_RATIO_1_1
- GO7007_ASPECT_RATIO_4_3_NTSC
- GO7007_ASPECT_RATIO_4_3_PAL
- GO7007_ASPECT_RATIO_16_9_NTSC
- GO7007_ASPECT_RATIO_16_9_PAL
+ Choices are:
+ GO7007_ASPECT_RATIO_1_1
+ GO7007_ASPECT_RATIO_4_3_NTSC
+ GO7007_ASPECT_RATIO_4_3_PAL
+ GO7007_ASPECT_RATIO_16_9_NTSC
+ GO7007_ASPECT_RATIO_16_9_PAL
- __u32 Bit-wise OR of control flags (below)
- flags
+ __u32 Bit-wise OR of control flags (below)
+ flags
Flags in struct go7007_comp_params:
- GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used
- to produce streams appropriate for
- random seeking.
+ GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used
+ to produce streams appropriate for
+ random seeking.
- GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header.
+ GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header.
GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS
@@ -337,56 +337,56 @@ features of the GO7007SB encoder, which are described below:
Fields in struct go7007_mpeg_params:
- enum go7007_mpeg_video_standard
- mpeg_video_standard The MPEG video standard in which to
- compress the video.
-
- Choices are:
- GO7007_MPEG_VIDEO_MPEG1
- GO7007_MPEG_VIDEO_MPEG2
- GO7007_MPEG_VIDEO_MPEG4
-
- __u32 Bit-wise OR of control flags (below)
- flags
-
- __u32 The profile and level indication to be
- pali stored in the sequence header. This
- is only used as an indicator to the
- decoder, and does not affect the MPEG
- features used in the video stream.
- Not valid for MPEG1.
-
- Choices for MPEG2 are:
- GO7007_MPEG2_PROFILE_MAIN_MAIN
-
- Choices for MPEG4 are:
- GO7007_MPEG4_PROFILE_S_L0
- GO7007_MPEG4_PROFILE_S_L1
- GO7007_MPEG4_PROFILE_S_L2
- GO7007_MPEG4_PROFILE_S_L3
- GO7007_MPEG4_PROFILE_ARTS_L1
- GO7007_MPEG4_PROFILE_ARTS_L2
- GO7007_MPEG4_PROFILE_ARTS_L3
- GO7007_MPEG4_PROFILE_ARTS_L4
- GO7007_MPEG4_PROFILE_AS_L0
- GO7007_MPEG4_PROFILE_AS_L1
- GO7007_MPEG4_PROFILE_AS_L2
- GO7007_MPEG4_PROFILE_AS_L3
- GO7007_MPEG4_PROFILE_AS_L4
- GO7007_MPEG4_PROFILE_AS_L5
+ enum go7007_mpeg_video_standard
+ mpeg_video_standard The MPEG video standard in which to
+ compress the video.
+
+ Choices are:
+ GO7007_MPEG_VIDEO_MPEG1
+ GO7007_MPEG_VIDEO_MPEG2
+ GO7007_MPEG_VIDEO_MPEG4
+
+ __u32 Bit-wise OR of control flags (below)
+ flags
+
+ __u32 The profile and level indication to be
+ pali stored in the sequence header. This
+ is only used as an indicator to the
+ decoder, and does not affect the MPEG
+ features used in the video stream.
+ Not valid for MPEG1.
+
+ Choices for MPEG2 are:
+ GO7007_MPEG2_PROFILE_MAIN_MAIN
+
+ Choices for MPEG4 are:
+ GO7007_MPEG4_PROFILE_S_L0
+ GO7007_MPEG4_PROFILE_S_L1
+ GO7007_MPEG4_PROFILE_S_L2
+ GO7007_MPEG4_PROFILE_S_L3
+ GO7007_MPEG4_PROFILE_ARTS_L1
+ GO7007_MPEG4_PROFILE_ARTS_L2
+ GO7007_MPEG4_PROFILE_ARTS_L3
+ GO7007_MPEG4_PROFILE_ARTS_L4
+ GO7007_MPEG4_PROFILE_AS_L0
+ GO7007_MPEG4_PROFILE_AS_L1
+ GO7007_MPEG4_PROFILE_AS_L2
+ GO7007_MPEG4_PROFILE_AS_L3
+ GO7007_MPEG4_PROFILE_AS_L4
+ GO7007_MPEG4_PROFILE_AS_L5
Flags in struct go7007_mpeg_params:
- GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and
- bitrate control settings to comply
- with DVD MPEG2 stream requirements.
- This overrides most compression and
- bitrate settings!
+ GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and
+ bitrate control settings to comply
+ with DVD MPEG2 stream requirements.
+ This overrides most compression and
+ bitrate settings!
- GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header.
+ GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header.
- GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at
- the start of each GOP.
+ GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at
+ the start of each GOP.
GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE
@@ -404,7 +404,7 @@ features of the GO7007SB encoder, which are described below:
----------------------------------------------------------------------------
- Installing the WIS PCI Voyager Driver
+ Installing the WIS PCI Voyager Driver
---------------------------------------------------------------------------
The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
index 1706fbf06847..8c85a9c3665a 100644
--- a/drivers/staging/go7007/s2250-board.c
+++ b/drivers/staging/go7007/s2250-board.c
@@ -21,12 +21,10 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include "s2250-loader.h"
#include "go7007-priv.h"
#include "wis-i2c.h"
-extern int s2250loader_init(void);
-extern void s2250loader_cleanup(void);
-
#define TLV320_ADDRESS 0x34
#define VPX322_ADDR_ANALOGCONTROL1 0x02
#define VPX322_ADDR_BRIGHTNESS0 0x0127
@@ -34,7 +32,7 @@ extern void s2250loader_cleanup(void);
#define VPX322_ADDR_CONTRAST0 0x0128
#define VPX322_ADDR_CONTRAST1 0x0132
#define VPX322_ADDR_HUE 0x00dc
-#define VPX322_ADDR_SAT 0x0030
+#define VPX322_ADDR_SAT 0x0030
struct go7007_usb_board {
unsigned int flags;
@@ -43,7 +41,7 @@ struct go7007_usb_board {
struct go7007_usb {
struct go7007_usb_board *board;
- struct semaphore i2c_lock;
+ struct mutex i2c_lock;
struct usb_device *usbdev;
struct urb *video_urbs[8];
struct urb *audio_urbs[8];
@@ -114,7 +112,7 @@ static u16 vid_regs_fp_pal[] =
};
struct s2250 {
- int std;
+ v4l2_std_id std;
int input;
int brightness;
int contrast;
@@ -165,7 +163,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value)
return -ENOMEM;
usb = go->hpi_context;
- if (down_interruptible(&usb->i2c_lock) != 0) {
+ if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
printk(KERN_INFO "i2c lock failed\n");
kfree(buf);
return -EINTR;
@@ -175,7 +173,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value)
buf,
16, 1);
- up(&usb->i2c_lock);
+ mutex_unlock(&usb->i2c_lock);
kfree(buf);
return rc;
}
@@ -203,19 +201,23 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
memset(buf, 0xcd, 6);
usb = go->hpi_context;
- if (down_interruptible(&usb->i2c_lock) != 0) {
+ if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
printk(KERN_INFO "i2c lock failed\n");
+ kfree(buf);
return -EINTR;
}
- if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0)
+ if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) {
+ kfree(buf);
return -EFAULT;
+ }
- up(&usb->i2c_lock);
+ mutex_unlock(&usb->i2c_lock);
if (buf[0] == 0) {
unsigned int subaddr, val_read;
subaddr = (buf[4] << 8) + buf[5];
val_read = (buf[2] << 8) + buf[3];
+ kfree(buf);
if (val_read != val) {
printk(KERN_INFO "invalid fp write %x %x\n",
val_read, val);
@@ -226,8 +228,10 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
subaddr, addr);
return -EFAULT;
}
- } else
+ } else {
+ kfree(buf);
return -EFAULT;
+ }
/* save last 12b value */
if (addr == 0x12b)
@@ -236,6 +240,45 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
return 0;
}
+static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
+{
+ struct go7007 *go = i2c_get_adapdata(client->adapter);
+ struct go7007_usb *usb;
+ u8 *buf;
+
+ if (go == NULL)
+ return -ENODEV;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return -EBUSY;
+
+ buf = kzalloc(16, GFP_KERNEL);
+
+ if (buf == NULL)
+ return -ENOMEM;
+
+
+
+ memset(buf, 0xcd, 6);
+ usb = go->hpi_context;
+ if (down_interruptible(&usb->i2c_lock) != 0) {
+ printk(KERN_INFO "i2c lock failed\n");
+ kfree(buf);
+ return -EINTR;
+ }
+ if (go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1) < 0) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ up(&usb->i2c_lock);
+
+ *val = (buf[0] << 8) | buf[1];
+ kfree(buf);
+
+ return 0;
+}
+
+
static int write_regs(struct i2c_client *client, u8 *regs)
{
int i;
@@ -350,14 +393,42 @@ static int s2250_command(struct i2c_client *client,
{
struct v4l2_control *ctrl = arg;
int value1;
+ u16 oldvalue;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
- printk(KERN_INFO "s2250: future setting\n");
- return -EINVAL;
+ if (ctrl->value > 100)
+ dec->brightness = 100;
+ else if (ctrl->value < 0)
+ dec->brightness = 0;
+ else
+ dec->brightness = ctrl->value;
+ value1 = (dec->brightness - 50) * 255 / 100;
+ read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
+ write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
+ value1 | (oldvalue & ~0xff));
+ read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
+ write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
+ value1 | (oldvalue & ~0xff));
+ write_reg_fp(client, 0x140, 0x60);
+ break;
case V4L2_CID_CONTRAST:
- printk(KERN_INFO "s2250: future setting\n");
- return -EINVAL;
+ if (ctrl->value > 100)
+ dec->contrast = 100;
+ else if (ctrl->value < 0)
+ dec->contrast = 0;
+ else
+ dec->contrast = ctrl->value;
+ value1 = dec->contrast * 0x40 / 100;
+ if (value1 > 0x3f)
+ value1 = 0x3f; /* max */
+ read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
+ write_reg_fp(client, VPX322_ADDR_CONTRAST0,
+ value1 | (oldvalue & ~0x3f));
+ read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
+ write_reg_fp(client, VPX322_ADDR_CONTRAST1,
+ value1 | (oldvalue & ~0x3f));
+ write_reg_fp(client, 0x140, 0x60);
break;
case V4L2_CID_SATURATION:
if (ctrl->value > 127)
@@ -541,7 +612,7 @@ static int s2250_probe(struct i2c_client *client,
dec->audio_input = 0;
write_reg(client, 0x08, 0x02); /* Line In */
- if (down_interruptible(&usb->i2c_lock) == 0) {
+ if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
data = kzalloc(16, GFP_KERNEL);
if (data != NULL) {
int rc;
@@ -560,7 +631,7 @@ static int s2250_probe(struct i2c_client *client,
}
kfree(data);
}
- up(&usb->i2c_lock);
+ mutex_unlock(&usb->i2c_lock);
}
printk("s2250: initialized successfully\n");
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
index bb22347af60e..d7bf82983274 100644
--- a/drivers/staging/go7007/s2250-loader.c
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -35,7 +35,7 @@ typedef struct device_extension_s {
#define MAX_DEVICES 256
static pdevice_extension_t s2250_dev_table[MAX_DEVICES];
-static DECLARE_MUTEX(s2250_dev_table_mutex);
+static DEFINE_MUTEX(s2250_dev_table_mutex);
#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref)
static void s2250loader_delete(struct kref *kref)
@@ -67,7 +67,7 @@ static int s2250loader_probe(struct usb_interface *interface,
printk(KERN_ERR "can't handle multiple config\n");
return -1;
}
- down(&s2250_dev_table_mutex);
+ mutex_lock(&s2250_dev_table_mutex);
for (minor = 0; minor < MAX_DEVICES; minor++) {
if (s2250_dev_table[minor] == NULL)
@@ -96,7 +96,7 @@ static int s2250loader_probe(struct usb_interface *interface,
kref_init(&(s->kref));
- up(&s2250_dev_table_mutex);
+ mutex_unlock(&s2250_dev_table_mutex);
if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
printk(KERN_ERR
@@ -128,7 +128,7 @@ static int s2250loader_probe(struct usb_interface *interface,
return 0;
failed:
- up(&s2250_dev_table_mutex);
+ mutex_unlock(&s2250_dev_table_mutex);
failed2:
if (s)
kref_put(&(s->kref), s2250loader_delete);
diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c
index cd19be6c00e0..03c4dfc138a1 100644
--- a/drivers/staging/go7007/snd-go7007.c
+++ b/drivers/staging/go7007/snd-go7007.c
@@ -26,7 +26,7 @@
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/i2c.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/system.h>
#include <sound/core.h>
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 6c3427bb6f4c..506dca6e942e 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -111,7 +111,8 @@ static int wis_tw9903_command(struct i2c_client *client,
i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1));
break;
}
-#if 0 /* The scaler on this thing seems to be horribly broken */
+#if 0
+ /* The scaler on this thing seems to be horribly broken */
case DECODER_SET_RESOLUTION:
{
struct video_decoder_resolution *res = arg;
diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
index 8fe543bd9910..3a4793a0fd05 100644
--- a/drivers/staging/hv/osd.c
+++ b/drivers/staging/hv/osd.c
@@ -30,6 +30,7 @@
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index beb99a547f09..4586650d65c3 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -4,6 +4,7 @@
menuconfig IIO
tristate "Industrial I/O support"
+ depends on !S390
---help---
The industrial I/O subsystem provides a unified framework for
drivers for many different types of embedded sensors using a
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 660a9c1a1f3f..768f44894d08 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -18,6 +18,8 @@
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
#include <linux/cdev.h>
#include "iio.h"
#include "trigger_consumer.h"
@@ -39,14 +41,14 @@ dev_t iio_devt;
EXPORT_SYMBOL(iio_devt);
#define IIO_DEV_MAX 256
-static char *iio_nodename(struct device *dev)
+static char *iio_devnode(struct device *dev, mode_t *mode)
{
return kasprintf(GFP_KERNEL, "iio/%s", dev_name(dev));
}
struct class iio_class = {
.name = "iio",
- .nodename = iio_nodename,
+ .devnode = iio_devnode,
};
EXPORT_SYMBOL(iio_class);
diff --git a/drivers/staging/iio/light/tsl2561.c b/drivers/staging/iio/light/tsl2561.c
index ea8a5efc19bc..fc2107f4c049 100644
--- a/drivers/staging/iio/light/tsl2561.c
+++ b/drivers/staging/iio/light/tsl2561.c
@@ -239,10 +239,6 @@ static int __devexit tsl2561_remove(struct i2c_client *client)
return tsl2561_powerdown(client);
}
-static unsigned short normal_i2c[] = { 0x29, 0x39, 0x49, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
static const struct i2c_device_id tsl2561_id[] = {
{ "tsl2561", 0 },
{ }
diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c
index 9111dcba37a1..8ccfff723eec 100644
--- a/drivers/staging/p9auth/p9auth.c
+++ b/drivers/staging/p9auth/p9auth.c
@@ -183,7 +183,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
user_buf_running = NULL;
hash_str = NULL;
node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
- user_buf = kzalloc(count, GFP_KERNEL);
+ user_buf = kzalloc(count+1, GFP_KERNEL);
if (!node_ptr || !user_buf)
goto out;
@@ -207,6 +207,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
list_add(&(node_ptr->list), &(dev->head->list));
node_ptr = NULL;
} else {
+ char *tmpu;
if (!cap_devices[0].head ||
list_empty(&(cap_devices[0].head->list))) {
retval = -EINVAL;
@@ -218,10 +219,10 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
* need to split it and hash 'user1@user2' using 'randomstring'
* as the key.
*/
- user_buf_running = kstrdup(user_buf, GFP_KERNEL);
- source_user = strsep(&user_buf_running, "@");
- target_user = strsep(&user_buf_running, "@");
- rand_str = strsep(&user_buf_running, "@");
+ tmpu = user_buf_running = kstrdup(user_buf, GFP_KERNEL);
+ source_user = strsep(&tmpu, "@");
+ target_user = strsep(&tmpu, "@");
+ rand_str = tmpu;
if (!source_user || !target_user || !rand_str) {
retval = -EINVAL;
goto out;
@@ -229,7 +230,8 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
/* hash the string user1@user2 with rand_str as the key */
len = strlen(source_user) + strlen(target_user) + 1;
- hash_str = kzalloc(len, GFP_KERNEL);
+ /* src, @, len, \0 */
+ hash_str = kzalloc(len+1, GFP_KERNEL);
strcat(hash_str, source_user);
strcat(hash_str, "@");
strcat(hash_str, target_user);
diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c
index 0d111ddfabb2..2eb8e3d43c4d 100644
--- a/drivers/staging/poch/poch.c
+++ b/drivers/staging/poch/poch.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/io.h>
+#include <linux/sched.h>
#include "poch.h"
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
index 90f962ee5fd8..5d04bf5b021a 100644
--- a/drivers/staging/pohmelfs/config.c
+++ b/drivers/staging/pohmelfs/config.c
@@ -527,10 +527,13 @@ out_unlock:
return err;
}
-static void pohmelfs_cn_callback(struct cn_msg *msg)
+static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
int err;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
switch (msg->flags) {
case POHMELFS_FLAGS_ADD:
case POHMELFS_FLAGS_DEL:
diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c
index fb1735533b74..857ff450b6c9 100644
--- a/drivers/staging/rt2860/common/cmm_data_2860.c
+++ b/drivers/staging/rt2860/common/cmm_data_2860.c
@@ -363,6 +363,8 @@ int RtmpPCIMgmtKickOut(
ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
+ if (!pTxD)
+ return 0;
pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c
index 9d589c240ed0..019cc4474ce8 100644
--- a/drivers/staging/rt2860/common/cmm_info.c
+++ b/drivers/staging/rt2860/common/cmm_info.c
@@ -25,6 +25,7 @@
*************************************************************************
*/
+#include <linux/sched.h>
#include "../rt_config.h"
INT Show_SSID_Proc(
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
index b396a9b570e2..ed27b8545a1b 100644
--- a/drivers/staging/rt2860/rt_linux.c
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -25,6 +25,7 @@
*************************************************************************
*/
+#include <linux/sched.h>
#include "rt_config.h"
ULONG RTDebugLevel = RT_DEBUG_ERROR;
diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h
index 3f498f6f3ff6..90fd40f24734 100644
--- a/drivers/staging/rt2860/rtmp.h
+++ b/drivers/staging/rt2860/rtmp.h
@@ -2060,7 +2060,7 @@ typedef struct _STA_ADMIN_CONFIG {
BOOLEAN AdhocBGJoined; // Indicate Adhoc B/G Join.
BOOLEAN Adhoc20NJoined; // Indicate Adhoc 20MHz N Join.
#endif
- // New for WPA, windows want us to to keep association information and
+ // New for WPA, windows want us to keep association information and
// Fixed IEs from last association response
NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo;
USHORT ReqVarIELen; // Length of next VIE include EID & Length
diff --git a/drivers/staging/rt3090/common/cmm_info.c b/drivers/staging/rt3090/common/cmm_info.c
index 5be0714666cb..3e51e98b474c 100644
--- a/drivers/staging/rt3090/common/cmm_info.c
+++ b/drivers/staging/rt3090/common/cmm_info.c
@@ -34,6 +34,7 @@
--------- ---------- ----------------------------------------------
*/
+#include <linux/sched.h>
#include "../rt_config.h"
diff --git a/drivers/staging/rt3090/rt_linux.c b/drivers/staging/rt3090/rt_linux.c
index d2241ecdf583..9b94aa6eb904 100644
--- a/drivers/staging/rt3090/rt_linux.c
+++ b/drivers/staging/rt3090/rt_linux.c
@@ -25,6 +25,7 @@
*************************************************************************
*/
+#include <linux/sched.h>
#include "rt_config.h"
ULONG RTDebugLevel = RT_DEBUG_ERROR;
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index d4fa65489655..b0802a7aeb5f 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -46,6 +46,7 @@
#undef DEBUG_TX_DESC
//#define CONFIG_RTL8192_IO_MAP
+#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include "r8192E_hw.h"
#include "r8192E.h"
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 87f8a1192762..f890a16096c0 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -38,6 +38,7 @@
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/wait.h>
+#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/firmware.h>
#include <asm/ioctl.h>
diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c
index 12d414deaad6..be99eb33d817 100644
--- a/drivers/staging/stlc45xx/stlc45xx.c
+++ b/drivers/staging/stlc45xx/stlc45xx.c
@@ -2591,3 +2591,4 @@ module_exit(stlc45xx_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
+MODULE_ALIAS("spi:cx3110x");
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 3d2a84c45829..e139eaeaa174 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -25,6 +25,7 @@
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
+#include <linux/sched.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 8960fa9ee7aa..00fe0803c21c 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -25,6 +25,7 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
+#include <linux/sched.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 8950724f168e..067082a7d759 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -51,10 +51,26 @@ static struct ieee80211_supported_band wbsoft_band_2GHz = {
.n_bitrates = ARRAY_SIZE(wbsoft_rates),
};
+static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
+{
+ u32 tmp;
+
+ if (pHwData->SurpriseRemove)
+ return;
+
+ pHwData->BeaconPeriod = beacon_period;
+ tmp = pHwData->BeaconPeriod << 16;
+ tmp |= pHwData->ProbeDelay;
+ Wb35Reg_Write(pHwData, 0x0848, tmp);
+}
+
static int wbsoft_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
- printk("wbsoft_add interface called\n");
+ struct wbsoft_priv *priv = dev->priv;
+
+ hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
+
return 0;
}
@@ -83,10 +99,16 @@ static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
return 0;
}
+static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
+ struct dev_addr_list *mc_list)
+{
+ return mc_count;
+}
+
static void wbsoft_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
- int mc_count, struct dev_mc_list *mclist)
+ u64 multicast)
{
unsigned int new_flags;
@@ -94,7 +116,7 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev,
if (*total_flags & FIF_PROMISC_IN_BSS)
new_flags |= FIF_PROMISC_IN_BSS;
- else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32))
+ else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
new_flags |= FIF_ALLMULTI;
dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
@@ -138,19 +160,6 @@ static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
}
-static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
-{
- u32 tmp;
-
- if (pHwData->SurpriseRemove)
- return;
-
- pHwData->BeaconPeriod = beacon_period;
- tmp = pHwData->BeaconPeriod << 16;
- tmp |= pHwData->ProbeDelay;
- Wb35Reg_Write(pHwData, 0x0848, tmp);
-}
-
static void
hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
{
@@ -244,7 +253,6 @@ static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
{
struct wbsoft_priv *priv = dev->priv;
- struct ieee80211_conf *conf = &dev->conf;
ChanInfo ch;
printk("wbsoft_config called\n");
@@ -254,7 +262,6 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
ch.ChanNo = 1;
hal_set_current_channel(&priv->sHwData, ch);
- hal_set_beacon_period(&priv->sHwData, conf->beacon_int);
hal_set_accept_broadcast(&priv->sHwData, 1);
hal_set_accept_promiscuous(&priv->sHwData, 1);
hal_set_accept_multicast(&priv->sHwData, 1);
@@ -277,6 +284,7 @@ static const struct ieee80211_ops wbsoft_ops = {
.add_interface = wbsoft_add_interface,
.remove_interface = wbsoft_remove_interface,
.config = wbsoft_config,
+ .prepare_multicast = wbsoft_prepare_multicast,
.configure_filter = wbsoft_configure_filter,
.get_stats = wbsoft_get_stats,
.get_tx_stats = wbsoft_get_tx_stats,